Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What does Python fix?

2 views
Skip to first unread message

Tim Peters

unread,
Jan 24, 2002, 8:39:26 PM1/24/02
to
[Tim]
> Which makes it refreshing that comparatively few insist Python is a
> broken Smalltalk dialect <wink>.

[James Althoff]
> But we all know that's *only* because y'all haven't given us syntax for
> nameless code blocks -- yet. <wink>

But we have! Take your <nameless code block> and write it like so:

def <aname>():
<nameless code block>

This is what Smalltalk was striving for, but it failed to achieve a key
insight: nameless code blocks are easier to reuse if they're named <wink>.


David Eppstein

unread,
Jan 24, 2002, 9:49:00 PM1/24/02
to
In article <mailman.1011922844...@python.org>,
"Tim Peters" <tim...@home.com> wrote:

> This is what Smalltalk was striving for, but it failed to achieve a key
> insight: nameless code blocks are easier to reuse if they're named <wink>.

But (unlike the unnamed lambda-forms) named code blocks are unable to
access the local variables of some other code block.
--
David Eppstein UC Irvine Dept. of Information & Computer Science
epps...@ics.uci.edu http://www.ics.uci.edu/~eppstein/

Jason Orendorff

unread,
Jan 24, 2002, 9:15:05 PM1/24/02
to
Time Peters wrote:
> [James Althoff]
> > But we all know that's *only* because y'all haven't given us syntax for
> > nameless code blocks -- yet. <wink>
>
> But we have! Take your <nameless code block> and write it like so:
>
> def <aname>():
> <nameless code block>
>
> This is what Smalltalk was striving for, but it failed to achieve a key
> insight: nameless code blocks are easier to reuse if they're
> named <wink>.

Look, obviously what's needed is some simple notation
like >> for indent and << for dedent, thus:

mylist.sort(lambda a, b: >> g = cmp(a.name, b.name);
if g: >> return g; <<
return cmp(a.id, b.id); << <<)

Now, I ask you, is that so bad?
I mean, you don't have to get all tongue-in-cheek about it. ;-)

## Jason Orendorff http://www.jorendorff.com/

Courageous

unread,
Jan 24, 2002, 10:08:14 PM1/24/02
to

>But (unlike the unnamed lambda-forms) named code blocks are unable to
>access the local variables of some other code block.

Java achieves this through inner classes and anonymous classes. While
no approach is superior, this approach has some goodness to it and is
worth considering, I think. While I'm not up to speed on what is or
isn't legal Python in this respect, a trial run in the interpreter
reveals to me that, while a class can be defined within a class in
Python, the inner class doesn't have access to the outer class' scope.
Maybe this should be looked at again?

Tim's certainly right about the anonymous lambda form as far as I can
tell, however. For example, I've seen many a lambda form in lisp which
_could_ be reused but obviously never will. Further, when I see
extensive use of the lambda form, I _usually_ also see a program which
suffers from diarrhea of the keyboard. Things could be organized better,
often enough.

C//

Jason Orendorff

unread,
Jan 24, 2002, 10:30:09 PM1/24/02
to
David Eppstein wrote:

> Tim Peters wrote:
> > This is what Smalltalk was striving for, but it failed to achieve a key
> > insight: nameless code blocks are easier to reuse if they're
> > named <wink>.
>
> But (unlike the unnamed lambda-forms) named code blocks are unable to
> access the local variables of some other code block.

I can't be 100% sure this is what you're referring to here,
but if you mean this sort of thing:

def cube_root(x):
""" Exercise 1.8 from SICP (Abelson and Sussman) """

def square(n):
return n * n

def cube(n):
return n * n * n

def good_enough(guess):
# NOTE reference to outer variable x
# and outer local function cube
return -0.000001 < cube(guess) - x < 0.000001

def improve_guess(y):
# NOTE reference to outer variable x
# and outer local function square
return (x / square(y) + 2 * y) / 3

guess = 1.0
while not good_enough(guess):
guess = improve_guess(guess)
return guess

It works in Python 2.2.

Also works in Python 2.1 if you add "from __future__ import nested_scopes".

David Eppstein

unread,
Jan 24, 2002, 11:10:53 PM1/24/02
to
In article <mailman.1011929742...@python.org>,
"Jason Orendorff" <ja...@jorendorff.com> wrote:

> I can't be 100% sure this is what you're referring to here,
> but if you mean this sort of thing:

Ok, you've convinced me that expanding lambda into unnamed code-blocks is
unnecessary, and confirmed Tim's point that naming the code blocks can be
better than lambdas for readability.

Although in that particular example, I'm not convinced that having any kind
of nested function is better than just expanding the expressions they
represent in-line, with appropriate comments...

Tim Peters

unread,
Jan 25, 2002, 2:01:59 AM1/25/02
to
[Jason Orendorff, shows vanilla use of nested scopes]

[David Eppstein]


> Ok, you've convinced me that expanding lambda into unnamed code-blocks is
> unnecessary, and confirmed Tim's point that naming the code blocks can be
> better than lambdas for readability.

I was just pulling James Althoff's leg -- he expected it, and I enjoy it.
Still, this is just another variant of "the eff-bot's favourite lambda
refactoring rule" (from a post by Fredrik Lundh):

1) write a lambda function
2) write a comment explaining what the heck that lambda does
3) study the comment for a while, and think of a name that captures
the essence of the comment
4) convert the lambda to a def statement, using that name
5) remove the comment

lambdas didn't really add anything to Python, except to give ex-Schemers
false hope <wink>.

> Although in that particular example, I'm not convinced that
> having any kind of nested function is better than just expanding the
> expressions they represent in-line, with appropriate comments...

And once you've got that comment worked out, you can jump straight to the
effbot's step #3!


Alex Martelli

unread,
Jan 25, 2002, 6:05:00 AM1/25/02
to
"David Eppstein" <epps...@ics.uci.edu> wrote in message
news:eppstein-CF37BE...@news.service.uci.edu...

> In article <mailman.1011922844...@python.org>,
> "Tim Peters" <tim...@home.com> wrote:
>
> > This is what Smalltalk was striving for, but it failed to achieve a key
> > insight: nameless code blocks are easier to reuse if they're named
<wink>.
>
> But (unlike the unnamed lambda-forms) named code blocks are unable to
> access the local variables of some other code block.

Not in Python -- a 'named code block' (the body of a local def statement)
and a lambda form have just the same access (or lack thereof) to local
variables of code blocks they're nested in.

I.e., in Python 2.1 (without from __future__) and older neither the
lambda nor the nested def can access those local variables, although
in 2.1 you get a warning about it:

>>> def foo(x):
... def bar(): return x
... return bar
...
<stdin>:1: SyntaxWarning: local name 'x' in 'foo' shadows use of 'x' as
global i
n nested scope 'bar'
>>> foo(23)()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in bar
NameError: global name 'x' is not defined
>>> def foo(x):
... return lambda: x
...
<stdin>:1: SyntaxWarning: local name 'x' in 'foo' shadows use of 'x' as
global i
n nested scope 'lambda'
>>> foo(23)()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in <lambda>
NameError: global name 'x' is not defined
>>>

In Python 2.2, both of these work fine:

>>> def foo(x):
... def bar(): return x
... return bar
...
>>> foo(23)()
23
>>> def foo(x):
... return lambda: x
...
>>> foo(23)()
23
>>>

No difference from this POV between the lambda and the nested def,
in any version of Python.


Alex

0 new messages