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.
| [reply] |
|
> 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.
| [reply] |
|
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".
| [reply] |
|
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.
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! | [reply] [d/l] [select] |
|
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.
| [reply] [d/l] |
|
Oh, I thought you meant "callback" by "delegate". They account for many closures.
| [reply] |
|
So did you get enough RL examples of closures or did you mean to ask about functional programming in general?
| [reply] |
|
|
|
|
|
|
> (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?
| [reply] [d/l] [select] |
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.
| [reply] |
Re: Real life uses for closures.
by DrHyde (Prior) on Feb 12, 2013 at 12:13 UTC
|
| [reply] |
|
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.
| [reply] [d/l] |
|
| [reply] |
|
|
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.
| [reply] |
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
| [reply] |
|
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.
| [reply] |
|
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.
| [reply] |
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. | [reply] |
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.
| [reply] |
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". | [reply] [d/l] [select] |