473,385 Members | 1,647 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Closures python,scheme,ruby


I've a vague idea of the differences,I don't know scheme anyway.

I'd like to see an example to show what is missing in python about
closures and
possibly understand if ruby is better in this sense.

Iuse ruby and python in parallel for my job just to learn them and their
differences and python is shorter and cleaner ,but i feel it's missing
something,
in closures.Any hints?

grazie Paolino
--
.....lotta dura per la verdura

Jul 18 '05 #1
5 1698
paolo veronelli <pa*************@yahoo.it> wrote in message news:<ma*************************************@pyth on.org>...
I've a vague idea of the differences,I don't know scheme anyway.

I'd like to see an example to show what is missing in python about
closures and
possibly understand if ruby is better in this sense.

Iuse ruby and python in parallel for my job just to learn them and their
differences and python is shorter and cleaner ,but i feel it's missing
something,
in closures.Any hints?

grazie Paolino


Python is cleaner but not shorter ;) I don't know about closures in Ruby,
the basic difference between Python and Scheme is that Python
closures are read-only, whereas Scheme closures are read-write
(Scheme has a set! primitive). Here is an example:

(define (outer)
(let ((x 1))
(lambda () (set! x 2) x)))

((outer))
2

You cannot do that in Python, unless you use ugly tricks with mutable objects.
Michele Simionato
Jul 18 '05 #2
paolo veronelli <pa*************@yahoo.it> writes:
I've a vague idea of the differences,I don't know scheme anyway.

I'd like to see an example to show what is missing in python about
closures


A long, long time ago, in a Python far away, there were three
namesapaces: local (to a function), global and builtin. When looking
up a name, Python would first search the local namespace (if there
were one, i.e. we're inside a function), if the name were not found,
it would search the global namespace, and, if still not found, fall
back on the builtin namespace.

(Let's forget about builtins, for this discussion. (You can always
explicitly access the builtins namespace via __builtins__.))
a = 3
def fn():
print a

fn() # => 3

No surprises there. "a" is found in the global namespace.

a = 3
def fn():
a = 4
print a # => 4

fn()
print a # => 3

Inside "fn" a local variable "a" is created (shadowing the global
one), it is printed, goes out of scope and disappears. Inside "fn" it
shadowed the global "a" ... which is why the global "a" is unaffected
by the "a = 4" inside "fn", and "3" was printed on the last line.

Now, let's make a tiny alteration to the last example:

a = 3
def fn():
print a # This is the added line
a = 4
print a

fn()
print a

Run this, and you'll get an error, on the line we added:

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/tmp/python-BxFkNE", line 7, in ?
fn()
File "/usr/tmp/python-BxFkNE", line 3, in fn
print a
UnboundLocalError: local variable 'a' referenced before assignment

Why?

Because the compiler decides that "a" refers to a local variable in
"fn" by noticing that there is an "a = ..." in the function body, and
therefore never looks for "a" outside the local scope. But the first
"print a" comes before that local variable is bound, so it's referring
to a variable which has not been bound yet.

This illustrates that the appearance of "a =" in a function body makes
python believe that "a" is local. But what if you want the function to
modify some global state? What if you want to modify the global "a" ?

For this reason, Python has the "global" keyword:

a = 3
def fn():
global a
print a # => 3
a = 4
print a # => 4

fn()
print a # => 4

All is perfect.

But then, one dark day, nested scopes were added to Python. What does
this mean? Well, in the good old times (say, python 1.5.2) you would
get the following behaviour:

a = 3
def outer():
a = 4
def inner():
print a
return inner

outer()() # => 3

Why? "a" is not found in the local scope of "inner", so Python looks
for it in the global scope, where it does find it ... and where it is
bound to "3".

But in a modern Python, the output of "outer()()" is "4", because
nowadays Python looks for the name in any enclosing function-local
scopes, before getting out to the global scope. So, in a modern
Python, the "a = 4" binding, which is local to "outer" is found.

Now, introducing a local binding of "a" in "inner", should offer no
surprises:

a = 3
def outer():
a = 4
def inner():
a = 5
print a
return inner

outer()() # =>
And adding the same "print a" we added to "fn" earlier ...
a = 3
def outer():
a = 4
def inner():
print a
a = 5
print a
return inner

outer()() # =>

.... gives us exactly the same error

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/tmp/python-BxFY2c", line 12, in ?
outer()()
File "/usr/tmp/python-BxFY2c", line 7, in inner
print a
UnboundLocalError: local variable 'a' referenced before assignment

We could try to fix it, as we did before, by adding a "global a"
declaration:

a = 3
def outer():
a = 4
def inner():
global a
print a # => 3
a = 5
print a # => 5
return inner

outer()() # =>
.... but this results in the intermediate local function scope (the one
of "outer") being ignored (as evidenced by the fact that the first
"print a" gives us "3" rather than "4"). So, it seems that nested
scopes were introduced into Python in a read-only fashion.

The problem is that there is no way of saying "mutate the binding for
the name, wherever you find it". You can say:

a) Mutate or create a binding in the builtin scope:

__builtins__.a = ...

b) Mutate or create a binding in the global scope:

global a
a = ...

c) Mutate or create a binding in the local scope:

a = ...

So, one solution might be to introduce a way of saying "Mutate the
binding, wherever you find it":

lexical a
a =

But, viewed from another perspective, the problem is that Python
offers no way to distinguish between mutating existing bindings and
creating new ones; both are spelt "=". If there were a way to specify
whether you mean "create a new binding" or "rebind the name", then
there would be no need for the "lexical" (or even the "global")
declaration.

This is what is done in some other languages. For example in Scheme:

- Find the nearest binding of "a" and rebind it to "3":

(set! a 3)

- Create a new (lexically nested) variable "a" and bind it to "3":

(let ((a 3) ...)
So, what is missing about Python closures, is the mutability of the
enclosed variables. There is a simple way of hacking around it: make
the enclosed variable a mutable, and mutate it, rather than trying to
rebind the name (thereby avoiding the "a =" syntax which tells Python
to create a local binding of "a") ...

def outer():
a = [4]
def inner():
print a[0]
a[0] = a[0] + 1
return inner

fn = outer()
fn() # => 4
fn() # => 5
fn() # => 6

It works, but it severely reduces the elegance and convenience of
closures. If you appreciate closures, you are likely to consider this
a big pain. If you don't appreciate closures you probabl can't see
what the fuss is about, and are likely to tell people that stateful
functions in Python should be implemented as methods of classes.

I happen to appreciate closures.
Jul 18 '05 #3
Jacek Generowicz wrote:
[extensive description of the situation with Python closures]
That's a great explanation, Jacek. Very informative.
It works, but it severely reduces the elegance and convenience
of closures. If you appreciate closures, you are likely to consider
this a big pain. If you don't appreciate closures you probably
can't see what the fuss is about, and are likely to tell people that
stateful functions in Python should be implemented as methods
of classes.

I happen to appreciate closures.


I really like closures too. They can make for some very simple and elegant
code.

For anyone who wonders what the fuss is about, I posted some Acrobat
JavaScript code a while back with two versions of a piece of code, one with
closures and one with objects:

http://groups.google.com/groups?selm....supernews.com

-Mike
Jul 18 '05 #4
On 15 Jul 2004 13:09:44 +0200, Jacek Generowicz <ja**************@cern.ch> wrote:
[...]
This illustrates that the appearance of "a =" in a function body makes
python believe that "a" is local. But what if you want the function to
modify some global state? What if you want to modify the global "a" ?
I was going to pick a nit and point to a corner case where an "a = ..."
in the function body still allows^Hed a (also) to refer to a non-local, i.e.,

def fn(): ... a = a # local a used to get bound to non-local a, IIRC
... print a
... import dis
dis.dis(fn)

2 0 LOAD_FAST 0 (a)
3 STORE_FAST 0 (a)

3 6 LOAD_FAST 0 (a)
9 PRINT_ITEM
10 PRINT_NEWLINE
11 LOAD_CONST 0 (None)
14 RETURN_VALUE

but code generation seems to have changed, or I misremember.
Maybe the change is to make it absolutely consistent with determining
semantics by full function body lookahead (which incidentally also
rubs me the wrong way for discovering yields to change a function
to a generator). I prefer meaning to depend just on what's
been read so far, top to bottom, left to right, unless there is some
overriding reason not to do it that way (e.g. normal expression and
assignment evaluation order).

I'm still a big python fan though ;-)
[...]I happen to appreciate closures.

I do too. What if
x <= expr
meant evaluate expr and then
find x (as if to do a read access) and rebind it, whatever name space it's found in?
(Might be dangerous if you include searching builtins though)
Hm, ... not sure about rebinding a binding discovered by attribute name access -- i.e.,
x.y <= expr
might rebind a class variable somewhere or an instance variable, depending.
Don't know how useful that might be.

Regards,
Bengt Richter
Jul 18 '05 #5
bo**@oz.net (Bengt Richter) writes:
What if
x <= expr
meant evaluate expr and then find x (as if to do a read access) and
rebind it, whatever name space it's found in?
I suspect that it's too Perlish for Python, but that sort of approach
is probably the simplest, clearest, most extensible ...

[Aside:

It's in situations like this that sexpr-based languages are very
adavantageous: you don't have to invent fancy syntax, you don't have
to come up with new keywords that break old code ... you just say what
you mean in the usual fashion:

(find-and-rebind x expr)

[Of course, you can still argue endlessly over how it should be spelt
(rebind, set!, setq, lexical-set ...) but at least the mechanism is
clear and uncontroversial.]

]
(Might be dangerous if you include searching builtins though)
Yes, you'd probably want to keep builtins out of it.
Hm, ... not sure about rebinding a binding discovered by attribute
name access -- i.e.,
x.y <= expr
might rebind a class variable somewhere or an instance variable, depending.
Don't know how useful that might be.


Could be fun ! :-)
Jul 18 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

220
by: Brandon J. Van Every | last post by:
What's better about Ruby than Python? I'm sure there's something. What is it? This is not a troll. I'm language shopping and I want people's answers. I don't know beans about Ruby or have...
699
by: mike420 | last post by:
I think everyone who used Python will agree that its syntax is the best thing going for it. It is very readable and easy for everyone to learn. But, Python does not a have very good macro...
14
by: Alexander May | last post by:
When I define a function in the body of a loop, why doesn't the function "close" on the loop vairable? See example below. Thanks, Alex C:\Documents and Settings\Alexander May>python Python...
65
by: Amol Vaidya | last post by:
Hi. I am interested in learning a new programming language, and have been debating whether to learn Ruby or Python. How do these compare and contrast with one another, and what advantages does one...
22
by: Francois | last post by:
I discovered Python a few months ago and soon decided to invest time in learning it well. While surfing the net for Python, I also saw the hype over Ruby and tried to find out more about it, before...
206
by: WaterWalk | last post by:
I've just read an article "Building Robust System" by Gerald Jay Sussman. The article is here: http://swiss.csail.mit.edu/classes/symbolic/spring07/readings/robust-systems.pdf In it there is a...
10
by: treble54 | last post by:
Does anyone know a way to use closures or blocks in python like those used in Ruby? Particularly those used in the { } braces.
2
by: Jon Harrop | last post by:
Just debating somewhere else whether or not Python might be considered a functional programming language. Lua, Ruby and Perl all seem to provide first class lexical closures. What is the current...
26
by: Aaron \Castironpi\ Brady | last post by:
Hello all, To me, this is a somewhat unintuitive behavior. I want to discuss the parts of it I don't understand. .... f= lambda: n .... 9 9
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.