Playing it safe with Safe::Isa
Earlier this year in Manhattan, a garage worker drove an Audi into an open car elevator shaft. The car fell three floors and the worker escaped through the sun roof.
Every year I see stories of people falling in elevator shafts — sometimes dying — when the elevator they are expecting to be there suddenly isn't.
But what do elevator shafts have to do with Perl?
There is a common idiom for checking an object's class that is remarkably like stepping through an elevator door without checking that the elevator is there:
$thing is an unblessed reference, you've just fallen down the elevator shaft and gotten a fatal error.
$thing is a scalar, then it's treated like a class name. That might be what you want, but if you really wanted an object, then you're in trouble if you call any object methods on it.
isa method comes from the UNIVERSAL class, so maybe you thought (or were taught) to call it as a function:
That is wrong, too, because
isa is supposed to be a method, and you've just skipped the entire
@ISA hierarchy. If any class defined its own
isa method, you'll get a different answer than what you should. (A mock object used in testing might do that, for instance.)
You might have learned to check for an object first, with Scalar::Util and
That is mostly correct (someone could have blessed an object into the class "0" for instance), but in any ordinary code, it will do what you want.
For example, imagine you're using failures and you've wrapped some possibly fatal code with
try from Try::Tiny and you need to test the error to see if it's an object of various types or just a string.
Do you really want to type
blessed in every conditional?
Or wrap it all in another
if just to test
Safe::Isa makes this easier by exporting an
$_isa variable containing a code reference that you can use in place of
UNIVERSAL::isa. It checks
isa for you, just the way you want:
This works because Perl treats a code reference on the right side of an arrow operator as a method to invoke. These are equivalent:
That makes our earlier
failures example a bit more concise:
Safe::Isa gives you several similar helpers, including
$_DOES, plus a generic
$_call_if_object code reference that works like this:
The lesson is this: calling a method on something that you aren't sure is an object is like stepping into an elevator without checking that it's there. Most of the time, you're safe, right until you have a long fall and crash.
Using Safe::Isa gives you a safe, concise way to look before you step.