lex parsimoniae
For the less classically trained Occam's Razor or to dumb it down even more, the answer is staring you in the face, is the topic for tonight.
Well to make a short story long, I was happily programming along, in the zone if you will, when I was flustered by a small problem. How to tell if something is an object??
The problem occurred in a class pre-loader, it gladly recursively searches though a name-space and loads in classes for future use. There is some sanity checking such as making sure the file at least ends in '.pm' as don't want any silly subversion or '.pl' files loading do we?
Anyway at the tail end of the process we do something like this
eval "require $a_class";
if ($@) {
my $err = $@;
my $advice = " $package may not be an Class!!\n\n";
warn("\n\n Load $package failed: \n Error=$err \n $advice\n");
}
else {
return
unless($a_class->can('blessed') );
$self->classes($a_class->new());
}
using the well proven "can('blessed')" which is just a variation on the good old
use Scalar::Util 'blessed';
if ( defined blessed($thing) ) { ... }
to make finally sure what we have is a class before an instance is loaded for future use.
So onto the Moose part now. Well anyone who has been reading my post knows that I am a fan of Roles and I have recently introduce some of them in the code base I am working with. Well things where happy today until I decided to refactor a little and created a few roles for some common code and then this started happening
Can't locate object method "new_object" via package "Moose::Meta::Role" at /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/Moose/Object.pm line 27.
The only advice my co-worker had was
moose poop!
don't known anything about that!
Well after a long while of searching and trying such things as
return
if($a_class->isa('Moose::Meta::Role');
I was beginning to pull out what little hair I had left on my head then old 'lex parsimoniae' hit and I added this
return
unless($a_class->can('blessed') and $a_class->can('new') );
and I was back in the game.
Seems a Role pass all the other tests I had in the system before the last 'blessed' part. Remember Johnny, a role is a 'blessed' class but it doesn't have a 'new'!.
The fix took a little while to jump out to me. I was of course blaming everything else in typical programmer fashion. I guess I should of saw that coming with all the babbling I have been doing on 'Roles' over the past little while. I most likely deserved that 20 mis of my life wasted.
Oh well live and learn. Still keen on 'Roles' though.
Huh?
$a_class->can('blessed')
means nothing like what you seem to think it means.Good to know maybe I will have to look at it again
It is generally a bug if a OO module has a
blessed
method. As it usually means they importedblessed
from Scalar::Util. ( which Moose does on your behalf ) without removing it from the namespace after it is no longer needed. namespace::clean namespace::autoclean or a simpleno Moose
just before the1;
will remove it for you. This applies equally to object oriented packages as well to non OO packages.The only methods you can be sure that a blessed object will have is the same ones that UNIVERSAL provides. Which it also provides to packages which are not object oriented.
The only reliable way to determine if a scalar holds an object is to use the
blessed
subroutine from Scalar::Util. There is no reliable way to determine if a package is meant to be used in an object oriented way. While most classes are instantiated with anew
method, it is not a requirement. A non object could also have anew
subroutine.