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:

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.)

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 :-)

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 = 0def 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).

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.

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.

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).

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.

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. :)

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.