&?ROUTINE 的_intended_ 值是多少?
What is the _intended_ value of &?ROUTINE?
Raku 的 Rakudo 实现跟踪了多个关于(非常有用!)&?ROUTINE 变量未提供正确值(例如,#1768 and 2362)的问题,因此我意识到它的行为不太正确。但我试图了解它的预期行为是什么——这似乎是解决该行为的重要第一步。
运行 此代码与 Rakudo v2021.06 生成注释中注明的输出。此输出的哪些部分是正确的,哪些是错误?
sub foo {
note '## ifs:';
do if True { say &?ROUTINE.name } # OUTPUT: «foo»
if True { say &?ROUTINE.name } # OUTPUT: «<unit>»
note '## ifs w/ topic:';
do if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«""»
if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«foo»
note '## fors:';
for 1 { say &?ROUTINE.name } # OUTPUT: «foo»
say &?ROUTINE.name for 1; # OUTPUT: «""»
note '## methods:';
42.&{ say &?ROUTINE.name } # OUTPUT: «foo»
my method m($a:) { say &?ROUTINE.name }
42.&m; # OUTPUT: «m»
}
foo
relevant docs 说 &?ROUTINE returns“Sub 的一个实例”,这听起来好像以上所有内容都应该是 'foo'。另一方面,方法是例程,所以我有点倾向于认为最后两个(匿名方法和命名方法)应该 而不是 是 'foo' .我也不确定是否所有的 '' 和 "" 值都代表错误,或者是否有一个原则在起作用,使某些(或全部?)这些预期行为成为可能。
(我还用 use soft
pragma 测试了上面的代码,以确保内联没有产生我可以用那个 pragma 修复的效果;它对输出没有影响)
&?ROUTINE
符号的计算结果应该是表示最近的词法封闭例程的对象 - 即最近的 Routine
类型的封闭声明。这包括 Sub
和 Method
。此外,鉴于这些原则上都是闭包,它应该评估例程的正确闭包克隆。
因此正确的实现会产生:
sub foo {
note '## ifs:';
do if True { say &?ROUTINE.name } # OUTPUT: «foo»
if True { say &?ROUTINE.name } # OUTPUT: «foo»
note '## ifs w/ topic:';
do if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«foo»
if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«foo»
note '## fors:';
for 1 { say &?ROUTINE.name } # OUTPUT: «foo»
say &?ROUTINE.name for 1; # OUTPUT: «foo»
note '## methods:';
42.&{ say &?ROUTINE.name } # OUTPUT: «foo»
my method m($a:) { say &?ROUTINE.name }
42.&m; # OUTPUT: «m»
}
foo
当前的 Rakudo 在许多情况下都犯了这个错误。尽管在编译器方面进行了大量工作,但我并不能很好地猜测它在这里做什么;我知道当我开始在我正在开发的新编译器前端中添加 &?ROUTINE
支持时,我不会复制当前的实现!
根据@Larry 的规范[1]:
&?ROUTINE
is always an alias for the lexically innermost Routine
(which may be a Sub
, Method
, or Submethod
) ...
You can get the current routine name by calling &?ROUTINE.name
. Outside of any [routine] declaration, this call returns failure.
Note that &?ROUTINE
refers to the current single [routine], even if it is declared multi
. To redispatch to the entire suite under a given short name, just use the named form to call the proto, since there are no anonymous multi
s.
脚注
[1] "@Larry" is/was 历史 shorthand 不断发展的事实上的 Raku 设计团队。 “spec”is/was 历史 shorthand 用于不断发展的设计。以上引自S06段The &?ROUTINE object
Raku 的 Rakudo 实现跟踪了多个关于(非常有用!)&?ROUTINE 变量未提供正确值(例如,#1768 and 2362)的问题,因此我意识到它的行为不太正确。但我试图了解它的预期行为是什么——这似乎是解决该行为的重要第一步。
运行 此代码与 Rakudo v2021.06 生成注释中注明的输出。此输出的哪些部分是正确的,哪些是错误?
sub foo {
note '## ifs:';
do if True { say &?ROUTINE.name } # OUTPUT: «foo»
if True { say &?ROUTINE.name } # OUTPUT: «<unit>»
note '## ifs w/ topic:';
do if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«""»
if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«foo»
note '## fors:';
for 1 { say &?ROUTINE.name } # OUTPUT: «foo»
say &?ROUTINE.name for 1; # OUTPUT: «""»
note '## methods:';
42.&{ say &?ROUTINE.name } # OUTPUT: «foo»
my method m($a:) { say &?ROUTINE.name }
42.&m; # OUTPUT: «m»
}
foo
relevant docs 说 &?ROUTINE returns“Sub 的一个实例”,这听起来好像以上所有内容都应该是 'foo'。另一方面,方法是例程,所以我有点倾向于认为最后两个(匿名方法和命名方法)应该 而不是 是 'foo' .我也不确定是否所有的 '' 和 "" 值都代表错误,或者是否有一个原则在起作用,使某些(或全部?)这些预期行为成为可能。
(我还用 use soft
pragma 测试了上面的代码,以确保内联没有产生我可以用那个 pragma 修复的效果;它对输出没有影响)
&?ROUTINE
符号的计算结果应该是表示最近的词法封闭例程的对象 - 即最近的 Routine
类型的封闭声明。这包括 Sub
和 Method
。此外,鉴于这些原则上都是闭包,它应该评估例程的正确闭包克隆。
因此正确的实现会产生:
sub foo {
note '## ifs:';
do if True { say &?ROUTINE.name } # OUTPUT: «foo»
if True { say &?ROUTINE.name } # OUTPUT: «foo»
note '## ifs w/ topic:';
do if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«foo»
if True -> $a { say $a; say &?ROUTINE.name } # OUTPUT: «True», # OUTPUT«foo»
note '## fors:';
for 1 { say &?ROUTINE.name } # OUTPUT: «foo»
say &?ROUTINE.name for 1; # OUTPUT: «foo»
note '## methods:';
42.&{ say &?ROUTINE.name } # OUTPUT: «foo»
my method m($a:) { say &?ROUTINE.name }
42.&m; # OUTPUT: «m»
}
foo
当前的 Rakudo 在许多情况下都犯了这个错误。尽管在编译器方面进行了大量工作,但我并不能很好地猜测它在这里做什么;我知道当我开始在我正在开发的新编译器前端中添加 &?ROUTINE
支持时,我不会复制当前的实现!
根据@Larry 的规范[1]:
&?ROUTINE
is always an alias for the lexically innermostRoutine
(which may be aSub
,Method
, orSubmethod
) ...You can get the current routine name by calling
&?ROUTINE.name
. Outside of any [routine] declaration, this call returns failure.Note that
&?ROUTINE
refers to the current single [routine], even if it is declaredmulti
. To redispatch to the entire suite under a given short name, just use the named form to call the proto, since there are no anonymousmulti
s.
脚注
[1] "@Larry" is/was 历史 shorthand 不断发展的事实上的 Raku 设计团队。 “spec”is/was 历史 shorthand 用于不断发展的设计。以上引自S06段The &?ROUTINE object