Bloodnok has asked for the wisdom of the Perl Monks concerning the following question:

Hi again, most venerated ones,

Yep, tis that time of week again when I get my candidacy for the 'stupidest question of the decade' award.

My question/quandary is, simply put, this...

Is the most scaleable, implementation agnostic (thanx bart), future proof way of determining whether, or not, a variable represents an object, the following...

eval { $ref->isa() }; if ($@) { # Isnt an object } else { # Is an object }
?

There, that's it, what could be simpler (apart from me;-)

TIA & rgds to all

At last, a user level that overstates my experience :-))

Replies are listed 'Best First'.
Re: To be, or not to be, an object ?
by moritz (Cardinal) on Jul 24, 2008 at 11:34 UTC
    I usually use Scalar::Util::blessed. Never failed me so far. Would your approach work with autobox?

    Update: Your suggested solution has a (nearly obvious) pitfall:

    sub Foo::isa { die "bla" }; my $ref = bless {}, 'Foo'; eval { $ref->isa() }; if ($@) { print "Not an object\n"; } else { print "An object\n"; }

    Also in general this construct:

    eval { ... } if ($@) { ... }

    Isn't all that reliable because a DESTROY sub might clear $@ accidentally. Rather use

    if (eval {...; 1}){ ... }

    Instead (Ok, this is nit-picking, but you asked for reliability...).

      Hi moritz ,

      JIC you were wondering about the justification for this diversion, I'm working in an environment whereby the ad-hoc downloading and use (pun intended:-) of CPAN modules is a non-trivial exercise:-(

      Back OT, if the conditional were to change to ... if ($@ =~ /can't call method without a package or object ref/) {..., then the problem would, methinx, be circumvented unless there was a package perverse enough to die "can't call method..." in an overloaded isa().

      BTW, wouldn't your latter point put at risk all that we're told regarding the use (pun unintended this time:-) of eval to catch errors and handle them locally - the risk of DESTROY f%*&^ing things up in such circumstances must be almost omnipresent... mustn't it ??
      Just a thought...

      At last, a user level that overstates my experience ... as I'm beginning to most ably demonstrate :-))
        Back OT, if the conditional were to change to ... if ($@ =~ /can't call method without a package or object ref/) {..., then the problem would, methinx, be circumvented unless there was a package perverse enough to die "can't call method..." in an overloaded isa().
        Yes. Except that I always hated this kind of hack, because it relies on the exact phrase of the error message. Which might be subject to change, to l10n or whatever.
        BTW, wouldn't your latter point put at risk all that we're told regarding the use (pun unintended this time:-) of eval to catch errors and handle them locally - the risk of DESTROY f%*&^ing things up in such circumstances must be almost omnipresent... mustn't it ??

        Yes, it is indeed. There was a lengthy thread on p5p about that, and how to fix it.

        Thankfully only very few modules actually use a eval inside a DESTROY block without localizing $@ first.

        If you don't need a return value from the eval block, you can also do this check:

        my $success = eval { # your stuff here... 1; };

        and then check for the truthness of $success.

Re: To be, or not to be, an object ?
by Corion (Patriarch) on Jul 24, 2008 at 11:33 UTC
Re: To be, or not to be, an object ?
by Bloodnok (Vicar) on Jul 24, 2008 at 11:54 UTC
    Thanx both for your quick responses.

    I know about Scalar::Util but hadn't even considered it - doh!! Having had a peek @ the code, AFAICT, it does something extremely similar - I'm now rather worried I might be gaining a little understanding ... looks somewhat worried

    Mmm, Autobox - what a thing that is ?! I'll try my approach with it and see ... might even let you know the results :-))

    Update

    There are, 2 aspects to the differences between my attempt and Grahams' (author of Scalar::Util), Graham...

    • creates a temporary method in the UNIVERSAL class
    • uses a call to ref on the suspect, before evaling the call to his new, temporary method
    Whereas I use the (now standard) isa() method and omitted the call to ref - since the call to isa() would, methinx, generate either a 'not an object' or 'not an reference' error - aka a short cut.

    At last, a user level that overstates my experience :-))
      There are, 2 aspects to the differences between my attempt and Grahams' (author of Scalar::Util), Graham...
      • creates a temporary method in the UNIVERSAL class

      Scalar::Util uses UNIVERSAL::a_sub_not_likely_to_be_here, but it's not a temporary method, because (unless I'm mistaken) it stays in the UNIVERSAL namespace forever.

      However, the XS version of Scalar::Util is pretty straightforward, it's blessed() does not use any dirty tricks at all, it just determines whether something is blessed, using the appropriate API.

        TFT, point taken.

        I would point out that temporary and forever are one and the same in this context i.e. the lifetime of the program useing Scalar::Utils.

        At last, a user level that overstates my experience :-))
Re: To be, or not to be, an object ?
by kyle (Abbot) on Jul 24, 2008 at 15:42 UTC

    Scalar::Util::blessed is the way to do this. If you're exceptionally paranoid, you have to check if it's defined, not merely true.

    use Scalar::Util 'blessed'; my $oh_bee_jay = bless {}, '0'; print "not blessed\n" if not blessed $oh_bee_jay; print "defined blessed\n" if defined blessed $oh_bee_jay; __END__ not blessed defined blessed

    I'd be surprised if this is an issue, though. Package '0' is not too popular.