Understanding the foreach keyword

Understanding the foreach keyword

A foreach loop is used to iterate over each element of a list.

The basic syntax is: foreach VAR (LIST) BLOCK

Where the variable VAR is set to each value of the LIST in turn and the
code in BLOCK is executed. (By BLOCK we mean code enclosed in braces).

Or, to put this another way, consider the following code sample:

Each element in @list is assigned to $var in turn, and the code in the
curly braces is executed.

In Perl, a list can be a simple list of values:

or produced by an expression like:

or from an array like:

or a function that returns a list:

or any combination of these.

So you can use foreach to do something with every element of an array:

or every element of a list:

or the keys (and values) of a hash:

or combinations of the above:

So with that introduction out of the way, let’s look at the foreach
mechanism in a little more detail, because there are some subtleties
here that you will want to be aware of.

Iterating through each element in a list – no control variable

If the variable after the foreach keyword is omitted, the Perl
‘topic’ variable $_ is set to each value.

This produces the following output:

Iterating through a list using a private control variable

If a variable is supplied after the foreach keyword, it is used to
receive each value of the list in turn. If it is preceded with the “my”
keyword, it is visible only within the loop. This is more formally called
‘lexically scoped’.

This produces the same output as the example above.

This code fragment shows more clearly that the scope of the $day variable
afer the foreach keyword is limited to the block of the foreach loop,
(the code inside the braces).

This code produces:

Beware of how foreach can localize the control variable…

If you don’t qualify the control variable with a ‘my‘, the variable is
nonetheless localized within the foreach loop block.

In this example $day is declared outside the foreach loop, but when
it is used in the loop, it’s value is implicitly localized to the loop.

This behavior is unique to foreach loops.

As this output shows, $day regains it’s previous value after the loop. It
does not, (as you might expect), retain the last value from the loop.

Side-effects : The control variable is an alias to the list element

If the control variable is on the left-side of an ‘=‘ (i.e. in formal
language, it is an ‘lvalue’), it will modify the corresponding element in the
LIST. This is because the control variable is ‘aliased’ to the element
in the list, and changes to the alias propogate to the real element.

Because we assigned the return value of the ucfirst function to the
topic variable $_, we also assign that value to the list element
itself. In other words, the first element of the @weekdays array was
monday, but after the loop, it has been changed to Monday, (and
tuesday has become Tuesday, and so on).

And of course, this behavior is the same if we use an explicit control
variable, such as $day, rather than the topic variable $_:

But the list element must be capable of being modified for this to work

You can’t modify the alias if the thing it is aliasing isn’t capable of being modified.

This code will result in the warning:

c-style for loops

Whilst a c-style for loop is possible, it’s rarely necessary.

The Perl range operator .. is a much more compact way of doing this:

A word on statement modifiers

Perl supports the idea of modifiers that can be appended to a simple
statement.

You may have seen simple statements modified in this way, such as:

In this case, print "Some message\n" is the simple statement and if ($some_condition_is_met)
is the modifier.

The foreach modifier executes the statement that precedes it once for
each item in the list.

which outputs:

In the case above, print length($_) . "\n" is the simple statement and
foreach qw(There's more than one way to do it) is the modifier.

More Advanced Usage – Labels

The full syntax for a foreach loop is more formally:

LABEL: foreach VAR (LIST) BLOCK

Where LABEL is a literal value , like OUTER or TEACHERS for example.
Labels are traditionally typed in upper case to highlight their
presence. They act like the labels you see in a goto or a here document.

So, how do we use a label in a foreach block? Like this:

Basically, we can use labels to short circuit to the next element in the
current loop, or an outer loop. Well chosen label names can also be
self-documenting to some extent.

See also

Scroll to Top