This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update IO-Compress to CPAN version 2.040
[perl5.git] / pod / perllol.pod
index f015a20..b35a0fe 100644 (file)
@@ -4,25 +4,26 @@ perllol - Manipulating Arrays of Arrays in Perl
 
 =head1 DESCRIPTION
 
-=head1 Declaration and Access of Arrays of Arrays
+=head2 Declaration and Access of Arrays of Arrays
 
-The simplest thing to build an array of arrays (sometimes imprecisely
-called a list of lists).  It's reasonably easy to understand, and
-almost everything that applies here will also be applicable later
-on with the fancier data structures.
+The simplest two-level data structure to build in Perl is an array of
+arrays, sometimes casually called a list of lists.  It's reasonably easy to
+understand, and almost everything that applies here will also be applicable
+later on with the fancier data structures.
 
 An array of an array is just a regular old array @AoA that you can
 get at with two subscripts, like C<$AoA[3][2]>.  Here's a declaration
 of the array:
 
+    use 5.010;  # so we can use say()
+
     # assign to our array, an array of array references
     @AoA = (
-          [ "fred", "barney" ],
-          [ "george", "jane", "elroy" ],
-          [ "homer", "marge", "bart" ],
+          [ "fred", "barney", "pebbles", "bambam", "dino", ],
+          [ "george", "jane", "elroy", "judy", ],
+          [ "homer", "bart", "marge", "maggie", ],
     );
-
-    print $AoA[2][2];
+    say $AoA[2][1];
   bart
 
 Now you should be very careful that the outer bracket type
@@ -33,11 +34,11 @@ but rather just a reference to it, you could do something more like this:
     # assign a reference to array of array references
     $ref_to_AoA = [
        [ "fred", "barney", "pebbles", "bambam", "dino", ],
-       [ "homer", "bart", "marge", "maggie", ],
        [ "george", "jane", "elroy", "judy", ],
+       [ "homer", "bart", "marge", "maggie", ],
     ];
-
-    print $ref_to_AoA->[2][2];
+    say $ref_to_AoA->[2][1];
+  bart
 
 Notice that the outer bracket type has changed, and so our access syntax
 has also changed.  That's because unlike C, in perl you can't freely
@@ -58,7 +59,7 @@ square or curly), you are free to omit the pointer dereferencing arrow.
 But you cannot do so for the very first one if it's a scalar containing
 a reference, which means that $ref_to_AoA always needs it.
 
-=head1 Growing Your Own
+=head2 Growing Your Own
 
 That's all well and good for declaration of a fixed data structure,
 but what if you wanted to add new elements on the fly, or build
@@ -88,16 +89,18 @@ array in it.
        $AoA[$i] = [ @tmp ];
     }
 
-It's very important that you make sure to use the C<[]> array reference
-constructor.  That's because this will be very wrong:
+It's important you make sure to use the C<[ ]> array reference
+constructor.  That's because this wouldn't work:
 
-    $AoA[$i] = @tmp;
+    $AoA[$i] = @tmp;   # WRONG!
 
-You see, assigning a named array like that to a scalar just counts the
-number of elements in @tmp, which probably isn't what you want.
+The reason that doesn't do what you want is because assigning a
+named array like that to a scalar is taking an array in scalar
+context, which means just counts the number of elements in @tmp.
 
-If you are running under C<use strict>, you'll have to add some
-declarations to make it happy:
+If you are running under C<use strict> (and if you aren't, why in
+the world aren't you?), you'll have to add some declarations to
+make it happy:
 
     use strict;
     my(@AoA, @tmp);
@@ -118,14 +121,14 @@ if you knew where you wanted to put it:
     my (@AoA, $i, $line);
     for $i ( 0 .. 10 ) {
        $line = <>;
-       $AoA[$i] = [ split ' ', $line ];
+       $AoA[$i] = [ split " ", $line ];
     }
 
 or even just
 
     my (@AoA, $i);
     for $i ( 0 .. 10 ) {
-       $AoA[$i] = [ split ' ', <> ];
+       $AoA[$i] = [ split " ", <> ];
     }
 
 You should in general be leery of using functions that could
@@ -134,7 +137,7 @@ such.  This would be clearer to the casual reader:
 
     my (@AoA, $i);
     for $i ( 0 .. 10 ) {
-       $AoA[$i] = [ split ' ', scalar(<>) ];
+       $AoA[$i] = [ split " ", scalar(<>) ];
     }
 
 If you wanted to have a $ref_to_AoA variable as a reference to an array,
@@ -165,16 +168,47 @@ If you wanted just to append to a row, you'd have
 to do something a bit funnier looking:
 
     # add new columns to an existing row
-    push @{ $AoA[0] }, "wilma", "betty";
+    push @{ $AoA[0] }, "wilma", "betty";   # explicit deref
+
+Prior to Perl 5.14, this wouldn't even compile:
+
+    push $AoA[0], "wilma", "betty";        # implicit deref
+
+How come?  Because once upon a time, the argument to push() had to be a
+real array, not just a reference to one. That's no longer true.  In fact,
+the line marked "implicit deref" above works just fine--in this
+instance--to do what the one that says explicit deref did.
+
+The reason I said "in this instance" is because that I<only> works
+because C<$AoA[0]> already held an array reference.  If you try that on an
+undefined variable, you'll take an exception.  That's because the implicit
+derefererence will never autovivify an undefined variable the way C<@{ }>
+always will:
 
-Notice that I I<couldn't> say just:
+    my $aref = undef;
+    push $aref,  qw(some more values);  # WRONG!
+    push @$aref, qw(a few more);        # ok
 
-    push $AoA[0], "wilma", "betty";  # WRONG!
+If you want to take advantage of this new implicit dereferencing behavior,
+go right ahead: it makes code easier on the eye and wrist.  Just understand
+that older releases will choke on it during compilation.  Whenever you make
+use of something that works only in some given release of Perl and later,
+but not earlier, you should place a prominent
 
-In fact, that wouldn't even compile.  How come?  Because the argument
-to push() must be a real array, not just a reference to such.
+    use v5.14;   # needed for implicit deref of array refs by array ops
 
-=head1 Access and Printing
+directive at the top of the file that needs it.  That way when somebody
+tries to run the new code under an old perl, rather than getting an error like
+
+    Type of arg 1 to push must be array (not array element) at /tmp/a line 8, near ""betty";"
+    Execution of /tmp/a aborted due to compilation errors.
+
+they'll be politely informed that
+
+    Perl v5.14.0 required--this is only v5.12.3, stopped at /tmp/a line 1.
+    BEGIN failed--compilation aborted at /tmp/a line 1.
+
+=head2 Access and Printing
 
 Now it's time to print your data structure out.  How
 are you going to do that?  Well, if you want only one
@@ -194,20 +228,20 @@ using the shell-style for() construct to loop across the outer
 set of subscripts.
 
     for $aref ( @AoA ) {
-       print "\t [ @$aref ],\n";
+       say "\t [ @$aref ],";
     }
 
 If you wanted to keep track of subscripts, you might do this:
 
     for $i ( 0 .. $#AoA ) {
-       print "\t elt $i is [ @{$AoA[$i]} ],\n";
+       say "\t elt $i is [ @{$AoA[$i]} ],";
     }
 
 or maybe even this.  Notice the inner loop.
 
     for $i ( 0 .. $#AoA ) {
        for $j ( 0 .. $#{$AoA[$i]} ) {
-           print "elt $i $j is $AoA[$i][$j]\n";
+           say "elt $i $j is $AoA[$i][$j]";
        }
     }
 
@@ -217,7 +251,7 @@ sometimes is easier to take a temporary on your way through:
     for $i ( 0 .. $#AoA ) {
        $aref = $AoA[$i];
        for $j ( 0 .. $#{$aref} ) {
-           print "elt $i $j is $AoA[$i][$j]\n";
+           say "elt $i $j is $AoA[$i][$j]";
        }
     }
 
@@ -227,18 +261,65 @@ Hmm... that's still a bit ugly.  How about this:
        $aref = $AoA[$i];
        $n = @$aref - 1;
        for $j ( 0 .. $n ) {
-           print "elt $i $j is $AoA[$i][$j]\n";
+           say "elt $i $j is $AoA[$i][$j]";
        }
     }
 
-=head1 Slices
+When you get tired of writing a custom print for your data structures,
+you might look at the standard L<Dumpvalue> or L<Data::Dumper> modules.
+The former is what the Perl debugger uses, while the latter generates
+parsable Perl code.  For example:
+
+    use v5.14;     # using the + prototype, new to v5.14
+
+    sub show(+) {
+       require Dumpvalue;
+       state $prettily = new Dumpvalue::
+                           tick        => q("),
+                           compactDump => 1,  # comment these two lines out
+                           veryCompact => 1,  # if you want a bigger dump
+                       ;
+       dumpValue $prettily @_;
+    }
+
+    # Assign a list of array references to an array.
+    my @AoA = (
+          [ "fred", "barney" ],
+          [ "george", "jane", "elroy" ],
+          [ "homer", "marge", "bart" ],
+    );
+    push $AoA[0], "wilma", "betty";
+    show @AoA;
+
+will print out:
+
+    0  0..3  "fred" "barney" "wilma" "betty"
+    1  0..2  "george" "jane" "elroy"
+    2  0..2  "homer" "marge" "bart"
+
+Whereas if you comment out the two lines I said you might wish to,
+then it shows it to you this way instead:
+
+    0  ARRAY(0x8031d0)
+       0  "fred"
+       1  "barney"
+       2  "wilma"
+       3  "betty"
+    1  ARRAY(0x803d40)
+       0  "george"
+       1  "jane"
+       2  "elroy"
+    2  ARRAY(0x803e10)
+       0  "homer"
+       1  "marge"
+       2  "bart"
+
+=head2 Slices
 
 If you want to get at a slice (part of a row) in a multidimensional
 array, you're going to have to do some fancy subscripting.  That's
 because while we have a nice synonym for single elements via the
 pointer arrow for dereferencing, no such convenience exists for slices.
-(Remember, of course, that you can always write a loop to do a slice
-operation.)
 
 Here's how to do one operation using a loop.  We'll assume an @AoA
 variable as before.
@@ -251,9 +332,13 @@ variable as before.
 
 That same loop could be replaced with a slice operation:
 
+    @part = @{$AoA[4]}[7..12];
+
+or spaced out a bit:
+
     @part = @{ $AoA[4] } [ 7..12 ];
 
-but as you might well imagine, this is pretty rough on the reader.
+But as you might well imagine, this can get pretty rough on the reader.
 
 Ah, but what if you wanted a I<two-dimensional slice>, such as having
 $x run from 4..8 and $y run from 7 to 12?  Hmm... here's the simple way:
@@ -276,7 +361,7 @@ have selected map for that
 
     @newAoA = map { [ @{ $AoA[$_] } [ 7..12 ] ] } 4 .. 8;
 
-Although if your manager accused of seeking job security (or rapid
+Although if your manager accused you of seeking job security (or rapid
 insecurity) through inscrutable code, it would be hard to argue. :-)
 If I were you, I'd put that in a function:
 
@@ -294,10 +379,10 @@ If I were you, I'd put that in a function:
 
 =head1 SEE ALSO
 
-perldata(1), perlref(1), perldsc(1)
+L<perldata>, L<perlref>, L<perldsc>
 
 =head1 AUTHOR
 
 Tom Christiansen <F<tchrist@perl.com>>
 
-Last update: Thu Jun  4 16:16:23 MDT 1998
+Last update: Tue Apr 26 18:30:55 MDT 2011