这是直接来自 Perl Cookbook :
的代码@colors = qw(red blue green yellow orange purple violet);
for my $name (@colors) {
no strict 'refs';
*$name = sub { "<FONT COLOR='$name'>@_</FONT>" };
}
它的目的是形成6个不同颜色名称的子程序。在解释部分,书中写着:
这些函数看起来都是独立的,但实际代码实际上只编译了一次。这种技术 节省了编译时间和内存使用。要创建一个正确的闭包,匿名中的任何变量 子程序必须是词法。这就是我在循环迭代变量上的原因。
正确关闭的含义是什么,如果省略my
将会发生什么?另外一个typeglob如何使用词法变量,即使为词法变量定义了typeglobs并且应该抛出错误?
答案 0 :(得分:7)
正如其他人所提到的那样,食谱正在使用术语“正确”来指代这样一个事实,即创建了一个子程序,该子程序带有一个来自更高词汇范围的变量,并且任何一个变量都无法达到其他方式。我使用过度简化的助记符“访问$color
变量'已关闭'”来记住这部分闭包。
声明“无法为词法变量定义typeglobs”误解了关于typeglobs的一些关键点。你把它读作“你不能用'我的'来创建一个类型的地球”是有道理的。请考虑以下事项:
my *red = sub { 'this is red' };
这会因为“my * red”附近出现“语法错误而死”,因为它试图使用“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";
这是合法的,输出将是
local red
red
red
在警告下,这会抱怨“Subroutine main :: red redefined”
答案 1 :(得分:6)
我认为“正确关闭”只意味着实际上是一种封闭。如果$ name不是词法,则所有subs都将引用相同的变量(其值将被重置为for循环之前的任何值,如果有的话)。
*$name
正在使用$ name的值作为引用* sigil的有趣类型的引用。因为$ name是一个字符串,所以它是一个符号引用(因此没有严格的'refs')。
答案 2 :(得分:1)
来自perlfaq7:
<强> What's a closure? 强>
关键字记录在perlref。
中关闭是一个计算机科学术语,具有精确但难以解释的含义 含义。通常,闭包在Perl中以匿名方式实现 持久引用其词外变量的子程序 自己的范围。这些词汇神奇地指的是变量 在定义子程序时(深度绑定)。
闭包最常用于编程语言中 函数的返回值本身就是一个函数,你可以 在Perl。请注意,某些语言提供匿名功能但是 无法提供适当的闭包:Python语言,用于 例。有关闭包的更多信息,请查看任何教科书 函数式编程。 Scheme是一种不仅支持的语言 但鼓励关闭。
答案继续以相当详细的方式回答这个问题。
Perl FAQs是一个很好的资源。但如果没有人读过它们,那么维护它们会有点浪费。
修改(以便更好地回答帖子中的后续问题):
1 /正确关闭是什么意思? - 见上文
2 /如果遗漏了我会怎么样? - 它不会起作用。试一试,看看会发生什么。
3 /一个typeglob如何使用词法变量? - 变量$name
仅用于定义要使用的typeglob的名称。它实际上并没有被用作类型地球。
这有用吗?