Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I managed to save a byte while golfing (unrelated, and sorry about stupid links), then wondered why did it work at all. With following SSCCE, the least level of consistency I'd expect is same output for both "for" cases, but hesitate to point which result of the two is correct and must be the same for them all, perhaps "1 2 2 2 1"?

use strict; use warnings; print "map\t"; 1 =~ /1/; map { print "$& "; 2 =~ /2/; print "$& "; } 0, 1; print "$&\n"; print "block\t"; my $n = 1; 1 =~ /1/; { print "$& "; 2 =~ /2/; print "$& "; redo if $n -- }; print "$&\n"; print "foreach\t"; 1 =~ /1/; for (0, 1) { print "$& "; 2 =~ /2/; print "$& "; } print "$&\n"; print "while\t"; my $m = 2; 1 =~ /1/; while ($m --) { print "$& "; 2 =~ /2/; print "$& "; }; print "$&\n"; print "for\t"; 1 =~ /1/; for (my $i = 0; $i <= 1; $i++) { print "$& "; 2 =~ /2/; print "$& "; } print "$&\n"; __END__ map 1 2 1 2 1 block 1 2 1 2 1 foreach 1 2 2 2 1 while 1 2 2 2 1 for 1 2 1 2 1

Replies are listed 'Best First'.
Re: Regexp vars localization in blocks
by hv (Prior) on Jul 26, 2023 at 11:06 UTC

    I feel that I should know the answer to this, but I haven't a clue. I note that the scope in the foreach and while blocks is being unwound on each iteration:

    our $x = 1; for (1, 0) { print "$x "; local $x = 2 if $_; print "$x "; } print "$x\n"; __END__ 1 2 1 1 1

    I would suggest reporting it to the Perl project on github as an unexpected inconsistency and possible bug.

Re: Regexp vars localization in blocks
by ikegami (Patriarch) on Jul 28, 2023 at 00:36 UTC

    In a while loop, there is a per-pass scope that extends beyond the body. The loop expression is evaluated in this scope.

    In a foreach loop, you also have a per-pass scope that extends beyond the body of the loop. The loop iterator var is found in this scope.

    While a C-style for loop has a statement-wide scope, doesn't have a per-pass scope beyond the loop body.

    map and bare loops similarly don't have a per-pass scope beyond the loop body.

    I don't know much about $& localization, but the results correlate to the existence of that larger per-loop scope.

      This C-style for:

      1 =~ /1/; for (my $i = 3; $i =~ /[34]/; $i++) { print $&; } print $&;

      says 341, not 344. Isn't it because of beyond-body, outer-implied-braceless scope, which is same as in similar while loop?

      Or did you mean something else, by "per-pass" (is it same as "per-loop") scope? The confusing part is why $& in OP (but not localized $x in hv's code) preserves its value between iterations.

      And further (maybe unrelated; sorry, have just seen it, can't un-see):

      1 =~ /1/; for ((my $i = 3) =~ /./; $i =~ /[34]/; $i++) { print $&; } print $&;

      says 343. Again, sorry if it's waste of time, these are (questionably) good in idle golf etc., seem not have bothered busy people in 30+ (?) years.

Re: Regexp vars localization in blocks
by Anonymous Monk on Jul 26, 2023 at 11:56 UTC
    Which perl version?