* FAQ sync for Perl 5.12 release candidate
[p5sagit/p5-mst-13.2.git] / pod / perlfaq4.pod
index 5549634..5c7e134 100644 (file)
@@ -62,7 +62,7 @@ are in base 10:
        print $string + 44; # prints 688, certainly not octal!
 
 This problem usually involves one of the Perl built-ins that has the
-same name a Unix command that uses octal numbers as arguments on the
+same name a unix command that uses octal numbers as arguments on the
 command line. In this example, C<chmod> on the command line knows that
 its first argument is octal because that's what it does:
 
@@ -537,7 +537,7 @@ doesn't matter and you end up with the previous date.
 
 (contributed by brian d foy)
 
-Perl itself never had a Y2K problem, although that never stopped people
+Perl itself never had a Y2K problem, although that nevers stopped people
 from creating Y2K problems on their own. See the documentation for
 C<localtime> for its proper use.
 
@@ -1197,43 +1197,115 @@ indentation correctly preserved:
 
 =head2 What is the difference between a list and an array?
 
-An array has a changeable length.  A list does not.  An array is
-something you can push or pop, while a list is a set of values.  Some
-people make the distinction that a list is a value while an array is a
-variable. Subroutines are passed and return lists, you put things into
-list context, you initialize arrays with lists, and you C<foreach()>
-across a list.  C<@> variables are arrays, anonymous arrays are
-arrays, arrays in scalar context behave like the number of elements in
-them, subroutines access their arguments through the array C<@_>, and
-C<push>/C<pop>/C<shift> only work on arrays.
+(contributed by brian d foy)
+
+A list is a fixed collection of scalars. An array is a variable that
+holds a variable collection of scalars. An array can supply its collection
+for list operations, so list operations also work on arrays:
+
+       # slices
+       ( 'dog', 'cat', 'bird' )[2,3];
+       @animals[2,3];
+
+       # iteration
+       foreach ( qw( dog cat bird ) ) { ... }
+       foreach ( @animals ) { ... }
+
+       my @three = grep { length == 3 } qw( dog cat bird );
+       my @three = grep { length == 3 } @animals;
+       
+       # supply an argument list
+       wash_animals( qw( dog cat bird ) );
+       wash_animals( @animals );
+
+Array operations, which change the scalars, reaaranges them, or adds
+or subtracts some scalars, only work on arrays. These can't work on a
+list, which is fixed. Array operations include C<shift>, C<unshift>,
+C<push>, C<pop>, and C<splice>.
+
+An array can also change its length:
+
+       $#animals = 1;  # truncate to two elements
+       $#animals = 10000; # pre-extend to 10,001 elements
+
+You can change an array element, but you can't change a list element:
+
+       $animals[0] = 'Rottweiler';
+       qw( dog cat bird )[0] = 'Rottweiler'; # syntax error!
+
+       foreach ( @animals ) {
+               s/^d/fr/;  # works fine
+               }
+       
+       foreach ( qw( dog cat bird ) ) {
+               s/^d/fr/;  # Error! Modification of read only value!
+               }
+
+However, if the list element is itself a variable, it appears that you 
+can change a list element. However, the list element is the variable, not
+the data. You're not changing the list element, but something the list
+element refers to. The list element itself doesn't change: it's still 
+the same variable.
 
-As a side note, there's no such thing as a list in scalar context.
-When you say
+You also have to be careful about context. You can assign an array to
+a scalar to get the number of elements in the array. This only works
+for arrays, though:
+
+       my $count = @animals;  # only works with arrays
+       
+If you try to do the same thing with what you think is a list, you
+get a quite different result. Although it looks like you have a list
+on the righthand side, Perl actually sees a bunch of scalars separated
+by a comma:
 
-       $scalar = (2, 5, 7, 9);
+       my $scalar = ( 'dog', 'cat', 'bird' );  # $scalar gets bird
 
-you're using the comma operator in scalar context, so it uses the scalar
-comma operator.  There never was a list there at all! This causes the
-last value to be returned: 9.
+Since you're assigning to a scalar, the righthand side is in scalar
+context. The comma operator (yes, it's an operator!) in scalar
+context evaluates its lefthand side, throws away the result, and
+evaluates it's righthand side and returns the result. In effect,
+that list-lookalike assigns to C<$scalar> it's rightmost value. Many
+people mess this up becuase they choose a list-lookalike whose
+last element is also the count they expect:
+
+       my $scalar = ( 1, 2, 3 );  # $scalar gets 3, accidentally
 
 =head2 What is the difference between $array[1] and @array[1]?
 
-The former is a scalar value; the latter an array slice, making
-it a list with one (scalar) value.  You should use $ when you want a
-scalar value (most of the time) and @ when you want a list with one
-scalar value in it (very, very rarely; nearly never, in fact).
+(contributed by brian d foy)
+
+The difference is the sigil, that special character in front of the
+array name. The C<$> sigil means "exactly one item", while the C<@>
+sigil means "zero or more items". The C<$> gets you a single scalar,
+while the C<@> gets you a list.
 
-Sometimes it doesn't make a difference, but sometimes it does.
-For example, compare:
+The confusion arises because people incorrectly assume that the sigil
+denotes the variable type.
 
-       $good[0] = `some program that outputs several lines`;
+The C<$array[1]> is a single-element access to the array. It's going
+to return the item in index 1 (or undef if there is no item there).
+If you intend to get exactly one element from the array, this is the
+form you should use.
 
-with
+The C<@array[1]> is an array slice, although it has only one index.
+You can pull out multiple elements simultaneously by specifying
+additional indices as a list, like C<@array[1,4,3,0]>.
 
-       @bad[0]  = `same program that outputs several lines`;
+Using a slice on the lefthand side of the assignment supplies list
+context to the righthand side. This can lead to unexpected results. 
+For instance, if you want to read a single line from a filehandle, 
+assigning to a scalar value is fine:
 
-The C<use warnings> pragma and the B<-w> flag will warn you about these
-matters.
+       $array[1] = <STDIN>;
+
+However, in list context, the line input operator returns all of the
+lines as a list. The first line goes into C<@array[1]> and the rest
+of the lines mysteriously disappear:
+
+       @array[1] = <STDIN>;  # most likely not what you want
+
+Either the C<use warnings> pragma or the B<-w> flag will warn you when
+you use an array slice with a single index.
 
 =head2 How can I remove duplicate elements from a list or array?
 
@@ -2497,17 +2569,9 @@ the C<PDL> module from CPAN instead--it makes number-crunching easy.
 
 See L<http://search.cpan.org/dist/PGPLOT> for the code.
 
-=head1 REVISION
-
-Revision: $Revision$
-
-Date: $Date$
-
-See L<perlfaq> for source control details and availability.
-
 =head1 AUTHOR AND COPYRIGHT
 
-Copyright (c) 1997-2009 Tom Christiansen, Nathan Torkington, and
+Copyright (c) 1997-2010 Tom Christiansen, Nathan Torkington, and
 other authors as noted. All rights reserved.
 
 This documentation is free; you can redistribute it and/or modify it