我想知道在此代码中是否
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,但没有一个进入从这个调用的代码。所以有两个问题,分开但相关:
List.sink
,或者一般情况下,当对象在汇上下文中发现自己时是否调用sink
?答案 0 :(得分: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
代码中的爆炸发生在.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 it和a video(需要Flash才能播放)。
还有一个最近发布的alpha质量App::MoarVM::Debug
,它允许您甚至远程调试程序。它的美妙之处在于它允许您在程序运行时转储对象内容并导航它们,因此如果您可以使用它的界面,它可以很方便。
就个人而言,我只是通过使用dd
例程来调试战略点中的东西,并查看它是否包含我希望它包含的内容。
如何判断List.sink是否实际被调用,或者一般来说,当对象在sink上下文中发现自己时是否调用了sink?
您可以使用提供does
方法的but
或sink
运算符混合使用某个角色。喜欢打印一些东西:
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.sink
在Iterator
上调用.sink-all
,默认情况下只会消耗这些值,但自定义迭代器也可以将该方法重写为无操作