Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do closures in Perl work?

Tags:

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  {     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"); 

So my questions are:

  1. If a variable is assigned to a function, is it automatically a reference to that function?
  2. In that above code, can I write $f = \make_saying("Howdy") instead? And when can I use the & because I tried using that in passing the parameters (&$f("world")) but it doesn't work.
  3. and lastly, In that code above how in he** did the words world and earthlings get appended to the words howdy and greetings.

Note: I understand that $f is somewhat bound to the function with the parameter howdy so that's my understanding how the world got appended. What I don't understand is the 2nd function inside. How that one operates its magic. Sorry I really don't know how to ask this one.

like image 881
Belmark Caday Avatar asked Jun 11 '13 08:06

Belmark Caday


People also ask

How does closure function work?

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.

How do you use closures?

To use a closure, define a function inside another function and expose it. To expose a function, return it or pass it to another function. The inner function will have access to the variables in the outer function scope, even after the outer function has returned.

What is closures and disadvantages of closures?

Disadvantages of closures There are two main disadvantages of overusing closures: The variables declared inside a closure are not garbage collected. Too many closures can slow down your application. This is actually caused by duplication of code in the memory.

What do closures return?

An autoclosure is a closure that's automatically created to wrap an expression that's being passed as an argument to a function. It doesn't take any arguments, and when it's called, it returns the value of the expression that's wrapped inside of it.


1 Answers

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.

like image 112
amon Avatar answered Sep 23 '22 21:09

amon