Quick and dirty closure example:
sub counter { my $start_value = shift; return sub { return $start_value++; } }
This is a subroutine that returns a new anonymous subroutine. That new subroutine references a lexical variable in an enclosing block. Now: when the subroutine exits, normally there'd be no more references to that variable, so it would disappear. But since the newly-returned subroutine has a reference to it (remember, you're allowed to see lexicals in a scope that encloses you), the new subroutine can still use the variable, even though no other code can directly address it (yeah, we can use cpan:Padwalker or something similar, but that's not really germane to the discussion).

Anyway. We've now got this new subroutine; it's called a closure because the block that is the subroutine can reference this otherwise-invisible variable - sometimes you hear it said that the sub has closed over the lexical variable.

my $counter1 = counter(5); my $counter2 = counter(20); print $counter1->(), $counter1->(), $counter1->(),"\n"; print $counter2->(),"\n"; print $counter1->(),"\n";
and we get
567 20 8
Notice that each closure preserves its own copy of the closed-over variable.

So big deal. Hidden variable. So what?

The big deal is twofold: one, the variable is completely controlled by the closure now and its state is carried along with the closure. So You can only look at the variable via the closure's interface. Second, and this is the really useful part, calling the counter sub again with a new starting value manufactures a completely new and separate closure! So you can create as many counters as you like; they all use the same code, but each one tracks its own internal state.

One of the really useful things to use this for is being able to "half-call" a subroutine (Technically, I think this is an example of currying, but let's use "half-call" for the sake of explanation.)

Let's say you had a subroutine that you knew some of the information you'd need to call it at one point, but wouldn't know the rest of the information until later. One way to do this is to build a hash, store the data, run until you have the rest, then call the sub after looking up the appropriate data. Not too complicated, but it does clutter the flow a bit.

We could instead build a closure at the point we have the first set of data:

sub build_one { my($foo, $bar, $baz) = @_; return sub { my $quux = shift; do_something($foo, $bar, $baz, $quux); } } # Figure out first three args... push @queue, build_one($alpha, $beta, $gamma); # repeat as necessary.
We've done the first part of the call: setting up one or more closures with the information we know now and sticking them in the queue of stuff to finish later.

When we get the rest of the data we need, we just pull the closures off one by one and call them with the rest of the data.

map { $_->($last_thing) } @queue;
And we've finished off all the stuff we had queued up to do once we knew the last piece of data. There are loads more ways to use closures; this is just to point you in the direction of thinking "I can make a sub that remembers things. What can I do with that? Do I need it for this problem?"

Have the appropriate amount of fun.


In reply to Re: Closures Explained by pemungkah
in thread Closures Explained by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.