in reply to list assignment and undef

I left one of your questions unanswered: Why do the values returned by 1..10 appear to be global?

$ perl -MDevel::Peek -e'Dump $_ for 1' SV = IV(0x816a408) at 0x814f6f0 REFCNT = 2 FLAGS = (PADBUSY,PADTMP,IOK,READONLY,pIOK) IV = 1 $ perl -MDevel::Peek -e'Dump $_ for 1..1' SV = IV(0x816a40c) at 0x814ed9c REFCNT = 1 FLAGS = (IOK,pIOK) IV = 1

I've touched on it before. Range operators in list context with constants for arguments are expanded once (at compile-time?) and cached.

I wish I could explain the following:

$ perl -le'for (1..2) { map { print($_++) } 1..2 }' 1 2 2 3 $ perl -le'for (1..2) { for (1..2) { print($_++) } }' 1 2 1 2

Replies are listed 'Best First'.
Re^2: list assignment and undef (range returns non-temps)
by Marshall (Canon) on Aug 26, 2009 at 14:44 UTC
    I did some testing to see what was going on in this last thing. The map{} version produces different results because somehow it appears that it is modifying the map{} input!

    I don't understand WHY? either, I didn't think that map{} could modify an input, but evidently that is true when the $_ var is modified. This modified input apparently is used on subsequent use of the map{}.

    My testing raises more questions than it provides answers, but one thing is that ("a","b","c","d") is different than ('a'..'d').

    I changed to a,b,c for input instead of 1,2,3 during testing to differentiate the "for (1..2)" from the map's 1,2.

    Anyway I hope looking at this test will stimulate other Monk brain cells!

    #!/usr/bin/perl -w use strict; $| =1; #autoflush on (sequence STDERR STDOUT timewise) foreach my $z (1..3) { my @a = map{ $_++} ('a'..'d'); print "z=$z variable a=@a\n"; } #prints #z=1 variable a=a b c d #z=2 variable a=b c d e #z=3 variable a=c d e f foreach my $z (1..3) { #for some reason this modifies the input to the map # my @a = map{ $_++} ("a","b","c","d"); #this works differently....ie, like the 2nd case in post! # my @a = map{my $x = $_; # $x++;} ("a","b","c","d"); print "z=$z variable a=@a\n"; } #prints #Modification of a read-only value attempted at #C:\TEMP\perl11.pl line 18.

      I didn't think that map{} could modify an input, but evidently that is true when the $_ var is modified.

      It's clearly documented: "Note that $_ is an alias to the list value, so it can be used to modify the elements of the LIST." Just like foreach loops.

      Many people use map { s/// }, but that clobbers the input in the process. List::MoreUtils's apply and Algorithm::Loops's Filter solve this problem, and so does

      s/// for my @out = @in;

      but one thing is that ("a","b","c","d") is different than ('a'..'d').

      Indeed. A constant range in list context is flattened into an array.

      $ perl -MO=Concise,-exec -e'print 1..3' 1 <0> enter 2 <;> nextstate(main 1 -e:1) v 3 <0> pushmark s 4 <$> const[AV ] s <----- 5 <1> rv2av lKP/1 6 <@> print vK 7 <@> leave[1 ref] vKP/REFC -e syntax OK

      As previously mentioned, the problem is that the members of the array aren't read-only.

        Great posts by ikegami!

        Some intervening posts happened during my "thinking phase".
        I don't think my post was "wasted" as it demo's this behavior and I learned something by doing it.