似乎动态变量并不总是在线程中的子例程调用中幸存下来:
sub foo($x, &y = &infix:<+>) {
my &*z = &y;
bar($x);
}
sub bar ($x) {
say &*z($x,$x);
my $promise = start { bar($x-1) if $x > 0 }
await $promise;
# bar($x-1) if $x > 0 # <-- provides the expected result: 6, 4, 2, 0
}
foo(3); # 6, 4, Dynamic variable &*z not found
使用更全局范围的变量也有效,因此并不是所有变量都丢失了 - 它似乎特定于动态:
our &b;
sub foo($a, &c = &infix:<+>) {
&b = &c;
bar($a);
}
sub bar ($a) {
say &b($a,$a);
my $promise = start { bar($a-1) if $a > 0 }
await $promise;
}
foo(3); # 6, 4, 2, 0
一旦在
foo()
中设置了变量, 在 bar()
中读取没有问题.但是当 bar()
从 promise 内部调用,&*z
的值不是在第一层递归而是在第二层消失。我感觉到一个错误,但也许我在递归/动态变量/线程之间做一些奇怪的事情,这让事情变得一团糟。
最佳答案
在当前语义下,start
将捕获它被调用的上下文。如果动态变量查找在线程堆栈上失败 start
在(线程池中的一个)上执行,然后它会回退到查看 start
时捕获的动态范围块被安排。
当start
块是在另一个 start
的执行过程中创建的块,同样的事情发生。但是,两者之间没有关系,这意味着“外部”start
捕获的上下文块也不会被搜索。虽然人们可以争辩说这种情况发生,但这样做似乎有潜在的问题。考虑这个例子:
sub tick($n = 1 --> Nil) {
start {
await Promise.in(1);
say $n;
tick($n + 1);
}
}
tick();
sleep;
这是一种(不完全是惯用的)每秒产生一次滴答声的方式。被内
start
为了保持对外部状态的引用,出于动态变量查找的目的,该程序将在内存中建立一个长度不断增加的链,这似乎是一种不受欢迎的行为。
关于multithreading - 动态变量和 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57581749/