2

I'm using PDL. If I am given variable $foo that can be a hash reference, an array reference, a scalar, or a piddle (which can be empty or null), how can I tell if it's a piddle?

ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
Zhang18
  • 4,800
  • 10
  • 50
  • 67

2 Answers2

4

The typical way to check if something is of a certain class is with isa.

if( $thing->isa("PDL") ) { ... }

This respects inheritance. So long as $thing is a subclass of PDL (or says it is) the above will work. This protects you both against custom subclasses and changes to PDL itself. Below is an example.

use strict;
use warnings;
use v5.10;

package MyPDL;
our @ISA = qw(PDL);

package main;

use PDL;
use Scalar::Util qw(blessed);

my $stuff = pdl [1..10];

say blessed $stuff;                                   # PDL
say "\$stuff is a PDL thing" if $stuff->isa("PDL");   # true

my $bar = MyPDL->new([1..10]);
say blessed $bar;                                     # MyPDL
say "\$bar is a PDL thing" if $bar->isa("PDL");       # true

However, method calls don't work on non-references and unblessed references; you'll get an error if you try. You can work around this in two ways. First is to use eval BLOCK to trap the error, like try in another language.

if( eval { $thing->isa("PDL") } ) { ... }

If $thing is not an object, eval will trap the error and return false. If $thing is an object, it will call isa on it and return the result.

The downside is this will trap any error, including an error from isa. Rare, but it happens. To avoid that, use Scalar::Util's blessed() to first determine if $thing is an object.

use Scalar::Util qw(blessed):

if( blessed $thing && $thing->isa("PDL") ) { ... }
Schwern
  • 153,029
  • 25
  • 195
  • 336
3

You can use Scalar::Util to find out if a variable is:

  • an object (using the blessed function)
  • a reference, and if so, what type of reference (using the reftype function)

You can use the isa method to find out whether an object is an instance of a particular class or inherits from that class.

Piddles are simply PDL objects, i.e. things that have been blessed into the PDL class, so

$foo->isa('PDL')

will return true if $foo is a piddle.

All together:

use strict;
use warnings 'all';
use 5.010;

use PDL;
use Scalar::Util qw(blessed reftype);

my $scalar   = 19;
my $arrayref = [ qw(foo bar) ];
my $hashref  = { baz => 'qux' };
my $piddle   = pdl [ 1..10 ];

foreach my $item ($scalar, $arrayref, $hashref, $piddle) {
    my $reftype;

    if ( defined(blessed($item)) ) {
        say 'piddle' if $item->isa('PDL');
    }
    elsif ( defined($reftype = reftype($item)) ) {
        say $reftype;
    }
    else {
        say 'Not a reference';
    }
}

Output:

Not a reference
ARRAY
HASH
piddle
ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110