467,136 Members | 1,399 Online
Bytes | Developer Community
Ask Question

Home New Posts Topics Members FAQ

Post your question to a community of 467,136 developers. It's quick & easy.

"Updating" lambda functions

Hi,

I'm trying to write a Python function that parses
an expression and builds a function tree from it
(recursively).

During parsing, lambda functions for the the terms
and sub-expressions are constructed on the fly.
Now my problem is lazy evaluation. Or at least I
think it is. :-)

I need to "update" a lambda function, like this:

fu = lambda x: x
...
fu = lambda x: fu(x) + 17
...
fu = lambda x: fu(x) * 3

Of course that doesn't work, because fu is resolved
when the lambda is called, not when it's defined, so
I'll run into an endless recursion.

My current solution is to define a helper function
which passes the lambda through its argument:

def add_17 (fu):
return lambda x: fu(x) + 17

def mul_3 (fu):
return lambda x: fu(x) * 3

fu = lambda x: x
...
fu = add_17(fu)
...
fu = mul_3(fu)

That works, but it strikes me as unclean and ugly.
Is there a better way to do it?

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)
Jul 18 '05 #1
  • viewed: 3206
Share:
53 Replies
On Thu, 16 Sep 2004 14:07:20 +0000, Oliver Fromme wrote:
I need to "update" a lambda function, like this:


That says you need to use classes, not lambda functions.
Jul 18 '05 #2
"Oliver Fromme" <ol**@haluter.fromme.com> wrote in message
news:2q*************@uni-berlin.de...

| That works, but it strikes me as unclean and ugly.
| Is there a better way to do it?

I don't like it either. Consider this:
composition = lambda f,g: lambda x: f(g(x))
add_17 = lambda x: x+17
mul_3 = lambda x: 3*x
fu = lambda x:x
fu(3) 3 fu = composition(add_17,fu)
fu(3) 20 fu = composition(mul_3,fu)
fu(3)

60
Jul 18 '05 #3
On 16 Sep 2004 14:07:20 GMT, Oliver Fromme <ol**@haluter.fromme.com> wrote:
Hi,

I'm trying to write a Python function that parses
an expression and builds a function tree from it
(recursively).

During parsing, lambda functions for the the terms
and sub-expressions are constructed on the fly.
Now my problem is lazy evaluation. Or at least I
think it is. :-)

I need to "update" a lambda function, like this:

fu = lambda x: x
...
fu = lambda x: fu(x) + 17
...
fu = lambda x: fu(x) * 3

Of course that doesn't work, because fu is resolved
when the lambda is called, not when it's defined, so
I'll run into an endless recursion.

My current solution is to define a helper function
which passes the lambda through its argument:

def add_17 (fu):
return lambda x: fu(x) + 17

def mul_3 (fu):
return lambda x: fu(x) * 3

fu = lambda x: x
...
fu = add_17(fu)
...
fu = mul_3(fu)

That works, but it strikes me as unclean and ugly.
Is there a better way to do it?

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)


You could exploit the way functions become bound methods, e.g.,
fu = lambda x: x
fu = (lambda f,x: f(x) + 17).__get__(fu)
fu = (lambda f,x: f(x) * 3).__get__(fu)
fu(1) 54 fu(0) 51 fu(-15) 6 fu(-16) 3 fu(1,2) Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: <lambda>() takes exactly 2 arguments (3 given) fu <bound method ?.<lambda> of <bound method ?.<lambda> of <function <lambda> at 0x008FD8B0>>>

or, you could make a magic function-composing object with magic composing properties,
exploiting the method-making mechanism in a different way, e.g.,
class FC(object): ... def __setattr__(self, name, f):
... if not hasattr(self, name): self.__dict__[name] = [f]
... else: self.__dict__[name].append(f)
... def __getattribute__(self, name):
... if name == '__dict__': return object.__getattribute__(self, '__dict__')
... return type(self).__dict__['_xfuns'].__get__(
... object.__getattribute__(self,name))
... def _xfuns(flist, x):
... for f in flist: x = f(x)
... return x
... fc = FC()
fc.fu = lambda x: x
fc.fu = lambda x: x + 17
fc.fu = lambda x: x * 3
fc.fu(1) 54 fc.fu(0) 51 fc.fu(-15) 6 fc.fu(1,2) Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: _xfuns() takes exactly 2 arguments (3 given) fc.bar = lambda x: x*3
fc.bar = lambda x: x+10
fc.bar(0) 10 fc.bar(2) 16 fc.fu(-18)

-3

All just to explore python's features, not to recommend specific uses ;-)

Regards,
Bengt Richter
Jul 18 '05 #4

"Oliver Fromme" <ol**@haluter.fromme.com> wrote in message
news:2q*************@uni-berlin.de...
fu = lambda x: x
fu = lambda x: fu(x) + 17

etc

I am curious if there is any reason other that habit carried over from
other languages to not write the above as

def fu(x): return x
def fu(x): return fu(x) + 17
etc

Granted, the latter takes 2 more keystrokes, but the resulting object gets
a proper .name attribute. And, of course, the def form is required for a
multiline body anyway.

(Note: I am not asking about the use of lambda *within* an expression or as
a return value, but only the immediate name-binding of the supposedly
anonymous function where one does not want anonymity.)

Terry J. Reedy

Jul 18 '05 #5
"Terry Reedy" <tj*****@udel.edu> wrote in message
news:ma**************************************@pyth on.org...

| I am curious if there is any reason other that habit carried over from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17
| etc

In my interpreter (IDLE 1.0 on Windows 98) it causes an infinite regress.
Jul 18 '05 #6
Elaine Jackson <elainejackson7355 <at> home.com> writes:

"Terry Reedy" <tjreedy <at> udel.edu> wrote in message
news:mailman.3428.1095385637.5135.python-list <at> python.org...

| I am curious if there is any reason other that habit carried over from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17
| etc

In my interpreter (IDLE 1.0 on Windows 98) it causes an infinite regress.


Yes, it will, exactly as the lambda version would have. (And all the
solutions suggested to you for the lambda form are equally applicable to the
def form.) The question is why use the lambda form when you *do* want to bind
your function to a name? Basically,

f = lambda args: body

is equivalent to

def f(args): body

except that the def body is a set of statements (so you have to use 'return'),
and the lambda body is a single expression.

Not that it's coming any time soon, but Python 3000 is supposed to remove
lambda functions, so when you really *do* want to bind a function to a name
(like in your case here), it would probably be a good habit to get into to use
defs instead.

Steve

Jul 18 '05 #7
On Fri, 17 Sep 2004 07:46:12 +0000 (UTC), Steven Bethard <st************@gmail.com> wrote:
Elaine Jackson <elainejackson7355 <at> home.com> writes:

"Terry Reedy" <tjreedy <at> udel.edu> wrote in message
news:mailman.3428.1095385637.5135.python-list <at> python.org...

| I am curious if there is any reason other that habit carried over from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17
| etc

In my interpreter (IDLE 1.0 on Windows 98) it causes an infinite regress.
Yes, it will, exactly as the lambda version would have. (And all the
solutions suggested to you for the lambda form are equally applicable to the
def form.) The question is why use the lambda form when you *do* want to bind
your function to a name? Basically,

f = lambda args: body

is equivalent to

def f(args): body

except that the def body is a set of statements (so you have to use 'return'),
and the lambda body is a single expression.

Yes, but

obj.f = lambda args: body

is possible without an intermediate local binding of f that might clobber a previous f, as in

def f(args): body
obj.f = f
del f # if you want to clean up. But better save the old f in that case?

I'd rather use lambda.

Not that it's coming any time soon, but Python 3000 is supposed to remove
lambda functions, so when you really *do* want to bind a function to a name
(like in your case here), it would probably be a good habit to get into to use
defs instead.

Well, if lambda is removed (or not ;-), I hope an anonymous def expression is allowed,
so we can write

obj.f = def(args):
body
or

obj.f = def(args): body

or

obj.f = (
def(args):
body
) # at or to the left of the def column, for final dedent without special ')' processing.
(where def body indentation is referenced from wherever the def is)

Regards,
Bengt Richter
Jul 18 '05 #8
Bengt Richter <bokr <at> oz.net> writes:
On Fri, 17 Sep 2004 07:46:12 +0000 (UTC), I wrote:

f = lambda args: body

is equivalent to

def f(args): body
Yes, but

obj.f = lambda args: body

is possible without an intermediate local binding of f that might clobber a
previous f


Yeah, I probably should have been clear about that. If 'f' is really just a
name (as it was in my example) the two syntaxes I gave are equivalent. If 'f'
really isn't just a name, then you do still want an anonymous function. In
the OP's example though, 'f' really was just a name.
Well, if lambda is removed (or not , I hope an anonymous def expression is
allowed...


Well, it's come up a number of times (one of the more recent is
http://mail.python.org/pipermail/pyt...e/226714.html), but it
doesn't seem like there was any agreement on (a) what it should look like, or
(b) why having such anonymous defs was such a gain over named defs. If you'd
like to champion a PEP about it... ;)

Steve
Jul 18 '05 #9

"Bengt Richter" <bo**@oz.net> wrote in message
news:ci*************************@theriver.com...
"Terry Reedy" <tjreedy <at> udel.edu> wrote in message
news:mailman.3428.1095385637.5135.python-list <at> python.org...

| I am curious if there is any reason other that habit carried over
from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17


obj.f = lambda args: body

is possible without an intermediate local binding of f that might clobber
a previous f, as in

def f(args): body
obj.f = f
del f # if you want to clean up. But better save the old f in that
case?

I'd rather use lambda.


Thanks. I had not thought of this variation. Similar would be
seq[n] = lambda <whatever>

Of course, I *might* prefer being able to write

def obj.f(params): <etc> # and
def seq[n](params): <etc>

Since def is effectively a binding statement, name to function object (like
import, name to module), these seem not entirely unreasonable to me.

Terry J. Reedy


Jul 18 '05 #10
What? is lambda is going away? Say it ain't so!

On Fri, Sep 17, 2004 at 08:26:19AM +0000, Bengt Richter wrote:
| >f = lambda args: body
| > is equivalent to
| >def f(args): body

Not really -- the item above is _bad style_, people write,

def f(args):
body

| obj.f = lambda args: body

Or more commonly,

func(arg, lambda args: body)

| I'd rather use lambda.

No joke. For the common case above, which occurs _everywhere_
in my 'deferred execution' code, one would write:

def somerandomname(args):
body
func(arg, somerandomname)

So, you've taken something that is a perfectly clear one-liner and
converted it into a 3 line chunk of code with _zero_ added clarity,
in fact, I'd say you've dramatically reduced clarity by requiring
the a name be 'minted'. Ugly. Multiply this by 10x in one of my
source files and you've taken something perfectly readable and
turned it into maze of confusion. This _hides_ the true intent
rather than making it clear that the function is temporary thingy.

| >Not that it's coming any time soon, but Python 3000 is supposed to remove
| >lambda functions

Expect me to whine very loudly on a daily basis when Python 3000
becomes near. In fact, let the preemptive supplication begin.

| Well, if lambda is removed (or not ;-), I hope an anonymous def
| expression is allowed, so we can write
|
| obj.f = def(args):
| body
| or
|
| obj.f = def(args): body
|
| or
|
| obj.f = (
| def(args):
| body
| )

Ewww. How is this better than lambda? Let's keep lambda, no?

Clark

--
Clark C. Evans Prometheus Research, LLC.
http://www.prometheusresearch.com/
o office: +1.203.777.2550
~/ , mobile: +1.203.444.0557
//
(( Prometheus Research: Transforming Data Into Knowledge
\\ ,
\/ - Research Exchange Database
/\ - Survey & Assessment Technologies
` \ - Software Tools for Researchers
~ *
Jul 18 '05 #11
In article <ma**************************************@python.o rg>, Clark C. Evans wrote:
What? is lambda is going away? Say it ain't so!
They keep threatening it, and it keeps not happening. In the meantime, we
can use this time to our advantage, preparaing our vocal chords for the
eventual screaming fits and wails of agonizing pain. ;)
| >Not that it's coming any time soon, but Python 3000 is supposed to remove
| >lambda functions

Expect me to whine very loudly on a daily basis when Python 3000
becomes near. In fact, let the preemptive supplication begin.


Since enough time has gone by since I last whined, let me just take this
opportunity to say, in a completely calm, diplomatic, and
non-confrontational way: "Ruby-style code blocks would be nice."

(o) Don't beg for code blocks again today
( ) Don't beg for code blocks again in the next three days
( ) Don't beg for code blocks again in the next week

[ OK ]
--
.:[ dave benjamin: ramen/[sp00] -:- spoomusic.com -:- ramenfest.com ]:.
"talking about music is like dancing about architecture."
Jul 18 '05 #12
Clark C. Evans wrote:
No joke. For the common case above, which occurs _everywhere_
in my 'deferred execution' code, one would write:

def somerandomname(args):
body
func(arg, somerandomname)

So, you've taken something that is a perfectly clear one-liner and
converted it into a 3 line chunk of code with _zero_ added clarity,
in fact, I'd say you've dramatically reduced clarity by requiring
the a name be 'minted'. Ugly.

I don't agree. I *still* have to stop and think every time I see a
lamba -- they parse completely differently in my mind than anything else
in Python does, and they confuse me every time. Yes, defining a small
function requires two extra lines... but, y'know, it's not like my
editor is going to run out of paper. And I find that a well-chosen
name, even for a single-use thing like this, greatly adds clarity. To
my mind, calling this func_callback(), or some such descriptive name,
makes the intent *much* more clear than 'lambda' does.
Multiply this by 10x in one of my
source files and you've taken something perfectly readable and
turned it into maze of confusion. This _hides_ the true intent
rather than making it clear that the function is temporary thingy.


Only when one is already familiar with lambdas. I've gotten to the
point where I *can* understand them, but it's still a struggle. It
seems to me that the benefits of having lambda are outweighed by the
fair amount of extra mental space that they use up. It just strikes me
as too much of a special case to deserve special syntax that has
absolutely no parallel elsewhere in Python.
| Well, if lambda is removed (or not ;-), I hope an anonymous def
| expression is allowed, so we can write
|
| obj.f = def(args):
| body
| or
|
| obj.f = def(args): body
|
| or
|
| obj.f = (
| def(args):
| body
| )

Ewww. How is this better than lambda? Let's keep lambda, no?


I certainly agree that none of these examples strike me as less
troublesome than lambda. Indeed, the second one effectively *is* lambda
syntax, except with added parens and a name change. And the others both
scream out that there *will* be problems with indenting properly.

I remain unconvinced that the utility of anonymity is so great that
either special case is justified.

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #13
>>>>> "Clark" == Clark C Evans <cc*@clarkevans.com> writes:

Clark> def somerandomname(args):
Clark> body
Clark> func(arg, somerandomname)

Clark> So, you've taken something that is a perfectly clear
Clark> one-liner and converted it into a 3 line chunk of code with
Clark> _zero_ added clarity, in fact, I'd say you've dramatically
Clark> reduced clarity by requiring the a name be 'minted'. Ugly.

What does "minting" a name mean?

You can always do

def L(args): body

func(arg, L)

You can even make it a habit to always call it L.

Clark> Expect me to whine very loudly on a daily basis when Python
Clark> 3000 becomes near. In fact, let the preemptive
Clark> supplication begin.

Heh, I can already anticipate the whining around py3000. It will
probably be a test bed for hundreds of new voting methods and give
sociology students thesis-fodder for years.

Clark> Ewww. How is this better than lambda? Let's keep lambda,
Clark> no?

I agree. Lambda doesn't suck anymore, so it deserves to live.

--
Ville Vainio http://tinyurl.com/2prnb
Jul 18 '05 #14
On Mon, Oct 11, 2004 at 10:54:05AM -0700, Jeff Shannon wrote:
| I don't agree. I *still* have to stop and think every time I see a
| lamba -- they parse completely differently in my mind than anything else
| in Python does, and they confuse me every time. Yes, defining a small
| function requires two extra lines... but, y'know, it's not like my
| editor is going to run out of paper. And I find that a well-chosen
| name, even for a single-use thing like this, greatly adds clarity. To
| my mind, calling this func_callback(), or some such descriptive name,
| makes the intent *much* more clear than 'lambda' does.

I beg to differ; and I'm talking about _my_ code, not yours.

| Only when one is already familiar with lambdas. I've gotten to the
| point where I *can* understand them, but it's still a struggle. It
| seems to me that the benefits of having lambda are outweighed by the
| fair amount of extra mental space that they use up. It just strikes me
| as too much of a special case to deserve special syntax that has
| absolutely no parallel elsewhere in Python.

If you don't like lambda -- don't use it. Just beacuse you are
unfamilar with a very helpful construct and are unwilling to learn
does not mean you should prevent others from continuing to enjoy
one of the more pleasant aspects of Python.

Kind Regards,

Clark
Jul 18 '05 #15
Dave Benjamin ha scritto:
Since enough time has gone by since I last whined, let me just take this
opportunity to say, in a completely calm, diplomatic, and
non-confrontational way: "Ruby-style code blocks would be nice."

(o) Don't beg for code blocks again today
( ) Don't beg for code blocks again in the next three days
( ) Don't beg for code blocks again in the next week

[ OK ]


do a b:
indentblock

would be uber cool, imho.
Jul 18 '05 #16
Clark C. Evans wrote:
On Mon, Oct 11, 2004 at 10:54:05AM -0700, Jeff Shannon wrote:
|
| .... It
| seems to me that the benefits of having lambda are outweighed by the
| fair amount of extra mental space that they use up. It just strikes me
| as too much of a special case to deserve special syntax that has
| absolutely no parallel elsewhere in Python.

If you don't like lambda -- don't use it. Just beacuse you are
unfamilar with a very helpful construct and are unwilling to learn
does not mean you should prevent others from continuing to enjoy
one of the more pleasant aspects of Python.


Except that one of the design principles of Python is that it being easy
to *read* is more important than being easy to write, with the
assumption that much of the code that one reads will be code written by
someone else. I do care how readable your code is, because (at least in
principle) someday I may need to maintain it. ("If you don't like X,
don't use it, but let others use it if they like" seems to be much more
Perlish than Pythonic, at least IMHO.)

Lambdas are hard to read, because they're significantly different,
syntactically, from any other construct in the language -- it's not that
I'm _unwilling_ to learn, it's that it is actively *difficult* to learn
because it doesn't fit well, conceptually, into the rest of the
language, so there's a mental impedance barrier that must be overcome.
In order to explain lambdas to someone who is not already familiar with
them, you have to explain first that it's kind of like a function def,
except that it uses totally different syntax (aren't function defs
supposed to use parens?), and you don't explicitly return anything even
though it *does* return a value, and oh yes, you can't actually use
statements because it has to be a single expression (and then you get to
explain the difference between statements and expressions, and explain
*why* there's a difference and that it really is a good thing)...
That's a lot of special treatment for those cases where there actually
might be a slight advantage to using an anonymous function, and "Special
cases aren't special enough to break the rules." Lambdas *do* break
many of Python's usual rules.

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #17
On Mon, Oct 11, 2004 at 11:58:44AM -0700, Jeff Shannon wrote:
| >If you don't like lambda -- don't use it. Just beacuse you are
| >unfamilar with a very helpful construct and are unwilling to learn
| >does not mean you should prevent others from continuing to enjoy
| >one of the more pleasant aspects of Python.
|
| Except that one of the design principles of Python is that it being easy
| to *read* is more important than being easy to write

Exactly! Lambdas make my code easy to read and therefore more
understandable. I don't use them beacuse they are easier to write,
I use them beacuse they make reviewing source code easier:

- they put simple expressions that are arguments right
where they are used

- they don't create random names that you have to worry
about name collision or finding something meaningful
(and not distracting)

- you are certain to know that the chunk of code is not
used anywhere else, that is, you can freely modify it

Lambdas are all about making code more maintainable.

| Lambdas are hard to read,

This is _your_ opinion; lots of other people disagree.

| because they're significantly different,
| syntactically, from any other construct in the language

This argument is just bogus. There are lots of things in Python
that are significantly different from each other:

- functions that return functoins, and hence can().be().chained()
- using expressions as function arguments
- list comprehensions
- *args and **kwargs
- overridable operators
- classes, meta-classes
- etc.

In any of these cases one _could_ of course, find a similar way
to do it with just a turning machine. But this isn't the point,
the point is to give special syntax to common things that have
specific meaning so that they are easily recognized.

Best,

Clark

Jul 18 '05 #18
Jeff Shannon ha scritto:

Let me say that all of this is in a big IMO block. Oh, and sorry for the
triple post, thunderbird got mad.
Except that one of the design principles of Python is that it being easy
to *read* is more important than being easy to write, with the
assumption that much of the code that one reads will be code written by
someone else. I do care how readable your code is, because (at least in
principle) someday I may need to maintain it. ("If you don't like X,
don't use it, but let others use it if they like" seems to be much more
Perlish than Pythonic, at least IMHO.)

I agree on the perlish thinking of 'some more feature you can avoid are
good'. But lambdas are a concept that can be (and actually is) used for
a lot of things where it is better than others.
Lambdas are hard to read, because they're significantly different,
syntactically, from any other construct in the language -- it's not that
I'm _unwilling_ to learn, it's that it is actively *difficult* to learn
because it doesn't fit well, conceptually, into the rest of the
language, so there's a mental impedance barrier that must be overcome.
IMO the problem is just that lambda is an onion (citing paul graham that
cites primo levi google for the explanation). It is a remnant of
academic computer science.

Would you like to have it like:
func arg1,arg2: arg1+arg2
?

Again, IMO the point is: once people explain this to you, would you find
hard it to understand or read a lambda once you find them again?
Is this different from the strangeness of array literals or generator
expression/LC ?
In order to explain lambdas to someone who is not already familiar with
them, you have to explain first that it's kind of like a function def,
except that it uses totally different syntax (aren't function defs
supposed to use parens?), and you don't explicitly return anything even
though it *does* return a value, and oh yes, you can't actually use
statements because it has to be a single expression (and then you get to
explain the difference between statements and expressions, and explain
*why* there's a difference and that it really is a good thing)...
then what you want is a better lambda. One where you can use return,
maybe, and where you can have statements and multiple expressions.
Don't throw away the baby with the bathwater.

That's a lot of special treatment for those cases where there actually
might be a slight advantage to using an anonymous function, and "Special
cases aren't special enough to break the rules." Lambdas *do* break
many of Python's usual rules.


Just because you're thinking of lambdas as special cases. Whenever a
case is very useful it is possible to break the rules. That's why there
are all those funny literals.
Jul 18 '05 #19
Jeff Shannon <jeff <at> ccvcorp.com> writes:
Lambdas are hard to read, because they're significantly different,
syntactically, from any other construct in the language


Yes, they are different (summarizing your points):
* no parens around argument list
* returns a value without the return statement
* contains a single expression, not a sequence of statements

Of course, comparing something like the new decorator syntax to the older
equivalent will also point out a construct that's "significantly different,
syntactically, from any other construct in the language":

@d1
@d2
def f():
pass

as opposed to

def f():
pass
f = d1(d2(f))

Some points (in parallel with yours, as much as possible):
* no parens, but functions are called
* rebinds a name without an assignment statement[1]
* appear as expressions, but act like statements
* appear before a def, but are applied after

I'd contend that lambda syntax is much more in-line with the rest of Python
than decorator syntax. Not that I'm suggesting we get rid of decorator
syntax -- I've already found it useful on a number of occasions. I just
wanted to point out that, all things considered, lambdas are probably more
consistent with Python than decorators are.

Steve

[1] Actually, I believe the function is not bound to a name until after the
decorators are applied, but I don't think it's completely unreasonable to talk
of this as a name rebinding.
Jul 18 '05 #20
gabriele renzi wrote:

then what you want is a better lambda. One where you can use return,
maybe, and where you can have statements and multiple expressions.
Don't throw away the baby with the bathwater.

But because of Python's line- and indentation-based syntax, doing all of
that on a single line is... um... awkward at best, to put it mildly.
And once you make a lambda multiline, then you lose most of the point of
it -- at least, as far as I understand what the point is (having an
in-line, anonymous callable). Once you allow statements and multiple
expressions, all you're gaining is anonymity, which seems like a pretty
paltry benefit to me.
That's a lot of special treatment for those cases where there
actually might be a slight advantage to using an anonymous function,
and "Special cases aren't special enough to break the rules."
Lambdas *do* break many of Python's usual rules.


Just because you're thinking of lambdas as special cases. Whenever a
case is very useful it is possible to break the rules. That's why
there are all those funny literals.

I agree that, if a case is *very* useful, it is possible to break the
rules. List comprehensions, for example, break some of the rules, but
they are indeed very useful, so the rule-breakage is more forgiveable.

Maybe I'm just ignorant or behind the times, but I still haven't seen a
real argument as to *why* lambdas are so useful. There's some
assertions about how avoiding giving something a name makes things
clearer, which I disagree with. ('Explicit is better than implicit.' I
don't see how 'no name' makes the purpose of a code segment clearer than
'some meaningfully descriptive name', no matter how many times it's
asserted.) There's complaints that it takes a whole two extra lines to
type a proper function def, as opposed to being able to use lambdas
inline... but again, I'd claim that with a properly named function, the
intent at point-of-use will be quite clear and the cost of two extra
lines of code is minimal. (I also tend to break complex expressions
into multiple steps to increase clarity -- packing as much as possible
into a single line doesn't strike me as all that desirable.) There's
complaints about polluting the namespace... but ISTM that it's not
*that* hard to come up with uniquely descriptive names. Lambdas may
once have had some utility in capturing and tinkering with the scoping
of names, but that became moot with the introduction of nested scopes
'way back when.

I understand that lambdas are very popular in other programming
languages (such as Lisp). But Python is not those languages, and which
constructs are useful may well be different. I don't know enough Lisp
to judge how helpful lambdas are there; I do know enough Python to
believe that I should be able to see the advantages if they were as
wonderful as their proponents say. My suspicion is that all of the
Python users who like lambdas originally discovered them in other
languages and are comfortable with them from that environment, but those
who have no previous exposure to lambdas tend to be unimpressed (at
best) by Python's take on them. This renders them, IMO, in the same
category as the ternary operator that's continually proposed by converts
from, say, C/C++ -- a feature whose usability is much greater in other
languages than in Python, and whose inclusion would only satisfy those
familiar with the feature from those other languages. The only
difference between the two features, IMO, is that someone managed to
talk Guido into including lambdas (which he reportedly regrets), and
nobody managed to talk him into including the ternary operator.

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #21
On Mon, 11 Oct 2004 12:36:21 -0400, "Clark C. Evans" <cc*@clarkevans.com> wrote:
What? is lambda is going away? Say it ain't so!

On Fri, Sep 17, 2004 at 08:26:19AM +0000, Bengt Richter wrote: I didn't write the following, I replied to it. Note the extra quoting level.
You are quoting Steven Bethard. See
http://groups.google.com/groups?hl=e...t%40python.org
;-)
| >f = lambda args: body
| > is equivalent to
| >def f(args): body
It really should be
f = lambda args: expr
is equivalent to
def f(args): return expr
except for little details like f.__name__ and perhaps vestigial unexecuted
byte code in the def version, until someone thinks it's worth the bother to optimize out.
Not really -- the item above is _bad style_, people write,

def f(args):
body

| obj.f = lambda args: body

Or more commonly, commonly compared to what? obj.f = ... ?
func(arg, lambda args: body)

| I'd rather use lambda. That line I wrote, though the context is snipped ;-)

No joke. For the common case above, which occurs _everywhere_
in my 'deferred execution' code, one would write:

def somerandomname(args):
body
func(arg, somerandomname)

So, you've taken something that is a perfectly clear one-liner and
converted it into a 3 line chunk of code with _zero_ added clarity,
in fact, I'd say you've dramatically reduced clarity by requiring
the a name be 'minted'. Ugly. Multiply this by 10x in one of my
source files and you've taken something perfectly readable and
turned it into maze of confusion. This _hides_ the true intent
rather than making it clear that the function is temporary thingy.
[Not Bengt]| >Not that it's coming any time soon, but Python 3000 is supposed to remove
| >lambda functions

Expect me to whine very loudly on a daily basis when Python 3000
becomes near. In fact, let the preemptive supplication begin.
[Bengt]| Well, if lambda is removed (or not ;-), I hope an anonymous def
| expression is allowed, so we can write
|
| obj.f = def(args):
| body
| or
|
| obj.f = def(args): body
|
| or
|
| obj.f = (
| def(args):
| body
| )

Ewww. How is this better than lambda? Let's keep lambda, no?

Sure, lambda is fine, but it doesn't allow statements, so something
like def is needed. Just dropping the def name and allowing the
def statement to be an expression seemed an easy step, since the
name is basically the only difference.

As seen above, finding an indentation style that is easy to read is
a challeng, especially if the anonymous def is a middle argument to
a functions call, e.g.,

func(arg1, (def(x): print x), arg3)

much as with lambda, you may need parentheses to show where the expression ends.
For a more complex def, we get into multiple lines in the arg list, e.g.,
expanded,

func(
arg1, # use a new line to get consistent indenting of arg list items
(def(x, base=10):
"""even anonymous defs could have doc strings"""
return int(x+'0', base) # weird function
),
arg3
)

or, more compactly,

func(arg1,
def(x, base=10):
"""even anonymous defs could have doc strings"""
return int(x+'0', base) # weird function
,arg3)

It's a tough style problem. But what would you do with lambda, given that
we don't have lots of insignificant silly parentheses?

Regards,
Bengt Richter
Jul 18 '05 #22
In article <10*************@corp.supernews.com>, Jeff Shannon wrote:
gabriele renzi wrote:

then what you want is a better lambda. One where you can use return,
maybe, and where you can have statements and multiple expressions.
Don't throw away the baby with the bathwater.
But because of Python's line- and indentation-based syntax, doing all of
that on a single line is... um... awkward at best, to put it mildly.


This is true. I think that Ruby's code block syntax offers a workable
alternative. Many will dispute this, saying it's too ugly, but this is
subjective and not based on any technical reasons. Here is what I've
proposed in the past:

def with_open_file(filename, proc):
f = open(filename)
try:
proc(f)
finally:
f.close()

with_open_file('data.txt', {|f|
for line in f:
print line
})

This is nearly identical to Ruby's syntax, except that instead of creating
an object with a call method, it creates a callable.
And once you make a lambda multiline, then you lose most of the point of
it -- at least, as far as I understand what the point is (having an
in-line, anonymous callable). Once you allow statements and multiple
expressions, all you're gaining is anonymity, which seems like a pretty
paltry benefit to me.
It's not so much the anonymity that matters, it's the ability to use them as
expressions. It allows you to create your own control structures without
disrupting the logical flow of your program. For instance, right now in
Python you'd have to write the above like this:

def doit(f):
for line in f:
print line

with_open_file('data.txt', doit)

To me, this reads, "When I say 'doit', I mean iterate through each line in
some given object 'f', and print that line. Now, with the open file, 'doit'."
Whereas, in the previous example, I'm saying, "With the open file, for each
line in the file, print the line." The difference is subtle, perhaps, but
the need to define a named function beforehand rearranges my code in a way
that I'm not particularly fond of.

Another example is the "after" procedure. If you're familiar with Tcl, you
may recognize the following idiom:

after(10, lambda: sprite.move(0, 5))

In an (imaginary) event-driven framework, this would wait 10 seconds before
moving "sprite" down 5 pixels. You might say that this could easily be
rewritten with a def, and you're right:

def doit():
sprite.move(0, 5)
after(10, doit)

Now, imagine you are setting up an animation this way:

after(10, lambda: sprite.move(0, 5))
after(15, lambda: sprite2.rotate(30))
after(20, lambda: sprite.scale(120, 120))
after(22, lambda: sprite2.move(50, 50))
after(22, lambda: sound1.play())
after(23, lambda: sprite.move(0, 0))
after(26, lambda: sound1.stop())

Imagine what happens when each one of these lambdas turns into a two-line
def. You could group the "def"s together, perhaps, but then you'd have to
give them all names like "move_sprite_0_5", which is totally redundant.
There are other ways to skin this cat, like switching to a more data-driven
model, but this is a practical use of anonymous functions; I do this kind of
thing all the time in JavaScript and ActionScript, which allow inline
anonymous functions.
I agree that, if a case is *very* useful, it is possible to break the
rules. List comprehensions, for example, break some of the rules, but
they are indeed very useful, so the rule-breakage is more forgiveable.
As was pointed out already in this thread, decorators break many of the same
rules. So far, I find anonymous functions much more useful than decorators.
The only problem is finding a suitable syntax, and I will admit this is
indeed a problem.
Maybe I'm just ignorant or behind the times, but I still haven't seen a
real argument as to *why* lambdas are so useful. There's some
assertions about how avoiding giving something a name makes things
clearer, which I disagree with. ('Explicit is better than implicit.' I
don't see how 'no name' makes the purpose of a code segment clearer than
'some meaningfully descriptive name', no matter how many times it's
asserted.)
In that case, why stop at functions? Why not make all intermediate values
have mandatory names? Why not ban this:

c = math.sqrt(a * a + b * b)

And require instead:

a2 = a * a
b2 = b * b
tmp = a2 + b2
c = math.sqrt(tmp)
There's complaints that it takes a whole two extra lines to
type a proper function def, as opposed to being able to use lambdas
inline... but again, I'd claim that with a properly named function, the
intent at point-of-use will be quite clear and the cost of two extra
lines of code is minimal. (I also tend to break complex expressions
into multiple steps to increase clarity -- packing as much as possible
into a single line doesn't strike me as all that desirable.) There's
complaints about polluting the namespace... but ISTM that it's not
*that* hard to come up with uniquely descriptive names. Lambdas may
once have had some utility in capturing and tinkering with the scoping
of names, but that became moot with the introduction of nested scopes
'way back when.

I understand that lambdas are very popular in other programming
languages (such as Lisp). But Python is not those languages, and which
constructs are useful may well be different. I don't know enough Lisp
to judge how helpful lambdas are there; I do know enough Python to
believe that I should be able to see the advantages if they were as
wonderful as their proponents say.
Lisp is not the only language that benefits from lambdas. Other languages
include JavaScript/ActionScript, C# (anonymous delegates), Java (anonymous
inner classes -- a poor substitute), Ruby, Tcl, Perl, and OCaml. They are
used in GUI callbacks, iteration patterns, flow control, data processing,
and in general any function or procedure that needs parts of its logic to be
parameterized. Only one of the aforementioned languages, OCaml, is
considered to be a functional language like Lisp or Scheme.
My suspicion is that all of the
Python users who like lambdas originally discovered them in other
languages and are comfortable with them from that environment, but those
who have no previous exposure to lambdas tend to be unimpressed (at
best) by Python's take on them. This renders them, IMO, in the same
category as the ternary operator that's continually proposed by converts
from, say, C/C++ -- a feature whose usability is much greater in other
languages than in Python, and whose inclusion would only satisfy those
familiar with the feature from those other languages. The only
difference between the two features, IMO, is that someone managed to
talk Guido into including lambdas (which he reportedly regrets), and
nobody managed to talk him into including the ternary operator.


I actually discovered lambdas in Python first (well, technically Tcl, but I
didn't know it at the time), and since then I have done a lot of programming
in Python. In fact, it would be safe to say that Python biases my use of
other languages to a greater degree than any other language biases my use of
Python. I don't use lambdas very often, but their use does come up, and I
would rather see them become more powerful (or see code blocks added to the
language) than have them be removed entirely. I'd like to see a ternary
operator too. Guido would have probably added one by now, but nobody could
agree on which syntax would be most "Pythonic". The same fate, I fear, is in
store for any sufficiently advanced anonymous function syntax in Python.

(Yet, somehow, decorators slipped through, even though nobody agreeed on a
syntax for that either. I don't have a rational explanation for that...)

--
.:[ dave benjamin: ramen/[sp00] -:- spoomusic.com -:- ramenfest.com ]:.
"talking about music is like dancing about architecture."
Jul 18 '05 #23
Dave Benjamin <ramen <at> lackingtalent.com> writes:
after(10, lambda: sprite.move(0, 5))
after(15, lambda: sprite2.rotate(30))
after(20, lambda: sprite.scale(120, 120))
after(22, lambda: sprite2.move(50, 50))
after(22, lambda: sound1.play())
after(23, lambda: sprite.move(0, 0))
after(26, lambda: sound1.stop())


Unfortunately, your "after" function is probably provided by your framework,
but if that framework was written a little more Python-friendly, the after
function would work like unittest.TestCase.assertRaises, e.g.

def after(sec, func, *args, **kwds):
# wait sec seconds
...
# call func
func(*args, **kwds)

This would let you write the code above as:

after(10, sprite.move, 0, 5)
after(15, sprite2.rotate, 30)
after(20, sprite.scale, 120, 120)
after(22, sprite2.move, 50, 50)
after(22, sound1.play)
after(23, sprite.move, 0, 0)
after(26, sound1.stop)

which is actually slightly more concise (character-wise) than the lambda code,
and doesn't force you to create a new lambda function to do something someone
already created a function for.

Again, I realize that in many cases having functions written like this is not
possible because the functions are defined by a framework, not the coder, but
if you happen to be one of the ones *writing* the framework, you can take
advantage of Python's *args and **kwds syntax to make this kind of thing
easier.

Steve

Jul 18 '05 #24
Dave Benjamin wrote:
In article <10*************@corp.supernews.com>, Jeff Shannon wrote:
Another example is the "after" procedure. If you're familiar with Tcl, you
may recognize the following idiom:

after(10, lambda: sprite.move(0, 5))

In an (imaginary) event-driven framework, this would wait 10 seconds before
moving "sprite" down 5 pixels. You might say that this could easily be
rewritten with a def, and you're right:

def doit():
sprite.move(0, 5)
after(10, doit)

Now, imagine you are setting up an animation this way:

after(10, lambda: sprite.move(0, 5))
after(15, lambda: sprite2.rotate(30))
after(20, lambda: sprite.scale(120, 120))
after(22, lambda: sprite2.move(50, 50))
after(22, lambda: sound1.play())
after(23, lambda: sprite.move(0, 0))
after(26, lambda: sound1.stop())


In this case, I'd redefine after to be:

def after(timeout, func, *args, **kwargs):
# whatever needs to be done to delay the call, then...
func(*args, **kwargs)

Then we can do the animation as:

after(10, sprite.move, 0, 5)
after(15, sprite2.rotate, 30)
after(20, sprite.scale, 120, 120)
# ...

I find this to read slightly better, and the implementation requires one
less level of indirection. I'll admit that I haven't explored much in
the area of function currying and closures, so there *may* be ways in
which using lambda is preferable to using a generic variable-argument
closure-returning function, but at least in the cases that spring to my
mind, lambda's advantage is slim at best.
As was pointed out already in this thread, decorators break many of the same
rules. So far, I find anonymous functions much more useful than decorators.
The only problem is finding a suitable syntax, and I will admit this is
indeed a problem.


And I'm not very happy with the decorator syntax either, to be honest.
Still, from the examples that cropped up during the Great Decorator
Syntax Debate (tm), it seems to me that, even though *I* don't
particularly need them, the potential benefits of decorators are greater
than the potential benefits of lambda. That is, I can see things that
can be done with user-defined descriptors that are difficult to do any
other way, whereas from what I've seen many/most uses of lambda can be
re-cast to use normal functions without too much pain. This provides a
bit more justification for having special syntax for user-defined
descriptors (i.e. decorators), though to be honest I'm not terribly
happy with the chosen syntax. Of course, this is all theoretical, since
at this point I've had no call to use either descriptors or lambdas...
In that case, why stop at functions? Why not make all intermediate values
have mandatory names? Why not ban this:

c = math.sqrt(a * a + b * b)

And require instead:

a2 = a * a
b2 = b * b
tmp = a2 + b2
c = math.sqrt(tmp)


Intermediate anonymous values make sense at a certain level of
granularity but not at all levels. Practicality beats purity.

On the other hand, I'd never write your first example -- I'd be
explicity about the grouping with extra parens.

c = math.sqrt( (a*a) + (b*b) )

It's not syntactically necessary, because it's following standard
operator precedence, but it scans much more quickly for me.

Indeed, maybe that's what this is all about. To my mind, when I see a
lambda, I already have to stop scanning, push a level on my mental
stack, figure out what the heck is going on with the lambda and what
it's going to return, and then pop back to the line in progress. In
contrast, when I'm scanning something using a (descriptively) named
function, the name should tell me enough of the purpose of the function
that I don't need to pause to figure it out. Thus, it's much quicker
for me to scan a reference to a named function than to scan a lambda
definition.

I understand that lambdas are very popular in other programming
languages (such as Lisp). But Python is not those languages, and which
constructs are useful may well be different. I don't know enough Lisp
to judge how helpful lambdas are there; I do know enough Python to
believe that I should be able to see the advantages if they were as
wonderful as their proponents say.


Lisp is not the only language that benefits from lambdas. Other languages
include JavaScript/ActionScript, C# (anonymous delegates), Java (anonymous
inner classes -- a poor substitute), Ruby, Tcl, Perl, and OCaml. They are
used in GUI callbacks, iteration patterns, flow control, data processing,
and in general any function or procedure that needs parts of its logic to be
parameterized. Only one of the aforementioned languages, OCaml, is
considered to be a functional language like Lisp or Scheme.


ISTM that many of these uses can be accomplished by using named
functions with variable arguments. I'll admit that I'm no language
expert, and TBH haven't used any of those languages. But my impression
is that the use of (named) function references, dynamic typing, and
convenient variable argument syntax can acheive most of the benefits
that are touted for lambdas.
(Yet, somehow, decorators slipped through, even though nobody agreeed on a
syntax for that either. I don't have a rational explanation for that...)


Nor do I ..... *sigh*

Jeff Shannon
Technician/Programmer
Credit International
Jul 18 '05 #25
In article <ma**************************************@python.o rg>, Steven Bethard wrote:
Unfortunately, your "after" function is probably provided by your framework,
but if that framework was written a little more Python-friendly, the after
function would work like unittest.TestCase.assertRaises, e.g.

def after(sec, func, *args, **kwds):
# wait sec seconds
...
# call func
func(*args, **kwds)

This would let you write the code above as:

after(10, sprite.move, 0, 5)
after(15, sprite2.rotate, 30)
after(20, sprite.scale, 120, 120)
after(22, sprite2.move, 50, 50)
after(22, sound1.play)
after(23, sprite.move, 0, 0)
after(26, sound1.stop)

which is actually slightly more concise (character-wise) than the lambda
code, and doesn't force you to create a new lambda function to do
something someone already created a function for.
Ahh, what clever solutions dynamic typing can afford. =) Very nice.
Again, I realize that in many cases having functions written like this is
not possible because the functions are defined by a framework, not the
coder, but if you happen to be one of the ones *writing* the framework,
you can take advantage of Python's *args and **kwds syntax to make this
kind of thing easier.


Even if modifying the framework function is not an option, you can still
accomplish similar results with an argument-binding function:

def bind(func, *args, **kwds):
return lambda: func(*args, **kwds)

after(10, bind(sprite.move, 0, 5))
after(15, bind(sprite2.rotate, 30))
after(20, bind(sprite.scale, 120, 120))
....

Or, in the "more readable" Python3k-enforced style:

def bind(func, *args, **kwds):
def doit():
return func(*args, **kwds)
return doit

after(10, bind(sprite.move, 0, 5))
....

(sorry, couldn't resist <g>)

--
.:[ dave benjamin: ramen/[sp00] -:- spoomusic.com -:- ramenfest.com ]:.
"talking about music is like dancing about architecture."
Jul 18 '05 #26
In article <10*************@corp.supernews.com>, Jeff Shannon wrote:
In this case, I'd redefine after to be:

def after(timeout, func, *args, **kwargs):
# whatever needs to be done to delay the call, then...
func(*args, **kwargs)
Apparently, you're not the only one. ;)
I find this to read slightly better, and the implementation requires one
less level of indirection. I'll admit that I haven't explored much in
the area of function currying and closures, so there *may* be ways in
which using lambda is preferable to using a generic variable-argument
closure-returning function, but at least in the cases that spring to my
mind, lambda's advantage is slim at best.
Python has many features that can delay evaluation and factor out
repetition, and this can largely explain why it's not so much of a nuisance
that it lacks a more powerful closure construct. For instance, on the dev
list, as quickly as the new "sort(key=lambda x: x[1])" idiom was introduced,
people started hunting for ways to squash the lambda, the winners being
"operator.attrgetter()" and "operator.itemgetter()". It is very likely that
anything you can do with a "lambda" you can also do using other features of
Python. Still, I think it's useful to note that the lambda version was the
first to be discussed, and the search for alternatives was in part motivated
by the threat of lambda's future demise. As long as lambda is there, people
will still use it for certain tasks, and sorting seems to be one of those
tasks.

The most convincing argument for (more powerful) lambdas over named
functions is in the design of custom control structures. For example, let's
say you wanted to define a do-while loop in Python. You could do it like this:

def do_while(proc, test):
while True:
proc()
if not test():
break

i = 0
def print_and_increment_i():
global i
print i
i += 1
def while_i_lt_10():
return i < 10
do_while(print_and_increment_i, while_i_lt_10)

With code blocks, you could implement something like this instead:

i = 0
do({||
print i
i += 1
}, while={||
return i < 10
})

As I write this, I feel a bit embarrassed; neither is really all that
readable, to be honest. But I'm going to post it anyway because I think it
illustrates my basic point, which is that the ability to use inline
functions allows you to implement control structures that would otherwise be
awkward and out-of-order. Real-world uses for custom control structures are
often application-specific and don't make much sense out of context. Say
you're working within a framework where you need to manage acquiring locks
and opening and closing resources:

lock.open({||
resource.acquire({|res|
res.dilly()
res.dally()
})
})

This would ensure that the lock gets closed even if the resource cannot be
acquired, and if everything works out, the resource gets released first, and
then the lock gets closed. The alternative people keep proposing would
result in code like this:

def do_while_resource_acquired(res):
res.dilly()
res.dally()

def do_while_lock_open():
resource.acquire(do_while_resource_acquired)

lock.open(do_while_lock_open)

Notice how the code now reads backwards?
And I'm not very happy with the decorator syntax either, to be honest.
I'm not really convinced that their usefulness demands syntax extension. On
the other hand, I've seen concrete examples in Ruby and other languages that
demonstrate the usefulness of code blocks, and in those cases, I think
syntax extension is worthwhile. But we all have different projects with
different needs, so one (wo)man's syntax extension is another's ugly wart.

Without macros, it's hard to please everyone. And with macros, it's hard to
please everyone. ;)
Intermediate anonymous values make sense at a certain level of
granularity but not at all levels. Practicality beats purity.
And one (wo)man's practicality is another's impurity.
On the other hand, I'd never write your first example -- I'd be
explicity about the grouping with extra parens.

c = math.sqrt( (a*a) + (b*b) )

It's not syntactically necessary, because it's following standard
operator precedence, but it scans much more quickly for me.

Indeed, maybe that's what this is all about. To my mind, when I see a
lambda, I already have to stop scanning, push a level on my mental
stack, figure out what the heck is going on with the lambda and what
it's going to return, and then pop back to the line in progress. In
contrast, when I'm scanning something using a (descriptively) named
function, the name should tell me enough of the purpose of the function
that I don't need to pause to figure it out. Thus, it's much quicker
for me to scan a reference to a named function than to scan a lambda
definition.
Yes, I can understand and sympathize with this viewpoint.
ISTM that many of these uses can be accomplished by using named
functions with variable arguments. I'll admit that I'm no language
expert, and TBH haven't used any of those languages. But my impression
is that the use of (named) function references, dynamic typing, and
convenient variable argument syntax can acheive most of the benefits
that are touted for lambdas.


And the use of wrenches, pliers, and mallets can achieve most of the
benefits that are touted for hammers. All of which happen to be objects. ;)
(Yet, somehow, decorators slipped through, even though nobody agreeed on a
syntax for that either. I don't have a rational explanation for that...)


Nor do I ..... *sigh*


*coughjavacough*

--
.:[ dave benjamin: ramen/[sp00] -:- spoomusic.com -:- ramenfest.com ]:.
"talking about music is like dancing about architecture."
Jul 18 '05 #27
On Mon, 11 Oct 2004 22:29:11 -0000, Dave Benjamin <ra***@lackingtalent.com> wrote:
In article <10*************@corp.supernews.com>, Jeff Shannon wrote:
gabriele renzi wrote:

then what you want is a better lambda. One where you can use return,
maybe, and where you can have statements and multiple expressions.
Don't throw away the baby with the bathwater.
But because of Python's line- and indentation-based syntax, doing all of
that on a single line is... um... awkward at best, to put it mildly.


This is true. I think that Ruby's code block syntax offers a workable
alternative. Many will dispute this, saying it's too ugly, but this is
subjective and not based on any technical reasons. Here is what I've
proposed in the past:

def with_open_file(filename, proc):
f = open(filename)
try:
proc(f)
finally:
f.close()

with_open_file('data.txt', {|f|
for line in f:
print line
})

This is nearly identical to Ruby's syntax, except that instead of creating
an object with a call method, it creates a callable.

How about extending lambda? E.g.,

with_open_file('data.txt', lambda f:<
for line in f:
print line:)
I.e., the first non-white-space after the initial ':<' defines suite indentation,
and a corresponding (to allow nesting) '>:' closes the lambda body (without necessarily
having to be out-dented). Hence you could do a one liner for the above example:

with_open_file('data.txt', lambda f:< for line in f: print line >:)

IMO, if you are familiar with lambda,

lambda f:< ... >:

is less of a jump than

{|f| ... }

What did I forget? ;-)

Obviously
lambda f:expr
can also be spelled
lambda f:< return expr >:
And once you make a lambda multiline, then you lose most of the point of
it -- at least, as far as I understand what the point is (having an
in-line, anonymous callable). Once you allow statements and multiple
expressions, all you're gaining is anonymity, which seems like a pretty
paltry benefit to me.


It's not so much the anonymity that matters, it's the ability to use them as
expressions. It allows you to create your own control structures without
disrupting the logical flow of your program. For instance, right now in
Python you'd have to write the above like this:

def doit(f):
for line in f:
print line

with_open_file('data.txt', doit)

To me, this reads, "When I say 'doit', I mean iterate through each line in
some given object 'f', and print that line. Now, with the open file, 'doit'."
Whereas, in the previous example, I'm saying, "With the open file, for each
line in the file, print the line." The difference is subtle, perhaps, but
the need to define a named function beforehand rearranges my code in a way
that I'm not particularly fond of.

I agree. [...]I actually discovered lambdas in Python first (well, technically Tcl, but I
didn't know it at the time), and since then I have done a lot of programming
in Python. In fact, it would be safe to say that Python biases my use of
other languages to a greater degree than any other language biases my use of
Python. I don't use lambdas very often, but their use does come up, and I
would rather see them become more powerful (or see code blocks added to the
language) than have them be removed entirely. I'd like to see a ternary
operator too. Guido would have probably added one by now, but nobody could
agree on which syntax would be most "Pythonic". The same fate, I fear, is in
store for any sufficiently advanced anonymous function syntax in Python.

(Yet, somehow, decorators slipped through, even though nobody agreeed on a
syntax for that either. I don't have a rational explanation for that...)


Maybe we can piggyback on that ;-)

@lambda f:<
f.__name__ += '_decorated_by_an_extended_lambda'
return f >:
def foo(): pass

Regards,
Bengt Richter
Jul 18 '05 #28
Dave Benjamin <ra***@lackingtalent.com> writes:
that it lacks a more powerful closure construct. For instance, on the dev
list, as quickly as the new "sort(key=lambda x: x[1])" idiom was introduced,
people started hunting for ways to squash the lambda, the winners being
"operator.attrgetter()" and "operator.itemgetter()".


But why would you want to need to remember such obscure functions? I
never heard of any of those. Maybe they should be eliminated instead of
lambda. There should be one obvious way to do it, and lambda suffices.
Jul 18 '05 #29
Paul Rubin <"http://phr.cx" <at> NOSPAM.invalid> writes:

Dave Benjamin <ramen <at> lackingtalent.com> writes:
...
"operator.attrgetter()" and "operator.itemgetter()".
But why would you want to need to remember such obscure functions? I
never heard of any of those.


Couldn't tell if this was a joke or not, so in case it wasn't, attrgetter and
itemgetter are being introduced in Python 2.4, I believe as a result of the
sort(key=...) and sorted(key=...) discussions.
Maybe they should be eliminated instead of
lambda. There should be one obvious way to do it, and lambda suffices.


This is the part that really sounded like a joke, but in case it wasn't...

I could write a sort function every time I wanted to sort a list, but why not
use the one that comes builtin with Python lists? I could write a strip
function to remove whitespace from the ends of a string, but why not use the
one that comes builtin with Python strs? Likewise, I could write a (lambda)
function every time I wanted to select an item by index, e.g.

lambda x: x[1]

but if Python has already defined one for me, why would I define it again?

Steve

Jul 18 '05 #30
On Mon, 11 Oct 2004 22:11:11 GMT, bo**@oz.net (Bengt Richter) wrote:
[...]
On Mon, 11 Oct 2004 12:36:21 -0400, "Clark C. Evans" <cc*@clarkevans.com> wrote:
[Bengt]

Just want to say this isn't my latest idea ;-) See below:
(the first non-white-space after the opening ':<' determines the suite indentation level,
and the matching >: ends the suite (without necessarily being outdented or on a separate line).
| Well, if lambda is removed (or not ;-), I hope an anonymous def
| expression is allowed, so we can write
|
| obj.f = def(args):
| body obj.f = lambda args:<
body: or

obj.f = lambda args:<
body >:
| or
|
| obj.f = def(args): body
obj.f = lambda args:< body >:
|
| or
|
| obj.f = (
| def(args):
| body
| ) There wouldn't be much reason to use the extra parens above.
Ewww. How is this better than lambda? Let's keep lambda, no?

Sure, lambda is fine, but it doesn't allow statements, so something
like def is needed. Just dropping the def name and allowing the
def statement to be an expression seemed an easy step, since the
name is basically the only difference.

I had second thoughts ;-)

As seen above, finding an indentation style that is easy to read is
a challeng, especially if the anonymous def is a middle argument to
a functions call, e.g.,

func(arg1, (def(x): print x), arg3)
much better (IMO) now:

func(arg1, lambda x:< print x >:, arg3)

much as with lambda, you may need parentheses to show where the expression ends.
For a more complex def, we get into multiple lines in the arg list, e.g.,
expanded,

func(
arg1, # use a new line to get consistent indenting of arg list items
(def(x, base=10):
"""even anonymous defs could have doc strings"""
return int(x+'0', base) # weird function
),
arg3
)

func(
arg1, # use a new line to get consistent indenting of arg list items
lambda x, base=10:<
"""even anonymous lambdas could have doc strings"""
return int(x+'0', base) # weird function:, arg3
)

or, more compactly,

func(arg1,
def(x, base=10):
"""even anonymous defs could have doc strings"""
return int(x+'0', base) # weird function
,arg3)
func(arg1,
lambda x, base=10:<
"""even anonymous lambdas could have doc strings"""
return int(x+'0', base) >:, # weird function
arg3)

One-liner:

func(arg1, lambda x, base=10:< "weird func doc"; return int(x+'0', base) >:, arg3)


It's a tough style problem. But what would you do with lambda, given that
we don't have lots of insignificant silly parentheses?


I guess I took a stab at answering my own question ;-)

Regards,
Bengt Richter
Jul 18 '05 #31
Op 2004-10-11, Jeff Shannon schreef <je**@ccvcorp.com>:
gabriele renzi wrote:

then what you want is a better lambda. One where you can use return,
maybe, and where you can have statements and multiple expressions.
Don't throw away the baby with the bathwater.

But because of Python's line- and indentation-based syntax, doing all of
that on a single line is... um... awkward at best, to put it mildly.


Which is one of the reasons I think the indentation-based syntax was
a mistake. If the syntax becomes an argument against a construct
in the language, something is wrong with the syntax IMO.

--
Antoon Pardon
Jul 18 '05 #32
Op 2004-10-11, Jeff Shannon schreef <je**@ccvcorp.com>:
Clark C. Evans wrote:
On Mon, Oct 11, 2004 at 10:54:05AM -0700, Jeff Shannon wrote:
|
| .... It
| seems to me that the benefits of having lambda are outweighed by the
| fair amount of extra mental space that they use up. It just strikes me
| as too much of a special case to deserve special syntax that has
| absolutely no parallel elsewhere in Python.

If you don't like lambda -- don't use it. Just beacuse you are
unfamilar with a very helpful construct and are unwilling to learn
does not mean you should prevent others from continuing to enjoy
one of the more pleasant aspects of Python.
Except that one of the design principles of Python is that it being easy
to *read* is more important than being easy to write, with the
assumption that much of the code that one reads will be code written by
someone else. I do care how readable your code is, because (at least in
principle) someday I may need to maintain it. ("If you don't like X,
don't use it, but let others use it if they like" seems to be much more
Perlish than Pythonic, at least IMHO.)

Lambdas are hard to read, because they're significantly different,
syntactically, from any other construct in the language


I didn't find them so. On the other hand I find having to come up
with a name for a function can be very inconvenient and not worth
the trouble. If python wants functions to be full fledged objects,
is needs some way to have unnamed functions, just as you can have
unnamed lists, numbers, instances etc.

Can you imaging the protest, from people if it would be decide
that no unnamed entities van be used. If you want to use a number
or a list, as an argument you first have to name it and then use
the name as argument. Well the reason for having anonymous numbers
and lists is the same reason for having anonymous functions.

-- it's not that
I'm _unwilling_ to learn, it's that it is actively *difficult* to learn
because it doesn't fit well, conceptually, into the rest of the
language, so there's a mental impedance barrier that must be overcome.
In order to explain lambdas to someone who is not already familiar with
them, you have to explain first that it's kind of like a function def,
except that it uses totally different syntax (aren't function defs
supposed to use parens?)


The problem is IMO that python uses two different kinds of ways to
assign an object to a name. You have the assignment and you have the
class and def statements. I would consider de class and def statements
the odd man out, because they combine the construcion of the object
with naming it, where normally the two are seperated.

--
Antoon Pardon
Jul 18 '05 #33
On Tue, Oct 12, 2004 at 08:19:55AM +0000, Antoon Pardon wrote:
| Op 2004-10-11, Jeff Shannon schreef <je**@ccvcorp.com>:
| > gabriele renzi wrote:
| >> then what you want is a better lambda. One where you can use return,
| >> maybe, and where you can have statements and multiple expressions.
| >> Don't throw away the baby with the bathwater.
| >
| > But because of Python's line- and indentation-based syntax, doing all of
| > that on a single line is... um... awkward at best, to put it mildly.
|
| Which is one of the reasons I think the indentation-based syntax was
| a mistake. If the syntax becomes an argument against a construct
| in the language, something is wrong with the syntax IMO.

Indentation based structure is a godsend; a divine insight if you may.
Python is much much better for it. However, just beacuse it can use
indentation, doesn't mean that indentation should be mandated for every
case. Python uses {} and [] to scope dict and list items, but this does
not mean that a indentation based version of this wouldn't be welcome.
In general, indentation is great for "outer-structure" that is,
delimiting large code blocks. While delimiter based scoping is good
for inner structures, small blocks of code. It should not be an
either/or thing, one should properly have the option of using either
option depending upon which style brings the most clarity.

Cheers,

Clark
Jul 18 '05 #34
Antoon Pardon wrote:
Op 2004-10-11, Jeff Shannon schreef <je**@ccvcorp.com>:

Lambdas are hard to read, because they're significantly different,
syntactically, from any other construct in the language


I didn't find them so. On the other hand I find having to come up
with a name for a function can be very inconvenient and not worth
the trouble. If python wants functions to be full fledged objects,
is needs some way to have unnamed functions, just as you can have
unnamed lists, numbers, instances etc.

Can you imaging the protest, from people if it would be decide
that no unnamed entities van be used. If you want to use a number
or a list, as an argument you first have to name it and then use
the name as argument. Well the reason for having anonymous numbers
and lists is the same reason for having anonymous functions.


Functions are at a different level of granularity than numbers and
lists. Anonymity makes sense for numbers and lists; it makes less sense
for collections of numbers and lists; and it makes still less sense for
organized collections of numbers, lists, and operations thereon, which
are structured in a meaningful way to express some (part of an)
algorithm. Similarly, I don't expect each line of code to have an
individual name, but once I collect lines of code into a file, I
certainly *do* expect to name that file, even if the file is only one or
two lines long.

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #35
Op 2004-10-12, Jeff Shannon schreef <je**@ccvcorp.com>:
Antoon Pardon wrote:
Op 2004-10-11, Jeff Shannon schreef <je**@ccvcorp.com>:

Lambdas are hard to read, because they're significantly different,
syntactically, from any other construct in the language
I didn't find them so. On the other hand I find having to come up
with a name for a function can be very inconvenient and not worth
the trouble. If python wants functions to be full fledged objects,
is needs some way to have unnamed functions, just as you can have
unnamed lists, numbers, instances etc.

Can you imaging the protest, from people if it would be decide
that no unnamed entities van be used. If you want to use a number
or a list, as an argument you first have to name it and then use
the name as argument. Well the reason for having anonymous numbers
and lists is the same reason for having anonymous functions.


Functions are at a different level of granularity than numbers and
lists. Anonymity makes sense for numbers and lists; it makes less sense
for collections of numbers and lists; and it makes still less sense for
organized collections of numbers, lists, and operations thereon, which
are structured in a meaningful way to express some (part of an)
algorithm.


I find it better to let the coder decide what makes sense in his program
and what not.
Similarly, I don't expect each line of code to have an
individual name, but once I collect lines of code into a file, I
certainly *do* expect to name that file, even if the file is only one or
two lines long.


So? If you then want to develop the code, do you put the new code in a
new file and then use a program to include it, or do you put unnamed
text in the already existing file?

--
Antoon Pardon
Jul 18 '05 #36
Op 2004-10-12, Clark C. Evans schreef <cc*@clarkevans.com>:
On Tue, Oct 12, 2004 at 08:19:55AM +0000, Antoon Pardon wrote:
| Op 2004-10-11, Jeff Shannon schreef <je**@ccvcorp.com>:
| > gabriele renzi wrote:
| >> then what you want is a better lambda. One where you can use return,
| >> maybe, and where you can have statements and multiple expressions.
| >> Don't throw away the baby with the bathwater.
| >
| > But because of Python's line- and indentation-based syntax, doing all of
| > that on a single line is... um... awkward at best, to put it mildly.
|
| Which is one of the reasons I think the indentation-based syntax was
| a mistake. If the syntax becomes an argument against a construct
| in the language, something is wrong with the syntax IMO.

Indentation based structure is a godsend; a divine insight if you may.
Python is much much better for it.
That's your opinion I disagree.

I find it especially annoying when I work interactively. I sometimes
copy and paste something from an other window and it is just frustrating
to get a syntax error back just because you had copied an extra space
in front of the expression.
However, just beacuse it can use
indentation, doesn't mean that indentation should be mandated for every
case. Python uses {} and [] to scope dict and list items, but this does
not mean that a indentation based version of this wouldn't be welcome.
In general, indentation is great for "outer-structure" that is,
delimiting large code blocks. While delimiter based scoping is good
for inner structures, small blocks of code. It should not be an
either/or thing, one should properly have the option of using either
option depending upon which style brings the most clarity.


Well it isn't an either/or thing and I have seen it often enough that
a proposed language structure was argued against because fitting it
in the indentation-based syntax was going to be difficult/awkward or
something like that. Suppose for the sake af the argument that someone
comes up with a language structute that has almost everyone agree with
that it would be usefull to include in the language. However the
most natural indentation for the structure would be something like this:

start:

code

control:

code

control:

code

I fear that alone would kill the possibility of including it in
python.

--
Antoon Pardon
Jul 18 '05 #37
Dave Benjamin <ra***@lackingtalent.com> wrote:
Now, imagine you are setting up an animation this way:

after(10, lambda: sprite.move(0, 5))
after(15, lambda: sprite2.rotate(30))
after(20, lambda: sprite.scale(120, 120))
after(22, lambda: sprite2.move(50, 50))
after(22, lambda: sound1.play())
after(23, lambda: sprite.move(0, 0))
after(26, lambda: sound1.stop())


Others have already mentioned altering the definition of the after()
function, but you do not always have a pre-existing function that does
exactly what you want, such as sprite2.rotate() or sound1.play(). Here
is how I would do it, if lambda wasn't available:

def lambda_():
sprite.move(0, 5)
after(10, lambda_)
def lambda_():
sprite2.rotate(30)
after(15, lambda_)
def lambda_():
sprite.scale(120, 120)
after(20, lambda_)
etc...

I haven't verified this code in an actual interpreter, but I see no
reason why it shouldn't work. I don't believe that there is any restriction
on redefining functions. (pychecker might complain, though)

This style isn't PEP 8 compliant, but if you don't like having two extra
lines, you can always shrink it down to just one extra:

def lambda_(): sprite.move(0, 5)
after(10, lambda_)
def lambda_(): sprite2.rotate(30)
after (15, lambda_)
etc...
- Michael Hobbs

Jul 18 '05 #38
Clark C. Evans <cc*@clarkevans.com> wrote:
In general, indentation is great for "outer-structure" that is,
delimiting large code blocks. While delimiter based scoping is good
for inner structures, small blocks of code. It should not be an
either/or thing, one should properly have the option of using either
option depending upon which style brings the most clarity.


The Haskell language (http://www.haskell.org) does exactly this. It uses
indentation to infer structure, but the programmer is allowed to explicitly
state structure using semicolons and braces.

- Michael Hobbs

Jul 18 '05 #39
Clark C. Evans wrote:
In general, indentation is great for "outer-structure" that is,
delimiting large code blocks. While delimiter based scoping is good
for inner structures, small blocks of code. It should not be an
either/or thing, one should properly have the option of using either
option depending upon which style brings the most clarity.


Except that the Python philosophy is that overall, the greatest clarity
is achieved by having a single obvious way to do things. In this
viewpoint, there may be individual cases where delimiter-based scoping
is clearer, but these are only local maxima; the use of a mixture of
different styles (indentation and delimiters) will, over the entire
corpus of Python-language programming, result in significantly less
total clarity.

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #40
Antoon Pardon wrote:
Op 2004-10-12, Jeff Shannon schreef <je**@ccvcorp.com>:

Functions are at a different level of granularity than numbers and
lists. Anonymity makes sense for numbers and lists; it makes less sense
for collections of numbers and lists; and it makes still less sense for
organized collections of numbers, lists, and operations thereon, which
are structured in a meaningful way to express some (part of an)
algorithm.


I find it better to let the coder decide what makes sense in his program
and what not.


Which is the Perl philosophy. Many people seem quite happy with Perl
because of this TMTOWTDI attitude; personally, I prefer Python's clarity
and simplicity.
Similarly, I don't expect each line of code to have an
individual name, but once I collect lines of code into a file, I
certainly *do* expect to name that file, even if the file is only one or
two lines long.


So? If you then want to develop the code, do you put the new code in a
new file and then use a program to include it, or do you put unnamed
text in the already existing file?


Actually, I effectively do both of those, depending on circumstances.
(Opening a new editor, typing in it, and then pasting that text into the
middle of an existing file.) However, in this (admittedly weak,
especially when pushed this far) analogy, a lambda is equivalent to
putting the text in a new file, and insisting that that file not be
given a name and be kept separate from the parent file, but be
programmatically included nonetheless. Would you *want* to do that,
even if your operating system allowed it?

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #41
On Wed, 2004-10-13 at 10:58 -0700, Jeff Shannon wrote:
Antoon Pardon wrote:
Op 2004-10-12, Jeff Shannon schreef <je**@ccvcorp.com>:

Functions are at a different level of granularity than numbers and
lists. Anonymity makes sense for numbers and lists; it makes less sense
for collections of numbers and lists; and it makes still less sense for
organized collections of numbers, lists, and operations thereon, which
are structured in a meaningful way to express some (part of an)
algorithm.


Hi Jeff,

Jumping in way late in this thread, I'll toss in my pennies and say I
still use lambda fairly regularly in one place, and it just happens to
be the very place where I learned of lambda in the first place: event
handlers for GUI programming. I first learned the technique in Tkinter
circa 1.5.2 and still use it in wxPython. It isn't strictly necessary,
but given the already cluttered nature of GUI programming, I'm pretty
reluctant to toss in four or five more names every time I want a
complicated event handler to get called with slightly different
arguments. Basically I use it as a poor-man's curry (if I understand
currying correctly, I've only seen conversations about it on this list
and that's the impression I was left with: that it's a way of providing
variations in the default arguments to a function).

As I know you're a wxPython user as well, I'd be curious to know how you
approach this particular problem.

Regards,
Cliff

--
Cliff Wells <cl************@comcast.net>

Jul 18 '05 #42
On Wed, Oct 13, 2004 at 10:58:14AM -0700, Jeff Shannon wrote:
| Antoon Pardon wrote:
| >I find it better to let the coder decide what makes sense in his program
| >and what not.
|
| Which is the Perl philosophy. Many people seem quite happy with Perl
| because of this TMTOWTDI attitude; personally, I prefer Python's clarity
| and simplicity.

On this list, that's damn near close to an ad hominem attack.

There are more than one way to do many of things in Python, and just
about every "feature" that gets added is yet another way to do
something that is already being done. This doesn't stop features
from being adopted, does it? Every list comprehension has an
equivalent version using a while-loop. I could go on with examples,
but your assertion is a leaky bucket, so why bother waste the space?
Your arguments thus far have been "I don't use it, thus it probably
isn't useful, and therefore, no one should be able to use it." It's
an uninformed position and frankly, not very helpful.

I use lambda because it:

- puts the definition of an expression right
where it is used;

- doesn't require me to mint a name, or worry about
other possible calls to the same expression; and

- is efficient use of vertical coding space.

All of these reasons provide clarity in maintaining code. If you
are working with a programming style that uses CPS, deferred
execution, or similar mechanism with heavy callbacks or passing
functions, you will understand the importance of the above features.

Kind Regards,

Clark
Jul 18 '05 #43
Cliff Wells wrote:
Hi Jeff,

Jumping in way late in this thread, I'll toss in my pennies and say I
still use lambda fairly regularly in one place, and it just happens to
be the very place where I learned of lambda in the first place: event
handlers for GUI programming. I first learned the technique in Tkinter
circa 1.5.2 and still use it in wxPython. It isn't strictly necessary,
but given the already cluttered nature of GUI programming, I'm pretty
reluctant to toss in four or five more names every time I want a
complicated event handler to get called with slightly different
arguments. Basically I use it as a poor-man's curry (if I understand
currying correctly, I've only seen conversations about it on this list
and that's the impression I was left with: that it's a way of providing
variations in the default arguments to a function).


That's my understanding of currying, as well, and I too know it only
from discussion on this list. ;) But I recall that Alex Martelli, some
time ago, provided a wonderful explanation of currying and a recipe or
two for how it can be generically accomplished. (Before that
explanation, I'd had no idea where the term came from and had been
trying to work out how it coud be etymologically related to, say,
currying horses... ;) ) I believe that his solution involved callable
class instances that store the function to be called and the known
parameters as attributes. That *was* quite a while ago (possibly even
pre-2.2), though, so I don't know whether it'd still be the most
effective recipe... and my memory about it is a bit flakey.
As I know you're a wxPython user as well, I'd be curious to know how you
approach this particular problem.


To be honest, I've rarely felt the need to do much currying in my
wxPython (or other) applications. Maybe it's a design thing -- I tend
to make every non-trivial component I use be a custom class/subclass,
even if I'm only going to use it in one place, and it seems appropriate
to have methods on that class which encapsulate its desired behavior to
the point where currying isn't necessary. The closest I've come to
needing currying is handled neatly by wxCallAfter(), which takes a
function and a list of arguments to pass to that function. Then again,
almost everything I've done so far has been fairly simple (as in low
complexity, not necessarily easy...), so it's possible that I'm the odd
one here...

Jeff Shannon
Technician/Programmer
Credit International
Jul 18 '05 #44
On Wed, Oct 13, 2004 at 10:47:56AM -0700, Jeff Shannon wrote:
| Except that the Python philosophy is that overall, the greatest clarity
| is achieved by having a single obvious way to do things.

When doing coding that uses alot of callbacks, use of lambda for
tiny, nameless, single-use expressions is the "single obvious way to
do something".

Assume for a moment the following programming costs:

2m Minting a name, that is, finding a name that is not 'foo'
which semantically adds to the readability and maintainability
of the code.

30s Verifying that a function name is not used more than once to
verify that changing its definition, or if it is reused,
making sure all the places where a change would affect is OK.

In one of my files, I've got 20 or so lambdas, typically only a few
characters to plug-in a computation. You're asking me to pay a 40
minute price just to mint names in this file? Then, I've had, over
the past year about 20 edits on that file, some of which change a
few of these lambdas, say 2 changes per edit on average. That's
another 20 minutes. So, over the last year, in this one file alone,
not having lambdas would have cost me an additional hour of time!
I've got 2 largish projects, each averaging about 20 files, so
that's about 40 hours of time chewed up with small efficiency hits.
Or, about $4,000 of billable time. I'd rather keep the money or
take a vacation, thank you very much.

I use Python beacuse it is a horribly efficient language for me to
write software with; it is efficient beacuse I have the flexibiltiy
to use several different constructs depending on which is more
clearly expresses the intent of the developer. While lambda is a
small part of this effiency, it is a factor. It clearly expresses a
simple, nameless single chunk of code that is never reused.

Propose another construct that has these features, and I'll gladly
use it instead of lambda.

Best,

Clark
Jul 18 '05 #45
In article <ma**************************************@python.o rg>,
"Clark C. Evans" <cc*@clarkevans.com> wrote:
On Wed, Oct 13, 2004 at 10:58:14AM -0700, Jeff Shannon wrote:
| Antoon Pardon wrote:
| >I find it better to let the coder decide what makes sense in his program
| >and what not.
|
| Which is the Perl philosophy. Many people seem quite happy with Perl
| because of this TMTOWTDI attitude; personally, I prefer Python's clarity
| and simplicity.

On this list, that's damn near close to an ad hominem attack.

There are more than one way to do many of things in Python, and just
about every "feature" that gets added is yet another way to do
something that is already being done. This doesn't stop features
from being adopted, does it? Every list comprehension has an
equivalent version using a while-loop. I could go on with examples,
but your assertion is a leaky bucket, so why bother waste the space?
Your arguments thus far have been "I don't use it, thus it probably
isn't useful, and therefore, no one should be able to use it." It's
an uninformed position and frankly, not very helpful.
While I don't really agree that lambda ought to be jettisoned,
if that's the point in question, I do think that these are
legitimate questions. The fact that list comprehensions for
example were adopted despite their redundance is indeed a
step backwards for the language as a whole, and if lambda were
being considered today for adoption it would need to be justified
in these terms. "Let the coder decide" is not a good general
principle for language design, as suggested by counter-example above.
I use lambda because it:

- puts the definition of an expression right
where it is used;

- doesn't require me to mint a name, or worry about
other possible calls to the same expression; and

- is efficient use of vertical coding space.

All of these reasons provide clarity in maintaining code. If you
are working with a programming style that uses CPS, deferred
execution, or similar mechanism with heavy callbacks or passing
functions, you will understand the importance of the above features.


Fine, I have used it myself. Since it's already in Python,
and in plenty of old code, there isn't much justification for
removing it. But if it were time to clean Python up to conform
to the clarity and simplicity goals that one hears so much about,
lambda would be gone for sure. Along with list comprehensions
and a boatload of gadgets. If Python were a decent functional
programming language, lambda would work better and be a natural
if not very important part of the language, but that isn't the
case and it makes about as much sense as legs on a snake. If
you really want a simple, clear language, that is.

Donn Cave, do**@u.washington.edu
Jul 18 '05 #46
Clark C. Evans wrote:
On Wed, Oct 13, 2004 at 10:58:14AM -0700, Jeff Shannon wrote:
| Antoon Pardon wrote:
| >I find it better to let the coder decide what makes sense in his program
| >and what not.
|
| Which is the Perl philosophy. Many people seem quite happy with Perl
| because of this TMTOWTDI attitude; personally, I prefer Python's clarity
| and simplicity.

On this list, that's damn near close to an ad hominem attack.


Only if you choose to read it that way. I pointed out that many people
are happy with Perl, thus implying that the philosophy behind
programming languages is largely a matter of taste. It makes sense to
choose a language whose design philosophy matches one's own. From this
and other previous discussions, it seems to me that Antoon Pardon has a
number of disagreements with Python's design goals; that's fine, he's
certainly entitled to his opinion, but there are others who *do* agree
with Python's design goals. ISTM that it would therefore be better,
overall, for those who disagree with Pythonic philosophy to look for a
different language that suits them better, and those who agree with
Pythonic philosophy to keep using Python. Trying to please everyone
with a single language just isn't gonna work, nor should it be expected
to. Pointing this fact out has nothing to do with my personal opinions
about Mr. Pardon, you, or anyone else.
Your arguments thus far have been "I don't use it, thus it probably
isn't useful, and therefore, no one should be able to use it." It's
an uninformed position and frankly, not very helpful.


No, my arguments thus far have been that, for almost every use for which
lambdas are beneficial, there's another approach that is more consistent
with core Pythonic philosophy that works almost as well or better.
There's lots of things that I don't use but that I think are extremely
useful (metaclasses, for instance). Heck, I find metaclasses even more
confusing than lambdas.... but I can also see that the *benefit* of
metaclasses is greater, and is extremely difficult to match in more
traditional Python.

I have tried to be clear that I'm not the most experienced or talented
developer ever; I'm a journeyman at best, and I know it, and I'm
perfectly willing to learn from others when the benefit of their
teaching is clear. But so far, the examples that I've been given for
when lambda is useful are limited to "a programming style that uses CPS,
deferred execution, or similar mechanism with heavy callbacks or passing
functions," which may be something that you do a lot of but still sounds
like a special case to me. And even within that style, alternate
solutions can provide most of the benefits that lambda does.

Oh, and I almost agree with you about list comprehensions -- they'd do
just as well to be left out of Py3K, because they've been superseded by
generator comprehensions. ;)

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #47
Clark C. Evans wrote:
Assume for a moment the following programming costs:

2m Minting a name, that is, finding a name that is not 'foo'
which semantically adds to the readability and maintainability
of the code.


Does it *really* take you two whole minutes to find a meaningful name?
Two minutes is a pretty long time if you're just sitting and thinking.
Even button1_callback() seems fairly readable and maintanable to me.
And anyhow, a fair number of the examples of lambda usage that I've seen
can be easily replaced with a reference to an existing function --
operator.mul() isn't that difficult...

To be honest, if I were worrying about programming costs, I'd be looking
at the time I'd spend trying to refactor my problem into something where
I could use (perhaps curried versions of) more generic callbacks. That
might be a pretty significant investment of time, actually. Of course,
it might (or might not) pay off with a cleaner and clearer overall
architecture... But perhaps this is a particular weakness of mine,
where I want to try to generalize things as much as practical.

Given the presumption that many, if not most, uses of lambda could be
generalized to some degree, I don't think it would be necessary to mint
a new name for each and every lambda that you currently use, even in
those cases where there *isn't* a pre-existing standard-lib function
that serves the same purpose as the lambda.
30s Verifying that a function name is not used more than once to
verify that changing its definition, or if it is reused,
making sure all the places where a change would affect is OK.


Good point, though well-modularized code should help with this. I can't
say that I have problems with intended-name clashes very often. Given
reasonable module sizes, I'd call 30s a maximum time rather than an
average time, but that *is* a valid consideration.
In one of my files, I've got 20 or so lambdas, typically only a few
characters to plug-in a computation. You're asking me to pay a 40
minute price just to mint names in this file? Then, I've had, over
the past year about 20 edits on that file, some of which change a
few of these lambdas, say 2 changes per edit on average. That's
another 20 minutes. So, over the last year, in this one file alone,
not having lambdas would have cost me an additional hour of time!
I've got 2 largish projects, each averaging about 20 files, so
that's about 40 hours of time chewed up with small efficiency hits.
Or, about $4,000 of billable time. I'd rather keep the money or
take a vacation, thank you very much.


I suspect that you could find a moderately generic approach or two that
could conveniently replace most of those lambdas, and which would
require no more maintenance work (and possibly less) than the lambdas
do, in a lot less time than 40 hours. Given that many of your lambdas
are probably variations on a theme, making generic functions might even
*save* you time. (Not that I'm quite convinced about your figure of 40
hours even if you *did* insist on using named functions in the exact
same style that you now use lambdas, rather than refactoring to take
advantage of the benefits that full functions give you.)

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #48
Op 2004-10-13, Jeff Shannon schreef <je**@ccvcorp.com>:
Antoon Pardon wrote:
Op 2004-10-12, Jeff Shannon schreef <je**@ccvcorp.com>:

Functions are at a different level of granularity than numbers and
lists. Anonymity makes sense for numbers and lists; it makes less sense
for collections of numbers and lists; and it makes still less sense for
organized collections of numbers, lists, and operations thereon, which
are structured in a meaningful way to express some (part of an)
algorithm.


I find it better to let the coder decide what makes sense in his program
and what not.


Which is the Perl philosophy. Many people seem quite happy with Perl
because of this TMTOWTDI attitude; personally, I prefer Python's clarity
and simplicity.


Well if that is the Perl attitude, please inform me who is to decide
what makes sense and what not to put in a program according to the
Python philosophy.

Similarly, I don't expect each line of code to have an
individual name, but once I collect lines of code into a file, I
certainly *do* expect to name that file, even if the file is only one or
two lines long.


So? If you then want to develop the code, do you put the new code in a
new file and then use a program to include it, or do you put unnamed
text in the already existing file?


Actually, I effectively do both of those, depending on circumstances.
(Opening a new editor, typing in it, and then pasting that text into the
middle of an existing file.) However, in this (admittedly weak,
especially when pushed this far) analogy, a lambda is equivalent to
putting the text in a new file, and insisting that that file not be
given a name and be kept separate from the parent file, but be
programmatically included nonetheless. Would you *want* to do that,
even if your operating system allowed it?


But a lambda has a name, if it hasn't it would be useless, just a
temporary one. Lamda's are typically used as an argument to a function
or method. Within that function they have a name. In that respect they
are no different from a list literal. And list literals are just
as much part of the code as lambda's. So are you argueing against
list literals as parameters or in expressions too? Because this
analogy of yours doesn't make a distinction between lambda's and
lists.

--
Antoon Pardon
Jul 18 '05 #49
Op 2004-10-14, Jeff Shannon schreef <je**@ccvcorp.com>:
Clark C. Evans wrote:
Assume for a moment the following programming costs:

2m Minting a name, that is, finding a name that is not 'foo'
which semantically adds to the readability and maintainability
of the code.
Does it *really* take you two whole minutes to find a meaningful name?


I can't speak for Clarc but yes it does for me, Because sometimes there
just isn't a meaningfull name IMO and the best you can come up with is
frase what the function does in words what would be easier expressed in
a formula.
Two minutes is a pretty long time if you're just sitting and thinking.
Even button1_callback() seems fairly readable and maintanable to me.
But that is not a meaningfull name. It doesn't add any information.
That it is a callback for button1 can be easily inferred from the
fact that it is used as the callback parameter.

IMO this is just as usefull as:

parameter = [3,5,8,23]
lng = len(parameter)
And anyhow, a fair number of the examples of lambda usage that I've seen
can be easily replaced with a reference to an existing function --
operator.mul() isn't that difficult...
I agree that my need for using lambda's has diminished as python has
evolved. But a reference to operator.xxx only helps if you want a
single operator as a function. As soon as you need to combine
operators you need to construct a new callable.
To be honest, if I were worrying about programming costs, I'd be looking
at the time I'd spend trying to refactor my problem into something where
I could use (perhaps curried versions of) more generic callbacks. That
might be a pretty significant investment of time, actually. Of course,
it might (or might not) pay off with a cleaner and clearer overall
architecture... But perhaps this is a particular weakness of mine,
where I want to try to generalize things as much as practical.

Given the presumption that many, if not most, uses of lambda could be
generalized to some degree, I don't think it would be necessary to mint
a new name for each and every lambda that you currently use, even in
those cases where there *isn't* a pre-existing standard-lib function
that serves the same purpose as the lambda.


I do wonder whether it would add readabilty. My impression is that
curried functions are not that easily understood and I fear that
those who have problems with lambda's will not be helped if the
lambda's are replaced with curried functions. IMO generalizing
when it isn't necessary can detract from readability too. If you
have need specific functionality and have a function that provides
just that specific functionality, you just need to understand that
function. If you have a more general function, you need to understand
that function and how the use of certain parameters transforms the
general case into your specific case.
Not that I'm against the use of curried functions or the use of
general functions.

--
Antoon Pardon
Jul 18 '05 #50
53 Replies

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by could ildg | last post: by
7 posts views Thread by andrewfsears@gmail.com | last post: by
6 posts views Thread by =?Utf-8?B?S2Fp?= | last post: by
29 posts views Thread by not.here.now@gmail.com | last post: by
2 posts views Thread by Mike Gleason jr Couturier | last post: by
2 posts views Thread by Joe Strout | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.