I just spent five minutes banging my head against a trivial mistake, and feel a need for confession.
I was planning to write a piece of code that would branch one of three ways, using the following construct:
my $state = ( 'b == a', 'b < a', 'b > a', )[$a <=> $b];
It's just an anonymous list that uses the output of the UFO operator as an index. It works because the UFO operator returns (-1,0,1), and Perl interprets -1 as the index of the last item in a list. The code has kind of a heavy Perl accent, but I like it because it's compact and easy to work with.
Thing is, I hadn't written that bit of code in a while, so I popped open a scratch file and wrote a toy version to refresh my memory. And that's when things blew up.
What I actually wrote was:
print ( 'b == a', 'b < a', 'b > a', )[$a <=> $b], "\n";
which gave me a syntax error, but the variant form:
print [ 'b == a', 'b < a', 'b > a', ]->[$a <=> $b], "\n";
worked just fine.
Like I said, I ran in circles for about five minutes before finally remembering that print() has a higher parentheses-precedent than anonymous lists do. The print statement was gobbling up the parentheses before they could be interpreted as an anonymous list.
I felt pretty dumb at that point, but when I do get hit by mistakes like that, I look for ways to avoid them in the future. In this case, there were two options. One was to stop being sloppy with my print() statements, and always include the parentheses. The correctly punctuated version:
print (( 'b == a', 'b < a', 'b > a', )[$a <=> $b], "\n");
does exactly what it's supposed to.
The other is to switch to the variant form above, which uses an anonymous listref instead of an anonymous list. Getting rid of the parentheses gets rid of the precedence issue entirely.
Of the two, I think I prefer the second. For one thing, I don't think I'll ever break myself of the print $x, "\n"; habit when I'm writing quick and dirty test code, but there's another, more respectable benefit. The most readable (to me) anonymous hash lookup takes more or less the same form:
my $status = { 'key 1' => 'value 1', 'key 2' => 'value 2', 'key 3' => 'value 3', }->{ $key };
so for the price of a couple extra characters, I get harmony between the list and hash versions. Plus, those versions are free from ambiguous-parentheses problems, which makes them both stronger and easier to read in the long run.
So.. for anyone tempted to use these kinds of lookups, I strongly recommend you pick up the []->[] and {}->{} forms right from the start. In the long run, they're less embarrassing.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: The perils of being tricky
by gaal (Parson) on Jun 04, 2005 at 18:34 UTC | |
by mstone (Deacon) on Jun 04, 2005 at 19:12 UTC | |
by kaif (Friar) on Jun 04, 2005 at 19:24 UTC | |
by mstone (Deacon) on Jun 04, 2005 at 19:32 UTC | |
by gaal (Parson) on Jun 05, 2005 at 07:22 UTC | |
by ysth (Canon) on Jun 05, 2005 at 07:50 UTC | |
|
Re: The perils of being tricky
by theorbtwo (Prior) on Jun 04, 2005 at 18:43 UTC | |
by mstone (Deacon) on Jun 04, 2005 at 19:19 UTC | |
|
Re: The perils of being tricky
by perrin (Chancellor) on Jun 05, 2005 at 02:57 UTC | |
by other90percent (Sexton) on Jun 05, 2005 at 05:59 UTC |