How do closures in Perl work?

后端 未结 3 1397
花落未央
花落未央 2021-02-18 20:19

Newbie in Perl again here, trying to understand closure in Perl.

So here\'s an example of code which I don\'t understand:

sub make_saying  {         


        
3条回答
  •  你的背包
    2021-02-18 20:45

    In Perl, scalar variables cannot hold subroutines directly, they can only hold references. This is very much like scalars cannot hold arrays or hashes, only arrayrefs or hashrefs.

    The sub { ... } evaluates to a coderef, so you can directly assign it to a scalar variable. If you want to assign a named function (e.g. foo), you have to obtain the reference like \&foo.

    You can call coderefs like $code->(@args) or &$code(@args).

    The code

    $f = \make_saying("Howdy")
    

    evaluates make_saying("Howdy"), and takes a reference to the returned value. So you get a reference that points to a coderef, not a coderef itself.

    Therefore, it can't be called like &$f("world"), you need to dereference one extra level: &$$f("world").


    A closure is a function that is bound to a certain environment.

    The environment consists of all currently visible variables, so a closure always remembers this scope. In the code

    my $x;
    sub foo {
      my $y;
      return sub { "$x, $y" };
    }
    

    foo is a closure over $x, as the outer environment consists of $x. The inner sub is a closure over $x and $y.

    Each time foo is executed, we get a new $y and therefore a new closure. Each time it is called, a different closure is returned.

    When we execute make_saying("Howdy"), the $salute variable is set to Howdy. The returned closure remembers this scope.

    When we execute it again with make_saying("Greetings"), the body of make_saying is evaluated again. The $salute is now set to Greetings, and the inner sub closes over this variable. This variable is separate from the previous $salute, which still exists, but isn't accessible except through the first closure.

    The two greeters have closed over separate $salute variables. When they are executed, their respective $salute is still in scope, and they can access and modify the value.

提交回复
热议问题