The Java community has resisted closures so far, even as competing languages such as C# add them. Closures are anonymous functions with closed scope. It’s best to think of a closure as a code block that you can use as an argument, with special scoping rules. This article dives deep into Closures and uses Ruby to show how closures work.
these are easier to understand in lisp than in ruby.
The syntax for these things in Ruby is a bit nasty. Literal blocks are denoted as:
{ | args | … }
But literal blocks are not first-class objects. You can create a procedure object from a literal block with:
f = Proc.new { | args | … }
and call the result with f.call(args)
In Lisp (and most other languages with first-class closures), the literal block (ie: lambda expression) is an actual first-class object. Ie, in Python, you can do:
f = lambda x: x + 1
f(3)
Unless I’m missing something, the equivalent Ruby code is:
f = Proc.new {|x| x + 1}
f.call(3)
which isn’t as elegant.
In Ruby you can also call Proc’s using:
f[3]
which is the same as f.call(3)
And, according to WikiBooks, A Proc is a first-class object in Ruby:
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls#M…
Proc’s might be first class objects, but blocks are not Proc’s. They are syntactic structures that can be converted to Proc’s. In other languages that support closures, literal lambda expressions are first-class objects, just like literal numbers or literal strings are first-class objects.
If blocks were first-class objects in Ruby, you could do:
fun = {|x| x + 1}
just like you can do:
num = 5
lambdas are not closures. Closures have persistent scope.
In python coroutines are the closest you get to closures (new in 2.5).
By the way Ruby code blocks are also not closures…
Do you mean Python lambdas, or lambdas in general? I’m pretty sure the term “lambda” in general refers to a closure, since it derives from Lisp’s “lambda” construct, which is a closure.
“By the way Ruby code blocks are also not closures…”
Yeah they are:
irb(main):001:0> def make_proc(x)
irb(main):002:1> y = 3
irb(main):003:1> return proc { x + y }
irb(main):004:1> end
=> nil
irb(main):005:0> p = make_proc(2)
=> #<Proc:0x02c18da4@(irb):3>
irb(main):006:0> p[]
=> 5
Edited 2007-01-19 06:28
Actually the equivalent in Ruby is nearly identical to Python:
f = lambda { |x| x + 1 }
f[3]
which is just as elegant (actually I like the syntax better, but that’s just an opinion).
> these are easier to understand in lisp than in ruby.
Probably, but you’d have to understand Lisp first, which isn’t that easy (based on experience – I know a lot of students who say it’s hard as hell).
Teaching functional programming, closures, lambda expressions, and a completely unreadable syntax all at once always proves to be a mistake, but the profs do it again and again anyway…
I remember last semester I had a teacher who seemed adamant that anonymous methods in C# were bad and shouldn’t ever be used: I used them anyway .
I don’t blame you, and doing anything short of non-trivial stuff with generics in C# 2.0 is made much easier by using anonymous methods, namely the new System.Predicate constructs. It also leads to more readable code.
Just curious, did he have a reason behind not using anonymous methods?
And about time! It always drives me mad when i think: hmh, why can’t i pass the function itself? I fear FP has dented my brain 😉
Here is a closure in Lisp:
(defun g (x) (setf v x) (defun f (a) (let ((t v)) (setf v a) t)))
Hope I got the parens right
Anyway give me a Ruby or C# equivalent please…
OK here is the “same” in Python (2.5 only):
def g(x): v=x; while True: t=(yield v); if t is not None: v=t; else: raise Error
I believe Ruby has no equivalent but I might be wrong…
Read this article: http://www.theserverside.net/tt/articles/showarticle.tss?id=Anonymo…
Javascript can do closures too. I find them very useful in web development.
C# also supports keeping the scope of anonymous method. But since I’m not a LISP expert, I cannot make a direct comparison. Yet here is an example that works
void AddCounter(ProgressBar p, Button b)
{
..b.clicked += delegate {
….p.Value++;
..}
}
AddCounter(myProgressBar, myButton);
Compiler generates a special class in order to maintain the scope of the delegate (which contains value of p). So it becomes:
class Temp {
..ProgressBar p;
..
..void HandleDelegate(… on click parameters …)
..{
….p.Value++;
..}
}
As far as I know there are 3 or 4 such templates for different needs (no score variables, function parameters, local class access, etc). (Lisp and others probably maintain such internal structures too. i.e: it has to be stored somewhere)
Edited 2007-01-18 05:27
…iolanguage.com
A closure should not be mistaken with anonymous method or “code block” or a lambda expression.
A closure is not simply an anonymous method or a lambda expression. You can even create a closure with a named method.
A closure is actually a formed when “function references free variables in it´s lexical environment”. It is not the function or code block itself. It is the runtime “thing” that it is created encapsulating the function and the references to the environment.
3.times { puts “Inside the times method.” }
does not create a closure. There´s no reference inside the method/code block, to any variables on its same lexical scope.
In the same way, a lamdba expression is not in itself a closure. You will, probably, end up creating closures if you use lambda expressions, but the lambda expressions themselves are not closures and do not, necessarily imply the creation of one.
f = lambda x: x + 1
creates an anonymous function which applied to a number sums 1 to it and assigns that function to f. This does not create a closure. It is simply an anonymous function. The code inside the block does not reference anything outside its lexical scope. Just its own argument.
This
(defun g (x) (setf v x) (defun f (a) (let ((t v)) (setf v a) t)))
does create a closure, as the function f is referencing v, which is not in its own scope but in the environment of f (i.e. it is defined in g).
Closures don´t even have to imply using anonymous methods, as you can see in the example, where f has a perfectly known name.
Closures are an interesting concept, leading to complicated discussions and errors (if not handled properly). And confusing them with the simpler concept of an anonymous function or a code block does not really help people understand them.
P.D. I hope I did explain it properly, but as I´m in a bit of a hurry, please feel free to expand and/or correct me if I said something wrong.
Although Java doesn’t provided a direct method for closures you can simulate them in many(not all by any stretch) cases with inner anonymous classes. Would be better if it had them properly but it’s not a bad solution.
I personally don’t like using closures in large projects anyway. Often documentation is limited and people use single character arguments names, you don’t even have a function name to give you a clue. The closure is usually doing something which would be useful elsewhere and should be factories out into a functor.
I find that they are often a convince for getting things up and running when you don’t want to spend your time building another class or search for the code which already does it. But doesn’t aid in readability or maintainability.
Note: From the previous post I mean anonymous functions not closures. You cannot do closures in java as far as I’m aware
Edited 2007-01-18 10:59
> You cannot do closures in java as far as I’m aware
You can create closures through inner classes, though they are limited in one way: If they are nested inside a method, all accessed local variables from that method must be marked ‘final’ (they cannot be changed anymore).
As gonzalo pointed out, the point about closures is really capturing variables from the scopes where the closure is defined. If you don’t do that it is not a closure but just an anonymous function.
Closures in languages that allow mutable variables are quite useful, but also quite prone to produce difficult errors.
In purely functional languages closures are much saner and safer since they automatically have referential transparency. I think it is kind of disturbing that people rip out features from functional languages to improve their procedural or OO languages without understanding the problems.
In purely functional languages closures are much saner and safer since they automatically have referential transparency. I think it is kind of disturbing that people rip out features from functional languages to improve their procedural or OO languages without understanding the problems.
Referential transparency is over-estimated. No body can tell why is it good, yet everyone mentions it.
> Referential transparency is over-estimated. No body can
> tell why is it good, yet everyone mentions it.
The advantage of referential transparency is that the function signature formally tells you what exactly a function does. You could also say that *not* having referential transparency is bad because today’s imperative languages allow arbitrary side-effects within a procedure without forcing the programmer to note them down in the procedure signature. It’s really a bit like the advantages of a static type system.
Having said that… there are attempts to do exactly what I described: To note down bounds for possible side-effects of a procedure. The confusing part is that this is done in purely functional languages, and for constructs that model side-effects in a pure language (these constructs are called monads). You get this when you combine monads with a static type system.
I would like to see similar things for imperative languages, but I think we’d need better mechanisms for side-effect aliasing first.
Defining the language in the language has a number of problems, both efficiency is harmed as is the ease of debugging. So I’m not convinced of the merit of closures.
“Defining the language in the language has a number of problems, both efficiency is harmed as is the ease of debugging. So I’m not convinced of the merit of closures.”
Defining the language in language is about macros, not lambdas.
Closures are useful, because they can “remember” the parameters they’re constructed with (see my example above).
I don’t quite understand why people advocating languages without anonymous methods or closures treat the them as if they’re insignificant.
People, please Java is fine as it’s. It has it’s own pros and cons. And do not attack other languages just because they contain features that Java don’t. (Or replace Java here with your language of choice).
Of course I can tell you what referential transparency is good for. But that would be quite a long posting. For example it makes concurrent programming much more transparent and easy. And it eliminates whole classes of bugs completely. For example “leaky encapsulation” in complex classes.
You might have a point that mutable variables are a nessecary evil in some situations. But saying that referential transparency is useless is like saying the const keyword in C++ is useless because you can write any program without any const keywords.
Here’s a function that takes a value, and returns a function that can be called to get that value increased by double.
double(val){
. . return function(way){
. . . . if(way == “by_multiplication”)
. . . . . . return val * 2;
. . . . if(way == “by_addition”)
. . . . . . return val + val;
. . }
}
Now if we do this…
doubler = double(6);
…it is equivalent to doing this…
doubler(way){
. . var val = 6; //<- From double() now seen as actual member value. This is what closures do.
. . if(way == “by_multiplication”)
. . . . return val * 2;
. . if(way == “by_addition”)
. . . . return val + val;
}
But we don’t have to give the function a name, because the context it’s called in is enough…
double(6)(‘by_multiplication’);
…or…
double(6)(‘by_addition’);
But this seems oddly familiar. Right! The OOP equivalent looks surprisingly similar…
6.double(‘by_multiplication’);
…or…
6.double(‘by_addition’);
Closures and objects as defined in CS are exactly the same concept, only seen from the POV of the action or data respectively. You can think of closures as ‘anonymous objects’, and objects as ‘named closures’.