Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
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?

Replies are listed 'Best First'.
Re: Closure Explanation
by AnomalousMonk (Chancellor) 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 02:16 UTC
    sub make_counter { my $start = shift; return sub { warn \$start; $start++ } }
Re: Closure Explanation
by Anonymous Monk on Apr 30, 2010 at 18:35 UTC
    Is callback the same as closure in Perl?
      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.

      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?

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?
[Corion]: ... that's not that great for quasi-disposable devices ;)
[Eily]: can't you just remote connect to the linux machine ?
[marto]: IIRC the hiemdal suite made life much easier on windows, and people on XDA developers put out released of windows only pages for adb that made it less of a pain
[marto]: Eily you can't remote connect the physical device via USB ;)
[Corion]: Eily: Sure, that's what I do, but some things you need to do on the Android device directly, like when navigating the bootloader :-)
[Eily]: marto you just need a longer cable :P
[Corion]: marto: Yeah, but I'm somewhat wary of installing random USB drivers downloaded from mega.nz , Google Drive or whatever, so Linux wins there due to there being no conflicts and me just having to edit one text file in the worst case, to add the USB vendor
[hippo]: Long USB cable FTW.
[Corion]: Eily: I've thought of that, but I don't like running long cables through the appartment because sooner or later I'll trip over it, pulling at least one device off its stand :)
[marto]: hmm, may have to patch CPAN::Meta to move from search.cpan to metacpan in the META.json/yml files

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (10)
As of 2018-05-23 09:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?