我真的很欣赏 Raku 的&?BLOCK
变量——它可以让你在一个未命名的块中递归,这非常强大。例如,这是一个简单的内联匿名阶乘函数:
{ when $_ ≤ 1 { 1 };
$_ × &?BLOCK($_ - 1) }(5) # OUTPUT: «120»
但是,在更复杂的情况下使用它时,我有一些疑问。考虑这段代码:
{ say "Part 1:";
my $a = 1;
print ' var one: '; dd $a;
print ' block one: '; dd &?BLOCK ;
{
my $a = 2;
print ' var two: '; dd $a;
print ' outer var: '; dd $OUTER::a;
print ' block two: '; dd &?BLOCK;
print "outer block: "; dd &?OUTER::BLOCK
}
say "\nPart 2:";
print ' block one: '; dd &?BLOCK;
print 'postfix for: '; dd &?BLOCK for (1);
print ' prefix for: '; for (1) { dd &?BLOCK }
};
这会产生这个输出(我已经缩短了块 ID):
Part 1:
var one: Int $a = 1
block one: -> ;; $_? is raw = OUTER::<$_> { #`(Block|…6696) ... }
var two: Int $a = 2
outer var: Int $a = 1
block two: -> ;; $_? is raw = OUTER::<$_> { #`(Block|…8496) ... }
outer block: -> ;; $_? is raw = OUTER::<$_> { #`(Block|…8496) ... }
Part 2:
block one: -> ;; $_? is raw = OUTER::<$_> { #`(Block|…6696) ... }
postfix for: -> ;; $_ is raw { #`(Block|…9000) ... }
prefix for: -> ;; $_ is raw { #`(Block|…9360) ... }
这就是我不明白的地方:为什么&?OUTER::BLOCK
引用(基于其ID)阻止两个而不是阻止一个?正确使用OUTER
with$a
会导致它引用外部范围,但同样的事情不适用于&?BLOCK
. 只是不能使用OUTER
with&?BLOCK
吗?如果没有,有没有办法从内部块访问外部块?(我知道我可以分配&?BLOCK
给外部块中的命名变量,然后在内部块中访问该变量。我认为这是一种解决方法,但不是完整的解决方案,因为它牺牲了引用未命名块的能力,这就是的大部分&?BLOCK
力量来自于。)
其次,我对第 2 部分感到非常困惑。我明白为什么&?BLOCK
前缀 for 后面的那个是指内部块。但是为什么&?BLOCK
在后缀 for 之前的那个也指的是它自己的块呢?是否在 for 语句的主体周围隐式创建了一个块?我的理解是后缀形式在很大程度上很有用,因为它们不需要块。这是不正确的吗?
最后,为什么有些块OUTER::<$_>
在其中而有些则没有?我对第 2 块特别困惑,它不是最外面的块。
提前感谢您提供的任何帮助!(如果上面显示的任何代码行为表明存在 Rakudo 错误,我很乐意将其写为问题。)