我可以在 Nil 上调用任何方法,这感觉不对
I can call any method on Nil and this feels wrong
我最近花了很多时间调试脚本,当我终于找到问题时,是因为代码如下所示:
class Foo {
has $.bar;
method () {
# do stuff
$!.bar;
}
}
原来问题出在 $!.bar
上,它应该是 $!bar
或 $.bar
。我明白了。
但是为什么这个不死?
更详细地看一下,这里的问题似乎是我试图在 $!
上调用一个(不存在的)方法 bar
,此时是Nil
因为没有任何错误。
看起来我实际上可以在 Nil
上调用我想要的任何方法,它们都默默地 return Nil
,包括 Nil.this-is-a-fake-method
和 [=20] =].
这是一个功能吗?如果是这样,理由是什么?
它是有意并记录在案的,是的。 Nil
的标题是 "Absence of a value or a benign failure",class documentation 提及
Any method call on Nil
of a method that does not exist, and consequently, any subscripting operation, will succeed and return Nil
.
say Nil.ITotallyJustMadeThisUp; # OUTPUT: «Nil»
say (Nil)[100]; # OUTPUT: «Nil»
say (Nil){100}; # OUTPUT: «Nil»
Synopsis 2 声明 "Any undefined method call on Nil
returns Nil
, so that Nil
propagates down method call chains. Likewise any subscripting operation on Nil
returns Nil
",因此其意图似乎是允许像 $foo.Bar()[0].Baz()
这样的表达式,而不需要在每一步检查 Nil
或特殊的 "Nil-safe" 方法调用和下标运算符。
这个问题(和霍布斯的回答)也让我感到...不安:我最终发现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
(( =
和 :=
的区别在这里:https://docs.raku.org/language/containers#Binding ))
...所以一般的想法是 'absent value or benign failure' 在常规代码中的普及程度远不如我(也许你也是?)突然担心:它确实发生了,但是,当你要使用正则表达式匹配 直接 并且在您特定的意外情况下直接调用 $!
.
上的方法
这让我更加了解 Nil
和 Any
之间的区别,并且提供的基本原理对我来说更有意义。
我最近花了很多时间调试脚本,当我终于找到问题时,是因为代码如下所示:
class Foo {
has $.bar;
method () {
# do stuff
$!.bar;
}
}
原来问题出在 $!.bar
上,它应该是 $!bar
或 $.bar
。我明白了。
但是为什么这个不死?
更详细地看一下,这里的问题似乎是我试图在 $!
上调用一个(不存在的)方法 bar
,此时是Nil
因为没有任何错误。
看起来我实际上可以在 Nil
上调用我想要的任何方法,它们都默默地 return Nil
,包括 Nil.this-is-a-fake-method
和 [=20] =].
这是一个功能吗?如果是这样,理由是什么?
它是有意并记录在案的,是的。 Nil
的标题是 "Absence of a value or a benign failure",class documentation 提及
Any method call on
Nil
of a method that does not exist, and consequently, any subscripting operation, will succeed and returnNil
.say Nil.ITotallyJustMadeThisUp; # OUTPUT: «Nil» say (Nil)[100]; # OUTPUT: «Nil» say (Nil){100}; # OUTPUT: «Nil»
Synopsis 2 声明 "Any undefined method call on Nil
returns Nil
, so that Nil
propagates down method call chains. Likewise any subscripting operation on Nil
returns Nil
",因此其意图似乎是允许像 $foo.Bar()[0].Baz()
这样的表达式,而不需要在每一步检查 Nil
或特殊的 "Nil-safe" 方法调用和下标运算符。
这个问题(和霍布斯的回答)也让我感到...不安:我最终发现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
(( =
和 :=
的区别在这里:https://docs.raku.org/language/containers#Binding ))
...所以一般的想法是 'absent value or benign failure' 在常规代码中的普及程度远不如我(也许你也是?)突然担心:它确实发生了,但是,当你要使用正则表达式匹配 直接 并且在您特定的意外情况下直接调用 $!
.
这让我更加了解 Nil
和 Any
之间的区别,并且提供的基本原理对我来说更有意义。