perl6“ P6opaque,Str”与简单的“ Str”类型-后续

lis*_*tor 7 string int tail perl6 raku

谢谢您以前的所有帮助!

我之前的问题在这里:

perl6“ P6opaque,Str”与简单的“ Str”类型

我终于可以在这里重现错误:

my @recentList = prompt("Get recentList: e.g. 1 2 3: ").words || (2,4,6);    
say "the list is: ", @recentList;    
for @recentList -> $x {
    say "one element is:  ", $x;
    say "element type is: ", $x.WHAT;
    say "test (1,2,3).tail(\"2\") : ", (1,2,3).tail("2");
    say ( (10.rand.Int xx 10) xx 15 ).map: { @($_.tail($x)); };
}
Run Code Online (Sandbox Code Playgroud)

只要我使用默认列表,只需在提示符下按回车键而不输入任何内容,结果就可以了。但是,如果输入数字,则会出现此错误:

Get recentList: e.g. 1 2 3: 2
the list is: [2]
one element is:  2
element type is: (Str)
test (1,2,3).tail("2") : (2 3)
This type cannot unbox to a native integer: P6opaque, Str
  in block  at intType.p6 line 9
  in block <unit> at intType.p6 line 5
Run Code Online (Sandbox Code Playgroud)

如果tail(“ 2”)有效,为什么tail($ x)失败?另外,在我的原始代码中,tail($ x.Int)不能解决问题,但是在这里可以做到。

非常感谢您的帮助 !!!

rai*_*iph 6

这充其量只是一个答案。到目前为止,解决这个问题一直是失败的尝试。我可能刚走进杂草。但是,我将发布我所拥有的。如果没有别的,也许可以提醒我们下面的前三个步骤是明智的。此后,我正在赌博,通过偷窃源代码来继续前进,如果我可以通过直接调试编译器来取得更快,更可靠的进步,如第三步中所述。


好的,第一步是MRE。您提供的是一个完全为R且为M的E。:)


步骤2是增加M(打高尔夫球)。我将其归结为:

Any.tail('0');    # OK
Any.tail('1');    # BOOM
Run Code Online (Sandbox Code Playgroud)

请注意,它可以是实际值:

1.tail('1');      # BOOM
(1..2).tail('1'); # BOOM
Run Code Online (Sandbox Code Playgroud)

但是一些值有效:

(1,2).tail('1');  # OK
Run Code Online (Sandbox Code Playgroud)

步骤#3可能应该遵循使用Rakudo Perl 6的代码中的说明来跟踪编译器的执行,例如,将says 粘贴在其源代码中并重新编译。

您可能还想尝试App :: MoarVM :: Debug。(我没有。)

使用这些方法,您将有能力以绝对精度跟踪编译器对您所投入的任何代码的处理方式。我建议您这样做,即使我没有这样做。也许您可以弄清楚我哪里出了问题。


在下面的文章中,我通过直接拼写Rakudo编译器的源代码来跟踪此问题。

在Rakudo源“方法尾巴”的搜索,得到4个匹配。对于我的高尔夫来说,匹配方法是中的匹配core/AnyIterableMethods.pm6

tail参数$n显然不是,Callable因此继续进行我们的摸索的相关行是Rakudo::Iterator.LastNValues(self.iterator,$n,'tail')

用于这导致搜索这个方法core/Iterator.pm6

这依次调用.new例程

这三行

nqp::if(
  n <= 0,                 # must be HLL comparison
  Rakudo::Iterator.Empty, # negative is just nothing
Run Code Online (Sandbox Code Playgroud)

解释为什么'0'有效。<=在进行数字比较之前,运算符会将其操作数强制转换为数字。因此,'0'强制到0,条件是True,结果是Rakudo::Iterator.Empty,并且Any.tail('0')屈服()并且没有抱怨。

紧接上述三行的代码是的else分支nqp::if。它以关闭nqp::create(self)!SET-SELF(iterator,n,f)

依次调用!SET-SELF例程,其中包含以下行:

($!lastn := nqp::setelems(nqp::list, $!size = size)),
Run Code Online (Sandbox Code Playgroud)

size在BOOM中,哪个尝试分配'1'$!size。但是$!size声明为

has int $!size;
Run Code Online (Sandbox Code Playgroud)

答对了。


还是?我不知道如果我真的正确的跟踪问题下来。我只是在github repo中编写代码,而没有实际运行编译器的检测版本并跟踪其执行,正如明智的步骤3所讨论的那样,它试图弄清楚您遇到的问题。

更糟糕的是,当我运行编译器时,它是一个旧的编译器,而我一直在研究的代码却是master...


为什么这样做?

(*,*).tail('1') # OK
Run Code Online (Sandbox Code Playgroud)

为此的代码路径可能是此方法。该参数$n不是a,Callable因此代码路径将通过$n以下行中使用的路径运行:

              nqp::unless(
                nqp::istype($n,Whatever) || $n == Inf,
                $iterator.skip-at-least(nqp::elems($!reified) - $n.Int)
Run Code Online (Sandbox Code Playgroud)

$n == Inf不应该是一个问题。该==会迫使其操作数数字和应该照顾$n'1'

nqp::elems($!reified) - $n.Int不应该是一个问题,无论是。

nqp ops doc显示nqp::elems始终返回int。因此,这归结为int - Int应该有效的。

这些线A怪显示,.Int最后一行中只加3个月前

因此,抓住稻草,如果尝试以下操作会发生什么:

(my int $foo = 1) - '1' # OK
Run Code Online (Sandbox Code Playgroud)

不,那不是问题。

看来这条路已经变冷了,或者我已经偏离了实际的执行路径。

我将发布我所拥有的。也许其他人可以从这里拿起它,或者我将在一三天内再去一次...