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

Securing a future for anonymous functions in Python

19 views
Skip to first unread message

Nick Coghlan

unread,
Dec 30, 2004, 8:28:46 AM12/30/04
to Python List
GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
Getting rid of lambda seems like a worthy goal, but I'd prefer to see it dropped
in favour of a different syntax, rather than completely losing the ability to
have anonymous functions.

Anyway, I'm looking for feedback on a def-based syntax that came up in a recent
c.l.p discussion:
http://boredomandlaziness.skystorm.net/2004/12/anonymous-functions-in-python.html

Cheers,
Nick.

--
Nick Coghlan | ncog...@email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net

Paul Rubin

unread,
Dec 30, 2004, 8:36:06 AM12/30/04
to
Nick Coghlan <ncog...@iinet.net.au> writes:
> Anyway, I'm looking for feedback on a def-based syntax that came up in
> a recent c.l.p discussion:

Looks like just an even more contorted version of lambda. It doesn't
fix lambda's main deficiency which is inability to have several
statements in the anonymous function.

Nick Coghlan

unread,
Dec 30, 2004, 9:00:31 AM12/30/04
to Python List

Do you consider generator expressions or list comprehensions deficient because
they don't allow several statements in the body of the for loop?

Jp Calderone

unread,
Dec 30, 2004, 9:06:26 AM12/30/04
to pytho...@python.org
On Fri, 31 Dec 2004 00:00:31 +1000, Nick Coghlan <ncog...@iinet.net.au> wrote:
>Paul Rubin wrote:
> > Nick Coghlan <ncog...@iinet.net.au> writes:
> >
> >>Anyway, I'm looking for feedback on a def-based syntax that came up in
> >>a recent c.l.p discussion:
> >
> >
> > Looks like just an even more contorted version of lambda. It doesn't
> > fix lambda's main deficiency which is inability to have several
> > statements in the anonymous function.
>
> Do you consider generator expressions or list comprehensions deficient because
> they don't allow several statements in the body of the for loop?
>

>>> (foo + bar
... for foo in range(13) if foo % 3 == 2
... for bar in range(16, 23) if 2 <= bar % 5 < 4)
<generator object at 0xb7dec10c>
>>>

Hmm. Two for loops and two if clauses. That's four altogether.
Does that qualify as "several"? :) Sure, they're not statements
according to the grammar, but that's entirely beside the point.

Jp

Nick Coghlan

unread,
Dec 30, 2004, 9:19:29 AM12/30/04
to Python List

And that's an expression, and hence perfectly legal as the body of an anonymous
function.

So if we feel like abusing our anonymous functions, we use generator expressions
to get if statements and for loops, sys.stdout.write() for print statements,
sys.stdin.read() for input statements, anonymous functions for def statements,
and throw in our own functions with lazily evaluated arguments for anything that
isn't already covered by the interpreter core (which isn't much).

I just don't understand why people complain so much about the restriction to a
single expression in lambdas, yet there is nary a peep about the same
restriction for generator expressions and list comprehensions.

Jp Calderone

unread,
Dec 30, 2004, 9:24:19 AM12/30/04
to pytho...@python.org
On Fri, 31 Dec 2004 00:19:29 +1000, Nick Coghlan <ncog...@iinet.net.au> wrote:
>Jp Calderone wrote:
> > On Fri, 31 Dec 2004 00:00:31 +1000, Nick Coghlan <ncog...@iinet.net.au> wrote:
> >
> >>Paul Rubin wrote:
> >>
> >>>Nick Coghlan <ncog...@iinet.net.au> writes:
> >>>
> >>>
> >>>>Anyway, I'm looking for feedback on a def-based syntax that came up in
> >>>>a recent c.l.p discussion:
> >>>
> >>>
> >>>Looks like just an even more contorted version of lambda. It doesn't
> >>>fix lambda's main deficiency which is inability to have several
> >>>statements in the anonymous function.
> >>
> >>Do you consider generator expressions or list comprehensions deficient because
> >>they don't allow several statements in the body of the for loop?
> >>
> >
> >
> > >>> (foo + bar
> > ... for foo in range(13) if foo % 3 == 2
> > ... for bar in range(16, 23) if 2 <= bar % 5 < 4)
> > <generator object at 0xb7dec10c>
> > >>>
> >
> > Hmm. Two for loops and two if clauses. That's four altogether.
> > Does that qualify as "several"? :) Sure, they're not statements
> > according to the grammar, but that's entirely beside the point.
> >
> > Jp
>
> And that's an expression, and hence perfectly legal as the body of an anonymous
> function.

Quoting my response again:

> Jp Calderone wrote:
> > Sure, they're not statements according to the grammar, but
> > that's entirely beside the point.

I thought this was obvious to anyone, oh well.

List and generator comprehensions have special syntax so that behavior
normally acheivable only with statements can be used to control their
execution. Lambdas don't have any similar special syntax.

I'm not saying "boo hoo lambdas are crippled fix them waah". I'm saying
"Lambdas and generator comprehensions are not comparable in this sense and
arguments based on one should not be used to support positions about the
other".

Jp

John Roth

unread,
Dec 30, 2004, 9:39:54 AM12/30/04
to

"Nick Coghlan" <ncog...@iinet.net.au> wrote in message
news:mailman.8597.1104413...@python.org...

> GvR has commented that he want to get rid of the lambda keyword for Python
> 3.0. Getting rid of lambda seems like a worthy goal, but I'd prefer to see
> it dropped in favour of a different syntax, rather than completely losing
> the ability to have anonymous functions.
>
> Anyway, I'm looking for feedback on a def-based syntax that came up in a
> recent c.l.p discussion:
> http://boredomandlaziness.skystorm.net/2004/12/anonymous-functions-in-python.html
>
> Cheers,
> Nick.

I think it's rather baroque, and I agree with Paul Ruben
that it needs multiple statement capability.

The syntax I prefer (and I don't know if it's actually been
suggested before) is to use braces, that is { and }.

In other words, an anonymous function looks like:
{p1, p2, p3 |
stmt1
stmt2
}

There are two reasons for using braces. One is
that it's the common syntax for blocks in a large number
of languages. The other is that it should be relatively
easy to disambiguate from dictionary literals, which are
the only other current use of braces.

The parameter list is optional, as is the bar ending
the list. The reason for the bar instead of a colon
is to help the parser in the case of a single parameter,
which would look like the beginning of a dictionary
literal. If the parser doesn't need the help, then a colon
would be more consistent, hence better.

A second issue is indentation. I'd set the indentation
boundary wherever the _second_ line of the construct
starts, as long as it's to the right of the prior
indentation boundary. The unfortunate part of this, and one of the
major stumbling blocks, is that it might take some
significant reconceptualizing of the lexer and parser,
which currently isn't set up to shift from expression
back to statement mode and then return to expression
mode.

John Roth

Michael Spencer

unread,
Dec 30, 2004, 1:02:14 PM12/30/04
to pytho...@python.org
Nick Coghlan wrote:
> GvR has commented that he want to get rid of the lambda keyword for
> Python 3.0. Getting rid of lambda seems like a worthy goal, but I'd
> prefer to see it dropped in favour of a different syntax, rather than
> completely losing the ability to have anonymous functions.
>
> Anyway, I'm looking for feedback on a def-based syntax that came up in a
> recent c.l.p discussion:
> http://boredomandlaziness.skystorm.net/2004/12/anonymous-functions-in-python.html
...
The proposed syntax is:
> accepts_func((def (a, b, c) to f(a) + g(b) - h(c)))
...
>
> Cheers,
> Nick.
>
From the blog Comments:
Nick said...
>
> A potentially easier to parse version moves the argument list to the end of the anonymous function and uses the existing keyword 'from'. That is:
>
> (def f(a) + g(b) - h(c) from (a, b, c))
> 11:46 PM
>
> Post a Comment

This alternative syntax seems more elegant to me because of the similarity with
generator expressions. But the 'def' still seems awkward.

<Idle speculation>

Isn't the important point that the arguments have delayed evaluation? If so,
the syntax could highlight this instead: i.e.,

(f(a) + g(b) - h(c) from args(a, b, c))

and, in general:

(expression from args(a, *args, **kw))

while we're at it, perhaps 'for' would be more appropriate:

(expression for args(a, *args, **kw))

I also wonder if a callable, args, that stored its argument list for delayed
evaluation would have other applications besides anonymous functions, but that
is another topic

</Idle speculation>

Michael Spencer


Ian Bicking

unread,
Dec 30, 2004, 2:07:39 PM12/30/04
to John Roth, pytho...@python.org
John Roth wrote:
> The syntax I prefer (and I don't know if it's actually been
> suggested before) is to use braces, that is { and }.
>
> In other words, an anonymous function looks like:
> {p1, p2, p3 |
> stmt1
> stmt2
> }

What's the advantage of something like that over the non-anonymous
equivalent:

def some_func(p1, p2, p3):
stmt1
stmt2

I appreciate some of the motivation, but merely avoiding giving
something a name doesn't seem like a laudible goal.

The one motivation I can see for function expressions is
callback-oriented programming, like:

get_web_page(url,
when_retrieved={page |
give_page_to_other_object(munge_page(page))})

The problem with the normal function in this case is the order of
statements is reversed:

def when_retrieved_callback(page):
give_page_to_other_object(munge_page(page))
get_web_page(url, when_retrieved=when_retrieved_callback)

Oh, and you have to type the name twice, which is annoying. For most
other functional programming constructs, list (and not generator)
comprehensions work well enough, and the overhead of naming functions
just isn't that big a deal.

I think this specific use case -- defining callbacks -- should be
addressed, rather than proposing a solution to something that isn't
necessary. Which is to say, no one *needs* anonymous functions; people
may need things which anonymous functions provide, but maybe there's
other ways to provide the same thing. Decorator abuse, for instance ;)

def get_web_page_decorator(url):
def decorator(func):
return get_web_page(url, when_retrieved=func)
return decorator

@get_web_page_decorator(url)
def when_retrieved(page):
give_page_to_other_object(munge_page(page))

Or even (given a partial function as defined in some PEP, the number of
which I don't remember):

@partial(get_web_page, url)
def when_retrieved(page):
give_page_to_other_object(munge_page(page))

It's okay not to like this proposal, I don't think I'm really serious.
But I do think there's other ways to approach this. Function
expressions could get really out of hand, IMHO, and could easily lead to
twenty-line "expressions". That's aesthetically incompatible with
Python source, IMHO.

--
Ian Bicking / ia...@colorstudy.com / http://blog.ianbicking.org

Roy Smith

unread,
Dec 30, 2004, 2:24:46 PM12/30/04
to
Ian Bicking <ia...@colorstudy.com> wrote:
> I think this specific use case -- defining callbacks -- should be
> addressed, rather than proposing a solution to something that isn't
> necessary. Which is to say, no one *needs* anonymous functions; people
> may need things which anonymous functions provide, but maybe there's
> other ways to provide the same thing. Decorator abuse, for instance ;)

I'm not a big functional programming fan, so it should not come as a
surprise that I don't often use lambda. The one place I do use it is in
unit tests, where assertRaises() requires a callable. If what you're
testing is an expression, you need to wrap it in a lambda.

I suppose you could call this a special case of a callback.

Skip Montanaro

unread,
Dec 30, 2004, 2:35:43 PM12/30/04
to John Roth, pytho...@python.org

John> In other words, an anonymous function looks like:
John> {p1, p2, p3 |
John> stmt1
John> stmt2
John> }

John> There are two reasons for using braces. One is that it's the
John> common syntax for blocks in a large number of languages.

Yeah, but it's not how blocks are spelled in Python. As Nick pointed out on
his blog, allowing statements within expressions risks making code more
difficult to read and understand.

People keep trying to make Python something it is not. It is not
fundamentally an expression-only language like Lisp, nor is it an
expression-equals-statement language like C. There are good reasons why
Guido chose the relationship between simple statements, compound statements
and expressions that he did, readability and error avoidance being key.

Skip

Carl Banks

unread,
Dec 30, 2004, 3:08:58 PM12/30/04
to
Nick Coghlan wrote:
> GvR has commented that he want to get rid of the lambda keyword for
Python 3.0.
> Getting rid of lambda seems like a worthy goal, but I'd prefer to see
it dropped
> in favour of a different syntax, rather than completely losing the
ability to
> have anonymous functions.

I shall either coin or reuse a new term here: "premature optimization
of the Python language."

(Please note that the word premature is not intended to be an accurate
description, but irony by analogy, so spare me any semantic
nitpicking.)

In much the same way that programmers often spend a lot of time
optimizing parts of their program that will yield very minor dividends,
while they could have spent that time working on other things that will
pay off a lot, many of the wannabe language designers here are spending
a lot of time on aspects of the language for which any improvement
would only pay small dividends.

I think the worry about anonymous functions is one of the most
widespread cases of "premature optimization of the Python Language."
One could argue about the various benefits of particular choices, maybe
even make a convincing case that one is best in accord with the design
goals of Python; but in the end, the divends are small compared to
improving other aspects of the language.


--
CARL BANKS

David Bolen

unread,
Dec 30, 2004, 4:44:39 PM12/30/04
to
Ian Bicking <ia...@colorstudy.com> writes:

> The one motivation I can see for function expressions is
> callback-oriented programming, like:
>
> get_web_page(url,
> when_retrieved={page |
> give_page_to_other_object(munge_page(page))})

This is my primary use case for lambda's nowadays as well - typically
just to provide a way to convert the input to a callback into a call
to some other routine. I do a lot of Twisted stuff, whose deferred
objects make heavy use of single parameter callbacks, and often you
just want to call the next method in sequence, with some minor change
(or to ignore) the last result.

So for example, an asynchronous sequence of operations might be like:

d = some_deferred_function()
d.addCallback(lambda x: next_function())
d.addCallback(lambda blah: third_function(otherargs, blah))
d.addCallback(lambda x: last_function())

which to me is more readable (in terms of seeing the sequence of
operations being performed in their proper order), then something like:

def cb_next(x):
return next_function()
def cb_third(blah, otherargs):
return third_function(otherargs, blah)
def cb_last(x):
return last_function()

d = some_deferred_function()
d.addCallback(cb_next)
d.addCallback(cb_third, otherargs)
d.addCallback(cb_next)

which has an extra layer of naming (the callback functions), and
requires more effort to follow the flow of what is really just a simple
sequence of three functions being called.

> I think this specific use case -- defining callbacks -- should be
> addressed, rather than proposing a solution to something that isn't

> necessary. (...)

I'd be interested in this approach too, especially if it made it simpler
to handle simple manipulation of callback arguments (e.g., since I often
ignore a successful prior result in a callback in order to just move on
to the next function in sequence).

-- David

Paul L. Du Bois

unread,
Dec 30, 2004, 5:01:34 PM12/30/04
to
Jp Calderone wrote:
> I'm not saying "boo hoo lambdas are crippled fix them waah". I'm
saying
> "Lambdas and generator comprehensions are not comparable in this
sense and
> arguments based on one should not be used to support positions about
the
> other".

This post and Michael Spencer's post which proposed (expr for args(a,
*b, **c)) got me wondering whether this could be done already today.
My solution is unfortuantely implementation-specific. I can't find a
way for a generator (let alone a generator expression) to refer to
itself; neither do generators have writable attributes. With those
features, one can imagine a more portable (and more verbose) solution.

I find that I don't really like the generator-like syntax. To me, it
makes sense for an unnamed function to look like a named function
without a name, eg:

callbacks['foo'] = def (a,b): ... expr or statement? ...

It seems to work in Lua (not that I'm a big fan of Lua). Thus, I'm not
sure what my point is with this code; maybe just that there are
workarounds if lambda ceases to exist. Also, with this sort of
solution, nobody can complain that genexps/listcomps/"lambdas" get
preferential treatment <wink>

Anyway, this is tested in Win32 python 2.4. It adds a function "fn"
(name stolen from Arc) which turns a specially-written generator
expression into an anonymous function. Default args, *args, *kwargs
are all unsupported. I'm sorry if google groups eats my leading
whitespace; I've one-lined things to reduce the effect.

def fn(gen):
"""Turns a generator expression into a callable."""
def anonymous(*args): return gen.next()
return anonymous

def args():
"""Works with fn(); yields args passed to anonymous()."""
while True: yield sys._getframe(2).f_locals['args']

args = args()

foo = fn(a + b * c for (a,b,c) in args)
assert foo(3,4,5) == 3+4*5
assert foo(4,5,6) == 4+5*6

Bengt Richter

unread,
Dec 30, 2004, 5:08:37 PM12/30/04
to
On Thu, 30 Dec 2004 23:28:46 +1000, Nick Coghlan <ncog...@iinet.net.au> wrote:

>GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
>Getting rid of lambda seems like a worthy goal, but I'd prefer to see it dropped
>in favour of a different syntax, rather than completely losing the ability to
>have anonymous functions.
>
>Anyway, I'm looking for feedback on a def-based syntax that came up in a recent
>c.l.p discussion:
>http://boredomandlaziness.skystorm.net/2004/12/anonymous-functions-in-python.html
>

Nit: You didn't try the code you posted ;-)

>>> funcs = [(lambda x: x + i) for i in range(10)]
>>>
>>> def incrementors():
... for i in range(10):
... def incrementor(x):
... return x + i
... yield incrementor
...
>>> #funcs = list(incrementors)
... funcs2 = list(incrementors())
>>>
>>> for f in funcs: print f(0),
...
9 9 9 9 9 9 9 9 9 9
>>> for f in funcs2: print f(0),
...
9 9 9 9 9 9 9 9 9 9

This is an easy trap to fall into, so if the new lambda-substitute could
provide a prettier current-closure-variable-value capture than passing a dummy default
value or nesting another def and passing the value in, to provide a private closure for each,
that might be something to think about.

IMO an anonymous def that exactly duplicates ordinary def except for leaving out
the function name and having a local indentation context would maximize flexibility
and also re-use of compiler code. People could abuse it, but that's already true
of many Python features.

From your web page:
----
def either(condition, true_case, false_case):
if condition:
return true_case()
else:
return false_case()

print either(A == B, (def "A equals B"), (def "A does not equal B"))
either(thefile, (def thefile.close()), (def 0))
----

I'd rather see (:something) than (def something) for this special case,
but the full-fledged anonymous def would spell it thus:

print either(A == B, (def():return "A equals B"), (def(): return "A does not equal B"))
either(thefile, (def(): return thefile.close()), (def(): return 0))

BTW,

funcs = [(lambda x: x + i) for i in range(10)]

might be spelled

funcs = [(def(x, i=i): return x + i) for i in range(10)]

or optionally

funcs = [(
def(x, i=i):
return x + i
) for i in range(10)]

or

funcs = [(def(x, i=i):
return x + i) for i in range(10)]
or
funcs = [(def(x, i=i):
return x + i)
for i in range(10)]
or
funcs = [def(x, i=i):
return x + i
for i in range(10)]
or
funcs = [
def(x, i=i):
return x + i
for i in range(10)]

and so on. (the def defines the indentation base if the suite is indented, and the closing ')'
terminates the anonymous def explicitly, or a dedent to the level of the def or less can do it,
as in the last two examples).

This one

(def f(a) + g(b) - h(c) from (a, b, c))

would be spelled (if I undestand your example)

(def(a, b, c): return f(a)+g(b)+h(c))

which seems to me familiar and easy to understand.

BTW, there are old threads where this and other formats were discussed. I am still
partial to the full anonymous def with nesting indentation rules. Syntactic sugar
could be provided for useful abbreviations (that could possibly be expanded by the
tokenizer -- re which possibilities I haven't seen any discussion than my own
recent post, BTW), but I'd like the full capability.

Regards,
Bengt Richter

John Roth

unread,
Dec 30, 2004, 5:24:03 PM12/30/04
to

"Ian Bicking" <ia...@colorstudy.com> wrote in message
news:mailman.8620.1104433...@python.org...

> John Roth wrote:
>> The syntax I prefer (and I don't know if it's actually been
>> suggested before) is to use braces, that is { and }.
>>
>> In other words, an anonymous function looks like:
>> {p1, p2, p3 |
>> stmt1
>> stmt2
>> }
>
> What's the advantage of something like that over the non-anonymous
> equivalent:
>
> def some_func(p1, p2, p3):
> stmt1
> stmt2
>
> I appreciate some of the motivation, but merely avoiding giving something
> a name doesn't seem like a laudible goal.

Actually, it is a laudable goal. It's always easier to understand
something when it's right in front of your face than if it's
off somewhere else.

This, of course, trades off with two other forces: avoiding
repetition and making the whole thing small enough to
understand.

So the niche is small, single use functions. The problem
with lambdas is that they're restricted to one expression,
which is too small.

Languages that are designed with anonymous functions
in mind use them very heavily. Smalltalk is the standard
example, and it's also one of the major (possibly the
only) attraction Ruby has over Python.

Python isn't designed that way, which restricts their
utility to a much smaller niche than otherwise.

> The one motivation I can see for function expressions is callback-oriented

> programming ...

Well, that's true, but that's a very global statement:
when you pass a function into another routine, it's
essentially a callback.

...

> Function expressions could get really out of hand, IMHO, and could easily
> lead to twenty-line "expressions". That's aesthetically incompatible with
> Python source, IMHO.

Anything can get out of hand; there's no way of legislating
good style without restricting the language so much that it
becomes unusable for anything really interesting. Even then
it doesn't work: see COBOL as a really good example of
good intentions gone seriously wrong.

Have you ever programmed in a language that does use
anonymous functions extensively like Smalltalk?

John Roth

Jeff Shannon

unread,
Dec 30, 2004, 6:15:51 PM12/30/04
to
David Bolen wrote:

>>I think this specific use case -- defining callbacks -- should be
>>addressed, rather than proposing a solution to something that isn't
>>necessary. (...)
>>
>>
>
>I'd be interested in this approach too, especially if it made it simpler
>to handle simple manipulation of callback arguments (e.g., since I often
>ignore a successful prior result in a callback in order to just move on
>to the next function in sequence).
>
>

It seems to me that what most people *actually* want, when asking for
lambdas, is a quicker and more convenient way to get closures. (At
least, that's what the vast majority of examples of lambda use seem to
be for.) Perhaps one could get a bit more traction by looking for
improved closure syntax instead of focusing on the anonymous function
aspect.

All of the suggestions for anonymous multiline functions (with embedded
indentation) seem to me to miss what seems to me to be the only
significant benefit of lambda -- its ability to be used in-line without
creating a huge ugly tangle. (I'd argue that lambdas create a *small*
ugly tangle, but apparently that's just me. ;) ) Lambdas do have some
value in defining callbacks, but that value derives almost exclusively
from the fact that they are in-line (rather than a few lines above).
Mimicking function-def indentation inside of another function's arglist
strikes me as an abomination just waiting to happen; in comparison, the
need to type a name twice seems trivial.

As a result, it seems to me that, rather than generalize lambdas into
"full" anonymous functions (with most of the negatives and few of the
positives of lambda), it would be much better to specialize them further
into inline-closure-creators, where they can serve a valuable purpose
without quite as much risk of code pollution.

Jeff Shannon
Technician/Programmer
Credit International

Bengt Richter

unread,
Dec 30, 2004, 7:31:45 PM12/30/04
to
On Thu, 30 Dec 2004 15:15:51 -0800, Jeff Shannon <je...@ccvcorp.com> wrote:

>David Bolen wrote:
>
>>>I think this specific use case -- defining callbacks -- should be
>>>addressed, rather than proposing a solution to something that isn't
>>>necessary. (...)
>>>
>>>
>>
>>I'd be interested in this approach too, especially if it made it simpler
>>to handle simple manipulation of callback arguments (e.g., since I often
>>ignore a successful prior result in a callback in order to just move on
>>to the next function in sequence).
>>
>>
>
>It seems to me that what most people *actually* want, when asking for
>lambdas, is a quicker and more convenient way to get closures. (At
>least, that's what the vast majority of examples of lambda use seem to
>be for.) Perhaps one could get a bit more traction by looking for
>improved closure syntax instead of focusing on the anonymous function
>aspect.

Not sure what you mean by closure here. To me it means the necessary
external environment needed to be captured for use by a function definition
getting exported from its definition environment. I.e., it is something
a function uses, and part of the function definition, but it isn't the
function itself. I would compare a closure more to a callable class instance's
self attributes, except that the latter are more flexible.

In fact, for a callback, a constructor call creating a suitable
callable class instance could sometimes work well as a substitute
for a lambda expression, ISTM. (I.e., when it is not important to
show the code in line, and the differences are in initialization parameters
rather than code).

>
>All of the suggestions for anonymous multiline functions (with embedded
>indentation) seem to me to miss what seems to me to be the only
>significant benefit of lambda -- its ability to be used in-line without
>creating a huge ugly tangle. (I'd argue that lambdas create a *small*
>ugly tangle, but apparently that's just me. ;) ) Lambdas do have some
>value in defining callbacks, but that value derives almost exclusively
>from the fact that they are in-line (rather than a few lines above).

They do let you define _code_ inline, which a constructor call doesn't do
(unless you pass a string to compile etc -- not cool).



>Mimicking function-def indentation inside of another function's arglist
>strikes me as an abomination just waiting to happen; in comparison, the
>need to type a name twice seems trivial.

Self-restraint can avoid abominations ;-)

>
>As a result, it seems to me that, rather than generalize lambdas into
>"full" anonymous functions (with most of the negatives and few of the
>positives of lambda), it would be much better to specialize them further
>into inline-closure-creators, where they can serve a valuable purpose
>without quite as much risk of code pollution.

There's always the temptation to be enforcer when being persuader
is not the easiest ;-)

(BTW, again, by closure, do you really mean deferred-action-thingie?)

Regards,
Bengt Richter

Jeff Shannon

unread,
Dec 30, 2004, 8:39:06 PM12/30/04
to
Bengt Richter wrote:

> On Thu, 30 Dec 2004 15:15:51 -0800, Jeff Shannon <je...@ccvcorp.com> wrote:
>
>>Mimicking function-def indentation inside of another function's arglist
>>strikes me as an abomination just waiting to happen; in comparison, the
>>need to type a name twice seems trivial.
>
> Self-restraint can avoid abominations ;-)

It can, but given the prevalence of lambda abominations (such as the
many that the Martellibot described among Cookbook submissions), is
there any reason to believe that there would be *more* restraint in
using a less-constrained feature?? :)

>>As a result, it seems to me that, rather than generalize lambdas into
>>"full" anonymous functions (with most of the negatives and few of the
>>positives of lambda), it would be much better to specialize them further
>>into inline-closure-creators, where they can serve a valuable purpose
>>without quite as much risk of code pollution.
>

> (BTW, again, by closure, do you really mean deferred-action-thingie?)

My understanding of "closure" (which may well be wrong, as I've
inferred it entirely from past discussions on this newsgroup) is that
it's a callable with some or all of its parameters already set; e.g.,

def one_and(foo):
def closure(arg):
return foo(1, arg)
return closure

incr = one_and(operator.add)

The function one_and() returns a closure, here bound to incr. It is
essentially a (partially) deferred action thingy, if you want to use
technical terms. ;) I suppose that one could look at it as the
environment in which to call a given function, exported for later use...

My thesis here is that one of the most common (legitimate) uses of
lambda is as an adapter, to create an intermediary that allows a
callable with a given signature to be used in places where a different
signature is expected -- that is, altering the number or order of
arguments passed to a given callable (and possibly also capturing the
current value of some other variable in the process). I feel that
it's more fruitful to focus on this "adapter" quality rather than
focusing on the "anonymous function" quality.

Nick Coghlan

unread,
Dec 30, 2004, 9:38:24 PM12/30/04
to Python List
Batista, Facundo wrote:
> [Nick Coghlan]
>
> #- I just don't understand why people complain so much about
> #- the restriction to a
> #- single expression in lambdas, yet there is nary a peep about
> #- the same
> #- restriction for generator expressions and list comprehensions.
>
> What *I* don't understand (and it could perfectly be plain ignorance, as
> never studied languages or computer sciences) is why anonymous functions
> are so important.

Speaking for myself, I find lazy evaluation of arguments is impractical without
them. Defining 2 or 3 named functions in order to make a single function call
seems rather unnecessarily verbose. I don't need to use lazy evaluation very
often, but when I do use it, it is generally because other approaches would be
much more complicated (or significantly less efficient).

This usage pattern is also why I do not find the restriction to a single
expression a problem in practice - since I'm merely delaying the evaluation of
what I would have supplied as a function argument anyway, I'm already working
with an expression.

Cheers,
Nick.

Nick Coghlan

unread,
Dec 30, 2004, 9:50:14 PM12/30/04
to Python List
Bengt Richter wrote:
> This is an easy trap to fall into, so if the new lambda-substitute could
> provide a prettier current-closure-variable-value capture than passing a dummy default
> value or nesting another def and passing the value in, to provide a private closure for each,
> that might be something to think about.

I forgot about that little trap. . .

Nick Coghlan

unread,
Dec 30, 2004, 10:07:51 PM12/30/04
to Python List
Carl Banks wrote:

> Nick Coghlan wrote:
> In much the same way that programmers often spend a lot of time
> optimizing parts of their program that will yield very minor dividends,
> while they could have spent that time working on other things that will
> pay off a lot, many of the wannabe language designers here are spending
> a lot of time on aspects of the language for which any improvement
> would only pay small dividends.

Whereas I see it as wannabe language designers only being able to tinker at the
edges of Python, because GvR already got the bulk of the language right.
Anonymous functions are the major core construct that doesn't 'fit right', so a
disproportionate amount of time is spent playing with ideas about them.

Nick Coghlan

unread,
Dec 30, 2004, 10:22:35 PM12/30/04
to Python List
Michael Spencer wrote:
> while we're at it, perhaps 'for' would be more appropriate:
>
> (expression for args(a, *args, **kw))

Hmm, what about an 'abbreviated generator expression' syntax:

(<expression> for <args-tuple>)

For instance:

(f(a) + g(b) - h(c) for (a, b, c))

(the 'in' clause of the standard generator expression is missing).

That does leave the question of the correct spelling of 'no arguments', which
generator expressions don't have to deal with. Perhaps:

(f.close() for ())

It does make for an interesting interpretation of the generator expression syntax:

(<expression> for <args-tuple> in <sequence> if <condition>)

def expression_func(<args-tuple>):
return <expression>

def generator():
for <args-tuple> in <sequence>
if <condition>:
yield expression_func(<args-tuple>)

Bengt Richter

unread,
Dec 30, 2004, 10:46:02 PM12/30/04
to
On Thu, 30 Dec 2004 17:39:06 -0800, Jeff Shannon <je...@ccvcorp.com> wrote:

>Bengt Richter wrote:
>
>> On Thu, 30 Dec 2004 15:15:51 -0800, Jeff Shannon <je...@ccvcorp.com> wrote:
>>
>>>Mimicking function-def indentation inside of another function's arglist
>>>strikes me as an abomination just waiting to happen; in comparison, the
>>>need to type a name twice seems trivial.
>>
>> Self-restraint can avoid abominations ;-)
>
>It can, but given the prevalence of lambda abominations (such as the
>many that the Martellibot described among Cookbook submissions), is
>there any reason to believe that there would be *more* restraint in
>using a less-constrained feature?? :)

Maybe. If people are determined to overcome limitations that needn't exist,
they are likely to invent horrible hacks ;-)

>
>>>As a result, it seems to me that, rather than generalize lambdas into
>>>"full" anonymous functions (with most of the negatives and few of the
>>>positives of lambda), it would be much better to specialize them further
>>>into inline-closure-creators, where they can serve a valuable purpose
>>>without quite as much risk of code pollution.
>>
>> (BTW, again, by closure, do you really mean deferred-action-thingie?)
>
>My understanding of "closure" (which may well be wrong, as I've
>inferred it entirely from past discussions on this newsgroup) is that
>it's a callable with some or all of its parameters already set; e.g.,
>
> def one_and(foo):
> def closure(arg):
> return foo(1, arg)
> return closure
>
> incr = one_and(operator.add)
>
>The function one_and() returns a closure, here bound to incr. It is
>essentially a (partially) deferred action thingy, if you want to use
>technical terms. ;) I suppose that one could look at it as the
>environment in which to call a given function, exported for later use...

Quoting from "Essentials of Programming Languages" (Friedman, Wand, Haynes):
(using *xxx yyy etc* for italics)
"""
In order for a procedure to retain the bindings that its free variables had
at the time it was created, it must be a *closed* package, independent of
the environment in which it is used. Such a package is called a closure.
In order to be self-contained, a closure must contain the procedure body,
the list of formal parameters, and the bindings of its free variables.
It is convenient to store the entire creation environment, rather than
just the bindings of the free variables. We sometimes say the procedure
*is closed over* or *closed in* its creation environment. We represent
closures as records.
"""

So it looks like you infer better than I remember, and attachment to
faulty memory has led me to resist better inferences ;-/

Closure is the name for the whole thing, apparently, not just the environment
the procedure body needs, which was the aspect that I (mis)attached the name to.

(Representing closures as records doesn't really belong in that paragraph IMO,
since it is not really part of the definition there, just a choice in that stage
of exposition in the book, using scheme-oriented examples. But I quoted verbatim.).

On the subject CLtL finally (after some stuff beyond my current caffeine level) says,
"""
The distinction between closures and other kinds of functions is somewhat pointless,
actually, since Common Lisp defines no particular representation for closures and
no way to distinguish between closures and non-closure functions. All that matters
is that the rules of lexical scoping be obeyed.
"""
I guess that clinches it ;-)

Might be a good python glossary wiki entry.

>
>My thesis here is that one of the most common (legitimate) uses of
>lambda is as an adapter, to create an intermediary that allows a
>callable with a given signature to be used in places where a different
>signature is expected -- that is, altering the number or order of
>arguments passed to a given callable (and possibly also capturing the
>current value of some other variable in the process). I feel that
>it's more fruitful to focus on this "adapter" quality rather than
>focusing on the "anonymous function" quality.
>

I see what you are saying (I think), but I think I'd still like a full
anonymous def, whatever adapter you come up with. And I prefer to be persuaded ;-)

Regards,
Bengt Richter

Steven Bethard

unread,
Dec 30, 2004, 11:14:31 PM12/30/04
to
Jeff Shannon wrote:
> My thesis here is that one of the most common (legitimate) uses of
> lambda is as an adapter, to create an intermediary that allows a
> callable with a given signature to be used in places where a different
> signature is expected -- that is, altering the number or order of
> arguments passed to a given callable (and possibly also capturing the
> current value of some other variable in the process). I feel that it's
> more fruitful to focus on this "adapter" quality rather than focusing on
> the "anonymous function" quality.

Maybe the 'functional' module proposed in PEP 309[1] could provide such
functions?

py> def ignoreargs(func, nargs, *kwd_names):
... def _(*args, **kwds):
... args = args[nargs:]
... kwds = dict((k, kwds[k])
... for k in kwds if k not in kwd_names)
... return func(*args, **kwds)
... return _
...
py> def f(x, y):
... print x, y
...
py> ignoreargs(f, 2)(1, 2, 3, 4)
3 4
py> ignoreargs(f, 2, 'a', 'b')(1, 2, 3, 4, a=35, b=64)
3 4

Steve

[1] http://python.fyxm.net/peps/pep-0309.html

Paul Rubin

unread,
Dec 31, 2004, 1:28:40 AM12/31/04
to
bo...@oz.net (Bengt Richter) writes:
> print either(A == B, (def "A equals B"), (def "A does not equal B"))
> either(thefile, (def thefile.close()), (def 0))

I'd really rather have some reasonable macro facility, than to resort
to using anonymous functions and deferred evaluation for common things
like that.

Ian Bicking

unread,
Dec 31, 2004, 4:01:45 AM12/31/04
to John Roth, pytho...@python.org
John Roth wrote:
>> I appreciate some of the motivation, but merely avoiding giving
>> something a name doesn't seem like a laudible goal.
>
> Actually, it is a laudable goal. It's always easier to understand
> something when it's right in front of your face than if it's
> off somewhere else.

Naming the function doesn't move it far away. It changes the order (you
have to define it before you use it), and it introduces a name.

>> The one motivation I can see for function expressions is
>> callback-oriented programming ...
>
> Well, that's true, but that's a very global statement:
> when you pass a function into another routine, it's
> essentially a callback.

Sure, technically. But I'm thinking of real use cases. One I'm
familiar with is things like map and filter. These are generally better
handled with list expressions (and MUCH more readable as such, IMHO).
Another is control structures, ala Ruby or Smalltalk. IMHO, we have all
the control structures we need -- while, for, if. Most "novel" control
structures in Ruby or Smalltalk are just another take on iterators. The
exception being callbacks, and perhaps some other lazy evaluation
situations (though outside of what I think of as "callbacks", I can't
think of any lazy evaluation situations off the top of my head).

So that's why I think callbacks are important; callbacks in the style of
Twisted Deferred, GUI events, etc.

>> Function expressions could get really out of hand, IMHO, and could
>> easily lead to twenty-line "expressions". That's aesthetically
>> incompatible with Python source, IMHO.
>
> Anything can get out of hand; there's no way of legislating
> good style without restricting the language so much that it
> becomes unusable for anything really interesting. Even then
> it doesn't work: see COBOL as a really good example of
> good intentions gone seriously wrong.

OK, I should go further -- even a two-line expression (i.e., an
expression that contains meaningful vertical whitespace) is
aesthetically incompatible with Python source. Which covers any
anonymous function that is more powerful than lambda. I'm not arguing
that it can be abused, but more that it isn't any good even when it's
not being abused.

> Have you ever programmed in a language that does use
> anonymous functions extensively like Smalltalk?

Yep, I've done a fair amount of Smalltalk and Scheme programming. I
don't expect Python to act like them. I appreciate the motivation, but
I don't think their solution is the right one for Python.

Alex Martelli

unread,
Dec 31, 2004, 12:38:24 PM12/31/04
to
Paul L. Du Bois <poly...@gmail.com> wrote:
...

> are all unsupported. I'm sorry if google groups eats my leading
> whitespace; I've one-lined things to reduce the effect.

It does/did, so let me repost while fixing it since this is truly,
deliciously evil:

> def fn(gen):
> """Turns a generator expression into a callable."""
> def anonymous(*args): return gen.next()
> return anonymous
>
> def args():
> """Works with fn(); yields args passed to anonymous()."""
> while True: yield sys._getframe(2).f_locals['args']
>
> args = args()
>
> foo = fn(a + b * c for (a,b,c) in args)
> assert foo(3,4,5) == 3+4*5
> assert foo(4,5,6) == 4+5*6

Paul, you really SHOULD have posted this BEFORE I had to send in the
files for the 2nd ed's Coobook... this gets my vote for the most
delightful abuse of sys._getframe even (and I've seen quite a few;-).

Kudos!!!


Alex

Steven Bethard

unread,
Dec 31, 2004, 1:19:59 PM12/31/04
to

So, I couldn't figure out why this worked until I started to write an
email to ask. Once I understood it, I figured it wouldn't hurt to send
my thoughts out anyway to (1) verify that I understand it right, and (2)
help anyone else who was trying to figure this out.


As I understand it sys._getframe(2).f_locals should get the names local
to the stack frame two above the current one. So, in the context of:
fn(... for ... in args)
sys._getframe(2).f_locals should be looking at the names local to the
'anonymous' function in the 'fn' function, because one stack frame up
from the 'args' function is the generator's 'next' function, and two
stack frames up is the 'anonymous' function. That means that:
sys._getframe(2).f_locals['args']
gets whatever object has been bound to 'args' in:
def anonymous(*args):
So then in:


foo = fn(a + b * c for (a,b,c) in args)

foo(3,4,5)
foo(4,5,6)
sys._getframe(2).f_locals['args'] will get (3, 4, 5) in the first foo
call, (4, 5, 6) in the second foo call, etc.


So basically the way a call like foo(3, 4, 5) works is:
(1) foo(3, 4, 5) calls gen.next() where gen is the generator expression
(2) gen.next() calls args.next()
(3) args.next() returns the (3, 4, 5) argument tuple of foo by looking
up the stack frames
(4) gen.next() binds (3, 4, 5) to the names a, b, c respectively
(5) gen.next() returns the value of "a + b * c" for these bindings
(6) foo(3, 4, 5) returns the same value (as gen.next() did)

Does that seem about right?

Steve

P.S. That's so *evilly* cool!

Scott David Daniels

unread,
Dec 31, 2004, 1:24:21 PM12/31/04
to
David Bolen wrote:
> So for example, an asynchronous sequence of operations might be like:
>
> d = some_deferred_function()
> d.addCallback(lambda x: next_function())
> d.addCallback(lambda blah: third_function(otherargs, blah))
> d.addCallback(lambda x: last_function())
>
> which to me is more readable (in terms of seeing the sequence of
> operations being performed in their proper order), then something like:
>
> def cb_next(x):
> return next_function()
> def cb_third(blah, otherargs):
> return third_function(otherargs, blah)
> def cb_last(x):
> return last_function()
>
> d = some_deferred_function()
> d.addCallback(cb_next)
> d.addCallback(cb_third, otherargs)
> d.addCallback(cb_next)
>
> which has an extra layer of naming (the callback functions), and
> requires more effort to follow the flow of what is really just a simple
> sequence of three functions being called.

But this sequence contains an error of the same form as the "fat":

while test() != False:
...code...

The right sequence using lambda is:
d = some_deferred_function()
d.addCallback(next_function)
d.addCallback(lambda blah: third_function(otherargs, blah))
d.addCallback(last_function)

And I would write it as:

def third_function_fixed_blah(blah):
def call_third(otherargs):
return third_function(otherargs, blah)
return call_third

d = some_deferred_function()
d.addCallback(next_function)
d.addCallback(third_function_fixed_blah, otherargs)
d.addCallback(last_function)

The name gives you the chance to point out that the argument order is
tweaked. In many such cases, I use curry (ASPN recipe #52549), which
should show up in Python as "partial" in the "functional" module
according to PEP 309 <http://www.python.org/peps/pep-0309.html>
(accepted but not included). I suppose it will show up in Python 2.5.

Programming is a quest is for clear, easy-to-read code, not quick,
easy-to-write code. Choosing a name is a chance to explain what you
are doing. lambda is used too often in lieu of deciding what to write.

--Scott David Daniels
Scott....@Acm.Org

Alex Martelli

unread,
Dec 31, 2004, 1:38:24 PM12/31/04
to
Steven Bethard <steven....@gmail.com> wrote:

> Does that seem about right?

Yep!

> P.S. That's so *evilly* cool!

We should have an Evilly Cool Hack of the Year, and I nominate Paul du
Bois's one as the winner for 2004. Do I hear any second...?


Alex

Paul Rubin

unread,
Dec 31, 2004, 1:46:08 PM12/31/04
to
ale...@yahoo.com (Alex Martelli) writes:
> We should have an Evilly Cool Hack of the Year, and I nominate Paul du
> Bois's one as the winner for 2004. Do I hear any second...?

The year's not over yet :).

Ian Bicking

unread,
Dec 31, 2004, 12:54:51 PM12/31/04
to David Bolen, pytho...@python.org
David Bolen wrote:
> Ian Bicking <ia...@colorstudy.com> writes:
>
>
>>The one motivation I can see for function expressions is
>>callback-oriented programming, like:
>>
>> get_web_page(url,
>> when_retrieved={page |
>> give_page_to_other_object(munge_page(page))})
>
>
> This is my primary use case for lambda's nowadays as well - typically
> just to provide a way to convert the input to a callback into a call
> to some other routine. I do a lot of Twisted stuff, whose deferred
> objects make heavy use of single parameter callbacks, and often you
> just want to call the next method in sequence, with some minor change
> (or to ignore) the last result.
>
> So for example, an asynchronous sequence of operations might be like:
>
> d = some_deferred_function()
> d.addCallback(lambda x: next_function())
> d.addCallback(lambda blah: third_function(otherargs, blah))
> d.addCallback(lambda x: last_function())

Steven proposed an ignoreargs function, and the partial function offers
the other side (http://www.python.org/peps/pep-0309.html). So this
would become:

d = some_deferred_function()
d.addCallback(ignoreargs(next_function, 1))
d.addCallback(partial(third_function, otherargs))
d.addCallback(ignoreargs(last_function, 1))

I'm not sure this is "better" than it is with lambda. It's actually
considerably less readable to me. Hmm... well, that makes me less
excited about those...

David Bolen

unread,
Dec 31, 2004, 2:15:59 PM12/31/04
to
Scott David Daniels <Scott....@Acm.Org> writes:

> David Bolen wrote:
> > So for example, an asynchronous sequence of operations might be like:
> > d = some_deferred_function()
> > d.addCallback(lambda x: next_function())
> > d.addCallback(lambda blah: third_function(otherargs, blah))
> > d.addCallback(lambda x: last_function())
> > which to me is more readable (in terms of seeing the sequence of
> > operations being performed in their proper order), then something like:
> > def cb_next(x):
> > return next_function()
> > def cb_third(blah, otherargs):
> > return third_function(otherargs, blah)
> > def cb_last(x):
> > return last_function()
> > d = some_deferred_function()
> > d.addCallback(cb_next)
> > d.addCallback(cb_third, otherargs)
> > d.addCallback(cb_next)
> > which has an extra layer of naming (the callback functions),
> > and
> > requires more effort to follow the flow of what is really just a simple
> > sequence of three functions being called.
>
> But this sequence contains an error of the same form as the "fat":

"this" being which of the two scenarios you quote above?

> while test() != False:
> ...code...

I'm not sure I follow the "error" in this snippet...

> The right sequence using lambda is:
> d = some_deferred_function()
> d.addCallback(next_function)
> d.addCallback(lambda blah: third_function(otherargs, blah))
> d.addCallback(last_function)

By what metric are you judging "right"?

In my scenario, the functions next_function and last_function are not
written to expect any arguments, so they can't be passed straight into
addCallback because any deferred callback will automatically receive
the result of the prior deferred callback in the chain (this is how
Twisted handles asynchronous callbacks for pending operations).
Someone has to absorb that argument (either the lambda, or
next_function itself, which if it is an existing function, needs to be
handled by a wrapper, ala my second example).

Your "right" sequence simply isn't equivalent to what I wrote.
Whether or not next_function is fixable to be used this way is a
separate point, but then you're discussing two different scenarios,
and not two ways to write one scenario.

-- David

Scott David Daniels

unread,
Dec 31, 2004, 2:58:04 PM12/31/04
to
David Bolen wrote:
> Scott David Daniels <Scott....@Acm.Org> writes:
>> while test() != False:
>> ...code...
> I'm not sure I follow the "error" in this snippet...

The code is "fat" -- clearer is:
while test():
...code...

>>The right sequence using lambda is:
>> d = some_deferred_function()
>> d.addCallback(next_function)
>> d.addCallback(lambda blah: third_function(otherargs, blah))
>> d.addCallback(last_function)
> By what metric are you judging "right"?

By a broken metric that requires you to mis-understand the original code
in the same way that I did. It was an idiotic response that required
more careful reading than I am doing this morning. The thing I've seen
in too much code (and though I saw in your code) is code like:

requires_function(lambda: function())

rather than:

requires_function(function)

It happens quite often, and I'm sure you've seen it. But I got your
code wrong, and for that I apologize.

--Scott David Daniels
Scott....@Acm.Org

Simo Melenius

unread,
Dec 31, 2004, 4:37:23 PM12/31/04
to
bo...@oz.net (Bengt Richter) writes:

> Closure is the name for the whole thing, apparently, not just the
> environment the procedure body needs, which was the aspect that I
> (mis)attached the name to.

Which brings me to the point where I'd welcome more flexibility in
writing to variables outside the local scope. This limitation most
often kicks in in closed-over code in function objects, although it's
a more general issue in Python's scoping.

As we know, you can't write to variables that are both non-local and
non-global (globals you can declare "global"). Now that effectively
makes free variables read-only (although, the objects they point to
can _still_ be mutated).

Allowing write access to variables in a closed-over lexical scope
outside the innermost scope wouldn't hurt because:

1) if you need it, you can already do it -- just practice some
cumbersome tricks make suitable arrangements (e.g. the classical
accumulator example uses an array to hold the counter value instead
of binding it directly to the free variable;

2) if you don't need or understand it, you don't have to use it;

3) and at least in function instances: if you accidentally do, it'll
change the bindings within your closure only which is definitely
less dangerous than mutating objects that are bound inside the
closure.

It must be noted, however, that such behaviour would change the way of
hiding nested variable names:

Now it's safe (though maybe lexically confusing) to use the same
variable names in inner functions. This could happen with common names
for temporary variables like "i", "x", "y".

On the other hand, one could introduce a way to declare variables from
global scope or from local scope, with default from lexical scope. (If
you want to explicitly hide an outer binding, you'd declare "local
foo", for example. You can already do "global foo".)

> I see what you are saying (I think), but I think I'd still like a
> full anonymous def, whatever adapter you come up with. And I prefer
> to be persuaded ;-)

I elaborated on this one in a post a few days ago. Indeed, it is
mostly a minor issue that _can_ be worked around(1). The problem is
that it eventually becomes irritating, when repeated all the time, to
name functions even if the name isn't used elsewhere.

It also creates an implicit dependency from the function call (one of
whose arguments points to the once-named function) to the once-named
function. That is, when you refactor some of your code, you must keep
two things paired all the time in your cut+paste maneuvers.


br,
S

(1) Everything can be worked around. In contrast: you can work around
the lack of a syntactic language by typing in machine code manually.
Sound stupid? Yes, it was done decades ago. How about using C to write
a "shell script" equivalent that you need, as a workaround to the
problem of lacking a shell? Stupid? Yes, but less -- it's been done.
How about writing callbacks by passing in a function pointer and a
data pointer, if you don't want to use a language like Python that
automates that task for you? Stupid? Yes, but not much -- it's been
done all the time. How about implementing an _anonymous_ function by
naming it, if you can't do it otherwise?

Message has been deleted

Simo Melenius

unread,
Dec 31, 2004, 4:56:09 PM12/31/04
to
Ian Bicking <ia...@colorstudy.com> writes:

> But I do think there's other ways to approach this. Function


> expressions could get really out of hand, IMHO, and could easily lead
> to twenty-line "expressions". That's aesthetically incompatible with
> Python source, IMHO.

You can already write unaesthetic hundred-line Python functions, if
you want to. Python's syntax doesn't yet impose a restriction on the
number of sequential statements :-) It sounds artificial to impose
such restrictions on these hypothetical "inline blocks", even if by
only allowing them to be plain expressions.

IMHO, the most pythonic way to write an "inline-block" is by reusing
existing keywords, using Python-like start-of-blocks and ending it by
indentation rules:

map (def x:
if foo (x):
return baz_1 (x)
elif bar (x):
return baz_2 (x)
else:
global hab
hab.append (x)
return baz_3 (hab),
[1,2,3,4,5,6])

and for one-liners:

map (def x: return x**2, [1,2,3,4,5,6])

As a side-effect, we also

- got rid of the "lambda" keyword;

- strenghtened the semantics of "def": a "def" already defines a
function so it's only logical to use it to define anonymous
functions, too;

- unified the semantics: function is always a function, and functions
return values by using "return". When learning Python, I learned the
hard way that "lambda"s are expressions, not functions. I'd pay the
burden of writing "return" more often in exchange for better
consistency.


my two cents,
br,
S

Steven Bethard

unread,
Dec 31, 2004, 5:26:38 PM12/31/04
to
Simo Melenius wrote:
> map (def x:
> if foo (x):
> return baz_1 (x)
> elif bar (x):
> return baz_2 (x)
> else:
> global hab
> hab.append (x)
> return baz_3 (hab),
> [1,2,3,4,5,6])

I think this would probably have to be written as:

map (def x:
if foo(x):
return baz_1(x)
elif bar(x):
return baz_2(x)
else:
global hab
hab.append(x)


return baz_3(hab)
, [1,2,3,4,5,6])

or:

map (def x:
if foo(x):
return baz_1(x)
elif bar(x):
return baz_2(x)
else:
global hab
hab.append(x)


return baz_3(hab)
,
[1,2,3,4,5,6])

Note the placement of the comma. As it is,
return baz_3(hab),
returns the tuple containing the result of calling baz_3(hab):

py> def f(x):
... return float(x),
...
py> f(1)
(1.0,)

It's not horrible to have to put the comma on the next line, but it
isn't as pretty as your version that doesn't. Unfortunately, I don't
think anyone's gonna want to revise the return statement syntax just to
introduce anonymous functions.

Steve

Simo Melenius

unread,
Dec 31, 2004, 5:56:30 PM12/31/04
to
Steven Bethard <steven....@gmail.com> writes:

> Simo Melenius wrote:
> > map (def x:
> > if foo (x):
> > return baz_1 (x)
> > elif bar (x):
> > return baz_2 (x)
> > else:
> > global hab
> > hab.append (x)
> > return baz_3 (hab),
> > [1,2,3,4,5,6])
>
> I think this would probably have to be written as:

...


> return baz_3(hab)
> , [1,2,3,4,5,6])
> or:

...


> return baz_3(hab)
> ,
> [1,2,3,4,5,6])
>
> Note the placement of the comma. As it is,
> return baz_3(hab),
> returns the tuple containing the result of calling baz_3(hab):

That one didn't occur to me; creating a one-item tuple with (foo,) has
been odd enough for me: only few times I've seen also the parentheses
omitted.

I did ponder the unambiguousness of the last line, though. One could
suggest a new keyword like "end", but keyword bloat is bad.

(Of course, if we trade the "lambda" keyword for another, new keyword
we're not exactly _adding_ keywords... :))

> It's not horrible to have to put the comma on the next line, but it
> isn't as pretty as your version that doesn't. Unfortunately, I don't
> think anyone's gonna want to revise the return statement syntax just
> to introduce anonymous functions.

There might not be a return statement: the anonymous function might
conditionally return earlier and have side-effects at the end of the
block (to implicitly return None). So the block-ending would need to
fit after any statement and be strictly unambiguous.


br,
S

Doug Holton

unread,
Dec 31, 2004, 6:09:53 PM12/31/04
to
Steven Bethard wrote:

> Simo Melenius wrote:
>
>> map (def x:
>> if foo (x):
>> return baz_1 (x)
>> elif bar (x):
>> return baz_2 (x)
>> else:
>> global hab
>> hab.append (x)
>> return baz_3 (hab),
>> [1,2,3,4,5,6])
>
>
> I think this would probably have to be written as:

Right the comma plus other things make this difficult for a parser to
handle correctly. Other people have already come up with working solutions.

We have a special way to pass a multiline closure as a parameter to a
function. Put it outside the parameter list.

First, the single-line way using curly braces:

newlist = map({x as int | return x*x*x}, [1,2,3,4,5,6])

Then the multi-line way. I had to add an overload of map to support
reversing the order of parameters (list first, then the closure):

newlist = map([1,2,3,4,5,6]) def (x as int):
return x*x*x

for item in newlist:
print item

Paul L. Du Bois

unread,
Dec 31, 2004, 6:41:41 PM12/31/04
to
Alex Martelli wrote:
> We should have an Evilly Cool Hack of the Year, and I nominate
> Paul Du Bois's one as the winner for 2004. Do I hear any second...?

Oh bother, I just realized I sent my first reply using a good email
address. Hope that cancel goes through quickly.

Anyway, thank you! I've submitted it as a recipe. It includes a
less-evil portable version, which might be improved further if PEP 288
ever comes through.

p

The recipe:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/361452

Steven Bethard

unread,
Dec 31, 2004, 7:00:22 PM12/31/04
to

Ok, now that we're past 0:00:00 UTC, I'll second that nomination! ;)

Steve

P.S. Happy New Year all!

Bengt Richter

unread,
Dec 31, 2004, 9:56:33 PM12/31/04
to

ISTM you don't need "end" -- just put the def expression in parens,
and let the closing paren end it, e.g.:

map((def x:


if foo (x):
return baz_1 (x)
elif bar (x):
return baz_2 (x)
else:
global hab
hab.append (x)

return baz_3 (hab)), [1,2,3,4,5,6])

>
>(Of course, if we trade the "lambda" keyword for another, new keyword
>we're not exactly _adding_ keywords... :))
>
>> It's not horrible to have to put the comma on the next line, but it
>> isn't as pretty as your version that doesn't. Unfortunately, I don't
>> think anyone's gonna want to revise the return statement syntax just
>> to introduce anonymous functions.
>
>There might not be a return statement: the anonymous function might
>conditionally return earlier and have side-effects at the end of the
>block (to implicitly return None). So the block-ending would need to
>fit after any statement and be strictly unambiguous.

Just use parens as necessary or when in doubt ;-)

Regards,
Bengt Richter

Terry Reedy

unread,
Dec 31, 2004, 10:25:40 PM12/31/04
to pytho...@python.org

"Simo Melenius" <firstname...@iki.fi-spam> wrote in message
news:m24qi2w3...@geist.local...

> bo...@oz.net (Bengt Richter) writes:
> Which brings me to the point where I'd welcome more flexibility in
> writing to variables outside the local scope.

This idea was discussed extensively on PyDev perhaps 2 years ago. (You can
check the archived summaries if interested enough ;-) As I remember, there
was no consensus either on the desireability of such a mechanism or on the
syntax (several were proposed).

Terry J. Reedy

Simo Melenius

unread,
Jan 1, 2005, 4:26:59 PM1/1/05
to
bo...@oz.net (Bengt Richter) writes:

> ISTM you don't need "end" -- just put the def expression in parens,
> and let the closing paren end it, e.g.:

I first rejected any parens as not being native to how
classes/toplevel functions/control blocks are written in Python.
However, this looks quite clear to me. I'd expect that in most cases
it would be difficult to mistake a block of statements in parentheses
with e.g. tuple notation. And parensing works with the old "lambda"
already, of course.


br,
S

Simo Melenius

unread,
Jan 1, 2005, 4:35:34 PM1/1/05
to
Doug Holton <a@b.c> writes:

> Steven Bethard wrote:
> > Simo Melenius wrote:
> >> map (def x:

Oops, I found a typo alreay. I meant to write "def (x):" -- no name
for anonymous functions but just the argument list, please :)

> Right the comma plus other things make this difficult for a parser to
> handle correctly. Other people have already come up with working

It is difficult since in Python we don't enjoy the ugly luxury of
stuffing statements inside {}s. But as Bengt pointed out, parentheses
don't actually look bad at all in this case.

> Then the multi-line way. I had to add an overload of map to support
> reversing the order of parameters (list first, then the closure):
>
> newlist = map([1,2,3,4,5,6]) def (x as int):
> return x*x*x

That doesn't seem to scale if you want to pass more than one anonymous
function arguments to the function or call an arbitrary function with
parameters in arbitrary order.


br,
S

Paul Rubin

unread,
Jan 5, 2005, 1:45:11 PM1/5/05
to
Nick Coghlan <ncog...@iinet.net.au> writes:
> Do you consider generator expressions or list comprehensions deficient
> because they don't allow several statements in the body of the for
> loop?

I don't see what it would mean to do otherwise.

Nick Coghlan

unread,
Jan 6, 2005, 6:02:43 AM1/6/05
to Python List

Exactly the same as a suite would in the innermost portion of the equivalent
explicit generator (i.e. where the implicit "yield <expr>" currently ends up).

If you could put a suite inside a function expression (i.e. replacing the
implicit "return <expr>") why not inside generator expressions as well?

Cheers,
Nick.

--
Nick Coghlan | ncog...@email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net

Alan Gauld

unread,
Jan 6, 2005, 5:36:00 PM1/6/05
to
On Thu, 30 Dec 2004 23:28:46 +1000, Nick Coghlan
<ncog...@iinet.net.au> wrote:

> GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
> Getting rid of lambda seems like a worthy goal,

Can I ask what the objection to lambda is?
1) Is it the syntax?
2) Is it the limitation to a single expression?
3) Is it the word itself?

I can sympathise with 1 and 2 but the 3rd seems strange since a
lambda is a well defined name for an anonymous function used in
several programming languages and originating in lambda calculus
in math. Lambda therefore seems like a pefectly good name to
choose.

So why not retain the name lambda but extend or change the syntax
to make it more capable rather than invent a wholly new syntax
for lambdas?

Slightly confused, but since I only have time to read these
groups regularly when I'm at home I have probably missed the bulk
of the discussion over the years.

Alan G.
Author of the Learn to Program website
http://www.freenetpages.co.uk/hp/alan.gauld

Jeff Shannon

unread,
Jan 6, 2005, 7:23:36 PM1/6/05
to
Alan Gauld wrote:

> Can I ask what the objection to lambda is?
> 1) Is it the syntax?
> 2) Is it the limitation to a single expression?
> 3) Is it the word itself?
>
> I can sympathise with 1 and 2 but the 3rd seems strange since a
> lambda is a well defined name for an anonymous function used in
> several programming languages and originating in lambda calculus
> in math. Lambda therefore seems like a pefectly good name to
> choose.

I think that the real objection is a little bit of 1), and something
that's kinda close to 2), but has nothing to do with 3).

The issue isn't that lambdas are bad because they're limited to a
single expression. The issue is that they're an awkward special case
of a function, which was added to the language to mollify
functional-programming advocates but which GvR never felt really "fit"
into Python. Other, more pythonic functional-programming features
have since been added (like list comprehensions and iterators).

It seems to me that in other, less-dynamic languages, lambdas are
significantly different from functions in that lambdas can be created
at runtime. In Python, *all* functions are created at runtime, and
new ones can be defined at any point in execution, so lambdas don't
get that advantage. Thus, their advantages are limited to the fact
that they're anonymous (but names are treated differently in Python
than in most other languages, so this is of marginal utility), and
that they can be created inline. This last bit makes them suitable
for creating quick closures (wrapping a function and tweaking its
parameters/return values) and for creating a delayed-execution object
(e.g. callbacks), so there's a lot of pressure to keep them, but
they're still a special case, and "special cases aren't special enough
to break the rules".

Jeff Shannon
Technician/Programmer
Credit International

Paul Rubin

unread,
Jan 6, 2005, 7:31:57 PM1/6/05
to
Jeff Shannon <je...@ccvcorp.com> writes:
> It seems to me that in other, less-dynamic languages, lambdas are
> significantly different from functions in that lambdas can be created
> at runtime.

What languages are those, where you can create anonymous functions
at runtime, but not named functions?! That notion is very surprising
to me.

Jeff Shannon

unread,
Jan 6, 2005, 10:04:41 PM1/6/05
to
Paul Rubin wrote:

Hm, I should have been more clear that I'm inferring this from things
that others have said about lambdas in other languages; I'm sadly
rather language-deficient (especially as regards *worthwhile*
languages) myself. This particular impression was formed from a
recent-ish thread about lambdas....

http://groups-beta.google.com/group/comp.lang.python/messages/1719ff05118c4a71,7323f2271e54e62f,a77677a3b8ff554d,844e49bea4c53c0e,c126222f109b4a2d,b1c9627390ee2506,0b40192c36da8117,e3b7401c3cc07939,6eaa8c242ab01870,cfeff300631bd9f2?thread_id=3afee62f7ed7094b&mode=thread

(line-wrap's gonna mangle that, but it's all one line...)

Looking back, I see that I've mis-stated what I'd originally
concluded, and that my original conclusion was a bit questionable to
begin with. In the referenced thread, it was the O.P.'s assertion
that lambdas made higher-order and dynamic functions possible. From
this, I inferred (possibly incorrectly) a different relationship
between functions and lambdas in other (static) languages than exists
in Python.

Doug Holton

unread,
Jan 6, 2005, 10:02:46 PM1/6/05
to
Alan Gauld wrote:
>>GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
>>Getting rid of lambda seems like a worthy goal,
>
>
> Can I ask what the objection to lambda is?
> 1) Is it the syntax?
> 2) Is it the limitation to a single expression?
> 3) Is it the word itself?
>
> I can sympathise with 1 and 2 but the 3rd seems strange since a
> lambda is a well defined name for an anonymous function used in
> several programming languages and originating in lambda calculus
> in math. Lambda therefore seems like a pefectly good name to
> choose.

I agree with keeping lambda functionality, and I don't care what name is
used, but there are people who do not like "lambda":
http://lambda-the-ultimate.org/node/view/419#comment-3069
The word "lambda" is meaningless to most people. Of course so is "def",
which might be why Guido van Robot changed it to "define":
http://gvr.sourceforge.net/screen_shots/

Even a simple word like "type" can be difficult to explain to beginners:
http://lambda-the-ultimate.org/node/view/337

Python is easier for beginners to learn than other mainstream
programming languages (like java or C++), but that's not to say it
doesn't have some stumbling blocks for beginners of course:
http://www.linuxjournal.com/article/5028

> So why not retain the name lambda but extend or change the syntax
> to make it more capable rather than invent a wholly new syntax
> for lambdas?

Yes, I agree, and either keep the "lambda" keyword or else reuse the
"def" keyword for anonymous methods. See this page Steven Bethard
created: http://www.python.org/moin/AlternateLambdaSyntax

I really don't think anyone should worry about lambda disappearing.

By the way, you've done great work with your learning to program site
and all the help you've given on the python-tutor list:

Terry Reedy

unread,
Jan 6, 2005, 10:30:42 PM1/6/05
to pytho...@python.org

"Alan Gauld" <alan....@btinternet.com> wrote in message
news:f1frt0dvi9tt37roe...@4ax.com...

> On Thu, 30 Dec 2004 23:28:46 +1000, Nick Coghlan
> <ncog...@iinet.net.au> wrote:
>
>> GvR has commented that he want to get rid of the lambda keyword for
>> Python 3.0.
>> Getting rid of lambda seems like a worthy goal,
>
> Can I ask what the objection to lambda is?
> 1) Is it the syntax?
> 2) Is it the limitation to a single expression?
> 3) Is it the word itself?

Depending on the person, any of the 3. Plus add
4) The constant complaints re: 2)

> I can sympathise with 1 and 2 but the 3rd seems strange since a
> lambda is a well defined name for an anonymous function used in
> several programming languages and originating in lambda calculus
> in math.

And that is why 'lambda' is wrong -- in Python, it is only an abbreviation
for a restricted group of def statements, which is *not* its 'well defined'
usage. Hence complaints re 2. If the syntax were def x: x + 2, etc, I
suspect the complaints would be far fewer.

For some new programmers, 'lambda' is as meaningless as elle*. All other
Python keywords are English words or obvious abbreviations thereof.

> So why not retain the name lambda but extend or change the syntax
> to make it more capable rather than invent a wholly new syntax
> for lambdas?

That you suggest this illustrates, to me, what is wrong with the name ;-)

Terry J. Reedy

* The Spanish name for the letter 'll', pronounced el-yea, which comes
after 'l' in their alphabet.

Alan Gauld

unread,
Jan 7, 2005, 3:55:19 AM1/7/05
to
On Thu, 06 Jan 2005 21:02:46 -0600, Doug Holton <a@b.c> wrote:
> used, but there are people who do not like "lambda":
> http://lambda-the-ultimate.org/node/view/419#comment-3069
> The word "lambda" is meaningless to most people. Of course so is "def",
> which might be why Guido van Robot changed it to "define":
> http://gvr.sourceforge.net/screen_shots/

The unfamiliar argument doesn't work for me. After all most
people are unfamiliar with complex numbers (or imaginary) numbers
but python still provides a complex number type. Just because the
name is unfamiliar to some doesn't mean we shouldn't use the
term if its the correct one for the concept.

Hopefully anyone who wants to use anonymous functions will know
that such are called lambdas and hopefully will have studied
lambda calculus to at least some level - certainly CS majors and
software engineering types should have...

> Python is easier for beginners to learn than other mainstream
> programming languages

Absolutely, but it has to decide (and soon I think) how important
that role is in the development of the language. Many of the more
recent features are beginner hostile - slots, properties, meta
classes, decorators etc... So is Python going to consciously try
to remain beginner friendly (which it remains by simply ignoring
the newer fatures!) or deliberately go for the "fully featured"
general purpose audience?

> Yes, I agree, and either keep the "lambda" keyword or else reuse the
> "def" keyword for anonymous methods. See this page Steven Bethard
> created: http://www.python.org/moin/AlternateLambdaSyntax

I agree, I'm much more concerned about the idea of losing
anonymous functions (aka lambdas) than about losing the name
lambda, its just that the name is so descriptive of what it does!
( In fact it was seeing the name lambda appearing in a Lisp
programme I was reading that got me started in Lambda calculus
many years ago...)

> By the way, you've done great work with your learning to program site
> and all the help you've given on the python-tutor list:

Aw shucks! Thanks ;-)

Anna

unread,
Jan 7, 2005, 6:54:50 AM1/7/05
to
Okay, I tried to post this previously but ran into the new Google
groups system which appears to have sent my original response into the
ether... Oops. Trying again.

Hi Alan:

Having taken some calculus (derivatives, limits, some integrals) but
never even heard of lambda calculus, to me, lambda means absolutely
NOTHING. Less than nothing.

Actually, in my encounters with others code in Python (including
reading near 1000 recipes for the recent edition of the Cookbook), what
I've discovered is that what lambda mostly means to me is:
"I don't wanna write clear, elegant Python - I wanna write fancy,
clever, obfuscated code, and lambda lets me do that!"

I've seen maybe 1 case in 10 where lambda appears, to me, to allow
clearer, cleaner code than defining a function. Most cases-it's an
ugly, incomprehensible hack.

So, if people really need anonymous functions in Python (and
apparently, they do), then at least lets get a word that actually
*means* something. Every other word in Python has an obvious meaning.
lambda doesn't.

So, I guess I don't like the word itself - any more than I like how
it's (mostly) used.

Anna Martelli Ravenscroft

Paul Rubin

unread,
Jan 7, 2005, 7:12:54 AM1/7/05
to
"Anna" <anna...@gmail.com> writes:
> Having taken some calculus (derivatives, limits, some integrals) but
> never even heard of lambda calculus, to me, lambda means absolutely
> NOTHING. Less than nothing.

Lambda calculus is from mathematical logic, but more to the point
"lambda" has been the term used in Lisp for this operation since time
immemorial. Since the kinds of programmers who want to use anonymous
functions have probably been exposed to Lisp at one time or another,
"lambda" should not cause any confusion.

Steve Holden

unread,
Jan 7, 2005, 7:23:23 AM1/7/05
to

That's probably not the most enthusiastic evangelical approach to
functional programming I've ever heard :-)

Perhaps what we really need is a good Lisp subsystem for Python?

regards
Steve
--
Steve Holden http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/
Holden Web LLC +1 703 861 4237 +1 800 494 3119

Paul Rubin

unread,
Jan 7, 2005, 7:41:54 AM1/7/05
to
Steve Holden <st...@holdenweb.com> writes:
> Perhaps what we really need is a good Lisp subsystem for Python?

I've thought the other way around, it would be nice to have a Python
subsystem for Lisp.

Jacek Generowicz

unread,
Jan 7, 2005, 8:38:01 AM1/7/05
to
"Anna" <anna...@gmail.com> writes:

> Having taken some calculus (derivatives, limits, some integrals) but
> never even heard of lambda calculus, to me, lambda means absolutely
> NOTHING. Less than nothing.

And before you took calculus, the chances are that derivatives, limits
and integrals meant less than nothing to you.

But now, I am quite sure, you know that in Python lambda is a keyword
which creates anonymous functions. Now that you know what lambda does,
what's the problem with it? (It certainly doesn't mean "Less than
nothing" to you now.)

> So, I guess I don't like the word itself

Fair enough. I guess there are people out there who might have a
distaste for the word "class" or "def" or any of the other words which
are keywords in Python.

> Every other word in Python has an obvious meaning. lambda doesn't.

Obvious to whom?

The meaning of every word is obvious, once you have been taught it;
and a complete mystery if you have not.

What do you make of "seq[2:-2]"? It means "less than nothing" to the
uninitiated. Just like lambda.

Getting students in my Python courses to understand "seq[2:-2]" takes
about as much (maybe even a bit more) effort as getting them to
understand lambda[*]. But once they have been taught these features,
they can handle them just fine.


[*] Funnily enough, getting them to understand that "lambda x: fn(x)"
is just a very silly way of writing "fn", can be quite a struggle
at times ... but that's probably a consequence of the context in
which lambda is introduced.

Steven Bethard

unread,
Jan 7, 2005, 10:44:57 AM1/7/05
to
Alan Gauld wrote:
> On Thu, 06 Jan 2005 21:02:46 -0600, Doug Holton <a@b.c> wrote:
>
>>used, but there are people who do not like "lambda":
>>http://lambda-the-ultimate.org/node/view/419#comment-3069
>>The word "lambda" is meaningless to most people. Of course so is "def",
>>which might be why Guido van Robot changed it to "define":
>>http://gvr.sourceforge.net/screen_shots/
>
>
> The unfamiliar argument doesn't work for me. After all most
> people are unfamiliar with complex numbers (or imaginary) numbers
> but python still provides a complex number type. Just because the
> name is unfamiliar to some doesn't mean we shouldn't use the
> term if its the correct one for the concept.

I'm not sure this is really a fair comparison. What's the odds that if
you're unfamiliar with complex numbers that you're going to have to read
or write code that uses complex numbers? Probably pretty low. I don't
think I've ever had to read or write such code, and I *do* understand
complex numbers. Lambdas, on the other hand, show up in all kinds of
code, and even though I hardly ever use them myself, I have to
understand them because other people do (over-)use them.

Steve

Nick Coghlan

unread,
Jan 7, 2005, 11:00:50 AM1/7/05
to Python List
Jacek Generowicz wrote:
> [*] Funnily enough, getting them to understand that "lambda x: fn(x)"
> is just a very silly way of writing "fn", can be quite a struggle
> at times ... but that's probably a consequence of the context in
> which lambda is introduced.

If you genuinely taught them that, you may have done them a disservice:

Py> def f(x):
... print x
...
Py> f1 = f
Py> f2 = lambda x: f(x)
Py> f1("hi")
hi
Py> f2("hi")
hi
Py> def f(x):
... print x * 2
...
Py> f1("hi")
hi
Py> f2("hi")
hihi

Nick Coghlan

unread,
Jan 7, 2005, 11:11:18 AM1/7/05
to Python List
Paul Rubin wrote:
> "Anna" <anna...@gmail.com> writes:
>
>>Having taken some calculus (derivatives, limits, some integrals) but
>>never even heard of lambda calculus, to me, lambda means absolutely
>>NOTHING. Less than nothing.
>
>
> Lambda calculus is from mathematical logic, but more to the point
> "lambda" has been the term used in Lisp for this operation since time
> immemorial.

I think that's part of the problem though - people familiar with lambda calculus
and Lisp's lambdas want Python's lambdas to be equally capable, and they just
plain *aren't*.

If you have a complex function, the Pythonic way is to give it a meaningful
name. Having a way to defer evaluation of a simple expression *is* quite handy,
but 'lambda' is the wrong name for it - the parallels to lambda calculus and
Lisp's lambda functions are likely to be misleading, rather than helpful.

Add in the fact that there are many, many Python programmers with non-CS
backgrounds, and the term 'lambda' sticks out like a sore thumb from amongst
Python's other English-based keywords. 'def' is probably the second-most cryptic
when you first encounter it, but it is a good mnemonic for "define a function",
so it's still easy to parse. "Lambda is the term mathematicians use to refer to
an anonymous function" is nowhere near as grokkable ;)

For me, the alternative syntax discussion is based on 3 of the 4 mentioned reasons:

1. The syntax
I don't like re-using colons as something other than suite delimiters - it
breaks up the affected expression too much (particularly function calls). Code
with dict literals inside function calls bugs me for the same reason (it's OK
when the literal is separated out into an assignment statement for the dict).
It's also too easy to write lambdas which look ambiguous, even though they
technically aren't.
Finally, Python has a reputation as "executable pseudocode". Lambda
expressions don't read like any sort of psuedocode you're likely to see outside
a maths department.

2. The limitation to a single expression
I consider this no more of a problem than the restriction to a single
expression in the main loop of a generator expression or a list comprehension.
When those get too complicated, you switch to using a real for loop somewhere.
Deferred expressions are no different - when the guts get too complicated,
switch to a named function.

3. The word 'lambda' itself
This _is_ one of my objections for the reasons stated above: for people
unfamiliar with the term, they don't know what it is; for people familiar with
the term, it isn't what they think it should be.
Python already has a perfectly good keyword for functions, which has the
additional virtue of being half the length of lambda (this matters, since this
is a keyword that gets embedded in expressions - all the other keywords
currently in that category are three letters or less: and, or, is, in, for)

4. People complaining about 2
Oh hell yes, this bugs me. And I think changing the syntax and calling them
"deferred expressions" instead of "lambdas" would go a long way towards
eliminating the griping.

Jacek Generowicz

unread,
Jan 7, 2005, 11:38:56 AM1/7/05
to
Nick Coghlan <ncog...@iinet.net.au> writes:

> Jacek Generowicz wrote:
> > [*] Funnily enough, getting them to understand that "lambda x: fn(x)"
> > is just a very silly way of writing "fn", can be quite a struggle
> > at times ... but that's probably a consequence of the context in
> > which lambda is introduced.
>
> If you genuinely taught them that, you may have done them a disservice:

Yes, I was wondering whether I should add lots of caveats to the above.

> Py> def f(x):
> ... print x
> ...
> Py> f1 = f
> Py> f2 = lambda x: f(x)
> Py> f1("hi")
> hi
> Py> f2("hi")
> hi
> Py> def f(x):
> ... print x * 2
> ...
> Py> f1("hi")
> hi
> Py> f2("hi")
> hihi

There are far less contrived situations in which my original statement
(taken at face value) is wrong. Functions with optional arguments, for
example.

What actually happens is that some of them end up writing:

lambda x: int(x)

in a situation where they want to specify something which will perform
conversions of the type:

"123" -> 123

ie, string to integer conversions.

Usually one or two have trouble grasping that "int" would be perfectly
adequate in this situation.

Nick Coghlan

unread,
Jan 7, 2005, 12:49:01 PM1/7/05
to Python List
Jacek Generowicz wrote:
> Yes, I was wondering whether I should add lots of caveats to the above.

I thought that might be the case. When teaching, I guess I can understand the
need to avoid "well, technically, this isn't always true". It sounds like the
students were having a tough enough time of it already :)

> Usually one or two have trouble grasping that "int" would be perfectly
> adequate in this situation.

The ability to pass around functions at run-time was probably the hardest thing
to get my head around when I started with Python, after a history of working in
languages where "the compiler knows about types and functions, and the runtime
knows about variables and instances".

Donn Cave

unread,
Jan 7, 2005, 2:35:54 PM1/7/05
to
In article <10trupr...@corp.supernews.com>,
Jeff Shannon <je...@ccvcorp.com> wrote:
...

> Hm, I should have been more clear that I'm inferring this from things
> that others have said about lambdas in other languages; I'm sadly
> rather language-deficient (especially as regards *worthwhile*
> languages) myself. This particular impression was formed from a
> recent-ish thread about lambdas....
>
> http://groups-beta.google.com/group/comp.lang.python/messages/1719ff05118c4a71
> ,7323f2271e54e62f,a77677a3b8ff554d,844e49bea4c53c0e,c126222f109b4a2d,b1c962739
> 0ee2506,0b40192c36da8117,e3b7401c3cc07939,6eaa8c242ab01870,cfeff300631bd9f2?th
> read_id=3afee62f7ed7094b&mode=thread
>
> (line-wrap's gonna mangle that, but it's all one line...)
>
> Looking back, I see that I've mis-stated what I'd originally
> concluded, and that my original conclusion was a bit questionable to
> begin with. In the referenced thread, it was the O.P.'s assertion
> that lambdas made higher-order and dynamic functions possible. From
> this, I inferred (possibly incorrectly) a different relationship
> between functions and lambdas in other (static) languages than exists
> in Python.

One could easily be led astray by that post. He may be right
in some literal sense about "the true beauty of lambda function",
inasmuch as beauty is in the eye of the beholder, but in practical
terms, functions are functions.

I took this up on comp.lang.functional some time back. I rewrote
a well known piece of Haskell (State monad), moving functions from
lambda expressions to named function declarations in a "where"
clause and I think undisputably making it easier to understand,
and I asserted that this is representative of the general case -
lambda is a non-essential feature in Haskell. I don't know if
anyone was persuaded, but I didn't see any counter-arguments either.

But of course even if I'm right about that, it doesn't mean the
feature should be stripped from Haskell, that would be an atrocity.
It may not be essential, but it's eminently useful and natural.

Is it useful and natural in Python? Is it worth breaking code over?
Why do we even bother to discuss this here? There aren't good answers
to those questions.

Donn Cave, do...@u.washington.edu

Paul Rubin

unread,
Jan 7, 2005, 4:24:39 PM1/7/05
to
Nick Coghlan <ncog...@iinet.net.au> writes:
> Add in the fact that there are many, many Python programmers with
> non-CS backgrounds, and the term 'lambda' sticks out like a sore thumb
> from amongst Python's other English-based keywords. 'def' is probably
> the second-most cryptic when you first encounter it, but it is a good
> mnemonic for "define a function", so it's still easy to parse. "Lambda
> is the term mathematicians use to refer to an anonymous function" is
> nowhere near as grokkable ;)

Richard Feynman told a story about being on a review committee for
some grade-school science textbooks. One of these book said something
about "counting numbers" and it took him a while to figure out that
this was a new term for what he'd been used to calling "integers".

"Integer" is a math term but I think that if we need to use the
concept of integers with someone unfamiliar with the term, it's best
to just introduce the term and then use it, rather than make up new
terminology like "counting numbers" even if those words sound more
like conversational English.

For the same reason I don't have any problem with "lambda", though
it's not that big a deal.

I also just can't believe that Pythonistas keep getting into these
arguments over whether lambda is too confusing, while at the same time
there's no such discussion over far more abstruse Python features like
metaclasses.

Bengt Richter

unread,
Jan 7, 2005, 5:02:19 PM1/7/05
to
On 07 Jan 2005 14:38:01 +0100, Jacek Generowicz <jacek.ge...@cern.ch> wrote:
[...]

>
>[*] Funnily enough, getting them to understand that "lambda x: fn(x)"
> is just a very silly way of writing "fn", can be quite a struggle
> at times ... but that's probably a consequence of the context in
> which lambda is introduced.
Actually, it may _usually_ be silly, but it could be a way of deferring
a name lookup instead of using the current binding of a name:

>>> def bar(): return 'this is bar'
...
>>> def foo(f=bar): print f()
...
>>> def bar(): return 'this is updated bar'
...
>>> foo()
this is bar
>>> def foo(f=lambda:bar()): print f()
...
>>> foo()
this is updated bar
>>> def bar(): return 'this updated bar was picked up by silly lambda'
...
>>> foo()
this updated bar was picked up by silly lambda

Regards,
Bengt Richter

Bengt Richter

unread,
Jan 7, 2005, 6:34:16 PM1/7/05
to
On 07 Jan 2005 13:24:39 -0800, Paul Rubin <http://phr...@NOSPAM.invalid> wrote:

>Nick Coghlan <ncog...@iinet.net.au> writes:
>> Add in the fact that there are many, many Python programmers with
>> non-CS backgrounds, and the term 'lambda' sticks out like a sore thumb
>> from amongst Python's other English-based keywords. 'def' is probably
>> the second-most cryptic when you first encounter it, but it is a good
>> mnemonic for "define a function", so it's still easy to parse. "Lambda
>> is the term mathematicians use to refer to an anonymous function" is
>> nowhere near as grokkable ;)
>
>Richard Feynman told a story about being on a review committee for
>some grade-school science textbooks. One of these book said something
>about "counting numbers" and it took him a while to figure out that
>this was a new term for what he'd been used to calling "integers".
>
>"Integer" is a math term but I think that if we need to use the
>concept of integers with someone unfamiliar with the term, it's best
>to just introduce the term and then use it, rather than make up new
>terminology like "counting numbers" even if those words sound more
>like conversational English.

<rant>
It's an example of the educational establishment's conspiracy to keep
children from too quickly outshining teachers who feel threatened by raw
intelligence rather than elated at the opportunity to help it form.
Forcing kids to learn a throwaway baby-goo language before they
get the real thing is a kind of abuse IMO.
</rant>

>
>For the same reason I don't have any problem with "lambda", though
>it's not that big a deal.
>
>I also just can't believe that Pythonistas keep getting into these
>arguments over whether lambda is too confusing, while at the same time
>there's no such discussion over far more abstruse Python features like
>metaclasses.

Some things are considered to be behind the pythonostasis and only for the priests? ;-)

Regards,
Bengt Richter

Jeff Shannon

unread,
Jan 7, 2005, 7:12:47 PM1/7/05
to
Paul Rubin wrote:

> Richard Feynman told a story about being on a review committee for
> some grade-school science textbooks. One of these book said something
> about "counting numbers" and it took him a while to figure out that
> this was a new term for what he'd been used to calling "integers".

With all due respect to Richard Feynman, I'd have thought that
"counting numbers" would be non-negative integers, rather than the
full set of integers... which, I suppose, just goes to show how
perilous it can be to make up new, "more natural" terms for things. ;)

Alan Gauld

unread,
Jan 7, 2005, 7:36:43 PM1/7/05
to
On Fri, 07 Jan 2005 08:44:57 -0700, Steven Bethard
<steven....@gmail.com> wrote:
> > The unfamiliar argument doesn't work for me. After all most
> > people are unfamiliar with complex numbers (or imaginary) numbers
>
> complex numbers. Lambdas, on the other hand, show up in all kinds of
> code, and even though I hardly ever use them myself, I have to
> understand them because other people do (over-)use them.

That's a fair point I suppose but I still don't see much point in
introducing new names and syntaxes when the existing name is a
sensible one, even if unfamiliar to many. After all it works in
Lisp and Haskell - Haskell even uses Lambda as its emblem...

And besides it may just encoursage some to go and explore Lambda
calculus, it did for me... And my programing improved enormously
as a result. So maybe having the name as a stimulant to research
is a good thing...

OTOH I do accept the point made by another poster that Pythons
single expression limitations mean that they are a poor imitation
of lambdas in other languages. And provided I get some kind of
anonymous code block to pass around I don't care too much if the
name lambda disappears, provided the concept remains! And the
syntax is reasonably simple to use where lambdas get used now.

(Without lambdas of any kind I might finally make the jump
to Ruby that I've been toying with for a while but I just hate
those Perl-like @ symbols...)

<OT::Aside>
We often see people stating that programming shouldn't be called
a science because there is no mathematical basis, such claimants
usually haven't seen Predicate or Lambda calculus. I know, I used
to be in that category and while I don't explicitly use either
when programming (or only rarely) awareness of the principles
suddenly made a lot of the "rules of programming" that I'd been
taught make perfect sense (no side-effects, avoid globals, etc)
Its like the fact that I rarely use Maxwell's equations when
designing electronic circuits - but its nice to
know what the underlying theory is actually based on!
</Aside>

All IMHO of course! :-)

Terry Hancock

unread,
Jan 7, 2005, 8:03:44 PM1/7/05
to pytho...@python.org

Speaking of "natural", I think "counting numbers" would indeed be
the "natural numbers" 1,2,3, ...

So, yeah, I agree. Jargon definitely has its place: I once told a colleague
(in an effort to avoid jargon) that one star was "faster" than another star.

Only after registering his incomprehension, did I really think about the
fact that that had at least 4 or 5 possible meanings (in fact, I meant that
the frequency of its periodic change in radial velocity was higher -- but
I could've meant that it was receeding faster, had a higher amplitude of
radial velocity change, etc.).

I think "lambda" is fine. Basically if you find you need one, you probably
ought to be using the CS term anyway. It would make looking up the
theory that much easier, anyway.

Cheers,
Terry

--
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

BJörn Lindqvist

unread,
Jan 7, 2005, 8:23:32 PM1/7/05
to pytho...@python.org
The more features a language has, the harder it becomes to learn. An
example of that is C++ which has almost everything. Classes, structs,
templates, strange keywords that noone uses like auto, inline const,
passing by reference/value, enum, union, lots of macros, multiple
inheritance, namespaces etc. I'll bet that you could shave off 50% of
C++'s features and it would still be 95% as usable[*].

Judging by the number of PEP proposals and syntax additions that
appear on the mailing list every day Python could some day become as
bloated. We don't want that, do we? So how do we avoid feature bloat?:

1. We stop adding features, either now or at some point in the future.
2. We remove some features.

Either way we have to put a limit on the number of features we want
Python to have. Let's call that number X where X is a number much
smaller than infinity. With a set limit, the discussion becomes "which
features should be selected for use in Python?" instead of "should
this feature be added/removed?" Personally, I don't care either way if
lambda is removed or retained, but I would much rather have the "with"
keyword someone proposed, do-while loops or whatever. I think there
are way too many good features out there just waiting to take lambdas
place.

* - Please don't ask me to make that bet.

--
mvh Björn

Steven Bethard

unread,
Jan 7, 2005, 8:27:42 PM1/7/05
to
Alan Gauld wrote:
> On Fri, 07 Jan 2005 08:44:57 -0700, Steven Bethard
> <steven....@gmail.com> wrote:
>
>>>The unfamiliar argument doesn't work for me. After all most
>>>people are unfamiliar with complex numbers (or imaginary) numbers
>>
>>complex numbers. Lambdas, on the other hand, show up in all kinds of
>>code, and even though I hardly ever use them myself, I have to
>>understand them because other people do (over-)use them.
>
>
> That's a fair point I suppose but I still don't see much point in
> introducing new names and syntaxes when the existing name is a
> sensible one, even if unfamiliar to many. After all it works in
> Lisp and Haskell - Haskell even uses Lambda as its emblem...

Yeah, I personally expect that if GvR doesn't like lambda now, he won't
like any of the new syntaxes either. But I'm in the camp that won't
miss lambda if it's gone, so I'm not too worried. ;)

Steve

James Stroud

unread,
Jan 7, 2005, 10:28:09 PM1/7/05
to pytho...@python.org
On Friday 07 January 2005 01:24 pm, Paul Rubin wrote:
> Nick Coghlan <ncog...@iinet.net.au> writes:
> > Add in the fact that there are many, many Python programmers with
> > non-CS backgrounds, and the term 'lambda' sticks out like a sore thumb
> > from amongst Python's other English-based keywords.
>
> Richard Feynman told a story about being on a review committee for
> some grade-school science textbooks. One of these book said something
> about "counting numbers" and it took him a while to figure out that
> this was a new term for what he'd been used to calling "integers".


I think we should not try too hard to make everything "English" like. Its a
crappy language anyway (though its the only one I speak good). Matt Neuberg,
in _AppleScript: The Definitive Guide_, refers to "the English-likeness
monster". His example is that instead of

x = 4

you have to say

copy 4 to x

I think every reader of this list would prefer to look at the former.

The point is that once we learn new symbolics of expression, they are as
simple to decipher as plain old English if we format properly and
gIvEnThAtwEiNcLuDEsOmEhElPfUlfORmaTtInGInOuRcOdEFroMtImEtOtiME.

So I think that being fearful of new additions to the language (read "more
ability for expression") is mainly fear of abuse by poor programmers--and
that is akin to being afraid of the dark.

James

--
James Stroud, Ph.D.
UCLA-DOE Institute for Genomics and Proteomics
611 Charles E. Young Dr. S.
MBI 205, UCLA 951570
Los Angeles CA 90095-1570
http://www.jamesstroud.com/

Roy Smith

unread,
Jan 7, 2005, 11:08:08 PM1/7/05
to
In article <mailman.345.11051548...@python.org>,
James Stroud <jst...@mbi.ucla.edu> wrote:

> On Friday 07 January 2005 01:24 pm, Paul Rubin wrote:
> > Nick Coghlan <ncog...@iinet.net.au> writes:
> > > Add in the fact that there are many, many Python programmers with
> > > non-CS backgrounds, and the term 'lambda' sticks out like a sore thumb
> > > from amongst Python's other English-based keywords.
> >
> > Richard Feynman told a story about being on a review committee for
> > some grade-school science textbooks. One of these book said something
> > about "counting numbers" and it took him a while to figure out that
> > this was a new term for what he'd been used to calling "integers".
>
>
> I think we should not try too hard to make everything "English" like. Its a
> crappy language anyway (though its the only one I speak good). Matt Neuberg,
> in _AppleScript: The Definitive Guide_, refers to "the English-likeness
> monster". His example is that instead of
>
> x = 4
>
> you have to say
>
> copy 4 to x

The syntax was taken directly from HyperCard.

Anna

unread,
Jan 9, 2005, 11:49:51 AM1/9/05
to

Actually - whether or not I understood the [2:-2] notation, knowing
nothing else, the "seq" would clue me in that we're probably doing
something with sequences...

Personally, I like lambdas less than regular expressions (of which I'm
particularly UNfond but understand their usefulness at times). At least
with regular expressions - I know that the gibberish I need to decipher
(probably) has to do with text parsing... With class and def, I at
least have a *name* to start with - class Square pretty obviously is
going to have something to do with geometric shapes, I would hope (or
maybe with boring people...). def getfoo() tells me I'm the function is
likely to go elsewhere and get something. It's a *start*, a handle, to
deciphering whatever the following statements are doing. (Yes, I
realize that often class and function names suck - but more often than
not, they give *some* clue).

Whereas, with lambda - I have *nothing* to go on. With lambdas, all I
know is that the programmer wanted to hide whatever it is the program
is doing behind the curtain... (at least that's the way it comes
across). So, not only is the word itself not descriptive of anything to
me - even knowing that it means "anonymous function" - the use of it
precludes descriptiveness, as compared to defining a function. IMHO,
YMMV, etc etc

Anna

Jacek Generowicz

unread,
Jan 10, 2005, 3:59:18 AM1/10/05
to
"Anna" <anna...@gmail.com> writes:

> With class and def, I at least have a *name* to start with - class
> Square pretty obviously is going to have something to do with
> geometric shapes, I would hope (or maybe with boring people...).

Or maybe with multiplying something by itself. Or maybe the author
made some changes in his program, and forgot to rename the class
sensibly, and the class' functionality has nothing to do with squares
of any sort any more. Or maybe he felt the name "Square" was very
appropriate for something else in his program and inadvertently gave
the same name to two different entities thereby clobbering the one
whose use was intended at this point.

> def getfoo() tells me I'm the function is likely to go elsewhere and
> get something. It's a *start*,

All too often a start in the wrong direction.

> a handle, to deciphering whatever the following statements are
> doing. (Yes, I realize that often class and function names suck

Yup. I waste quite some time because of crappily chosen names.

> - but more often than not, they give *some* clue).
>
> Whereas, with lambda - I have *nothing* to go on.

Aaah. OK, you object to lambda because it gives you no clue as to what
the function does, rather than with the word "lambda" itself? Is that
it?

So, IIUC, you consider

def add_one(x):
return x+1

map(add_one, seq)

to be clearer than

map(lambda x:x+1, seq)

?

> With lambdas, all I know is that the programmer wanted to hide
> whatever it is the program is doing behind the curtain...

I find this a strange way of looking at it, given that, with lambda,
what the program is doing is right there in front of your very eyes at
the very point at which it is doing it. Were there a name, _then_ you
could argue that the functionality is hidden ... and you would have to
look the name up, to make sure that it really represents what you
inferred it meant (and, to be absolutely sure, you'd have to double
check that it hasn't been rebound by some other part of the program in
some nasty way). None of these problems arise with lambda.

> IMHO, YMMV, etc etc

Of course. Same here.

> Personally, I like lambdas less than regular expressions (of which
> I'm particularly UNfond but understand their usefulness at
> times). At least with regular expressions - I know that the
> gibberish I need to decipher (probably) has to do with text
> parsing...

Hmm, that tells you about as much as lambda does. With lambda you know
that the gibberish you need to decipher has to do with functions :-)

Jacek Generowicz

unread,
Jan 10, 2005, 4:02:46 AM1/10/05
to
Nick Coghlan <ncog...@iinet.net.au> writes:

> > Usually one or two have trouble grasping that "int" would be perfectly
> > adequate in this situation.
>
> The ability to pass around functions at run-time was probably the
> hardest thing to get my head around when I started with Python,

And I suspect that this particular case is further complicated by the
fact that int is not a function ... it's a type!

I can imagine it might make a newbie's brain melt. Still, most of them
survive and thoroughly enjoy the course :-)

Anna

unread,
Jan 10, 2005, 6:47:05 AM1/10/05
to

Jacek Generowicz wrote:
> "Anna" <anna...@gmail.com> writes:
>
> > With class and def, I at least have a *name* to start with - class
> > Square pretty obviously is going to have something to do with
> > geometric shapes, I would hope (or maybe with boring people...).
>
> Or maybe with multiplying something by itself. Or maybe the author
> made some changes in his program, and forgot to rename the class
> sensibly, and the class' functionality has nothing to do with squares
> of any sort any more. Or maybe he felt the name "Square" was very
> appropriate for something else in his program and inadvertently gave
> the same name to two different entities thereby clobbering the one
> whose use was intended at this point.

Idjits abound. ;-)

Can't make anything foolproof because fools are so ingenious.

> > Whereas, with lambda - I have *nothing* to go on.
>
> Aaah. OK, you object to lambda because it gives you no clue as to
what
> the function does, rather than with the word "lambda" itself? Is that
> it?
>
> So, IIUC, you consider
>
> def add_one(x):
> return x+1
>
> map(add_one, seq)
>
> to be clearer than
>
> map(lambda x:x+1, seq)

Completely, totally, and unambiguously: the version with the defined
function is immediately clear to me; the version with the lambda is
decipherable, but requires deciphering (even at 2nd and 3rd glance).
But first, wouldn't something like:

[x+1 for x in seq]

be even clearer?

Given an example more complex (which you must admit, lambdas usually
are) - the name of the function is something my brain can hold on to to
represent the group of operations; where with the lambda, I need to
mentally go through each operation each time I try to read it. And the
more complex f is, the harder time I have holding it all in my head
while I figure out how to get from the beginning value x to the ending
value f(x). lambda is an O(N*N) problem for my brain.

I could see someone more mathematically-minded being happier with
lambda. It's not, after all, the word "lambda" itself; I would still
have some issues with using, say "function", instead of "lambda", but
at least then I would immediately know what I was looking at...

Anna

Ville Vainio

unread,
Jan 10, 2005, 8:42:06 AM1/10/05
to
>>>>> "James" == James Stroud <jst...@mbi.ucla.edu> writes:

James> I think we should not try too hard to make everything
James> "English" like. Its a crappy language anyway (though its
James> the only one I speak good). Matt Neuberg,

QOTW material, unless you stole this from someone else :-).

--
Ville Vainio http://tinyurl.com/2prnb

Jacek Generowicz

unread,
Jan 10, 2005, 11:45:25 AM1/10/05
to
"Anna" <anna...@gmail.com> writes:

> Jacek Generowicz wrote:
> > "Anna" <anna...@gmail.com> writes:
> >
> > > With class and def, I at least have a *name* to start with - class
> > > Square pretty obviously is going to have something to do with
> > > geometric shapes, I would hope (or maybe with boring people...).
> >
> > Or maybe with multiplying something by itself. Or maybe the author
> > made some changes in his program, and forgot to rename the class
> > sensibly, and the class' functionality has nothing to do with squares
> > of any sort any more. Or maybe he felt the name "Square" was very
> > appropriate for something else in his program and inadvertently gave
> > the same name to two different entities thereby clobbering the one
> > whose use was intended at this point.
>
> Idjits abound. ;-)

Yup ... which is one reason why lambda is so useful. Everything there
is to know about it is right in front of your eyes. There is no chance
that some idjit changed the meaning of lambda, or the code which
appears within it (unless that refers to some external names, of
course).

> > So, IIUC, you consider
> >
> > def add_one(x):
> > return x+1
> >
> > map(add_one, seq)
> >
> > to be clearer than
> >
> > map(lambda x:x+1, seq)
>
> Completely, totally, and unambiguously:

Curious. It's very much the other way around for me.

> the version with the defined function is immediately clear to me;
> the version with the lambda is decipherable, but requires
> deciphering (even at 2nd and 3rd glance). But first, wouldn't
> something like:
>
> [x+1 for x in seq]
>
> be even clearer?

I'm glad you mentioned that. My next question was going to be
something along the lines of what you think of the equivalent list
comprehension, which is spectacularly devoid of any names to give you
any hints whatsoever.

As to whether it is clearer. That depends. I would venture to suggest
that, given a pool of laboratory rats with no previous exposure to
Python, more of them would understand the map-lambda than the list
comprehension.

There are no words in the list comprehension at all (besides the
common "seq"): it's all syntax. Even if "map" and "lambda" ring no
bells by association with anything you might have learned outside of
Python, they sure are a lot easier to look up in the documentation.

> Given an example more complex (which you must admit, lambdas usually
> are)

Well, they can't be _that_ much more complex in Python :-) But I'll
grant you, they are often more complex that the one above.

> - the name of the function is something my brain can hold on to to
> represent the group of operations; where with the lambda, I need to
> mentally go through each operation each time I try to read it. And the
> more complex f is, the harder time I have holding it all in my head
> while I figure out how to get from the beginning value x to the ending
> value f(x). lambda is an O(N*N) problem for my brain.

Fair enough. If I understand the code just by looking at it, then I
prefer to see it inline. If its meaning isn't obvious immediately,
then I'd go for the named function too. But I still value the ability
to inline-define the function while developing ... even if the inline
function will be outlined in the final product.

But, how do you feel about the individual lines of code in the body of
a multi-line function? They don't have individual names.

> I could see someone more mathematically-minded being happier with
> lambda. It's not, after all, the word "lambda" itself;

Aaah ... you did suggest (upthread) that it was the word itself which
gave you problems ... which is what piqued my interest.

Jeff Shannon

unread,
Jan 10, 2005, 12:53:13 PM1/10/05
to
Jacek Generowicz wrote:
> "Anna" <anna...@gmail.com> writes:
>
>>But first, wouldn't something like:
>>
>>[x+1 for x in seq]
>>
>>be even clearer?
>
> I'm glad you mentioned that. [...]

>
> As to whether it is clearer. That depends. I would venture to suggest
> that, given a pool of laboratory rats with no previous exposure to
> Python, more of them would understand the map-lambda than the list
> comprehension.

I would venture to suggest the exact opposite, that the syntax of a
list comprehension is in itself suggestive of its meaning, while 'map'
and 'lambda' are opaque until you've researched them. The verb 'to
map', in this mathematical sense, is not part of standard usage among
anyone that *I* know. Instead, they'd speak of doing something for
(or to) each item in a group -- exactly what list comps express.

Speaking for *this* laboratory rat, at least, map/lambda was always a
nasty puzzle for me and difficult to sort out. But when list comps
were introduced, after reading just a sentence or two on how they
worked, they were completely clear and understandable -- much more so
than map/lambda after many months of exposure.

Anna

unread,
Jan 10, 2005, 1:16:12 PM1/10/05
to
Same here.

Anna

unread,
Jan 10, 2005, 1:22:19 PM1/10/05
to
You cut something from that...

"""It's not, after all, the word "lambda" itself; I would still
have some issues with using, say "function", instead of "lambda", but
at least then I would immediately know what I was looking at..."""

I would have fewer ambiguities about using, say "func" rather than
lambda. Lambda always makes me feel like I'm switching to some *other*
language (specifically, Greek - I took a couple of semesters of Attic
Greek in college and quite enjoyed it.) But, the fact that lambda
doesn't MEAN anything (and has come - I mean - DELTA at least has a
fairly commonly understood meaning, even at high-school level math.
But, lambda? If it was "func" or "function" or even "def", I would be
happier. At least that way I'd have some idea what it was supposed to
be...

BTW - I am *quite* happy with the proposal for "where:" syntax - I
think it handles the problems I have with lambda quite handily.

Anna

Steve Holden

unread,
Jan 10, 2005, 7:44:42 PM1/10/05
to
Anna wrote:

> You cut something from that...
>
> """It's not, after all, the word "lambda" itself; I would still
> have some issues with using, say "function", instead of "lambda", but
> at least then I would immediately know what I was looking at..."""
>
> I would have fewer ambiguities about using, say "func" rather than
> lambda. Lambda always makes me feel like I'm switching to some *other*
> language (specifically, Greek - I took a couple of semesters of Attic
> Greek in college and quite enjoyed it.) But, the fact that lambda

Good God, you mean there's a language just for the attic? Those Greeks
certainly believed in linguistic specialization, didn't they?

> doesn't MEAN anything (and has come - I mean - DELTA at least has a
> fairly commonly understood meaning, even at high-school level math.
> But, lambda? If it was "func" or "function" or even "def", I would be
> happier. At least that way I'd have some idea what it was supposed to
> be...
>

Well, I suspect that Church originally chose lambda precisely because of
its meaninglessness, and I'm always amused when mathematical types try
to attribute an intuitive meaning to the word. It's purely a learned
association, which some arrogantly assume simply *everyone* knows or
should know.

Not that I'm trying to write off lambda supporters as arrogant (though I
*do* have a suspicion that many of them break the wrong end of their
boiled eggs).

> BTW - I am *quite* happy with the proposal for "where:" syntax - I
> think it handles the problems I have with lambda quite handily.
>

Whereas I find it to be an excrescence, proving (I suppose) that one
man's meat is another person's poison, or something.

regards
Steve

[who only speaks Ground Floor English]
--
Steve Holden http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/
Holden Web LLC +1 703 861 4237 +1 800 494 3119

Tim Peters

unread,
Jan 10, 2005, 9:15:50 PM1/10/05
to pytho...@python.org
...

[Anna]


>> BTW - I am *quite* happy with the proposal for "where:" syntax - I
>> think it handles the problems I have with lambda quite handily.

[Steve Holden]


> Whereas I find it to be an excrescence, proving (I suppose) that one
> man's meat is another person's poison, or something.

I've been waiting for someone to mention this, but looks like nobody
will, so I'm elected. Modern functional languages generally have two
forms of local-name definition, following common mathematical
conventions. "where" was discussed here. The other is "let/in", and
seems a more natural fit to Python's spelling of block structure:

let:
suite
in:
suite

There's no restriction to expressions here. I suppose that, like the
body of a class, the `let` suite is executed starting with a
conceptually empty local namespace, and whatever the suite binds to a
local name becomes a temporary binding in the `in` suite (like
whatever a class body binds to local names becomes the initial value
of the class __dict__). So, e.g.,

i = i1 = 3
let:
i1 = i+1
from math import sqrt
in:
print i1, sqrt(i1)
print i1,
print sqrt(i1)

would print

4 2
3

and then blow up with a NameError.

LIke it or not, it doesn't seem as strained as trying to pile more
gimmicks on Python expressions.

Jacek Generowicz

unread,
Jan 11, 2005, 3:26:09 AM1/11/05
to
Steve Holden <st...@holdenweb.com> writes:

> Well, I suspect that Church originally chose lambda precisely because
> of its meaninglessness,

IAANM, Church didn't choose lambda at all. He chose to put a "hat"
(like a circumflex accent) above the bound name. Then, because of some
typesetting difficulties, this was transformed into the nearest thing
that looked like it: a capital lambda in front of the name ... and
later the capital lambda turned into a lowercase one.

Jacek Generowicz

unread,
Jan 11, 2005, 3:34:50 AM1/11/05
to
Jeff Shannon <je...@ccvcorp.com> writes:

> Jacek Generowicz wrote:
> > "Anna" <anna...@gmail.com> writes:
> >
> >>But first, wouldn't something like:
> >>
> >>[x+1 for x in seq]
> >>
> >>be even clearer?
> > I'm glad you mentioned that. [...]
>
> > As to whether it is clearer. That depends. I would venture to suggest
>
> > that, given a pool of laboratory rats with no previous exposure to
> > Python, more of them would understand the map-lambda than the list
> > comprehension.
>
>
> I would venture to suggest the exact opposite, that the syntax of a
> list comprehension is in itself suggestive of its meaning, while 'map'
> and 'lambda' are opaque until you've researched them.

In the population of all laboratory rats, I think that the proportion
that would understand either form, would be as good as zero.

Given a population with previous exposure to computer programming, my
money is on the map-lambda version. But this last point is mostly
irrelevant. The fact is that you cannot program computers without
doing a bit of learning ... and the lambda, map and friends really do
not take any significant learning.

> Speaking for *this* laboratory rat, at least, map/lambda was always a
> nasty puzzle for me and difficult to sort out. But when list comps
> were introduced, after reading just a sentence or two on how they
> worked, they were completely clear and understandable -- much more so
> than map/lambda after many months of exposure.

Forgetting about lambda, map, filter and reduce, do you find that you
pass callables around in your Python programs, or is this not
typically done in your programs?

michele....@gmail.com

unread,
Jan 11, 2005, 4:04:41 AM1/11/05
to
Jacek:

> Given a population with previous exposure to computer programming, my
> money is on the map-lambda version. But this last point is mostly
> irrelevant. The fact is that you cannot program computers without
> doing a bit of learning ... and the lambda, map and friends really do
> not take any significant learning.

This kind of "sociological" study would be pretty interesting to me ;-)

Personally, I find out that my mind manage pretty well one-level of
indirection
at time, not two. Consider for instance

def add1(x): return x+1
map(add1, mylist)

Here there are *two* levels of indirection:

first, I need to define add1;
second I need to translate mentally map to a loop.

Using lambda does not help:

map(lambda x: x+1, mylist)

still would require two levels for me, one to recognize the lambda
and one to convert map to a loop.

This is too much for me, so I just write

[x+1 for x in mylist]

where everything is explicit (or if you wish, I have just to recognize
that there
is a loop going on, pretty easy).

However, if I can skip a level of indirection (i.e. I do not need to
define
a function) I just prefer map:

map(int, mylist)

is simpler for me than

[int(x) for x in mylist]

since the latter introduces an useless x (which is also polluting my
namespace,
but this not my point, I could use a generator-expression instead).

So, in practice, I only use map with built-in or with predefined
functions, i.e. functions
which are already there for some other purpose; I do not like to be
forced to write a
function (or a lambda) for the only purpose of using map (at least in
Python).

Incidentally, I am not fond of the name "lambda" too. "fn", as Paul
Graham says,
looks much better.

What I would like, in Python, is some facility to manage callbacks in
the standard
library, then I would live pretty well without lambdas.
Just IMHO, YMMV, etc.

Michele Simionato

Bengt Richter

unread,
Jan 11, 2005, 5:25:59 AM1/11/05
to
On Mon, 10 Jan 2005 21:15:50 -0500, Tim Peters <tim.p...@gmail.com> wrote:

>...
>
>[Anna]
>>> BTW - I am *quite* happy with the proposal for "where:" syntax - I
>>> think it handles the problems I have with lambda quite handily.
>
>[Steve Holden]
>> Whereas I find it to be an excrescence, proving (I suppose) that one
>> man's meat is another person's poison, or something.
>
>I've been waiting for someone to mention this, but looks like nobody
>will, so I'm elected. Modern functional languages generally have two
>forms of local-name definition, following common mathematical
>conventions. "where" was discussed here. The other is "let/in", and

Well, I did say it reminded me of some kind of weird let ;-)
http://groups-beta.google.com/groups?q=%20Reminds%20me%20of%20some%20kind%20of%20weird%20let&hl=en&lr=&sa=N&tab=wg

I could get to like it ;-)

Hm, a little extension to this could provide a new way to populate closure variables,
and also (never mind, one thing at a time ;-)

#1: If you gave your 'let' above a list of 'externs' that can be rebound from within the let.
E.g.,

let(sqrt):

the effect in your example would be to eliminate the NameError you mention.
The compiler would make an entry for sqrt in the enclosing namespace, and generate
code to bind/rebind if assigned from within the let.

This would be an interesting way to create closure bindings:

let(foo):
preset = 'another way to make closure vairables'
in:
def foo(): return preset
...
print foo()

#2: Making the in: suite callable as a light weight function with no arguments. An optional
binding name after in would bind like def and create a persistent named callable instead of just an
implicitly called anonymous suite.

Then you could define the same effective foo by

let:
preset = 'another way to make closure vairables'
in foo:
return preset # return now legal
...
print foo()

The combination would work like:

let(rebindable):
factor = 10
in bar:
rebindable *= factor

rebindable = 2
bar()
print rebindable # => 20
rebindable += 5
bar()
print rebindable # => 250

You can see this could be used nicely in case functionality, with a dict of named in-functions.

What do you think?

Regards,
Bengt Richter

Nick Coghlan

unread,
Jan 11, 2005, 5:54:53 AM1/11/05
to Python List
Tim Peters wrote:
> LIke it or not, it doesn't seem as strained as trying to pile more
> gimmicks on Python expressions.

Some of us are piling gimmicks on statements, not expressions :)

And I'm looking for out-of-order code execution as well as local namespaces, so
the let/in syntax wouldn't help much. (The out-of-order execution is what really
makes the property definition example pretty, IMO)

Cheers,
Nick.

--
Nick Coghlan | ncog...@email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net

Carl Banks

unread,
Jan 11, 2005, 6:06:48 AM1/11/05
to
Tim Peters wrote:
> ...
>
> [Anna]
> >> BTW - I am *quite* happy with the proposal for "where:" syntax - I
> >> think it handles the problems I have with lambda quite handily.
>
> [Steve Holden]
> > Whereas I find it to be an excrescence, proving (I suppose) that
one
> > man's meat is another person's poison, or something.
>
> I've been waiting for someone to mention this, but looks like nobody
> will, so I'm elected. Modern functional languages generally have two
> forms of local-name definition, following common mathematical
> conventions. "where" was discussed here. The other is "let/in", and
> seems a more natural fit to Python's spelling of block structure:
>
> let:
> suite
> in:
> suite

Ah. During that discussion, I did kind of suggest this (spelling it
where...do) as an alternative to where (thinking I was clever). Only
no one seemed to take notice, probably because I suggested something
more poignant at the same time.

Now I see why I liked the idea so much; it was exactly like let forms.


> There's no restriction to expressions here. I suppose that, like the
> body of a class, the `let` suite is executed starting with a
> conceptually empty local namespace, and whatever the suite binds to a
> local name becomes a temporary binding in the `in` suite (like
> whatever a class body binds to local names becomes the initial value
> of the class __dict__). So, e.g.,
>
> i = i1 = 3
> let:
> i1 = i+1
> from math import sqrt
> in:
> print i1, sqrt(i1)
> print i1,
> print sqrt(i1)
>
> would print
>
> 4 2
> 3
>
> and then blow up with a NameError.
>
> LIke it or not, it doesn't seem as strained as trying to pile more
> gimmicks on Python expressions.

Indeed.


--
CARL BANKS

Jeff Shannon

unread,
Jan 11, 2005, 3:41:44 PM1/11/05
to
Jacek Generowicz wrote:

> Given a population with previous exposure to computer programming, my
> money is on the map-lambda version. But this last point is mostly
> irrelevant. The fact is that you cannot program computers without
> doing a bit of learning ... and the lambda, map and friends really do
> not take any significant learning.

I guess we'll have to agree to disagree, because given the same
conditions, I *still* think that a list comprehension expresses its
semantics more clearly than map/lambda. I'd also point out that not
all Python programmers will have significant prior exposure to
programming ideas, and even those who do will not necessarily have
prior exposure to lambdas.

It's true that programming requires learning, and that map/lambda
aren't a tremendous burden to learn. Still, to my mind they make a
program a tiny increment more complicated. (I find that reading a
lambda requires mentally pushing a stack frame to parse the lambda and
another to translate map() into a loop, whereas a list comp's
expression doesn't require such a shift, and a function name works as
a good placeholder that makes reading easier.) It's not a big
difference in any individual case, but incremental differences build up.

From the sounds of it, you may have the opposite experience with
reading map/lambda vs. reading list comps, though, so we could go back
and forth on this all week without convincing the other. :)

>>Speaking for *this* laboratory rat, at least, map/lambda was always a
>>nasty puzzle for me and difficult to sort out. But when list comps
>>were introduced, after reading just a sentence or two on how they
>>worked, they were completely clear and understandable -- much more so
>>than map/lambda after many months of exposure.
>
> Forgetting about lambda, map, filter and reduce, do you find that you
> pass callables around in your Python programs, or is this not
> typically done in your programs?

Sure, I pass callables around quite a bit. Usually they're GUI
callbacks or the like. Usually they're also either complex enough
that lambda would be undesireable if not impossible, or they're simple
and numerous (e.g. calling a function with different parameters) such
that it's easy to write a factory function that returns closures
rather than feed the parameter in with a lambda.

Donn Cave

unread,
Jan 11, 2005, 4:33:57 PM1/11/05
to
In article <10u8e65...@corp.supernews.com>,
Jeff Shannon <je...@ccvcorp.com> wrote:
...

> From the sounds of it, you may have the opposite experience with
> reading map/lambda vs. reading list comps, though, so we could go back
> and forth on this all week without convincing the other. :)

I'm with him. List incomprehensions do not parse well in
my eyes. I am reduced to guessing what they mean by a kind
of process of elimination. map is simply a function, so
it doesn't pose any extra reading problem, and while lambda
is awkward it isn't syntactically all that novel.

Donn Cave, do...@u.washington.edu

Jacek Generowicz

unread,
Jan 12, 2005, 3:29:32 AM1/12/05
to
Donn Cave <do...@u.washington.edu> writes:

> List incomprehensions do not parse well in my eyes.

Are you familiar with the Haskell syntax for list comprehensions?

For example:

http://www.zvon.org/other/haskell/Outputsyntax/listQcomprehension_reference.html

Does their striking similarity to mathematical set notation help at
all ?

Jacek Generowicz

unread,
Jan 12, 2005, 3:23:47 AM1/12/05
to
Jeff Shannon <je...@ccvcorp.com> writes:

> I guess we'll have to agree to disagree

Indeed :-)

> I find that reading a lambda requires mentally pushing a stack frame
> to parse the lambda and another to translate map() into a loop,
> whereas a list comp's expression doesn't require such a shift

> From the sounds of it, you may have the opposite experience with


> reading map/lambda vs. reading list comps

No, I'm perefectly happy with both. I'm just trying to understand the
underlying reasons for people having trouble with one or the other, in
order to be better armed when the didactic need might arise.

One more question. Imagine that Python had something akin to Smalltalk
code blocks. Would something like

map([x | x+1], seq)

be any better for you than

map(lambda x:x+1, seq)

?

Donn Cave

unread,
Jan 12, 2005, 2:51:32 PM1/12/05
to
In article <tyf8y6z...@pcepsft001.cern.ch>,

Jacek Generowicz <jacek.ge...@cern.ch> wrote:
> Donn Cave <do...@u.washington.edu> writes:
>
> > List incomprehensions do not parse well in my eyes.
>
> Are you familiar with the Haskell syntax for list comprehensions?
>
> For example:
>
> http://www.zvon.org/other/haskell/Outputsyntax/listQcomprehension_reference.h

I haven't used it more than once or twice in the modest
amount of Haskell code I've written, but I've seen it
a few times.

> Does their striking similarity to mathematical set notation help at
> all ?

Not a bit.

If it's any more obvious than the Python version, I suppose
it's the | -- my parser sees [a|b] on the first pass.

But it isn't like I ever made any real effort to get comfortable
with Python list comprehensions. I was just relaying my (lack of)
intuitive grasp of them, compared to map and lambda.

Donn Cave, do...@u.washington.edu

Jeff Shannon

unread,
Jan 12, 2005, 6:24:18 PM1/12/05
to
Jacek Generowicz wrote:

> One more question. Imagine that Python had something akin to Smalltalk
> code blocks. Would something like
>
> map([x | x+1], seq)
>
> be any better for you than
>
> map(lambda x:x+1, seq)
>
> ?

I'd say that this is very slightly better, but it's much closer (in my
mind) to map/lambda than it is to a list comprehension. In this case,
at least the code block is visually self-contained in a way that
lambdas are not, but I still have to do more mental work to visualize
the overall results than I need with list comps.

0 new messages