4.4. Doing Something with Every Element in a ListProblemYou want to repeat a procedure for every element in a list. Often you use an array to collect information you're interested in; for instance, login names of users who have exceeded their disk quota. When you finish collecting the information, you want to process it by doing something with every element in the array. In the disk quota example, you might send each user a stern mail message. Discussion
Let's say we've used foreach $user (@bad_users) { complain($user); } Rarely is this recipe so simply applied. Instead, we often use functions to generate the list: foreach $var (sort keys %ENV) { print "$var=$ENV{$var}\n"; }
Here we're using
Not only can we add complexity to this formula by building up the list in the foreach $user (@all_users) { $disk_space = get_usage($user); # find out how much disk space in use if ($disk_space > $MAX_QUOTA) { # if it's more than we want ... complain($user); # ... then object vociferously } }
More complicated program flow is possible. The code can call
The variable set to each value in the list is called a
loop variable
or
iterator variable
. If no iterator variable is supplied, the global variable foreach (`who`) { if (/tchrist/) { print; } }
or combining with a while (<FH>) { # $_ is set to the line just read chomp; # $_ has a trailing \n removed, if it had one foreach (split) { # $_ is split on whitespace, into @_ # then $_ is set to each chunk in turn $_ = reverse; # the characters in $_ are reversed print; # $_ is printed } }
Perhaps all these uses of
Fortunately, your fears would be unfounded, at least in this case. Perl won't permanently clobber
There is cause for some concern though. If the
If a lexical variable (one declared with foreach my $item (@array) { print "i = $item\n"; }
The @array = (1,2,3); foreach $item (@array) { $item--; } print "@array\n";
This aliasing means that using a
For example, if we used # trim whitespace in the scalar, the array, and all the values # in the hash foreach ($scalar, @array, @hash{keys %hash}) { s/^\s+//; s/\s+$//; }
For reasons hearkening back to the equivalent construct in the Unix Bourne shell, the for $item (@array) { # same as foreach $item (@array) # do something } for (@array) { # same as foreach $_ (@array) # do something } This style often indicates that its author writes or maintains shell scripts, perhaps for Unix systems administration. As such, their life is probably hard enough, so don't speak too harshly of them. Remember, TMTOWTDI. This is just one of those ways.
If you aren't fluent in Bourne shell, you might find it clearer to express "for each See Also
The "For Loops," "Foreach Loops," and "Loop Control" sections of
perlsyn
(1) and
Chapter 2
of
Programming Perl
; the "Temporary Values via local( )" section of
perlsub
(1); the
"Scoped Declarations"
section of
Chapter 2
of
Programming Perl
; we talk about |
|