string - Perl 6 中的 “P6opaque, Str” 与简单的 “Str” 类型

标签 string int tail raku

这是my previous question的后续.

我终于能够在这里重现错误:

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)); };
}

只要我使用默认列表,只需在提示符下按回车键而不输入任何内容,结果就可以了。但是如果我输入一个数字,它会出现这个错误:
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

如果 tail("2") 有效,为什么 tail($x) 失败?此外,在我的原始代码中, tail($x.Int) 不会纠正问题,但在这里确实如此。

最佳答案

这充其量是一个答案。这是迄今为止解决这个问题的失败尝试。我可能只是在杂草中徘徊。但我会公布我所拥有的。如果不出意外,也许它可以提醒以下前三个步骤是明智的;此后,当我通过直接调试编译器(如第三步中讨论的那样)可能会取得更快、更可靠的进展时,我正在赌我通过挖掘源代码继续前进的能力。

好的,第一步是 MRE .你提供的是一个完全 R 和足够 M 的 E。:)

第 2 步是增加 M(打高尔夫球)。我把它归结为:

Any.tail('0');    # OK
Any.tail('1');    # BOOM

请注意,它可以是实际值:
1.tail('1');      # BOOM
(1..2).tail('1'); # BOOM

但有些值是有效的:
(1,2).tail('1');  # OK

第 3 步可能应该按照 Playing with the code of Rakudo Perl 6 中的说明进行操作。跟踪编译器的执行,例如通过粘贴 say s 在其源代码中并重新编译它。

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

使用这些方法,您将有能力绝对精确地跟踪编译器对您抛出的任何代码所做的事情。我建议你这样做,即使我没有这样做。也许你能弄清楚我哪里出错了。

在下文中,我通过直接挖掘 Rakudo 编译器的源代码来追踪这个问题。

search for "method tail" in the Rakudo sources产生了 4 场比赛。对于我的高尔夫,匹配方法是 a match in core/AnyIterableMethods.pm6 .
tail参数 $n显然不是 Callable所以继续我们洞穴探险的相关线路是 Rakudo::Iterator.LastNValues(self.iterator,$n,'tail') .

对此进行搜索会导致 this methodcore/Iterator.pm6 .

这反过来调用 this .new routine .

These three lines :
nqp::if(
  n <= 0,                 # must be HLL comparison
  Rakudo::Iterator.Empty, # negative is just nothing

解释原因 '0'作品。 <=运算符在进行数字比较之前将其操作数强制转换为数字。所以'0'强制到 0 ,条件为 True ,结果是 Rakudo::Iterator.Empty ,以及 Any.tail('0') yield ()并且不提示。

紧跟在上面三行之后的代码是nqp::if的else分支.它以 nqp::create(self)!SET-SELF(iterator,n,f) 结束.

这反过来又调用了 !SET-SELF例程,其中有一行:
($!lastn := nqp::setelems(nqp::list, $!size = size)),

哪个尝试分配 size ,在我们的 BOOM 案例中是 '1' , 至 $!size .但是 $!size is declared as :
has int $!size;

答对了。

或者是吗?我不知道我是否真的正确地追踪了问题。我只是在 github 存储库中挖掘代码,实际上并没有运行编译器的检测版本并跟踪其执行情况,正如讨论的第 3 步,试图找出您遇到的问题的明智之举。

更糟糕的是,当我运行编译器时,它是旧的,而我正在探索的代码是 master ...

为什么这样做?
(*,*).tail('1') # OK

这个的代码路径大概是 this method .参数$n不是 Callable所以代码路径将通过使用 $n 的路径运行在行中:
              nqp::unless(
                nqp::istype($n,Whatever) || $n == Inf,
                $iterator.skip-at-least(nqp::elems($!reified) - $n.Int)
$n == Inf应该没有问题。 ==将其操作数强制转换为数字,这应该处理 $n正在 '1' .
nqp::elems($!reified) - $n.Int也不应该有问题。

nqp ops 文档显示 nqp::elems always returns an int .所以这归结为 int - Int哪个应该工作。

唔。

A blame of these lines显示 the .Int in the last line was only added 3 months ago .

所以,捕获稻草,如果有人尝试会发生什么:
(my int $foo = 1) - '1' # OK

不,这不是问题。

这条线索似乎已经变冷了,或者更确切地说,我已经偏离了实际的执行路径。

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

关于string - Perl 6 中的 “P6opaque, Str” 与简单的 “Str” 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57136084/

相关文章:

python - 如何实现tail -F的pythonic等价物?

php - 拖尾日志文件并将结果写入新文件

java - 在java中将美国日期转换为欧盟日期

javascript - 将数组转换为字符串,同时按对分组

C++ string.length() 奇怪的行为

c++ - atoi() 用于 int128_t 类型

string - 无法在 golang 中使用 "\n"正确拆分字符串

javascript - JSDOM 从字符串中删除尾随的新行和空格

c# - 将 10 进制数转换为 .NET 中任意进制数的最快方法?

perl - 如何跟踪远程文件?