Like C's arrays, perl supports the concept of an array, which can be
though of as a list of elements. Like C++'s vector
class,
perl's arrays grow as required, so there is no need to worry about memory
allocation issues when store elements in a perl array. To declare an
array variable, we use the special prefix character @
.
We can iterate over the array by using a foreach
loop:
#!/usr/bin/perl -w use strict; my @a; $a[0] = 'a'; $a[3] = 'b'; $a[7] = 'c'; print "Iteration #1\n"; foreach my $v (@a) { print defined $v ? "$v " : "undef "; } print "\n"; print "\nIteration #2\n"; foreach my $i (0..$#a) { print "\$a[$i] = ", defined $a[$i] ? "$a[$i]" : "undef", "\n"; } print "\n"; # simpler: print "Iteration #3 (using \$_ default)\n"; for (@a) { print defined $_ ? "$_ " : "undef "; } print "\n"; print "\nIteration #4 (using \$_ default)\n"; for (0..$#a) { print "\$a[$_] = ", defined $a[$_] ? $a[$_] : "undef", "\n"; }
There are several things to note about the above program:
@
character followed by the array name, but when we
access elements in the array, we use the array name prefixed with a
$
character. This is because each array element is a scalar
value. Therefore if @a
is an array, then $a[1]
is a scalar representing the second value in the array.
undef
). For example, in the above code, we initialized
elements 0
, 3
and 7
. Therefore
elements 1
, 2
, 4
, 5
and 6
will be created but will not have an initial value.
The number of elements in array created above is 8.
foreach
loop. The loop:
foreach my $v (@a) { ... }
will assign to the variable $v
the value of each element in
the array. First time through the loop, $v
will be assigned
the value of $a[0]
which is the string 'a'
,
second time it will get $a[1]
which is undef
and so on. The loop body tests whether the value is defined and if so
it displays it, otherwise it displays the string undef
$a[$i]
notation in the
body of the loop. To do this we set up our loop as follows:
foreach my $i (0..$#a) { ... }
The notation 0..$#a
will create a list of integers
from 0 upto and including $#a
. The special scalar value
$#a
gives the index of the last element in the array (in the
above example, $#a
will be 7
). Then as above,
the loop index variable $i
will assume the value of each
of these integers on each successive iteration though the loop.
An equivalent way of writing this loop is to use a
for
loop written in C-like notation:
for (my $i = 0; $i <= $#a; $i++) { ... }
However, this is rarely used in perl. (Note that the test condition
says $i <= $#a
and not $i < $#a
, as you
might expect. This is because $#a
represents the last index
in the array, which is not the same as the number of elements in the
array).
$_
and is quite frequently used in perl. In the loop:
foreach (@a) { ... }
Instead of $v
assume the values of all the elements
in the array, $_
is assigned the values instead. Similarly,
in the loop:
foreach (0..$#a) { ... }
the default $_
variable is successively assigned the numbers
0
to $#a
(inclusive). The $_
variable can them be used inside the loop body as an index variable to
access and display the elements of the array.
foreach (@array)
loop that iterates over arrays and a conventional
for (my $i = 0; $i < $num; $i++)
loop by examining the contents inside the parenthesis. Therefore, you
don't often see foreach
used in perl scripts. Just use
for
(as used in Iteration #3 and #4 above) and perl will
know which one you mean.
push/pop
and shift/unshift
It is common in perl to initialize an entire array with a list literal rather than initializing each element individually. To do this, we can use a list literal, which is basically a list of scalar values separated by commas and enclosed in parenthesis. For example:
#!/usr/bin/perl -w use strict; my @a = ('def', 123); push @a, 456; unshift @a, 'xyz'; print "@a\n"; print @a, "\n"; print "Popped ", pop @a, " from \@a \n"; print "Shifted ", shift @a, " from \@a\n"; print "@a\n";
Given the initial definition of @a
, we have $a[0] ==
'def'
and $a[1] == 123
. This is more efficient than
initializing each array element separately.
We can add elements to the back or front of an array by using the
push
and unshift
functions, respectively.
note that like push_back()
for C++ vector
s,
we don't have to worry about ensuring there is enough room in the perl
array when doing these operations -- perl takes care of it for us.
The second argument to push
and unshift
is actually a list. Therefore we can use push
and
shift
to add a list of elements to an array. In the above
example, the second (scalar) arguments are converted to lists of one
element which is then added to the @a
array.
The next two print
lines show that we can actually display
the values in an array. While the two lines look similar, their output
is different:
print "@a\n"; # displays: abc def 123 456 print @a, "\n"; # displays: abcdef123456
When an array is displayed inside double quotes each array element is displayed with a space separating each element. When an array is printed outside of the quotes, the array elements are displayed without an interleaving space character.
pop
and unshift
basically do the opposite
of push
and shift
, respectively. Each function
will remove one element from either the back or front of the array
and return that value as a result.
qw
short cut, list assignment and list/scalar
context
Using the ('...', '....', ...)
notation described above
to create a list literal of string scalars can be quite cumbersome.
Therefore perl allows you to create a list literal of strings using the
qw
construct as demonstrated by the following code:
#!/usr/bin/perl -w use strict; my @a = qw/this is a list/; # equivalent to ('this', 'is', 'a', 'list') print join(",", @a), "\n"; my ($one, $two) = @a; print "$one/$two\n"; my ($a, $b, $c, $d, $e) = @a; print "$a,$b,$c,$d,$e\n"; my ($val1) = @a; my $val2 = @a; print "$val1 $val2\n"; @a = sort @a; print "@a\n";
All the elements of the list are specified between the /.../
delimiters (you can actually use any pair of corresponding delimiters
for the qw
construct). This notation makes the creation
of lists of strings much easier.
The above code also demonstrates the use of the join
function which takes a delimiter string and an array. It will create a
string which consists of all the elements of the array separated by
the specified delimiter string.
The code my ($one, $two) = @a;
shows how we can extract
elements from a list and assignment them to scalars. In this code
fragment, the variable $one
will get the first element
of the list and $two
will get the second element.
This is equivalent to saying:
my $one = $a[0]; my $two = $a[1];
If we try to assign more variables than there are elements in the
list, then the remaining variables will be left as undef
.
For example, in the statement my ($a, $b, $c, $d, $e) = @a;
,
the variable $e
will not be defined, since the array
has only four elements. Note that when declaring more than one
variable with my
, you must include the variables inside
parenthesis.
The two statements:
my ($val1) = @a; my $val2 = @a;
demonstrate the importance of list context versus array context.
In the first case, $val1
, because it is being declared
inside parenthesis, is in list context. This means that @a
will also be treated as a list. When the assignment happens, $val1
will get the value of the first element of the array @a
.
In the second assignment, however, $val2
is in scalar context,
therefore @a
will be evaluated as a scalar. When an array
is evaluated as a scalar, it returns the number of elements in the array.
Therefore, the statement print "$val1 $val2\n";
will display this 4
.
There are other important situations where between list and scalar context arise. See page 51 of S&P for details.
The final couple of statements in the above code demonstrate the use of
the sort
function which lexicographically sorts an array.
Note that there is no harm in using the same variable on the left and
right hand side of the assignment when doing the sorting. Note that
arrays are lexicographically sorted. Therefore, the statement
print join(",",sort (123, 9, 50)), "\n";
will display 123,50,9
because the list is being sorted
alphabetically, and not numerically. Another function called
reverse
can be used to reverse arrays.
Another use of list assignments is to swap to scalars. For example, the
code fragment ($v1, $v2) = ($v2, v1)
will swap the values
stored in the scalar variables $v1
and $v2
.
Last modified: Mon Mar 24 17:17:03 2003