in reply to Multiple uses of (?{ code }) do not appear to be called

Yet another variant, which allows you to keep your original my @o.

The idea is to wrap a kind of "throw-away" subroutine around the push ... code. The subroutine is created anew every time the ?{...} code is being called.

sub foo { my $window = "a b X20 c X5 d e X17 X12"; my @o; my @m = ($window =~ m/(X\d+(?{(sub {push @o, @_})->(pos)}))/g); print join(" ", "Matches:", @m, "\n"); print join(" ", "Offsets:", @o, "\n\n"); }

It thus is working around the closure effect of "binding" the first instance of the dynamic variable @o to the ?{...} code.

(I'm not saying that this is in any way better than the other suggestions (in particular blazar's suggestion using our @o)... but heh, Perl would only be half as much fun if there weren't always more than one way to do it :)

Replies are listed 'Best First'.
Re^2: Multiple uses of (?{ code }) do not appear to be called
by bsdz (Friar) on Dec 29, 2006 at 15:48 UTC
    I did try something similar using external anonymous subs but that didn't work. Interesting that it works if the sub is inline.

      Thing is, if you declare the sub outside of the ?{...} code, that code will bind the first instance of the subroutine. Printing the coderefs shows what's going on:

      sub foo { my $window = "a b X20 c X5 d e X17 X12"; my @o; my $push_o = sub { push @o, @_ }; print "subN=$push_o\n"; my @m = ($window =~ m/(X\d+(?{print "sub1=$push_o\n"; $push_o->(po +s)}))/g); print join(" ", "Matches:", @m, "\n"); print join(" ", "Offsets:", @o, "\n\n"); }

      Output:

      subN=CODE(0x8119060) sub1=CODE(0x8119060) sub1=CODE(0x8119060) sub1=CODE(0x8119060) sub1=CODE(0x8119060) Matches: X20 X5 X17 X12 Offsets: 7 12 20 24 subN=CODE(0x8131ac0) sub1=CODE(0x8119060) sub1=CODE(0x8119060) sub1=CODE(0x8119060) sub1=CODE(0x8119060) Matches: X20 X5 X17 X12 Offsets: subN=CODE(0x8119d50) sub1=CODE(0x8119060) sub1=CODE(0x8119060) sub1=CODE(0x8119060) sub1=CODE(0x8119060) Matches: X20 X5 X17 X12 Offsets:

      Despite three subroutines being created (--> "subN=..."), the one actually being called within ?{...} is always the same, first one (--> "sub1=..."). This sub in turn is bound to the first instance of the variable @o ...

Re^2: Multiple uses of (?{ code }) do not appear to be called
by Anonymous Monk on Dec 30, 2006 at 06:41 UTC
    There is an appreciation of this at http://use.perl.org/~jjore/journal/32016 I like it too. Unfortunately, on perl-5.8.3 I get a segmentation fault.
Re^2: Multiple uses of (?{ code }) do not appear to be called
by ikegami (Patriarch) on Mar 12, 2007 at 23:32 UTC
    It's much easier, safer and faster to use package variables when dealing with regexps.
    sub foo { my $window = "a b X20 c X5 d e X17 X12"; local our @o; my @m = ($window =~ m/(X\d+(?{ push @o, pos }))/g); print join(" ", "Matches:", @m, "\n"); print join(" ", "Offsets:", @o, "\n\n"); }

    Update: Oops, this has already been said elsewhere in the thread. I didn't enter this thread at the root node.