The following are all implemented differently:
- for (EXPR; EXPR; EXPR) ("C-style for loop", an augmented while loop.)
- for (EXPRX..EXPRY) (A range and nothing else.)
- for (reverse CONSTX..CONSTY) (A constant range, preceded by reverse.)
- for (reverse EXPRX..EXPRY) (A variable range, preceded by reverse.)
- for (@ARRAY) (An array and nothing else.)
- for (reverse @ARRAY) (Reverse of an array and nothing else.)
- for (reverse LIST) (Reverse of any list that doesn't fit the above patterns.)
- for (LIST) (Any list that doesn't fit the above patterns.)
You might find the difference between foreach (@ARRAY) and foreach (LIST) interesting.
{
my $x = 1;
my $y = 4;
# The initial values are saved.
my @a;
foreach ($x..$y) {
push @a, $_;
$y++;
}
print("@a\n");
# 1 2 3 4
}
{
my $x = 1;
my $y = 4;
# The initial values are saved.
my @a;
foreach (reverse $x..$y) {
push @a, $_;
$x--;
}
print("@a\n");
# 4 3 2 1
}
{
my @a = (1, 2, 3, 4);
my $i = 5;
# Loops "while (pass_num < @a)".
# In this case, that means loop forever.
foreach (@a) { # Loops "while (pass_num < @a)"
push(@a, $i++);
if (@a == 20) { push(@a, '...'); last; } # Avoid infinite loop.
}
print("@a\n");
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...
}
{
my @a = (1, 2);
my @b = (3, 4);
my $i = 5;
# Creates a list at the start of the
# loop and iterates over that list.
# In this case, elements are added to @b,
# but not to the list on the stack, so
# it loops 4 times.
foreach (@a, @b) {
push(@b, $i++);
}
print("@a @b\n");
# 1 2 3 4 5 6 7 8
}
The difference between
foreach (reverse CONSTX..CONSTY)
and
foreach (reverse EXPRX..EXPRY)
is that the list in built at compile time in the former.
>perl -le "for (1..2) { for (reverse 1..3) { print; $_=5; } }"
3
2
1
5
5
5
>perl -le "for (1..2) { for (reverse 1..($x=3)) { print; $_=5; } }"
3
2
1
3
2
1