Wednesday, 16 June 2010

Is there anything wrong with this?

So, we all think reusing other code and not reinventing the wheel is generally a good thing.

And using Moose is generally good.

So, I want to test if something is an object. I am using Moose.

1) Create a large hash to compare keys against, and then do


my $not_object_ref = {
HASH => 1, ARRAY => 1, GLOB => 1,...
};

my $is_object;
if ( my $ref = ref $object ) {
if ( ! $not_object_ref->{$ref} ) {
$is_object++;
}
}

# stuff that uses boolean value of $is_object


2) Use a Moose Attribute and eval


has q{_i_am_an_object} => (
isa => q{Object},
is => q{rw},
);

sub _is_object {
my ( $self, $object ) = @_;
my $is_object = 0;
eval {
$self->_i_am_an_object( $object ); # test if this is an object
$is_object++;
} or do {}; # I like PBP and perl critic :)
return $is_object;
}

my $is_object = $self->_is_object( $object );
# stuff that uses boolean value of $is_object


I don't know if this is a pure abuse of the Moose Attribute system, or if there is a much neater way of doing it, but certainly it has merit over the whole keeping track of what refs are not objects. And certainly, if you want to check against the object type, you change the isa to the class name, and give it a better method name.

It's probably more of an abuse of eval :)

Andy

4 comments:

LeoNerd said...

Perhaps I missed the entire point of your post, but.. What's wrong with Scalar::Util::blessed?

use Scalar::Util qw( blessed );

sub is_object { !! blessed $_[0] }

Unknown said...

Doh! Missed that one. Thanks.

Unknown said...

Since you're using Moose, the isa option on the attribute will check that its value is a valid Object type so you would not need to do any is_object testing later.

Unknown said...

Thanks for your response.

That's true, and certainly if the plan is to store it in the attribute long term.

However, I just wanted a quick way of it being checked, without the need to write the eval each time against the attribute, so just did that in an is_object method. This also has the upside of being able to give my attribute a more unlikely to clash name.

Just in case you want to know why. The reasoning behind not wanting to store in this case is that I am writing a spidering role, which is going to retrieve lots of webservice responses for caching on a filesystem for later much more parallel use. The purpose is fetch all, utilising the cache_it flag. Submit lots of jobs to LSF with the use_cache flag, so they get them from there. The spider doesn't care about what it caches, just to know that if what it has just found is an object, loop through that as well.