Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Real life uses for closures.

by BrowserUk (Patriarch)
on Feb 12, 2013 at 02:38 UTC ( [id://1018281]=perlquestion: print w/replies, xml ) Need Help??

BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

Besides simple C-style 'static' storage (which can now be done more easily with state variables); currying and delegates (are they essentially the same thing?); what uses do people put closures to?

I'm looking for real world examples (in Perl or other languages), rather than contrived text book examples.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re: Real life uses for closures.
by Dallaylaen (Chaplain) on Feb 12, 2013 at 09:32 UTC

    Event loop programming.

    Ever written anything with Tk or AnyEvent? Both are almost useless without closures.

    The app runs as follows: something happens in the outside world (e.g. socket receives data, or user pushes button, or timer fires), and a corresponding sub is called by the event loop engine. Such a sub is called a callback.

    Of course, if you only expect two or three kinds of events, there's no need for closures. However, in a real world app one needs to create callbacks on the fly, without knowing beforehand what exacly they whould do. And closures rock.

    PSGI

    PSGI allows returning a closure instead of immediate [200, [ header...], [body...]]. It's great if you want to answer to the user ASAP and then do some long-running stuff. Again, not useful for a hello world.

    Scope guards

    Suppose you need to free some resource after leaving a particular code section. One can surround the code with layers of eval's and rethrows. Or one can use a guard object (e.g. Guard) that does its work in DESTROY, no matter why it was destroyed. Very often the code passed to guard's constructor is a closure holding a reference to the resource in question.

    And there are much more (class method generation, infinite sequences, etc) uses of closures. However, most of them require a rather large application/module surrounding them to prove truly useful, maybe that's why textbook examples don't look convincing.

    A sub{ ... } can do, say, 95% of what string eval can, but is also perfectly controllable and predictable.

      > However, in a real world app one needs to create callbacks on the fly, without knowing beforehand what exacly they whould do. And closures rock.

      Good points, I agree with you about the use cases!

      Just your definition of closures seems to be reduced to just generating anonymous functions.

      That's not the point, the main characteristic of closures is accessing variables from the outer scope at definition/generation time, most efficiently even shared between multiple closure-functions.

      So a real-world example should include shared private variables.

      Cheers Rolf

        To be honest, at the time of my writing my "definition" of closures was "functions holding refs to outer variables". I went to re-read the wikipedia article shortly after posting.

        That said, I have yet to come across a case where several functions share the same context (aside from global variables, e.g. my $foo in the beginning of a package). If I was to design something like that (especially if the context was supposed to be mutable), I would probably end up with a class. Perl is object-oriented, after all.

        An example I could imagine was several AnyEvent callback sharing the same resource guard - where resource is not released until all callbacks have either fired, or failed. But this is, again, closer to "generation of subs" then to "use of full power of closures".

Re: Real life uses for closures. (update: disambiguation)
by LanX (Saint) on Feb 12, 2013 at 03:30 UTC
    What are "delegates"? Talking about C#?

    Most things which can be done with closures can be done with OOP and vice versa.

    I normally prefer closures because it's light weighted and works in different languages alike.

    just a very simple example of encapsulation.

    { my $var; sub getter { $var }; sub setter { $var = shift }; }

    (EDIT: Applied in Perl OO one gets private class-variables in package scope instead of public package variables!)

    In JS which "only" has prototype-kind of OO, it's possible to simulate many "classical" OO-models just by applying closure extensions. (That is having a "real" class as pattern to construct object instances.)

    TIMTOWTDI.

    Cheers Rolf

    UPDATE

    OK people, please lets get the terminology right:

    Closures are NOT synonymous for

    • anonymous functions,
    • nor for currying
    • nor do they need to be produced dynamically by a generator function!

    Closures are functions which access closed over variables from an (normally restricted) outer scope at definition time.

    Look at the example I gave, getter and setter are closures, $var is a closed over lexical variable, and because of the surrounding curlies the variable is only accessible by those closure functions.

    No currying, no anonymous functions no dynamic generation!!!

    Most of you use them every day!!!

    Whenever you define a file-scoped lexical variable then all functions within this file accessing this variable are closures!

      What are "delegates"? Talking about C#?

      I don't know C#. My use of the term delegates comes from The D programming language and is best described as a pointer to a method.

      That is, it is a pointer to a function that carries an implicit reference to an object instance. Ie. Equivalent to this in perl:

      use Some::Class; my $inst = new Some::Class(); my $delegate = sub{ Some::Class::methodName( $inst, @_ ); };
      Closures are NOT synonymous for: ... nor for currying

      Agreed. But currying is one use for closures not easily achieved without them.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Oh, I thought you meant "callback" by "delegate". They account for many closures.
        So did you get enough RL examples of closures or did you mean to ask about functional programming in general?

        Cheers Rolf

      > (EDIT: Applied in Perl OO one gets private class-variables in package scope instead of public package variables!)

      lets elaborate, in the following code you can see a simplified standard Perl class with private and public variables and methods.

      The private data is only visible and accessible within the methods because of Perl's closure mechanism.

      { package TEST_CLASS; my $private_class_var; our $public_class_var; my $private_method = sub { my ($self,@args)=@_; print "-- private_method(@args)\n"; }; sub public_method { my ($self,@args)=@_; print "- public_method(@args)\n"; $self->$private_method(7..9); } sub new { my ($class,%args)=@_; bless \%args, $class; return \%args; } } my $obj = TEST_CLASS->new(a=>1,b=>2); $obj->public_method(1..3); $obj->private_method(4..6);

      prints

      - public_method(1 2 3) -- private_method(7 8 9) Can't locate object method "private_method" via package "TEST_CLASS" a +t /tmp/tst_pkg.pl line 32.

      So, does this count as real life example?

      Cheers Rolf

Re: Real life uses for closures.
by zwon (Abbot) on Feb 12, 2013 at 05:42 UTC

    I often use closures when I need to pass a callback as a function argument. I'm not sure what do you mean by delegates, but it is always currying or partial application.

    Note also, that state doesn't support initialization in list context, so when I need this I, again, use closures.

Re: Real life uses for closures.
by DrHyde (Prior) on Feb 12, 2013 at 12:13 UTC

      Oh, and if you want something really closurey, Sort::MultipleFields. There's no clean way of doing what that does without using closures.

      The other obvious approach to that problem is to build some code using eval. In fact, I find that you can almost always replace eval with a closure.

        Technically none of the examples from Sort::MultipleFields employ closures; they just use anonymous functions. Closures "close over" a variable.

        package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Real life uses for closures.
by davido (Cardinal) on Feb 12, 2013 at 21:43 UTC

    Bytes::Random::Secure uses a closure to share the same lazily-instantiated CSPRNG across several functions while avoiding making it accessable as a package global -- for several reasons. This could be achieved through other means, such as a private accessor function with its own state variable holding onto the RNG instance. Then each of the functions that shares the same RNG would use the accessor function to obtain a reference to the RNG instance, but it would be a little less convenient to implement, and would impose a minimum Perl version requirement for no good reason, which is something I really worked hard to avoid.

    This isn't a slam-dunk endorsement of closures over state variables, since a similar outcome could be acheived using state variables with a little more work. And backward compatibility probably isn't one of the "real world" reasons you are interested in taking into consideration. But in this particular case, the simplicity that closures lend, and the advantage of backward compatibility conspired to give this approach an edge over more modern techniques.


    Dave

Re: Real life uses for closures.
by nikosv (Deacon) on Feb 12, 2013 at 18:13 UTC

    GUI wise,could use a closure for events + state. For example click a button which fires an event but also encapsulates state too, for example keeping track of how many times that button has been clicked, etc

    Could also be used for filtering data and since the question is language agnostic take a loot at Jon Skeet's The Beauty of Closures

      take a loot at Jon Skeet's The Beauty of Closures

      Thanks for the link. The content was very interesting; and right on subject for my enquiry.

      (That said, now I remember what put me of learning C#. It just as bad a Java for making your source code look like you suffer from Tourette's: Predicate ... predicate ... predicate ... predicate. :)


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Heh, reading that link, one of the basic things I've used closures for lately is filtering a list in different ways. I had one utility function that goes into a loop parsing email files from a directory (and if successful, finally returning the attachments from the one you want according to some parameters) and skipping files that it's already seen before. Then I found that in some particular case I needed to call the function multiple times and have it remember what it had seen from the previous call. So I turned the filtering function into a parameter, allowing you to maintain the hash of 'seen' email files outside of the loop in the main function (but keeping the original behaviour by default, which is what I want most of the time). Pretty basic example...but there it is.
Re: Real life uses for closures.
by Anonymous Monk on Feb 12, 2013 at 13:06 UTC
    Closures are also great for use in HTML templates. The closure provides the value of the field. It has access to values that are not otherwise exposed.
Re: Real life uses for closures.(Reply to all respondees!)
by BrowserUk (Patriarch) on Feb 12, 2013 at 17:24 UTC

    Many thanks to all respondees for making me think hard.

    There is a lot of guff written on the web about the importance of closures; mostly supported by a) largely opaque, academic arguments; b) partiality for particular languages that (first) support(ed) them; c) trivial textbook examples where their use can often be replaced by less esoteric language constructs.

    Real life examples of why they are useful are hard to find.

Re: Real life uses for closures.
by ikegami (Patriarch) on Feb 14, 2013 at 08:09 UTC
    Technically, f is a closure which captures $constant:
    package Module; my $constant = 'foo'; sub f { ... $constant ... } 1;

    Given your mention of state, this is probably not quite what you had in mind when you mentioned "simple C-style 'static' storage".

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-03-19 08:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found