http://qs321.pair.com?node_id=72247

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

I am posting this because I think I finally get it, and I want to check with the senior monks to see if I'm right. Also, I want other monks to share in my epiphany. :)

When I first started learning Perl, I had a heck of a time distinguishing between scalar and array context. After I got that distinction, I had an even harder time figuring out the difference between array and list context. Here's some code that demonstrates the differences:

use strict; my @array = ('foo', 'bar', 'baz'); my $temp; $temp = @array; print "$temp\n"; $temp = ('foo', 'bar', 'baz'); print "$temp\n"; ($temp) = @array; print "$temp\n"; ($temp) = @array[0..2]; print "$temp\n"; $temp = @array[0..2]; print "$temp\n";
Think these all print the same thing? Think again. On running the above script, you will get
3 baz foo foo baz
as your output. Here's why:
  1. This assignment has a scalar on the left hand side. This forces the array to be evaluated in a scalar context, which gives the length of the array.
  2. This assignment has a scalar on the left hand side. This forces the list to be evaluated in a scalar context, which gives the last element of the list.
  3. This assignment has a list on the left hand side. @array is thus evaluated in an array context. When Perl sets assigns one array to another, it sets the first element of one array equal to the first element of the other array, the second element equal to the next element, etc. Extra values are thrown away, so $temp is now equal to the first value of @array, or 'foo'.
  4. This assignment also has a list on the left hand side, and an array slice (containing all the elements of the original array) on the right. The behavior is the same as in 3.
  5. This assignment has a scalar on the left and the array slice (a.k.a. a list) on the right. This looks like a combination of 1. and 4., so you would think that the answer would be 3 or 'foo'. It turns out to be 'baz', because lists assigned to scalar context return the last element of the list.
So my current understanding is this:

  1. The difference between a list and an array is that an array is an allocated chuck of memory, whereas a list is a bunch of scalars that are the result of an expression.
  2. Arrays and lists act the same in list context.
  3. Arrays and lists act very differently in scalar context; the former return their size, and the latter return their last element.
This last difference can be very subtle; for instance, these two subroutines do NOT return the same value (set their results equal to scalars to see how):
sub func1 { return('foo', 'bar' 'baz'); } sub func2 { my @array = ('foo', 'bar', 'baz'); return @array; }
Is my understanding right? Anything else about lists that I should know about?

-Ton
-----
Be bloody, bold, and resolute; laugh to scorn
The power of man...