Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Closure Explanation

by bichonfrise74 (Vicar)
on Apr 30, 2010 at 01:48 UTC ( #837669=perlquestion: print w/ replies, xml ) Need Help??
bichonfrise74 has asked for the wisdom of the Perl Monks concerning the following question:

I got this code from this article perl.com.
sub make_counter { my $start = shift; return sub { $start++ } } my $from_ten = make_counter(10); my $from_three = make_counter(3); print $from_ten->() . "\n"; print $from_ten->() . "\n"; print $from_three->() . "\n";
I tried to read the article on the explanation of the code above but I could not figure out how it is able to 'retain/remember' the old values.
Can someone further dissect or rewrite this code to show what is exactly happening?

Comment on Closure Explanation
Download Code
Re: Closure Explanation
by Anonymous Monk on Apr 30, 2010 at 02:16 UTC
    sub make_counter { my $start = shift; return sub { warn \$start; $start++ } }
Re: Closure Explanation
by AnomalousMonk (Abbot) on Apr 30, 2010 at 02:56 UTC

    See Closure on Closures (and also How A Function Becomes Higher Order and How To: Make An Iterator) and their various 'Reply' and 'Also' sections for applications, amplifications, etc.

    I don't think I could come up with an explanation better than the above or than those contained in standard references. If you still have problems, you might try asking specific questions – with examples, if possible!

    BTW: I put these refs. together using Super Search on 'closure'!

    Update: Closure may also be helpful.

Re: Closure Explanation
by almut (Canon) on Apr 30, 2010 at 06:22 UTC

    Just think of it this way: when a function closes over a lexical variable, that instance of the variable (and its associated storage location) won't be freed, as it normally would when the variable goes out of scope — i.e. it continues to remain accessible to the function.

    Note that you can (in theory) have more than one closure sharing the same variable instance (kind of their private global variable). Extending the Anonymous Monk's code:

    #!/usr/bin/perl sub make_counter_pair { my $start = shift; warn "lexical variable ".\$start." created"; return ( sub { warn "accessing ".\$start; $start++ }, sub { warn "accessing ".\$start; $start++ } ) } my ($c1, $c2) = make_counter_pair(10); my ($c3, $c4) = make_counter_pair(3); print $c1->() . "\n"; print $c2->() . "\n"; print $c1->() . "\n"; print $c2->() . "\n"; print $c3->() . "\n"; print $c4->() . "\n"; print $c3->() . "\n"; print $c4->() . "\n";

    would give

    lexical variable SCALAR(0x604ff0) created at ./837669.pl line 5. lexical variable SCALAR(0x6323f0) created at ./837669.pl line 5. accessing SCALAR(0x604ff0) at ./837669.pl line 8. 10 accessing SCALAR(0x604ff0) at ./837669.pl line 12. 11 accessing SCALAR(0x604ff0) at ./837669.pl line 8. 12 accessing SCALAR(0x604ff0) at ./837669.pl line 12. 13 accessing SCALAR(0x6323f0) at ./837669.pl line 8. 3 accessing SCALAR(0x6323f0) at ./837669.pl line 12. 4 accessing SCALAR(0x6323f0) at ./837669.pl line 8. 5 accessing SCALAR(0x6323f0) at ./837669.pl line 12. 6

    As you can see by looking at the addresses, each pair of closures shares one variable, so the respective value is incremented every time one of the two counter functions is called.

Re: Closure Explanation
by Anonymous Monk on Apr 30, 2010 at 18:35 UTC
    Is callback the same as closure in Perl?

      No, a callback need not be closed over any variables. A closure may be called by any means a normal function is.


      TGI says moo

        Do you have a sample code showing the difference between the two?

      Closure example:
      sub rtn_closure { my $i = shift; return sub { $i++ }; } # f's i starts at 5 my $f = rtn_closure(5); print $f->(),"\n"; # Prints 5 print $f->(), "\n"; # Prints 6 # g gets a separate i that starts at 10 my $g = rtn_closure(10); print $g->(), "\n"; # Prints 10 print $g->(), "\n"; # Prints 11 print $f->(), "\n"; # Prints 7
      Callback example:
      sub exec_callback { my $f = shift; $f->(); } exec_callback(sub {print "hello\n"});
      Does that help? A callback does not have to close over any variables, although it could. A closure occurs whenever a function refers to a variable in an outer scope.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://837669]
Approved by AnomalousMonk
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (6)
As of 2014-09-19 04:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (129 votes), past polls