views:

40

answers:

2

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?

A: 

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.

DDaviesBrackett
I think you misunderstood me (or i misundertood your answer :P): Look at the first example i posted. I assign a new value to the variable x that is defined outside the closure. Though this assignment happens *after* the closure has been defined the closure uses the *new* value of x (100 instead of 5). Why doesnt the closure just use the value assigned to x at the point where the closure is defined?
Ragmaanir
@Ragmaanir because that's the whole point of a closure! if it used the value the variable had when it was defined, then it'd have the same meaning as a parameter. If that's the behaviour you want, pass the value as a parameter rather than closing over the variable.
DDaviesBrackett
@DDaviesBrackett: I dont see how this would be the same as a parameter. IMO it would be like a constant because you cant replace the value when invoking the closure. Parameters though can be passed on each invocation. The reason to not use parameters is because you *have* to pass them on each invocation. But what are use cases where you need the closure to recognize the reassignments to a variable *after* the closure has been defined? In your example this is used (only) for the counter variable i think. Is this behavior perhaps intended for *non-mutable* values (like int)?
Ragmaanir
A: 

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.

supercat