Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scalar::Util vs. ref function

What's the difference between the built in ref($object) and Scalar::Util blessed($object)? Is one preferred over the other?

use strict;
use warnings;

use Scalar::Util qw(blessed isvstring);

my $object = foo->new();

print "Object is a " . blessed($object) . "\n";
print "Object is a " . ref($object) . "\n";

my $version = 5.00.03;

print "Version is a " . ref(\$version) . "\n";
if (isvstring($version)) {
    print "Version is a VSTRING\n";
}

package foo;
sub new {
    my $class = shift;
    my $self = {};

    bless($self, $class);
    return $self;
}
like image 227
David W. Avatar asked Dec 09 '10 20:12

David W.


1 Answers

According to POD, blessed() only works on blessed references (e.g. a references passed to a bless() call).

It returns undef on everything else, including hash/array refs where ref() returns HASH/ARRAY (and a bunch of other types as delineated in perldoc ref). To get reference type you can, of course call Scalar::Util::reftype.

As for whether one should be used over another, I think it depends largely on what the logic is.

  • If you only want to distinguish real blessed references from everything else, blessed() provides a more concise way than taking a ref and then verifying that the value is not on of standard ones returned by unblessed reference.

    my $ref_type = ref($my_ref);
    print "USING REF: ";
    if (      $ref_type
           && $ref_type ne ref({})
           && $ref_type ne ref([])
           && $ref_type ne "SCALAR"
           # Could also use a hash with all allowed values of ref() instead
           && $ref_type !~ /^(CODE|REF|GLOB|...)$) { 
        print "I am an object of class $ref_type\n";
    } else {
        print "I'm a reference of type $ref_type\n";
    }
    
    
    # vs... 
    
    
    print "USING SCALAR_UTIL: ";
    my $ref_type = blessed($my_ref);
    print $ref_type ? "I am an object of class $ref_type\n"
                    : "I am a reference of type " . reftype($my_ref) . "\n";
    
  • If you need fine distinctions between both blessed references and different ublessed ones, then a single ref() call is more concise than a combination of blessed and reftype.

  • One edge case where there's an actual functional difference between the two approaches, as noted in the comments by Eric Strom, is when someone creates a class which matches one of ref() hardcoded values (e.g. bless [], 'HASH' - in which case they are either Way Dumb or Way Too Clever By Half).

    my $sssft = bless [], 'HASH'; # sssft = someone_should_suffer_for_this
    ref_description_using_ref($sssft);
    ref_description_using_scalar_util($sssft);
    
    
    # OUTPUT:
    USING REF: I'm a reference of type HASH
    USING SCALAR_UTIL: I am an object of class HASH
    

DISCLAIMER: Based on documentation, there should be no difference between the two when the argument is a reference blessed into a class (e.g. it returns class name). But I haven't checked "Scalar::Util" source to confirm.

like image 192
DVK Avatar answered Oct 20 '22 06:10

DVK