我以为在一个程序的顶层中, will end
和 will 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';
重写
为什么
不同will end
的行为与will leave
看起来will end
的错误类似于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]
will end
的块范围与will leave
的块范围不同?
它们具有相同的外部词汇范围,与UNIT
范围对应。
它们以不同的 dynamic 范围运行。留下块作为离开封闭块的一部分。在编译器完全完成您的代码并进行清理后,最终块运行:
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()
}
}
为什么
END
块的行为与will end
块有所不同?
因为您将$foo
用于一种,另一个使用$_
。