The perils of Perl 5's indirect object syntax
Perl lets you call object methods in two different ways:
- $obj->method()
- method $obj
The latter form is usually called only for things like clone $obj, which is pretty ugly. For more about indirect object syntax and some of the pain it causes, see When Is Backwards-Compatibility Not Worth It?.
It's funny that Max posted that blog entry the other day, because I just was shown a problem that was caused indirectly by it. Mike O'Regan showed me some code that he was surprised even compiled, because it certainly wasn't working.
sub custom_sort { return $a->{foo} cmp $b->{foo} || a$->{bar} cmp b$->{bar} }
See the a$ instead of $a? Yuck. But it compiles just fine. Why? Well, let's see what B::Deparse decompiles it out as:
$ perl -MO=Deparse foo.pl sub custom_sort { return $$a{'foo'} cmp $$b{'foo'} || $-->a > {'bar'} cmp $-->b > {'bar'}; } foo.pl syntax OK
Turns out that it's calling method a on the object $- and then seeing if that is greater than {'bar'}. Double-ugh.
Perl 6 still has indirect object syntax, but you must follow it with a colon, as in method $obj: @args. Larry says in Perl 6 it's completely unambiguous.