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

This started out of a thread in get a certain number of words from a line, but I thought I'd try to get input from a larger number of monks. Can anyone distill the essential difference bewteen \(1,2,3) and \(1..3)? The first produces a reference to 3, while the seconds produces a reference to an anonymous array [1,2,3].
Is this the "special case" feature from perlref ?
Taking a reference to an enumerated list is not the same as using square brackets--instead it's the same as creating a list of references!
@list = (\$a, \@b, \%c); @list = \($a, @b, %c); # same thing!
As a special case, \(@foo) returns a list of references to the contents of @foo, not a reference to @foo itself. Likewise for %foo, except that the key references are to copies (since the keys are just strings rather than full-fledged scalars).
The special case talks about returning a list of references to the contents of @foo, but it seems more like it returns a reference to a list (whose contents are copied from @foo). It Did What I Meant in the original code, but the documentation seems a little fuzzy to me. Further illumination appreciated.
#!/usr/bin/perl -w use Data::Dumper; $ref=\(1..3); $enum_list_ref=\(1,2,3); @a=(\(1..3),\(5..9)); print "\n".Dumper($ref)."\n"; print "\n".Dumper($enum_list_ref)."\n"; print "\n".Dumper(\@a)."\n";
Update: Must have been a bug in 5.8.0. I upgraded to 5.8.4 and I get results consistant with everyone else.


-- All code is 100% tested and functional unless otherwise noted.

Replies are listed 'Best First'.
Re: list references
by Enlil (Parson) on Jun 15, 2004 at 22:07 UTC
    They both seem to produce the same thing: $ref=\(1..3); will return a reference to the last thing in the list of references namely a scalar reference to 3 (as usually happens with lists on the right and scalars on the left). But then again so does $enum_list_ref. That is
    use Data::Dumper; use strict; use warnings; my $ref=\(1..3); my $oth_ref = \(1,2,3); print Dumper $ref,$oth_ref __OUTPUT__ $VAR1 = \3; $VAR2 = \3;
    On the other hand @a=(\(1..3),\(5..9)); will flatten the lists out before assigning to the array so you get the same thing as if you had written:
    @a = (\1,\2,\3,\5,\6,\7,\8,\9);
    the same thing would happen with @a=(\(1,2,3),\(5,6,7,8,9)) That is:
    use Data::Dumper; use strict; use warnings; my @array = \(1 .. 3, 5 ..9); my @array2 = \(1,2,3,5,6,7,8,9); my @array3 = (\(1 ..3),\(5,6,7,8,9)); print Dumper \@array,\@array2,\@array3 __OUTPUT__ $VAR1 = [ \1, \2, \3, \5, \6, \7, \8, \9 ]; $VAR2 = [ \1, \2, \3, \5, \6, \7, \8, \9 ]; $VAR3 = [ \1, \2, \3, \5, \6, \7, \8, \9 ];

    -enlil

      Maybe I've got a funky version of perl. When I run both your snippets I get answers different from yours. For the first program I get...
      greg@sparky:~/test$ cat enlil1 #!/usr/bin/perl use Data::Dumper; use strict; use warnings; my $ref=\(1..3); my $oth_ref = \(1,2,3); print Dumper $ref,$oth_ref greg@sparky:~/test$ ./enlil1 $VAR1 = [ 1, 2, 3 ]; $VAR2 = \3;
      ...and for the second...
      greg@sparky:~/test$ cat enlil2 #!/usr/bin/perl use Data::Dumper; use strict; use warnings; my @array = \(1 .. 3, 5 ..9); my @array2 = \(1,2,3,5,6,7,8,9); my @array3 = (\(1 ..3),\(5,6,7,8,9)); print Dumper \@array,\@array2,\@array3; greg@sparky:~/test$ ./enlil2 $VAR1 = [ [ 1, 2, 3 ], [ 5, 6, 7, 8, 9 ] ]; $VAR2 = [ \1, \2, \3, \5, \6, \7, \8, \9 ]; $VAR3 = [ [ 1, 2, 3 ], \5, \6, \7, \8, \9 ];
      Here's what my 'perl -V' looks like...


      -- All code is 100% tested and functional unless otherwise noted.
Re: list references
by BrowserUk (Patriarch) on Jun 15, 2004 at 22:13 UTC

    You can prove that it is a list of references to the contents of the array, not a reference to a list of copies:

    @a = 1..3; # print a reference to each of the values print \$_ for @a; SCALAR(0x197c58c) SCALAR(0x197c598) SCALAR(0x197c5a4) # now the list of references - note the same addresses print for \( @a ); SCALAR(0x197c58c) SCALAR(0x197c598) SCALAR(0x197c5a4) ## And finally, modify (increment) the original values ## through those references. $$_++ for \( @a ); # And show the originals are modified. print "@a"; 2 3 4


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re: list references
by NetWallah (Canon) on Jun 15, 2004 at 23:02 UTC
    The problem you are dealing with is context.

    $ref=\(1..3);

    This is in a SCALAR context .. it evaluates the list, and gets the value "3". It assigns a REFERENCE to this value to $ref. Hence $$ref will have the value 3.

    To get an ARRAY, to do what I think you want, try this:

    $ref = [1..3];

    This generates an anonymous array REFERENCE , pointing to the array (1,2,3), and assigns that to $ref.

    @$ref now is an array (1,2,3).

    Offense, like beauty, is in the eye of the beholder, and a fantasy.
    By guaranteeing freedom of expression, the First Amendment also guarantees offense.

      I'm beginning to think this is some sort of bug. Here's what I get for your example...
      greg@sparky:~/test$ perl -e '$ref=\(1..3); print $$ref' Not a SCALAR reference at -e line 1. greg@sparky:~/test$ perl -e '$ref=\(1..3); print "@$ref\n"' 1 2 3


      -- All code is 100% tested and functional unless otherwise noted.
        Yes - that DOES look strange.
        Here is what I get on my " perl, v5.8.3 built for MSWin32-x86-multi-thread"
        C:\> perl -e "$ref=\(1..3); print $$ref" 3 C:\>perl -e "$ref=\(1..3); print qq(@$ref\n)" Not an ARRAY reference at -e line 1. C:\>perl -e "$ref=[1..3]; print qq(@$ref\n)" 1 2 3

        Offense, like beauty, is in the eye of the beholder, and a fantasy.
        By guaranteeing freedom of expression, the First Amendment also guarantees offense.