variables crash inside (?{})

Discussion in 'Perl Misc' started by Jerome Abela, May 2, 2006.

  1. Jerome Abela

    Jerome Abela Guest

    Hi there,

    The following code comes directly from perlre(1), except it's inside a
    sub:

    animals();
    animals();
    sub animals {
    my ($color, $animal);
    $_ = "The brown fox jumps over the lazy dog";
    /the (\S+)(?{ $color = $^N }) (\S+)(?{ $animal = $^N })/i;
    print "color = $color, animal = $animal\n";
    }

    But its output is surprizing (at least with v5.8.5 and v5.8.7):

    color = brown, animal = fox
    color = , animal =

    Everything works if I don't declare lexical variables, so it may be
    related to some kind of scoping from inside the (?{}). But I can't find
    any reasonable explanation for this behavior.

    I need help from more knowledgeable people: how can I write more robust
    code to be used from (?{}) expressions ?

    Or, as an alternative, how can I store data matched inside nested
    groups ? My real original code is more like:
    m/special\((?:before(group)after(?{save it, using $^N}))*\)/
    where the {save using $^N} part only works once because of the bug
    above.


    Jerome.
    Jerome Abela, May 2, 2006
    #1
    1. Advertising

  2. Jerome Abela

    Guest

    "Jerome Abela" <> wrote:
    > Hi there,
    >
    > The following code comes directly from perlre(1), except it's inside a
    > sub:
    >
    > animals();
    > animals();
    > sub animals {
    > my ($color, $animal);
    > $_ = "The brown fox jumps over the lazy dog";
    > /the (\S+)(?{ $color = $^N }) (\S+)(?{ $animal = $^N })/i;
    > print "color = $color, animal = $animal\n";
    > }
    >
    > But its output is surprizing (at least with v5.8.5 and v5.8.7):
    >
    > color = brown, animal = fox
    > color = , animal =
    >
    > Everything works if I don't declare lexical variables, so it may be
    > related to some kind of scoping from inside the (?{}). But I can't find
    > any reasonable explanation for this behavior.



    The regex gloms onto the $color and $animal which are in scope the first
    time the regex is encountered, and doesn't update them. The second time
    animals is called, a different $color and $animal are created, but the
    regex is still using the old ones.

    It appears to be just like as if you did:

    animals();
    animals();
    sub animals {
    my ($color, $animal);
    sub foo {
    $color="brown";
    $animal="fox";
    };
    foo();
    print "color = $color, animal = $animal\n";
    }

    Only this generates a 'Variable "$color" will not stay shared' warning
    while the regex does not generate warnings.


    > I need help from more knowledgeable people: how can I write more robust
    > code to be used from (?{}) expressions ?


    Considering the "highly experimental" disclaimer, I would suggest you can't
    write robust code to be used thus. Ignoring that, use a package variable.

    >
    > Or, as an alternative, how can I store data matched inside nested
    > groups ?


    I've never had problems doing that with plain old regular expressions.

    > My real original code is more like:
    > m/special\((?:before(group)after(?{save it, using $^N}))*\)/
    > where the {save using $^N} part only works once because of the bug
    > above.


    How about something like:

    my ($thing) = m/special\(((?:beforegroupafter)*)\)/ or die;
    my (@data) = $thing=~/before(group)after/g;

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , May 2, 2006
    #2
    1. Advertising

  3. Jerome Abela wrote:
    > Hi there,
    >
    > The following code comes directly from perlre(1), except it's inside a
    > sub:
    >
    > animals();
    > animals();
    > sub animals {
    > my ($color, $animal);
    > $_ = "The brown fox jumps over the lazy dog";
    > /the (\S+)(?{ $color = $^N }) (\S+)(?{ $animal = $^N })/i;
    > print "color = $color, animal = $animal\n";
    > }
    >
    > But its output is surprizing (at least with v5.8.5 and v5.8.7):
    >
    > color = brown, animal = fox
    > color = , animal =
    >
    > Everything works if I don't declare lexical variables, so it may be
    > related to some kind of scoping from inside the (?{}). But I can't find
    > any reasonable explanation for this behavior.


    There is no reasonable explaination for why (?{}) doesn't play nicely
    with lexical variables. There's an unreasonable one analagous to the
    mechanism that results in the the "will not remain shared" warning.

    This is a know problem but (?{}) is still considered experimental isn't
    it?

    > I need help from more knowledgeable people: how can I write more robust
    > code to be used from (?{}) expressions ?


    Until further notice use only package variables inside (?{}).

    Simply change

    my ($color, $animal);

    to

    local our ($color, $animal);
    Brian McCauley, May 2, 2006
    #3
  4. Jerome Abela

    Jerome Abela Guest

    Thanks a lot, Xho and Brian !

    Now, I have a nice explanation of what happens (the regex creates a
    closure on the lexical variables when executed for the first time), and
    I have the solution, which consist in using "our", so that both the
    closure and my local variables refer to the same thing.

    Thank you to both of you !

    > How about something like:
    > my ($thing) = m/special\(((?:beforegroupafter)*)\)/ or die;
    > my (@data) = $thing=~/before(group)after/g;


    "before", "group", and "after" are complex regexps, so it hurts to
    execute them twice.


    Jerome.
    Jerome Abela, May 3, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy Eshtry
    Replies:
    0
    Views:
    624
    Andy Eshtry
    Mar 1, 2004
  2. Dave
    Replies:
    0
    Views:
    795
  3. DC Gringo
    Replies:
    4
    Views:
    4,817
    mfreidge
    Dec 17, 2007
  4. Replies:
    9
    Views:
    935
  5. console kid
    Replies:
    6
    Views:
    237
    Balog Pal
    Mar 31, 2011
Loading...

Share This Page