我可以在Nil上调用任何方法,这感觉不对


14

最近,我花了很多时间调试脚本,当我最终发现问题时,是由于代码如下所示:

class Foo {
    has $.bar;
    method () {
        # do stuff
        $!.bar;
    }
}

原来问题在于$!.bar它应该是$!bar$.bar。我明白了

但是为什么不死呢?

详细看这个,它看起来像这里的问题是,我试图调用(不存在)的方法bar$!,它在这一点上Nil,因为再也没有出现过任何差错。

看起来我可以实际调用任何我想要的方法了Nil,它们都默默地返回Nil,包括Nil.this-is-a-fake-method和之类的东西Nil.reverse-entropy(123)

这是功能吗?如果是这样,有什么根据?

Answers:


13

是有意记录的,是的。标题为Nil“缺少值或良性失败”,并且类文档中提到

任何Nil不存在的方法调用,因此任何下标操作都将成功并返回Nil

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的每一步,或特殊的“无安全方法调用和下标运算符。


4
确实。和相当长的一段时间前就已经和:github.com/rakudo/rakudo/commit/174727377f(2013年12月)也请参阅相关的猜测:design.raku.org/S02.html#Nil
伊丽莎白Mattijsen

1
@ElizabethMattijsen啊,我认为S02有答案。“上的任何未定义的方法调用Nil返回Nil,从而使Nil向下传播方法调用链。” 因此,您$foo.Bar().Baz().Blah()无需执行每个步骤的零测试或使用特殊?.类型的运算符即可完成操作(只要最后正确处理了零)即可。我将对其进行编辑,谢谢。
hobbs

1
Nil不会出错并且会抛出更多错误的A Nil在Obj-C和NS框架中以类似的方式广泛使用,从而允许链式调用不断传递到Nil。我不知道异常和捕获异常的确切性能损失,但是我猜想Nil,如果不那么灵活,链接可以更有效。
user0721090601

1
(但这是一个完全不知情的猜测,所以我很高兴lizmat或jnthn告诉我我错了,我需要闭嘴:
user0721090601

2
Nil类有一个FALLBACK docs.raku.org/language/typesystem#index-entry-FALLBACK_(method) 方法,该方法返回Nil。基本上,在由于找不到方法而引发异常之前,将进行检查FALLBACK并在可用时调用。
伊丽莎白·马蒂森 Elizabeth Mattijsen)

5

这个问题(和霍布斯的回答)也让我感到不安:我最终发现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))

...所以一般的想法是,“缺失的价值或良性失败”在常规代码中的传播远不如我(也许您也是如此)突然担心的那样:但是,当您使用正则表达式时,它确实会发生直接匹配并且在与您直接调用上的方法相关的特定偶然情况下匹配$!

这使我更加了解 NilAny,并且所提供的理由对我来说更有意义。


2
Nil将容器设置为其默认状态。您可以更改默认值。my $foo is default(42) = 5; $foo = Nil; say $foo; # 42
布拉德·吉尔伯特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.