为什么 `will end` 的行为与程序级范围内的 `will leave` 不同?

Why does `will end` behave differently than `will leave` in program-level scope?

我认为在程序的顶层 will endwill leave 的行为方式相同,因为 exit/leave 只有一个大的外部作用域。我认为其中任何一个都是检查变量最终值的好方法。

但是对于 will end 它就像变量从未被初始化一样:

my $foo will end { put "Final value for $foo is '$_'"} = 'bar';

put "$foo is now '$foo'";

$foo ~= ' baz';

输出

$foo is now 'bar'
Use of uninitialized value $_ of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
  in block  at phaser_end.p6 line 1
Final value for $foo is ''

但是,只需将 will end 更改为 will leave 即可满足我对其中任何一个的期望:

my $foo will leave { put "Final value for $foo is '$_'"} = 'bar';

put "$foo is now '$foo'";

$foo ~= ' baz';

输出

$foo is now 'bar'
Final value for $foo is 'bar baz'

为什么这里的行为有所不同?

我正在使用 Rakudo-Star 2017.07.

更新

为了获得我期望的 will end 效果,我必须使用单独的 END 块:

END块:

my $foo = 'bar';

END { put "Final value for $foo is '$foo'"};

put "$foo is now '$foo'";

$foo ~= ' baz';

我想真正的问题归结为为什么 END 块的行为与 will end 块不同。

will end块:

my $foo will end { put "Final value for $foo is '$_'"} = 'bar';

put "$foo is now '$foo'";

$foo ~= ' baz';

重写

Why does will end behave differently than will leave

看起来 will end 有一个类似于 this old and now resolved bug for will begin 的错误。

除此之外,一切都如我所料:

my $leave will leave { say ['leave:', $_, OUTERS::<$leave>] } = 'leave';
my $end   will end   { say ['end:',   $_, OUTERS::<$end>]   } = 'end';
my $begin will begin { say ['begin:', $_, OUTERS::<$begin>] } = 'begin';
               END   { say ['END:',   $_, OUTERS::<$end>, $end] }

$_ = 999;

显示

[begin: (Any) (Any)]
[leave: leave leave]
[END: 999 end end]
[end: 999 end]

Is the scope for the block with will end different than the scope of the block with will leave?

它们具有与 UNIT 作用域对应的相同外部 lexical scope

他们运行在不同的dynamic scopes. Leave blocks run as part of leaving the enclosing block. End blocks run after the compiler has completely finished with your code and is cleaning up:

sub MAIN(@ARGS) {
    ...
    # UNIT scope -- your code -- is about to be created and compiled:
    $comp.command_line ...
    # UNIT scope no longer exists. We compiled it, ran it, and left it.
    ...
    # do all the necessary actions at the end, if any
    if nqp::gethllsym('perl6', '&THE_END') -> $THE_END {
        $THE_END()
    }
}

why does the END block behave differently than the will end block?

因为你在一个中使用了 $foo 而在另一个中使用了 $_