如何检查 Perl 变量是否为 PDL 格式(即是否为 piddle)?
How can I check if a Perl variable is in PDL format (i.e. is a piddle)?
我正在使用 PDL。如果给我的变量 $foo
可以是散列引用、数组引用、标量或 piddle(可以为空或 null),我如何判断它是不是 piddle?
您可以使用 Scalar::Util 来确定变量是否:
- 一个对象(使用
blessed
函数)
- 引用,如果是,是什么类型的引用(使用
reftype
函数)
您可以使用 isa
方法来查明对象是特定 class 的实例还是继承自该 class。
Piddles 只是 PDL 对象,即被祝福到 PDL
class 中的东西,所以
$foo->isa('PDL')
如果 $foo
是一个 piddle,return 为真。
总计:
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';
}
}
输出:
Not a reference
ARRAY
HASH
piddle
检查某物是否属于某个 class 的典型方法是使用 isa
.
if( $thing->isa("PDL") ) { ... }
这尊重inheritance。只要 $thing
是 PDL 的子 class(或者说它是),以上内容就可以工作。这可以保护您免受自定义子 classes 和 PDL 本身的更改。下面是一个例子。
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
但是,方法调用不适用于非引用和非祝福引用;如果你尝试,你会得到一个错误。您可以通过两种方式解决此问题。首先是使用 eval BLOCK
来捕获错误,就像另一种语言中的 try
。
if( eval { $thing->isa("PDL") } ) { ... }
如果 $thing
不是对象,eval
将捕获错误并且 return 为假。如果 $thing
是一个对象,它将调用 isa
并 return 结果。
缺点是这会捕获 任何 错误,包括来自 isa
的错误。罕见,但它发生了。为避免这种情况,请使用 Scalar::Util's blessed() 首先确定 $thing
是否为对象。
use Scalar::Util qw(blessed):
if( blessed $thing && $thing->isa("PDL") ) { ... }
我正在使用 PDL。如果给我的变量 $foo
可以是散列引用、数组引用、标量或 piddle(可以为空或 null),我如何判断它是不是 piddle?
您可以使用 Scalar::Util 来确定变量是否:
- 一个对象(使用
blessed
函数) - 引用,如果是,是什么类型的引用(使用
reftype
函数)
您可以使用 isa
方法来查明对象是特定 class 的实例还是继承自该 class。
Piddles 只是 PDL 对象,即被祝福到 PDL
class 中的东西,所以
$foo->isa('PDL')
如果 $foo
是一个 piddle,return 为真。
总计:
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';
}
}
输出:
Not a reference
ARRAY
HASH
piddle
检查某物是否属于某个 class 的典型方法是使用 isa
.
if( $thing->isa("PDL") ) { ... }
这尊重inheritance。只要 $thing
是 PDL 的子 class(或者说它是),以上内容就可以工作。这可以保护您免受自定义子 classes 和 PDL 本身的更改。下面是一个例子。
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
但是,方法调用不适用于非引用和非祝福引用;如果你尝试,你会得到一个错误。您可以通过两种方式解决此问题。首先是使用 eval BLOCK
来捕获错误,就像另一种语言中的 try
。
if( eval { $thing->isa("PDL") } ) { ... }
如果 $thing
不是对象,eval
将捕获错误并且 return 为假。如果 $thing
是一个对象,它将调用 isa
并 return 结果。
缺点是这会捕获 任何 错误,包括来自 isa
的错误。罕见,但它发生了。为避免这种情况,请使用 Scalar::Util's blessed() 首先确定 $thing
是否为对象。
use Scalar::Util qw(blessed):
if( blessed $thing && $thing->isa("PDL") ) { ... }