这里适当关闭是什么意思

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并且应该抛出错误?

ben*_*kah 7

正如其他人所提到的那样,食谱使用术语"正确"来指代这样一个事实,即创建一个子程序,该子程序带有一个来自更高词汇范围的变量,并且该变量不再能通过任何其他方式达到.我使用过度简化的助记符"访问$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"


yst*_*sth 6

我认为"正确关闭"只是意味着一个封闭.如果$ name不是词法,则所有subs将引用相同的变量(其值将被重置为for循环之前的任何值,如果有的话).

*$name正在使用$ name的值作为有趣的解除引用*sigil的参考.因为$ name是一个字符串,所以它是一个符号引用(因此没有严格的'refs').