"Updating" lambda functions

J

Jeff Shannon

Antoon said:
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.
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
 
C

Cliff Wells

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
 
C

Clark C. Evans

| >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
 
J

Jeff Shannon

Cliff said:
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
 
C

Clark C. Evans

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
 
D

Donn Cave

"Clark C. Evans said:
| >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, (e-mail address removed)
 
J

Jeff Shannon

Clark said:
| >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
 
J

Jeff Shannon

Clark said:
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
 
A

Antoon Pardon

Op 2004-10-13 said:
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.

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

Antoon Pardon

Op 2004-10-14 said:
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.
 
J

JCM

Jeff Shannon said:
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.

I'd be looking at the time spent posting to newsgroups.
 
A

Alex Martelli

Jeff Shannon said:
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.

I think the most effective way to make general curries today is by
closures. E.g., if what you want to curry are the starting parameters:

def curry(function, *curried_params):
def curried(*free_params):
return function(*(curried_params+free_params))
return curried

In 2.4 you can even set curried.func_name=function.func_name ...;-)

For an important special case, currying the first parameter into a
Python-coded function, function.__get__(first_parameter) happens to
work; I confess that sometimes I've coded functions that take a "first
parameter" that is in fact a tuple of quite a few things just to be able
to use this *delightful* approach (not recommended, I've just got a love
affair with currying, and _dream_ of it being a Python "intrinsic"!-).


Alex
 
A

Alex Martelli

Jeff Shannon said:
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

Amen, hallelujah. There are thousands and thousands of programming
languages, and more are born all the time. Trying to make one language
please all is a doomed endeavour: "if you want PL/I, you know where to
find it" (apparently that was Ritchie's stock answer to Thompson's
occasional whines that C didn't allow this, that, or the other -- C
shares with Python the underlying ideal of "there should be one obvious
way", indeed Python shares 4.5 of the 5 principles that the ANSI C
Standard introduction defines as "the Spirit of C").

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

"Generator expressions" is the recommended terminology nowadays. But I
agree, list(x+x for x in foo) is a perfectly acceptable alternative to
the equivalent List Comprehension [x+x for x in foo] and in Python 3.0
the latter is therefore likely to be removed, as part of the overall
idea of removing many "legacy" things, accumulated over the years, and
make Python more pythonic.

Hacking on CPython on a vast scale is too hard to bother, but if and
when pypy matures, assuming 3.0 still looks far away at that point, I'd
like to make a "prototype 3.0" based strictly on removing stuff (moving
some redundant stuff to a legacy package in the standard library where
feasible, or else just excising it). Ah well, one can dream!-)


Alex
 
A

Antoon Pardon

Op 2004-10-13 said:
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.

I don't think I have a problem with python design goals. But I see
nothing in the design goals that contradicts the notion of an
anonymious function.

Further more I can't think of Python as having design goals, more
something like design guidelines. Guidelines whose priority changes
depending on the subject and favor of the person.

One time it is an exception is never important enough to break the
rule, the next time it is practicallity beats purity. As such I
feel that often enough arguments carry very little weight and it
all boils down to what feels right and after one has such a feeling
one just picks the guidelines that supports this feeling and declares
it has the highest priority in this case.

It is very well possible I do unjustice to a number of people now,
but that is the impression I get.
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,

My philosophy is to use the language that I think is best suited
to solve the problem in front of me. As python changes I will
continue to evaluate it in that respect.
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.

IMO there is nothing to be gained by saying some method of programming
is unpythonic or not. As python changes what is pythonic and what is
not will change too. I wouldn't be surprised that in some days before
version 2, some people would have called nested scopes unpythonic
and suggested that those who wanted them should look for an other
language. IMO saying something is unpythonic is just saying you
are against it, because once it is adapted it becomes pythonic.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,616
Members
45,306
Latest member
TeddyWeath

Latest Threads

Top