Michael Limberger
Need me? Email mike@limberger.ca
Perl
Reinventing the for loop
Hash keys, the babycart, and /e
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. |
|---|---|
/g | Every match. That is the loop. |
/e | Run the replacement as Perl. print fires per key. |
/r | Return 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.