string - Perl 6 中的“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)); };
}
只要我使用默认列表,只需在提示符处按回车键而不输入任何内容,结果就可以了。但是如果我输入一个数字,它会给出这个错误:
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 可能应该按照使用Rakudo Perl 6 的代码中say
的说明来跟踪编译器的执行,例如通过在其源代码中粘贴s 并重新编译它。
您可能还想尝试App::MoarVM::Debug。(我没有。)
使用这些方法,您将有能力以绝对精确的方式跟踪编译器对您抛出的任何代码所做的事情。我建议你这样做,即使我没有这样做。也许你能弄清楚我哪里出错了。
在下文中,我通过直接探索 Rakudo 编译器的源代码来跟踪这个问题。
在Rakudo 源中搜索“方法尾”得到 4 个匹配项。对于我的高尔夫来说,匹配方法是在core/AnyIterableMethods.pm6
.
tail
参数$n
显然不是 aCallable
所以继续我们探索的相关线路是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
解释为什么'0'
有效。<=
运算符在进行数值比较之前将其操作数强制为数值。所以'0'
强制到0
,条件是True
,结果是Rakudo::Iterator.Empty
,并且Any.tail('0')
产量()
和不抱怨。
紧跟以上三行的代码是nqp::if
. 它以 结束nqp::create(self)!SET-SELF(iterator,n,f)
。
这反过来又调用了!SET-SELF
例程,该例程具有以下行:
($!lastn := nqp::setelems(nqp::list, $!size = size)),
size
哪个尝试分配'1'
给$!size
. 但是$!size
被声明为:
has int $!size;
答对了。
或者是吗?我不知道我是否真的正确地追踪了问题。我只是在 github 存储库中挖掘代码,而不是实际运行编译器的检测版本并跟踪其执行,正如在尝试找出您遇到的问题的明智步骤 #3 中所讨论的那样。
更糟糕的是,当我运行一个编译器时,它是一个旧的,而我正在探索的代码是master
......
为什么这行得通?
(*,*).tail('1') # OK
这个的代码路径大概就是这个方法。该参数$n
不是 aCallable
所以代码路径将通过在行中使用的路径运行$n
:
nqp::unless(
nqp::istype($n,Whatever) || $n == Inf,
$iterator.skip-at-least(nqp::elems($!reified) - $n.Int)
$n == Inf
应该问题不大。将==
强制其操作数为数字,这应该照顾$n
being '1'
。
nqp::elems($!reified) - $n.Int
应该也不成问题。
nqp ops 文档显示nqp::elems
始终返回int
. 所以这归结为int - Int
应该起作用的。
唔。
这些行的责备表明,最后一行中的the.Int
仅在 3 个月前添加。
所以,抓住稻草,如果一个人尝试会发生什么:
(my int $foo = 1) - '1' # OK
不,这不是问题。
看来这条线索已经变冷了,或者更确切地说,我已经偏离了实际的执行路径。
我会发布我所拥有的。也许其他人可以从这里拿走,或者我会在一三天内再去一次……
推荐阅读
- python - 具有多个关键字参数的函数的 Joblib 并行化
- javascript - 如何在 addEventListner 方法之外访问变量值?
- react-native - 如何使用 React 导航 5.X 将堆栈导航与底部选项卡导航器一起使用
- android - Kotlin Coroutines viewModelScope 中的改造调用
- ios - 以更高的分辨率将 UILabel 渲染到 UIImage
- deep-learning - 在 deeplearning4j 中运行 ResNet 时出现异常
- python - Netmiko 和 Textfsm 路径和环境问题窗口
- reinforcement-learning - Q Learning 中如何表示 n 维向量状态向量?
- r - 从数据框创建 sf 多边形
- javascript - 比较 JavaScript 中的两个变量字符串