Portrait of Michael Limberger

Michael Limberger

Need me? Email mike@limberger.ca

Perl

Reinventing the for loop

Hash keys, the babycart, and /e

2024-10-10

This note reinvents a for-loop on purpose. Walking through a basic idea the long way is still one of the better ways to see how Perl thinks about iteration.

The hash, then the sane walk

A hash is a map from keys to values. The % sigil marks it. Here it lives behind a reference, so we write %{$db} to look inside.

my $db = { name => 'Mike', age => '45' };

for my $key (reverse sort keys %{$db})
{
    print qq|$key: $db->{$key}\n|;
}

The unhinged alternative

qq|@{[ reverse sort keys %{$db} ]}| =~ s~\S+~print qq|$&: $db->{$&}\n|~ger;

Same output, and no for.

The babycart

@{[ ... ]} is not one operator. It is an anonymous array, a dereference, and an interpolation, in a trenchcoat. People call it the babycart. It lets you run code inside a string and drop the result in place.

The substitution engine

\S+Each non-whitespace token: a key.
/gEvery match. That is the loop.
/eRun the replacement as Perl. print fires per key.
/rReturn a new string. The literal does not need to be writable.
$&Whatever just matched.
In production, use a for loop. The pieces are real. The combination is cursed. Keep it for golf and teaching.