我最近花了很多时间调试一个脚本,当我最终发现问题时,是因为代码看起来像这样:
class Foo {
has $.bar;
method () {
# do stuff
$!.bar;
}
}
Run Code Online (Sandbox Code Playgroud)
原来,问题是与$!.bar
,它应该是要么$!bar
或$.bar
。我明白了。
但这为什么不死?
详细看这个,它看起来像这里的问题是,我试图调用(不存在)的方法bar
上$!
,它在这一点上Nil
,因为再也没有出现过任何差错。
看起来我实际上可以调用我想要的任何方法,Nil
并且它们都默默地返回Nil
,包括像Nil.this-is-a-fake-method
和这样的东西Nil.reverse-entropy(123)
。
这是一个功能吗?如果是这样,理由是什么?
hob*_*bbs 13
是的,它是有意并记录在案的。标题Nil
是“缺少值或良性失败”,类文档中提到
对
Nil
不存在的方法的任何方法调用,以及因此的任何下标操作,都将成功并返回Nil
。Run Code Online (Sandbox Code Playgroud)say Nil.ITotallyJustMadeThisUp; # OUTPUT: «Nil?» say (Nil)[100]; # OUTPUT: «Nil?» say (Nil){100}; # OUTPUT: «Nil?»
概要 2指出“任何未定义的方法调用Nil
返回Nil
,以便Nil
向下传播方法调用链。同样的任何对Nil
返回的下标操作Nil
”,因此意图似乎是允许表达式,例如$foo.Bar()[0].Baz()
不需要Nil
在每一步检查,或特殊的“无安全” " 方法调用和下标运算符。
这个问题(以及 hobbs 的回答)也让我感到……不安:我最终找到了https://docs.raku.org/language/traps:它解释了分配Nil
会产生不同的值,通常是Any
。以下基本的 REPL 交互也演示了这一点:
> my $foo = Nil
(Any)
> $foo.bar
No such method 'bar' for invocant of type 'Any'
in block <unit> at <unknown file> line 1
> my $bar := Nil
Nil
> $bar.baz
Nil
Run Code Online (Sandbox Code Playgroud)
((此处介绍=
和之间的区别:=
:https : //docs.raku.org/language/containers#Binding))
...所以一般的想法是,常规代码中的“缺失值或良性失败”远没有我(也许你也是?)突然担心的那样普遍:但是,当您要使用正则表达式时,它确实会发生直接匹配,并在与直接调用$!
.
这让我更加了解Nil
和之间的区别Any
,并且提供的基本原理对我来说更有意义。