I've been meaning to write about this gotcha for a long time, but somehow forgot. This was actually an undiscovered bug in Moose for several years:
use strict; use warnings; use Test::More; use Try::Tiny qw(try); { package Foo; use Scalar::Util qw(blessed); sub new { bless {}, $_[0] } } my $foo = Foo->new; is( try { blessed($foo) }, undef ); is( try { blessed $foo }, undef ); done_testing;
The first test passes. blessed has't been imported into main, so the code results in the error Undefined subroutine &main::blessed.
The second test, on the other hand, fails. This is because blessed has been invoked as a method on $foo.
The Moose codebase had several instances of if ( blessed $object ), in packages that did not import blessed at all. This worked for ages, because Moose::Object, the base class for most objects in the Moose ecosystem, didn't clean up that export, and therefore provided an inherited blessed method for pretty much any class written in Moose.
I think this example provides a very strong case for using namespace::clean or namespace::autoclean routinely in your classes.
To cover the other half of the problem, the no indirect pragma allows the removal of this unfortunate feature from specific lexical scopes.
1 comment:
Good post, short and concise.
How would you fix it using namespace::autoclean?
Will you be pushing no indirect to Moose::Object or the rest of Moose?
Post a Comment