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.

moose-hunt.jpg

3 Comments

Huh? $a_class->can('blessed') means nothing like what you seem to think it means.

  use v5.10; use strict;
  
  {
    package Foo;
    use Moose;
  }
  
  {
    package Bar;
    use Moo;
  }
  
  {
    package Baz;
    use Moose;
    use namespace::autoclean;
  }
  
  for my $class (qw( Foo Bar Baz ))
  {
    say $class, " : ", $class->can('blessed');
  }

It is generally a bug if a OO module has a blessed method. As it usually means they imported blessed 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 simple no Moose just before the 1; 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 a new method, it is not a requirement. A non object could also have a new subroutine.

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations