Eth*_*her 43
$x永远是一个标量.提示是sigil $:任何变量(或其他类型的解引用)$都是标量.(有关数据类型的更多信息,请参阅perldoc perldata.)
引用只是一种特殊类型的标量.内置函数ref将告诉您它是什么类型的引用.另一方面,如果你有一个受祝福的引用,ref只会告诉你引用的包名称,而不是数据的实际核心类型(祝福引用可以是hashrefs,arrayrefs或其他东西).您可以使用标量::的Util的reftype会告诉你它是什么类型的参考:
use Scalar::Util qw(reftype);
my $x = bless {}, 'My::Foo';
my $y = { };
print "type of x: " . ref($x) . "\n";
print "type of y: " . ref($y) . "\n";
print "base type of x: " . reftype($x) . "\n";
print "base type of y: " . reftype($y) . "\n";
Run Code Online (Sandbox Code Playgroud)
...产生输出:
type of x: My::Foo
type of y: HASH
base type of x: HASH
base type of y: HASH
Run Code Online (Sandbox Code Playgroud)
有关其他类型引用的更多信息(例如coderef,arrayref等),请参阅此问题:如何让Perl的ref()函数返回REF,IO和LVALUE?和perldoc perlref.
注意:您应不使用ref来实现与祝福的对象(例如代码分支$ref($a) eq "My::Foo" ? say "is a Foo object" : say "foo not defined";) -如果你需要基于一个变量,使用类型的任何决定isa(即if ($a->isa("My::Foo") { ...或if ($a->can("foo") { ...).另见多态性.
bri*_*foy 18
标量始终包含单个元素.标量变量中的任何内容始终是标量.引用是标量值.
如果您想知道它是否是参考,您可以使用ref.如果您想知道引用类型,可以使用Scalar :: Util中的reftype例程.
如果您想知道它是否是对象,可以使用Scalar :: Util中的blessed例程.不过,你永远不应该关心受祝福的包裹是什么.有一些方法可以告诉你一个对象:如果你想检查它是否有你要调用的方法,请使用; 如果你想看到它继承自某些东西,请使用; 如果你想看到对象处理一个角色,请使用.UNIVERSALcanisaDOES
如果你想知道这个标量是否实际上只是一个标量,但是与一个类相关联,那就试试吧tied.如果您有对象,请继续检查.
如果你想知道,如果它看起来像一个号码,你可以使用looks_like_number从标量::的Util.如果它看起来不像数字并且它不是引用,那么它就是一个字符串.但是,所有简单值都可以是字符串.
如果您需要做一些更奇特的事情,可以使用Params :: Validate等模块.
我喜欢多态而不是手动检查某些东西:
use MooseX::Declare;
class Foo {
use MooseX::MultiMethods;
multi method foo (ArrayRef $arg){ say "arg is an array" }
multi method foo (HashRef $arg) { say "arg is a hash" }
multi method foo (Any $arg) { say "arg is something else" }
}
Foo->new->foo([]); # arg is an array
Foo->new->foo(40); # arg is something else
Run Code Online (Sandbox Code Playgroud)
这比手动检查强大得多,因为您可以像使用任何其他类型约束一样重用“检查”。这意味着当您想要处理数组、散列和小于 42 的偶数时,您只需为“小于 42 的偶数”编写一个约束,并为这种情况添加一个新的多方法。“调用代码”不受影响。
您的类型库:
package MyApp::Types;
use MooseX::Types -declare => ['EvenNumberLessThan42'];
use MooseX::Types::Moose qw(Num);
subtype EvenNumberLessThan42, as Num, where { $_ < 42 && $_ % 2 == 0 };
Run Code Online (Sandbox Code Playgroud)
然后让 Foo 支持这个(在那个类定义中):
class Foo {
use MyApp::Types qw(EvenNumberLessThan42);
multi method foo (EvenNumberLessThan42 $arg) { say "arg is an even number less than 42" }
}
Run Code Online (Sandbox Code Playgroud)
然后Foo->new->foo(40)打印arg is an even number less than 42而不是arg is something else.
可维护。