gpt4 book ai didi

perl - 闭包中的局部变量可见性与局部 `sub` s

转载 作者:行者123 更新时间:2023-12-05 08:45:28 26 4
gpt4 key购买 nike

Perl 5.18.2 似乎接受“本地子程序”。

例子:

sub outer()
{
my $x = 'x'; # just to make a simple example

sub inner($)
{
print "${x}$_[0]\n";
}

inner('foo');
}

如果没有“本地子程序”,我会这样写:

#...
my $inner = sub ($) {
print "${x}$_[0]\n";
}

$inner->('foo');
#...

最重要的是,我认为两者是等价的。

然而,第一个变体并没有像 Perl 提示的那样工作:

Variable $x is not available at ...

其中 ... 描述了 $x 在“本地子程序”中引用的行。

谁能解释一下; Perl 的本地子程序与 Pascal 的本地子程序有根本的不同吗?

最佳答案

问题中的术语“本地子程序”似乎指的是lexical subroutines .这些是私有(private)子程序,仅在定义它们的范围( block )内可见,在定义之后;就像私有(private)变量一样。

但它们是用mystate定义(或预先声明)的,如my sub subname { ... }

只是在另一个里面写一个 sub subname { ... } 并不能使它成为“本地”(在任何版本的 Perl 中),但它被编译就像它是一起写的一样其他子例程并放置在它们包的符号表中(例如 main::)。


问题提到 closure在标题中,这是对此的评论

A closure in Perl是程序中的一个结构,通常是一个标量变量,具有对子的引用,并且在其(运行时)创建时从其范围携带环境(变量)。另见 perlfaq7 entry在上面。乱解释。例如:

sub gen { 
my $args = "@_";

my $cr = sub { say "Closed over: $args, my args: @_" }
return $cr;
}

my $f = gen( qw(args for gen) );

$f->("hi closed");
# Prints:
# Closed over: args for gen, my args: hi closed

匿名子“关闭”了定义它的范围内的变量,从某种意义上说,当它的生成函数返回其引用并超出范围时,由于该引用的存在,这些变量仍然存在。由于匿名 sub 是在运行时创建的,因此每次调用其生成函数并重新创建其中的词法时,anon sub 也是如此,因此它始终可以访问当前值。因此,返回的对 anon-sub 的引用使用词法数据,否则这些数据将消失。一点魔法。

回到“本地”潜艇的问题。如果我们想对问题引入实际的闭包,我们需要从 outer 子例程返回一个代码引用,比如

sub outer {
my $x = 'x' . "@_";
return sub { say "$x @_" }
}
my $f = outer("args");
$f->( qw(code ref) ); # prints: xargs code ref

或者,根据主要问题,如 v5.18.0 中所述从 v5.26.0 稳定,我们可以使用命名的词法(真正嵌套!)子例程

sub outer {
my $x = 'x' . "@_";

my sub inner { say "$x @_" };

return \&inner;
}

在这两种情况下,my $f = outer(...); 都有从 outer 返回的代码引用,它正确地使用了局部词法变量 ($ x),以及它们的最新值。

但是我们不能在 outer 内部使用普通命名的 sub 作为闭包

sub outer {
...

sub inner { ... } # misleading, likely misguided and buggy

return \&inner; # won't work correctly
}

这个 inner 是在编译时创建的,并且是全局的,因此它从 outer 使用的任何变量都将从 outer 被烘焙时得到它们的值第一次打电话。所以 inner 只有在 outer 被下一次调用时才是正确的——当 outer 中的词法环境被重新创建但 inner 没有。例如,我可以很容易地找到 this post , 并查看条目 in perldiag (或将 use diagnostics; 添加到程序中)。


在我看来,在某种程度上,这是一个穷人的对象,因为它具有功能和数据,是在其他时间在其他地方制作的,并且可以与传递给它的数据一起使用(两者都可以待更新)

关于perl - 闭包中的局部变量可见性与局部 `sub` s,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72656597/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com