为什么Duration.new适用于Int而不适用于Rat



对于持续时间,为什么我需要手动将Rat强制为Real,而不是Int?

这是基于MoarVM版本2020.01.1的Rakudo版本2020.01在OSX上实现Perl6.d

say $v.WHAT; #(Int)
$v = Duration.new( $v );
say $v;     #20 
my $w = 20.0;
say $w.WHAT; #(Rat)
$w = Duration.new( $w.Real );
say $w;     #20 
my $x = 20.0;
say $x.WHAT; #(Rat)
$x = Duration.new( $x );
say $x;     #hangs

这是一个错误。已修复https://github.com/rakudo/rakudo/commit/f70d95e299.

它对Rat的作用不同于任何其他类型的原因是,Rat的情况经过优化,不必进行任何强制,因此不需要检查强制的结果。在这种情况下,该值被直接放入新的Duration对象中。但是,它这样做并没有去容器化,所以Duration对象实际上引用了示例中的变量$x。这通常都很好,但由于这种自引用,.gist逻辑不知何故创建了一个无限循环,试图创建Duration的表示。必须承认,我并没有真正研究它到底在哪里进入了一个循环。

无论如何,通过确保该值在Duration对象内被解除污染,问题就消失了,因为这样它就不能再进行自引用了。