http://www.perlmonks.org?node_id=380510

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

perlref states that there is a difference between taking a reference to a list, and a reference to an array:
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). 
So I have two questions:
  1. Why the distinction? Why are there two seperate behaviors?
  2. What is happening that creates the difference in behavior?
#!/usr/bin/perl use strict; # example 1 my $ref1 = \(qw(one two three)); # should be called in list context # example 2 my @list = qw(one two three); my $ref2 = \@list; # example 3 # returns same as example 1 my $ref3 = \(@list); # should be called in list context print ref $ref1, "\n"; print ref $ref2, "\n"; print ref $ref3, "\n";
Based on these examples, my best guess is that the parentheses are the key. Going back to the "if it looks like a function, then it is a function" philosophy behind the interpreter, I guess \() does look like a function. As such, \("one","two","three") and \(@list) gets executed like a function call with n arguments (3 in the case of the list). @list gets flattened like any other list passed as an argument and so the behavior is basically the same for both cases.

That's my best guess anyway...


dsb
This @ISA my cool %SIG

Replies are listed 'Best First'.
Re: \ Operator in referencing
by Gilimanjaro (Hermit) on Aug 06, 2004 at 13:56 UTC
    It has nothing to do with functions...

    \() returns a list of references to the variables in the list, so in this case a list of three references to the scalars. (Think (\"one",\"two",\"three")). But you assign it to a scalar... (So it becomes the last entry the list, which is 'three')

    Example 2's $ref2 is just a reference to @list, so it indeed will return ARRAY when you ask what is refers to...

    And Example 3's \() will give you a list of references to what's in the parentheses. But @list in list context, gets it's list expanded, so it's a list of three scalars again and assigning it to a scalar will give you the last entry 'three' again, thus ref $ref3 still is 'SCALAR'.

    use Data::Dumper; print Dumper($ref1), "\n"; print Dumper($ref2), "\n"; print Dumper($ref3), "\n";
    Should clear things up...

    Update
    In case of the $n = qw(one two three) makes $n eq 'three' not being clear, refer to chapter 2.3.4 of Programming Perl... It boils down to the list 'knowing' that it's being used in scalar context, and thus evaluating to the value of the last element, just like in C.

    An array is slightly different from a list; an array returns it's size when evaluated in scalar context. Only in example 2 do you make the list an array by assigning it to @list.

Re: \ Operator in referencing (unusual)
by tye (Sage) on Aug 06, 2004 at 15:39 UTC
    Why the distinction? Why are there two seperate behaviors?

    Because the author of that feature thought it was a neat idea. Note that if your thinking on flattened lists were correct then \(@a,@b,@c) would be the same as map {\$_} @a,@b,@c which is the same as (\(@a),\(@b),\(@c)) (which would make this quirk of \(...) less interesting). But instead \(@a,@b,@c) is the same as (\@a,\@b,\@c). And \(@a,(@b),@c) is the same as (\@a,\(@b),\@c) which is the same as ( \@a, map(\$_,@b), \@c ).

    What is happening that creates the difference in behavior?

    The C code that was added to the perl.exe source code to implement \ specifically looks for parens and does something different when it sees them.

    There is no general principle of Perl that explains this quirk of \(...). It is just specific to \ and that is just the way that it was implemented.

    The one thing I don't like about it is that it is different from how anything else in Perl works (and so is surprising, at least when you first run into it). But that is a fairly minor problem and the fairly minor utility of the shortcut makes it an acceptable design, IMHO.

    - tye        

Re: \ Operator in referencing
by ishnid (Monk) on Aug 06, 2004 at 14:36 UTC
    The whole 'reference of a list' thing is principally a shorthand way of getting a list of references (and we know how good at shorthand Perl is!).

    Using the \() notation (as in your example 3) is much easier (and readable) than something like this:
    my @list_of_refs = map \$_, @list;
Re: \ Operator in referencing
by Prior Nacre V (Hermit) on Aug 06, 2004 at 13:43 UTC

    I'll think you'll find this is nothing more than operator precedence. The @list in parentheses is evaluated first and expands to a list. You then take a reference to that list which, as you have correctly stated, expands to a list of references.

    Regards,

    PN5