Perl中的闭包如何工作?

Bel*_*day 21 perl closures

Perl的新手再次来到这里,试图closure在Perl中理解.

所以这是一个我不明白的代码示例:

sub make_saying  {
    my $salute = shift;
    my $newfunc = sub {
        my $target = shift;
        print "$salute, $target!\n";
    };
    return $newfunc;            # Return a closure
}
$f = make_saying("Howdy");      # Create a closure
$g = make_saying("Greetings");  # Create another closure
# Time passes...
$f->("world");
$g->("earthlings");
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 如果将变量赋给函数,它是否自动引用该函数?
  2. 在上面的代码中,我可以写$f = \make_saying("Howdy")吗?我什么时候可以使用,&因为我尝试使用它传递参数(&$f("world"))但它不起作用.
  3. 最后,在上面怎么在他**做的话代码worldearthlings获得追加的话howdygreetings.

注意:我知道$ f与参数的函数绑定在一起,howdy所以我理解了如何world附加.我不明白的是里面的第二个功能.那个人如何运作它的魔力.对不起,我真的不知道怎么问这个.

amo*_*mon 16

在Perl中,标量变量不能直接保存子程序,它们只能保存引用.这非常类似于标量不能保存数组或哈希,只有arrayrefs或hashrefs.

sub { ... }一个CODEREF求值,这样你就可以直接把它分配给一个标量.如果要分配命名函数(例如foo),则必须获取类似的引用\&foo.

你可以像$code->(@args)或那样调用coderefs &$code(@args).

代码

$f = \make_saying("Howdy")
Run Code Online (Sandbox Code Playgroud)

计算make_saying("Howdy")并引用返回的值.所以你得到一个指向coderef的引用,而不是coderef本身.

因此,它不能被称为&$f("world"),你需要取消引用一个额外的级别:&$$f("world").


闭包是绑定到特定环境的函数.

环境由所有当前可见的变量组成,因此闭包始终会记住此范围.在代码中

my $x;
sub foo {
  my $y;
  return sub { "$x, $y" };
}
Run Code Online (Sandbox Code Playgroud)

foo是一个封闭$x,因为外部环境包括$x.内部子是一个封闭$x$y.

每次foo执行,我们都会获得$y一个新的闭包.每次调用它时,都会返回一个不同的闭包.

执行时make_saying("Howdy"),$salute变量设置为Howdy.返回的闭包记住了这个范围.

当我们再次执行它时,再次评估make_saying("Greetings")主体make_saying.在$salute现在设置为Greetings,和内子在关闭这个变量.此变量与前一个变量分开$salute,后者仍然存在,但除第一个闭包外无法访问.

两个接待者已经关闭了单独的$salute变量.当它们被执行时,它们各自$salute仍然在范围内,并且它们可以访问和修改该值.