At $work, we just fixed a tiny bug by adding a use Try::Tiny and a semicolon.
A colleague asked «how did it even compile, before?»
Well, welcome to another weird corner of #Perl!
So, when neither try nor catch are declared, the source:
try {
print "in try";
} catch {
print "in catch";
}
return 42;is parsed as(print "in try")->try((print "in catch")->catch(return 42));because of the Indirect Object Syntax (the thing that makes my $obj = new Class @args equivalent to my $obj = Class->new(@args), and also allows print { $filehandle } @values)«but wait!», you’ll say, «why am I not getting
Can't locate object method "try" via package "1"?» (after all, print returns 1, and sub 1::try is definitely not there)and the answer is: the missing semicolon!
see, before looking up a method, perl evaluates all its arguments, in order from left to right. So it first evaluates
print "in try", then print "in catch", then return 42, at which point the control returns to the caller *and neither try nor catch are ever looked up*!Indeed, if you run:
sub thing {
try {
print "in try";
} catch {
print "in catch";
};
return 42;
}
thing;(notice the semicolon before return!) you'll get (pardon the newlines):in try
in catch
Can't locate object method "catch" via package "1"and the program dies.
Maybe I should mandate
no indirect in all our files…@Perl