I love Scalar::Util and List::Util. They allow me to do stuff in a cleaner, clearer, and more abstract fashion, which is what good code is all about.

Until I tried to convert the following code:

use UNIVERSAL qw( isa ); .... my $is_blah = isa( $thing, 'Some::Class' ) && $x == 3; ... if ( isa($value, 'HASH') || isa($value, 'ARRAY') ) { # Do something here }

I tried to convert that code to the following:

use Scalar::Util qw( blessed reftype ); ... my $is_blah = blessed( $thing ) eq 'Some::Class' && $x == 3; ... my $r = reftype( $value ); if ( $r eq 'HASH' || $r eq 'ARRAY' ) { # Do something here }

Except, that code isn't equivalent. Both reftype() and blessed() return undef, not the empty string. So, the most obvious use for reftype() and the second most obvious use for blessed() don't DWIM. Plus, ref() returns the empty string, which means they don't behave as the internal they're supposed to replace.

So, now I have to do (blessed($thing)||'') and my $r = reftype($value)||'; How annoying!


My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Replies are listed 'Best First'.
Re: Why reftype and blessed are making my life harder than it needs to be
by xdg (Monsignor) on Feb 09, 2006 at 21:01 UTC

    Your conversion doesn't really have equivalent semantics. isa includes subclass relationships, which you won't get with ref or blessed.

    In the example you gave, what's wrong with this (assuming you don't really want @ISA semantics):

    my $is_blah = ref( $thing ) eq 'Some::Class' && $x == 3;

    I tend to think of blessed as a boolean -- not a replacement for ref (excepting if blessing into the empty string is something to check for).

    And while it's a bit verbose, you could tackle the reftype bit this way:

    my $r = ref( $value ) && reftype( $value );

    That doesn't really gain you much over reftype( $value ) || q{} except maybe a moment's less thought for the next reader about why the empty string is the alternative if reftype is false.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Thank you! I completely missed that inequivalence. I've changed that test to now read:
      my $is_class = eval { $thing->isa( 'Some::Class' ) }; my $is_blah = $is_class && $x == 3;
      As for the reftype one ... I wonder if reftype can legally be anything other than GLOB/IO/ARRAY/HASH/CODE/REF/SCALAR? Meaning, q{} cannot legally be returned from reftype().

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

        Reading the code for it, it looks like it can't return q{}. If ref returns the empty string, reftype returns undef. Otherwise, it looks like it gives one of the underlying types. Looks like blessing into the empty string will still slip past reftype. (Bug or feature? You make the call...)

        -xdg

        Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      blessed() isn't a boolean because package names may be false: "" or "0". If you want a boolean, check for defined( blessed( ... ) ) instead. That's why blessed() returns undef on non-blessed: the "false" value of ref() is actually a valid true value.

      bless( ..., "\0" ); # "" bless( ..., 0 ); # "0"

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        As I said, I tend to think of it as a boolean -- largely because I only use it in situations when I'm pretty sure I won't be blessing objects into "0" or "\0".

        Interestingly, reftype only checks the length of ref, which is why it can probably be fooled by "\0".

        -xdg

        Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Why reftype and blessed are making my life harder than it needs to be
by merlyn (Sage) on Feb 09, 2006 at 20:35 UTC
    Since the empty string is a valid blessed class, reftype and blessed are doing the right thing there by using undef when the value is not blessed. Otherwise, how would you distinguish the empty blessing from the unblessed, religious overtones notwithstanding?

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Since the empty string is a valid blessed class
      No, it's not. If the second argument of bless is the empty string, the thing being blessed is blessed into main. If you turn on warnings, Perl will tell you so.
      Otherwise, how would you distinguish the empty blessing from the unblessed, religious overtones notwithstanding?
      That's easy. blessed returns main in the first case, and so does ref. ref returns the empty string if its argument isn't a reference - and that's never ambigious, and hence there would be any ambiguity if blessed would do the same.
      #!/usr/bin/perl use strict; use warnings; use Scalar::Util 'blessed'; my $ref = bless [], ""; print ref $ref, "\n"; print blessed $ref, "\n"; __END__ Explicit blessing to '' (assuming package main) at "..." line 8. main main
      Perl --((8:>*

        It's easy to bless into "". This trades on knowledge that package names are null terminated strings.

        bless( ..., "\0" )

        ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        Since the empty string is a valid blessed class
        No, it's not. If the second argument of bless is the empty string, the thing being blessed is blessed into main. If you turn on warnings, Perl will tell you so.
        I'm pretty sure you can bless into "" from XS code. Didn't go so far as to try it though.
      That's fair enough. So, how would you recommend I handle the cases I bring up?

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: Why reftype and blessed are making my life harder than it needs to be
by demerphq (Chancellor) on Feb 09, 2006 at 20:22 UTC

    Actually its really weird you bring this up today. Ive encountered this annoyance before and ended up writing my own reftype for Data::Dump::Streamer which returns an Pl_no when the item isn't a ref. And I just a few hours ago wrote on my todo list that this should be included in Scalar::Util as _reftype(). Unfortunately the Pl_no logic doesnt work with blessed as '0' and '' are both valid (but evil) classnames.

    Anyway, if you want to avoid this problem you can use DDS::reftype() instead.

    ---
    $world=~s/war/peace/g

Re: Why reftype and blessed are making my life harder than it needs to be
by Jenda (Abbot) on Feb 09, 2006 at 21:05 UTC

    I may be missing something, but isn't the difference that the isa($thing, 'Some::Class') returns true even if the $thing is blessed into a subclass of the Some::Class while the blessed($thing) eq 'Some::Class' is true only for $things blessed directly to Some::Class more important than whether you have to do something to silence use warnings 'uninitialized';?