Reputation: 509
NOTE: See the end of this post for final explanation.
This is probably a very basic question, but I'm still trying to master a few of the fundamentals regarding references in Perl, and came across something in the perldsc page that I'd like to confirm. The following code is in the Generating Array of Arrays section:
while ( <> ) {
push @AoA, [ split ];
}
Obviously, the <>
operation in the while
loop reads one line of input in at a time. I am assuming at this point that line is then put into an anonymous array via the [ ]
brackets, we'll call this @zero
. Then the split command places everything in a given line separated by whitespace within the array (e.g., the first word is assigned to $zero[0]
, the second to $zero[1]
and so on). The scalar reference of @zero
is then pushed onto @AoA
.
The next line of input is passed via the <>
operator and gets assigned to a completely new anonymous array (e.g. @one
), and its scalar reference is pushed onto @AoA
.
Once @AoA
is populated, I could then access its contents with a nested foreach
loop; the first iterating through the "rows" (e.g. for $row (@AoA)
), and a second, inner loop, foreach
to access the columns of that particular row.
The latter (accessing said "columns" would be done by dereferencing
(e.g., for $column (@$row)
) the particular $row
being read by the previous, "outer" foreach
loop.
Is my understanding correct? I'm assuming you could still access any element of the @AoA just as you would if it were assigned vs. being anonymous? That is $element = $AoA[8][1];
.
I'm want to verify my thought process here. Is the automatic declaration of a unique, anonymous array each time through the loop part of the autovivication
in Perl? I guess that is what is throwing me off a bit. Thanks.
EDIT: Based on the comments below my understanding regarding the anonymous array is still unclear, so I want to take a shot at one more description to see if it meets everyone's understanding.
Starting with the push @AoA, [split];
statement, split takes in the line from $_ and returns a list parsed by whitepace. That list is captured by [ ]
, which then returns an array reference. That array reference (created by [ ]
) is then pushed onto @AoA. Is this accurate re: [ ]
? The next step (dereferencing / use of @AoA) was covered very well by @krico below.
FINAL ANSWER/EXPLANATION: Based on all of the comments / feedback here, some further research on my part, and testing it seems my understanding was correct. I'll break it down here, so others can easily reference it later. See @krico's response below for a more explicit code representation that follows the steps outlined here.
while ( <> ) {
push @AoA, [ split ];
}
<>
operatorsplit
function takes that line in via $_
and parses it based on whitespace (the default).split
then returns a LIST.[ ]
is an anonymous array that provides the perl data structure for the List passed by split
.push @AoA
pushes the reference to the anonymous array onto its queue as element $AoA[0]
(the second anonymous array reference will be put into $AoA1, etc...).@AoA
is a 2D array, holding reference values (scalar values) to each of the previously generated anonymous arrays.@AoA
can be dereferenced appropriately to work with the underlying/reference elements taken in from the input file. The default dereferencing technique is CIRCUMFIX (see perlfef below); however as of 5.19 a new method of dereferencing is available and will be released in 5.20, POSTFIX. Articles are linked below.References: Perl References Documentation, Perl References Tutorial, Perl References Question noted by @Eli Hubert, Mike Friedman's blog post about differences between arrays and lists, Upcoming Postfix dereferencing in Perl, and Postfix dereferencing Article
Upvotes: 4
Views: 320
Reputation: 51
This is what is going on:
When you do $AoA[8][2] you are implicitly dereferencing the scalar. It's the same as $AoA[8]->[2].
Upvotes: 2
Reputation: 5728
The same code a little more readeable and you should understand it.
my $line;
while ( $line = <STDIN> ) {
my @parts = split $line;
my $partsRef = \@parts;
push @AoA, $partsRef;
}
Now, if you wanted to print the 2nd part of the 5th line you could say.
my $ref = @AoA[4];
my @parts = @$ref;
print $parts[1];
Get it?
Upvotes: 1