7

我想知道,在这段代码中,

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}

might-sink;
say might-sink;

might-sink在接收器上下文中的第一次调用实际上调用List.sink了 ,也就是说,什么都不做。我的预感是确实如此,但我不确定是这种情况还是根本没有reified,所以直到稍后才会抛出失败。我在这里尝试了调试选项,但没有一个进入从这个调用的代码中。所以两个问题,分开但相关:

  1. 如何使用 Perl 6 调试器或模块调试这些函数?
  2. 我怎样才能知道它List.sink是否真的被调用了,或者一般来说,sink当一个对象在接收器上下文中发现自己时是否被调用?
4

1 回答 1

7

即使您显式调用.sink了该返回值,Failure也不会崩溃:

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}

might-sink.sink;
say "Did not explode";
# OUTPUT: Did not explode

代码中的爆炸发生在调用期间的再现.gist期间say,它会遍历您的前 100 个元素Array并调用.gist它们。当它在Failure元素上这样做时,它会引爆它。

您将下沉列表对象本身和下沉它包含的单个值混为一谈。您正确提到List.sink的是无操作,但Seq.sink会消耗自己¹,但它也不会爆炸,因为只是Seq沉没,而不是其单个元素:(+"a", 42).Seq.sink

如果你想强制潜在的Failure爆炸,你可以:

1 use fatal:。Failures这将导致编译器致命失败,导致它们在许多传递的地方爆炸。这是一个词法编译指示,它也自动在try {}块中启用。

use fatal;
sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}
might-sink;

# OUTPUT:
# boo!
#  in block <unit> at

2: Hyper over.self方法调用。它由Mu(所以被所有对象继承)提供并且简单地返回self,所以它是一个无操作(除了做decont)。但是,由于大多数调用武装的方法都会导致它们Failure引爆,因此调用.self它们会导致它们爆炸。

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}
might-sink».self;

# OUTPUT:
# boo!
#  in block <unit> at

如何使用 Perl 6 调试器或模块调试这些函数?

不要自己使用调试器,但perl6-debug-m应该在您的 Rakudo 安装中预装。它需要您安装Debugger::UI::CommandLine模块。你只是使用它而不是perl6运行你的程序,它应该在命令行上提供一些关于它做什么的说明。还有一篇关于它的博客文章一个视频(需要 Flash 才能播放)。

还有一个最近发布的 alpha 质量App::MoarVM::Debug,让您甚至可以远程调试程序。它的美妙之处在于它可以让您在程序运行时转储对象内容并导航它们,因此如果您可以忍受它的界面,它会很方便。

就个人而言,我只使用dd例程在战略点中转储内容并查看它是否包含我期望它包含的内容来进行调试。

如何确定 List.sink 是否实际被调用,或者一般来说,当对象在接收器上下文中发现自己时是否调用了接收器?

does您可以使用或操作符来混合角色but,该操作符提供了sink一种可以执行您可以观看的操作的方法。比如打印一些东西:

sub foo {
    return [<a b c>] does role { 
        method sink { say "sink called" }
    }
}
foo
# OUTPUT: sink called

更高级的方法是转储优化后的QAST 树并查看它是否包含您期望的调用。CoreHackers::Q模块使转储的 QAST 树更易于可视化。

PS:关于隐含下沉的话题,值得注意的是R#1571列举了几个错误,并建议对处理下沉的内部系统进行完全重新设计。


¹ - 更准确地说,Seq.sink调用.sink-allits Iterator,默认情况下它只是简单地使用这些值,但自定义迭代器也可以将该方法覆盖为无操作。

于 2018-05-17T19:36:09.183 回答