这里适当关闭是什么意思

时间:2012-08-21 15:16:59

标签: perl closures subroutine lexical typeglob

这是直接来自 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并且应该抛出错误?

3 个答案:

答案 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的名称。它实际上并没有被用作类型地球。

这有用吗?