Special closure use-cases: Why use closures?
Update
I am designing an experimental programming language and the question is wether to include closures or just use first-class-functions. To decide this i need realistic use-cases/examples that show the benefit of closures over first-class-functions. I know that you can achieve everything that you can achieve with one of the two without them, but there are several use-cases for e.g. first-class-functions where the code is easier to read (e.g. shorter or not split up into several classes). E.g:
Ruby:
[1,5,7].map{|x| x*x }
开发者_运维问答[1,'test',3].select{|x| x.kind_of? Integer}.map{|x| x.to_s }
big_array.each{ |item| puts item }
Without first-class-functions these examples would be a lot more verbose, since you would have to use for-loops or similar things.
Now, what use-cases show the usefulness of closures? Even though i use first-class-functions a lot, i really could not come up with good use-cases for closures. Do you have any good use-cases for closures?
Original Post
I dont get why closures bind to variables and not just to values, e.g.:
Ruby:
x = 5
l = lambda { x }
l.call #=> 5
x = 100
l.call #=> 100
Whats the use in referencing variables instead of just referencing the values stored in the variables at the point of definition of the closure? Like in this example:
Ruby:
x = 5
l = lambda { x }
l.call #=> 5
x = 100
l.call #=> 5, not 100
Are there good use-cases where it is necessary to reference variables instead of just the values of those variables at the point of definition of the closure?
The whole point of a closure is that the closed-over state can change. Arguably, closing over something that doesn't (or can't) change is bad form, because you're hiding a parameter.
Take the following contrived example, in C#:
var sb=new StringBuilder();
int counter = 0;
var Append=(int a, string s)=>
sb.Append(a*a + counter++, SomethingElse(s, "some constant"));
Append
closes over the StringBuilder and the counter so that I can sprinkle calls to it through my code rather than having to go through the SomethingElse
and sb.Append
ceremony every time. Closures would be less useful for this kind of thing if the state inside them couldn't change.
From what I understand (someone please help me out if I'm wrong) using a variable within a lambda expression changes a variable (say "Foo as Widget") into a New Holder(Of Widget), defined as shown below, and changes all references to Foo into references to Foo.Value. The holders for closed-over variables are then passed as parameters to a delegate factory.
Class Holder(Of T) Public Value As T Sub New(NewValue As T) Value = NewValue End Sub End Class
I'm not quite sure how often the extra layer of wrapping is really useful. I would think it more common that one would want to grab local variables by value. In my own code, before I upgraded to a version of VB which supported lambdas, I used delegate factories, e.g.
Sub SetText(ByVal St As String) Text = St End Sub ... elsewhere MyControl.BeginInvoke(NewInv(AddressOf SetText, someExpression))
Note that someExpression will be evaluated when the BeginInvoke itself is executed, not when the deferred action is actually performed. Note also that my NewInv() family of functions supports generic overrides of 1-4 parameters, and that if one needs an Action(Of T) rather than a MethodInvoker, I have a generic static class with another family of functions for that.
One advantage of this approach, btw: it works with edit/continue.
精彩评论