Sex*_*ast 6 perl closures subroutine typeglob lexical
这是Perl Cookbook直接推出的代码:
@colors = qw(red blue green yellow orange purple violet);
for my $name (@colors) {
no strict 'refs';
*$name = sub { "<FONT COLOR='$name'>@_</FONT>" };
}
Run Code Online (Sandbox Code Playgroud)
它的目的是形成6个不同颜色名称的子程序.在解释部分,该书内容如下:
这些函数看起来都是独立的,但实际代码实际上只编译了一次.这种技术节省了编译时间和内存使用.要创建正确的闭包,匿名子例程中的任何变量都必须是词法.这就是我在循环迭代变量上的原因.
什么是适当的闭合,如果my省略会发生什么?另外,一个typeglob如何使用词法变量,即使不能为词法变量定义typeglobs并且应该抛出错误?
正如其他人所提到的那样,食谱使用术语"正确"来指代这样一个事实,即创建一个子程序,该子程序带有一个来自更高词汇范围的变量,并且该变量不再能通过任何其他方式达到.我使用过度简化的助记符"访问$color变量是'关闭'"来记住这部分闭包.
语句"typeglobs不能为词汇变量定义"误解了关于typeglobs的一些关键点.你把它读作"你不能用'我'来创建一个类型的地球"是有道理的.考虑以下:
my *red = sub { 'this is red' };
Run Code Online (Sandbox Code Playgroud)
这将因"我的*红色"附近的"语法错误"而死亡,因为它试图使用"my"关键字定义一个typeglob.
但是,您示例中的代码并未尝试执行此操作.它定义了一个全局的typeglob,除非被覆盖.它使用词法变量的值来定义typeglob的名称.
顺便提一下,typeglob可以是词汇本地的.考虑以下:
my $color = 'red';
# create sub with the name "main::$color". Specifically "main:red"
*$color = sub { $color };
# preserve the sub we just created by storing a hard reference to it.
my $global_sub = \&$color;
{
# create a lexically local sub with the name "main::$color".
# this overrides "main::red" until this block ends
local *$color = sub { "local $color" };
# use our local version via a symbolic reference.
# perl uses the value of the variable to find a
# subroutine by name ("red") and executes it
print &$color(), "\n";
# use the global version in this scope via hard reference.
# perl executes the value of the variable which is a CODE
# reference.
print &$global_sub(), "\n";
# at the end of this block "main::red" goes back to being what
# it was before we overrode it.
}
# use the global version by symbolic reference
print &$color(), "\n";
Run Code Online (Sandbox Code Playgroud)
这是合法的,输出将是
local red
red
red
Run Code Online (Sandbox Code Playgroud)
在警告下,这将抱怨"Subroutine main :: red redefined"
我认为"正确关闭"只是意味着一个封闭.如果$ name不是词法,则所有subs将引用相同的变量(其值将被重置为for循环之前的任何值,如果有的话).
*$name正在使用$ name的值作为有趣的解除引用*sigil的参考.因为$ name是一个字符串,所以它是一个符号引用(因此没有严格的'refs').