调试函数调用

时间:2018-05-17 18:58:06

标签: debugging perl6 rakudo

我想知道在此代码中是否

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

might-sink;
say might-sink;

sink context中对might-sink的第一次调用实际上会调用List.sink,即无效。我的预感确实如此,但我不确定是否是这种情况,或者根本不是reified,所以直到稍后才会抛出失败。 我已经尝试了debugging options here,但没有一个进入从这个调用的代码。所以有两个问题,分开但相关:

  1. 如何使用Perl 6调试器或模块调试这些功能?
  2. 如何确定实际调用List.sink,或者一般情况下,当对象在汇上下文中发现自己时是否调用sink

1 个答案:

答案 0 :(得分:6)

即使您在该返回值上明确调用.sinkFailure也不会爆炸:

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

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

代码中的爆炸发生在.gist来电say期间,在Array通过.gist的前100个元素并在其上调用Failure。当它在List.sink元素上执行此操作时,它会引爆它。

您正在混淆列表对象本身的下沉以及它所包含的各个值的下沉。你正确地提到Seq.sink是一个无操作,但Seq消耗自己¹,但它也不会爆炸,因为只有(+"a", 42).Seq.sink正在沉没,而不是它的各个元素:{{ 1}}

如果你想强制潜在的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:超过.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来运行你的程序,它应该在命令行上提供一些关于它的功能的指令。还有blog post on ita video(需要Flash才能播放)。

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

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

  

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

您可以使用提供does方法的butsink运算符混合使用某个角色。喜欢打印一些东西:

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

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

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

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