perl - 此处正确关闭是什么意思

标签 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个具有不同颜色名称的不同子例程。该书在解释部分中写道:

These functions all seem independent, but the real code was in fact only compiled once. This technique saves on both compile time and memory use. To create a proper closure, any variables in the anonymous subroutine must be lexicals. That's the reason for the my on the loop iteration variable.



正确关闭的意思是,如果省略my会发生什么?再加上即使无法为词法变量定义typeglob,typeglob如何与词法变量一起使用,也应该引发错误?

最佳答案

正如其他人提到的那样,本食谱使用术语“适当”来指代这样的事实:创建了一个子例程,该子例程带有一个带有较高词法范围的变量,并且该变量不能再通过其他任何方式来获得。我使用过度简化的助记符“已关闭对$color变量的访问”来记住这部分闭包。

语句“不能为词法变量定义typeglob”会误解有关typeglob的一些关键点。您将其读为“您不能使用'my'来创建typeglob”在某种程度上是对的。考虑以下:

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

在警告下,它将提示“子程序main::red重新定义”

关于perl - 此处正确关闭是什么意思,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12058075/

相关文章:

swift - Swift 中的闭包如何在幕后捕获变量?

arrays - Perl中的子程序递归

Fortran 子例程 : How to load data only on first call

Perl:GD:SecurityImage,角度属性不起作用

perl - 难以将 Perl 脚本作为 Bash 别名运行

perl - Perl-由打印中未初始化的值引起的错误

javascript - 在 javascript 对象中调用私有(private)方法

sql - DBI 准备好的语句 - 绑定(bind)十六进制通配符字符串

swift - 变量未保存在闭包之外

perl - 在Perl中,是否有一种方法可以从自身内部重新启动当前正在运行的程序?