Pragmatism in the real world

Prefixing every key in a hash ref in Perl

I needed to prepend some text to every element in a Perl hash ref, so I came up with:

$hashref->{"prefix_$_"} = delete($hashref->{$_}) foreach (keys %$hashref);

which prefixes each key of $hashref with “prefix_”.

After talking it over with Cliff, he was concerned with modifying the list in place while simultaneously iterating over it and suggested this solution:

%$hashref = map { +"prefix_$_" => $hashref->{$_} } keys %$hashref;

One interesting thing about this solution is the requirement for a unary “+” in map in order to help Perl work out whether we are using map BLOCK LIST or map EXPR, LIST as in this case it guesses wrong without it. from the documentation:

{ starts both hash references and blocks, so map { ... could be either the start of map BLOCK LIST or map EXPR, LIST. Because Perl doesn’t look ahead for the closing } it has to take a guess at which it’s dealing with based on what it finds just after the {. Usually it gets it right, but if it doesn’t it won’t realize something is wrong until it gets to the } and encounters the missing (or unexpected) comma. The syntax error will be reported close to the }, but you’ll need to change something near the { such as using a unary + to give Perl some help

Of course, it’s knowing the quirks like this that makes you comfortable in a given language, in the same way that good JavaScript developers know about 53 bit integers.