调试函数调用

jjm*_*elo 7 debugging rakudo perl6

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

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

might-sink;
say might-sink;
Run Code Online (Sandbox Code Playgroud)

might-sinksink上下文中的第一次调用实际上是调用List.sink,即什么都不做.我的预感确实如此,但我不确定是否是这种情况,或者它根本没有具体化,所以直到后来才会抛出失败.我在这里尝试了调试选项,但没有一个进入从这个调用的代码.所以两个问题,分开但相关:

  1. 如何使用Perl 6调试器或模块调试这些功能?
  2. 我怎样才能知道List.sink是否实际调用了它,或者一般来说,sink当一个对象在sink上下文中找到它时调用它?

小智 6

即使您明确地调用.sink了该返回值,Failure也不会爆炸:

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

might-sink.sink;
say "Did not explode";
# OUTPUT: Did not explode
Run Code Online (Sandbox Code Playgroud)

在你的代码爆炸的移交过程中会发生.gistsay呼叫肚里通过你的第一个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
Run Code Online (Sandbox Code Playgroud)

2:.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
Run Code Online (Sandbox Code Playgroud)

如何使用Perl 6调试器或模块调试这些功能?

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

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

就个人而言,我只是通过使用dd例程来调试战略点中的东西,并查看它是否包含我希望它包含的东西.

我怎样才能知道List.sink是否实际被调用,或者一般来说,当一个对象在sink上下文中找到它时是否调用了sink?

您可以混合使用角色doesbut运算符,它们提供了sink一种可以观察的方法.喜欢印刷的东西:

sub foo {
    return [<a b c>] does role { 
        method sink { say "sink called" }
    }
}
foo
# OUTPUT: sink called
Run Code Online (Sandbox Code Playgroud)

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

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


¹ - 更准确地说,Seq.sink调用.sink-allIterator,默认情况下只是消耗值,但自定义迭代器也可以将该方法重写为无操作.