Saturday, September 13, 2008

Regarding closures

After reading/watching Stuart's nice slides on Closures in the context of JavaScript, I have started to like JavaScript. Personally, I don't accept any language as a high-level scripting language if it doesn't support closures. Python is therefore straight out of my window. Although Vala isn't a scripting language, it would be nice to have such support in there as well. It already supports lambda functions with no restrictions and Jürg has concrete plans to support closures, it's more a matter of when rather than why or how. When that support is there, just try and stop me from loving Vala. :)

UPDATE: Thanks to Anonymous, I now stand corrected that Python does fully support closures. Although I still don't like the fact that it restricts lambda functions to be one-liner but at least it's not straight out of the window anymore. :)

UPDATE#2: Andy Wingo informs me that python doesn't really fully support closures. He even put up a small code fragment to make his point. So I hereby throw python out the window, again. :)

19 comments:

Anonymous said...

Python does support closures. But it does not support anonymous functions (other than lambdas), maybe that's where the confusion lies?

The wikipedia article has an example:
http://en.wikipedia.org/wiki/Closure_(computer_science)

(PS. one existing compiled language that supports anonymous functions and full closures is D 2.0. D 1.0 only supports "partial" closures, it will fail if one tries to refer to stack-allocated data in closures.)

zeenix said...

Python does support closures. But it does not support anonymous functions (other than lambdas), maybe that's where the confusion lies?

Yeah, thanks for the info. I just updated my blog entry. :)

one existing compiled language that supports anonymous functions and full closures is D 2.0.

Hmm.. The thing is that I already love Vala for various other reasons so support for full closures will only increase the amount of love and respect for Vala. :)

bim said...

What I hate about javascript, is that (unlike other curly-braces languages) scopes are only created by functions, not with { } blocks. So you end up doing stupid tricks like:

(function(really_local_i) { ... })(i);

Anonymous said...

Python does not in fact support modifying the lexical bindings in a closure. So its closures are not as useful as one might think.

Andy

Simon Howard said...

Heh, I remember a friend of mine was describing stackless Python and all the awesome things you can do with it, like co-routines and cooperative threading. I thought about it for a bit and then pointed out that Ruby already does the same thing with call/cc, and you don't even need a specialised interpreter :-)

Anonymous said...

Could you stop bashing python every time you post, please ? No language is perfect. You don't like python, it's ok.

So you love Vala and js, great speak about it, no problem. So be positive about them. Why are you comparing everything to python if you just hate it so much ? Forget it altogether, get over it.

Olafur Arason said...

Python supports closures through lambda like you stated in the first update and the update 2 has no consequences.

Example:
>>>def foo(x):
... def bar(x,y):
... return x*y
... return lambda y: bar(x,y)

This works perfectly and is not to quirky:)

Anonymous said...

Regarding your update #2, that's got nothing to do with closures. If a local variable is assigned to in a function, an error will be used if it's referenced before assignment.

You can duplicate this behavior without any closures, using global variables:

x = 0
def f(y):
if y: return x
x = y
return x

------

In addition, anonymous functions (AKA lambdas) are not as crippled as you might think. They may only include one expression, but that's true of many other lambda-using languages as well (lisp, scheme, etc).

zeenix said...

Could you stop bashing python every time you post, please ? No language is perfect. You don't like python, it's ok.

Could you please stop reading my blog if you get so upset about me bashing python. I do that to make a big bunch of GNOME developers realize that contrary to their beliefs python is far from being a perfect language.

Anonymous said...

Regarding your update #2, that's got nothing to do with closures. If a local variable is assigned to in a function, an error will be used if it's referenced before assignment.

It has everything to do with closures, because x should be the variable closed over. Python borks and assumes it's a local variable when you try to assing something to it, because the lexical bindings in a closure are read-only.


In addition, anonymous functions (AKA lambdas) are not as crippled as you might think. They may only include one expression, but that's true of many other lambda-using languages as well (lisp, scheme, etc).


It's intellectually dishonest to pretend you know anything about lisp when you obviously have no clue about it.

Anonymous said...

For those who don't know, perl has very nice closures. And closures are very nice for callbacks in GUI programs, with GTK for example.

sil said...

Glad you liked the slides. I personally don't miss closures in Python; my JS coding style uses them a lot, but I don't seem to need them when writing Python. Not sure why!

voyou said...

Python borks and assumes it's a local variable when you try to assing something to it, because the lexical bindings in a closure are read-only.

You have that the wrong way round, I think. The lexical bindings in a closure are read only, because Python currently assumes that the first assignment in a function creates a new local variable.

Python 3 will include a new keyword "nonlocal", to specify that assignments to a particular variable rebind the name from the enclosing scope, rather than creating a new variable.

James Henstridge said...

In Python, lambdas are just single expression functions, nothing more. You can see this by disassembling the bytecode for equivalent functions and lambdas: http://paste.ubuntu.com/47047/

The lambda keyword is simply syntatic sugar for defining functions. If you want to do something the lambda syntax doesn't allow, use the standard function syntax.

As for altering variable bindings from parent scopes in closures, that is coming in Python 3.0 with the "nonlocal" keyword. Until then, you can work around this by using mutable variables such as lists (which don't require rebinding the variable name to another object).

behdad said...

Read the appendix in this great essay for a quick comparison of some common languages regarding closure support:

http://www.paulgraham.com/icad.html

Anonymous said...

Having or not having closures is not a deep property of a language. You can always get the closure effect by writing more code, witness the standard "void *data" parameter for C callbacks.

Closures are all about whether your language does the footwork of closing the functions for you.

Stopping halfway like Python does because of the stupid "implicit variable declaration on first assignment" feature are, in my book, signs of weakness in a language, and it irritates me.

- mvo

neil said...

In addition, anonymous functions (AKA lambdas) are not as crippled as you might think. They may only include one expression, but that's true of many other lambda-using languages as well (lisp, scheme, etc).

That's a bit misleading. Lisp/Scheme can have more than one expression in a lambda. But even if that were correct, limiting to a single expression in lisp/scheme would not be a major limitation anyway because all of the control flow statements such as loops and if-statements are actually just expressions. So you can have any amount of complexity in a single expression.

zeenix said...

As for altering variable bindings from parent scopes in closures, that is coming in Python 3.0 with the "nonlocal" keyword. Until then, you can work around this by using mutable variables such as lists (which don't require rebinding the variable name to another object).

Good to know! Until then we can say that Python doesn't fully support closures. :)

Anonymous said...

I was a disappointed when I realized that the only way to create an accumulator in python was through a data structure like a list. I at first thought that Paul Graham was wrong when he said that python does not fully support local variables. He was right. I wish he wasn't. I had really put my faith in python as the language to rule them all.