为什么子程序在 raku 中的“返回”映射中使用时无法访问动态变量?

Jul*_*lio 10 subroutine rakudo dynamic-variables raku

似乎 aasub在映射内部使用时无法访问动态变量并且该映射被“返回”。

考虑这段代码:

sub start {
    my $*something = 'foobar';
    
    # WORKS
    say 'first say-something:';
    say-something;
    
    # WORKS
    say 'mapped say-something, no return:';
    my @foo = (^2).map({say-something});
    
    # ERROR: Dynamic variable $*something not found
    say 'mapped say-something, with return:';
    return (^2).map({say-something});
}

sub say-something {
    say $*something;
    1
}

start;
Run Code Online (Sandbox Code Playgroud)

这将输出:

first say-something:
foobar
mapped say-something, no return:
foobar
foobar
mapped say-something, with return:

Dynamic variable $*something not found
  in sub say-something at main.raku line 18
  in block <unit> at main.raku line 14
Run Code Online (Sandbox Code Playgroud)

为什么子程序无法访问动态变量?有解决方法吗?

Jul*_*lio 11

例程map惰性的,因此块直到start返回后才运行。

从文档中:

multi method map(Hash:D \hash)
multi method map(Iterable:D \iterable)
multi method map(|c)
multi method map(\SELF: &block;; :$label, :$item)
multi sub map(&code, +values)
Run Code Online (Sandbox Code Playgroud)

出于说明目的,此处包含应用于列表的示例。

对于列表,它为每个元素调用&code并按序列收集返回值并将其返回。这种情况是惰性发生的,即 仅在访问返回值时才调用&code 。

因此,在您的情况下,一旦start返回,就会对映射进行评估,因此动态变量已经超出了范围。

解决此问题的方法是通过添加来强制急切map发生.eager

return (^2).map({say-something}).eager
Run Code Online (Sandbox Code Playgroud)