Lambda going out of fashion

A

Alex Martelli

Peter Otten said:
Alex said:
if len(somecontainer) > 0:

instead of the obvious

if somecontainer:

so it's not as if pythonistas in general are blessed with some magical
"redundancy avoidance spell"...

That is not always equivalent:
z = Numeric.zeros(5)
z array([0, 0, 0, 0, 0])
bool(z) False
len(z) > 0
True

Good point! Numeric sure has semantics here that can be confusing;-).

numarray's arrays just can't be used as the argument to bool(...) -- you
get a runtime error "An array doesn't make sense as a truth value. Use
sometrue(a) or alltrue(a)" ("in the face of ambiguity, refuse the
temptation to guess"). Still, this ALSO means that len(z)>0 is very
different from bool(z), for numarray as for Numeric.

Most containers don't choose to implement __nonzero__, so bool(z) just
calls __len__ instead; that's the scenario I had in mind, of course.
But sure, if somecontainer might define peculiar semantics in
__nonzero__, then in order to test if it's empty you can't use the
normal pythonic idiom of checking its truth value, but rather must check
its length. (I still prefer "if len(z):", avoiding the redundant ">0",
but that's just a small difference, of course).


Alex
 
N

Nick Coghlan

jfj said:
Don't worry, it's not gonna go away because too much software is
depending on it. If you don't follow the advice that lambda is
deprecated and you keep using it, more software will depend on it and it
will never disappear :)

No, that doesn't apply for Python 3.0

Indeed, lambda as it currently stands will disappear for the Python 2.x series.

Python 3.0 will be a case of "OK, let's take the things we learned were good and
keep them, and throw away the things we realised were bad"

Undoubtedly, the two languages will co-exist for quite some time.

Cheers,
Nick.
 
A

Alex Martelli

Nick Coghlan said:
Perhaps something like:

accepts_func( (def (a, b, c) to f(a) + o(b) - o(c)) )

Nice, except I think 'as' would be better than 'to'. 'as' should be a
full keyword in 3.0 anyway (rather than a surprisingly-NOT-keyword like
today), and "define something as somethingelse" seems marginally more
readable to me than "define something to somethingelse" anyway.


Alex
 
C

Craig Ringer

Fredrik said:
Craig Ringer wrote:




docstrings should be moved out of the C modules, and into resource
files. (possibly via macros and an extractor). when I ship programs
to users, I should be able to decide whether or not to include docstrings
without having to recompile the darn thing.
Good point. Unfortunately, many translation mechanisms - like Qt's, for
example - don't make it easy to translate strings in resource files
using the same tools as the core app. Translators have a hard enough job
already with one set of tools in my experience, lumping more on them
probably isn't nice. On the other hand, this isn't really Python's
problem - but neither is where they come from. Even if I load docstrings
from resource files, I still have a fair bit of work ahead to make
Python accept them if they're not plain ASCII. In my current project, I
actually gave up and changed sysdefaultencoding to utf-8 . (It's an
embedded interpreter, so it's not too bad - and all modules should
handle that correctly by now anyway).
I think the only reason that this hasn't already been done is to reduce the
amount of swearing during the conversion process (both for the core developer
and C extension developers...).
Agreed. However, it's my understanding that one can convert:

PyObject* *Py_BuildValue*( char *format, ...)

to
PyObject* *Py_BuildValue*( const char *format, ...)

(for example) without affecting module developers or users of that
function elsewhere in the core code. const _arguments_ are often very
safe, its const return values that tend to suck.
 
R

Robin Becker

Alex Martelli wrote:
......
By the way, if that's very important to you, you might enjoy Mozart
(http://www.mozart-oz.org/) -- I'm looking at it and it does appear to
go even further in this specific regard (rich support for multi -
paradigm programming). It's also blessed with a great book,
<http://www.info.ucl.ac.be/people/PVR/book.html> -- I've just started
browsing it, but it appears to be worthy of being called "SICP for the
21st century"...!-). Just like SICP made it worthwhile to learn a
little Scheme even if you'd never use it in production, so does CTMCP
(acronym for this new book by Van Roy and Haridi) work for Oz, it
appears to me.
......very interesting, but it wants to make me install emacs. :(
 
N

Nick Coghlan

Alex said:
Nice, except I think 'as' would be better than 'to'. 'as' should be a
full keyword in 3.0 anyway (rather than a surprisingly-NOT-keyword like
today), and "define something as somethingelse" seems marginally more
readable to me than "define something to somethingelse" anyway.

I actually flipped back and forth between preferring 'as' and 'to' while writing
the message.

It was the mathematical phrasing of "f is a function from R to R" (replacing the
capital R's with the symbol for the real numbers) that first made me think of
'to', since I was trying to emphasise the parallels with mathematical functions.
(To my mind, theoretical mathematics is one of the areas with significant
legitimate uses for lambda functions).

The '->' suggestion had a similar source.

The way I'd read the 'to' version out loud when explaining to someone what the
code did:

"DEFine an anonymous function from arguments a, b and c TO the value f of a plus
o of b minus o of c"

or the short version:

"DEFine a function from a, b and c TO f a plus o b minus o c"

As an even simpler example, (def (x) to x * x) would be "define a function from
x to x squared". (def () to <whatever>) would be "define a function from no
arguments to <whatever>"

'as' already implies renaming semantics due to from-style imports. In Py3k, it's
likely to pick up the naming duties in except clauses as well (i.e. "except
ValueError, TypeError as ex:").

'as' is also a candidate for optional static typing and adaptation (and
hopefully someone will talk Guido out of his punctuation happy version of that!).

I eventually decided that using 'as' for anonymous functions as well would just
be plain confusing.

Cheers,
Nick.
 
N

Nick Coghlan

Nick said:
Indeed, lambda as it currently stands will disappear for the Python 2.x
series.

Will NOT disappear. I repeat, will NOT disappear.

Cheers,
Nick.
Damn those missing negators. . .
 
S

Stephen Thorne

Nice, except I think 'as' would be better than 'to'. 'as' should be a
full keyword in 3.0 anyway (rather than a surprisingly-NOT-keyword like
today), and "define something as somethingelse" seems marginally more
readable to me than "define something to somethingelse" anyway.

I'm sorry, but I dislike this quite a bit, 'def arglist as expression'
just doesn't fit right for me.

After reading the discussion, and trying to glean answers to my
original questions, I realise that there's a pragmatic way of doing
the things that I mentally 'require' lambda for, without using lambda
at all. I might try and catalog lambda patterns and their alternatives
at some point.

Alex, thankyou for the feedback concerning the misuse of lambda. I
consider prevention of misuse to be much more important than the
denial of use. I recognise fully the frustration you must experience
when you see map(lambda x:f(x).

I think it is important to voice concern, and I recieved not a few
'me-too's in reply to this thread. But at the end of the day, I'm not
against removing lambda in py3k.

slightly-less-concerned-ly yr's
Stephen Thorne.
 
R

rzed

Hi guys,

I'm a little worried about the expected disappearance of lambda
in python3000. I've had my brain badly broken by functional
programming in the past, and I would hate to see things suddenly
become harder than they need to be.

An example of what I mean is a quick script I wrote for doing
certain actions based on a regexp, which I will simlify in this
instance to make the pertanant points more relevent.

{
'one': lambda x:x.blat(),
'two': lambda x:x.blah(),
}.get(someValue, lambda x:0)(someOtherValue)

The alternatives to this, reletively simple pattern, which is a
rough parallel to the 'switch' statement in C, involve creating
named functions, and remove the code from the context it is to
be called from (my major gripe).

So, the questions I am asking are:
Is this okay with everyone?
Does anyone else feel that lambda is useful in this kind of
context? Are there alternatives I have not considered?

Not addressing lambdas per se, but something similar to your pseudo-
switch statement can be done without using them at all. One way might
be to use a function dictionary wrapped in an accessor function, such
as this:

def dofns(key):
fd2 = {
0:'print "Key 0"',
1:'print "one"',
4:"\n".join(['for ix in range(15):',
' print "%s%d" % (" "*ix,ix)']),
}
try:
exec(fd2[key])
except KeyError:
print 'Key',key,'not found'

The keys can as easily be strings, of course. One virtue of this
method is that it allows multi-line statements and looping (as in fd2
[4]).

Now the actual 'switch' statement becomes as simple as:
dofns(key)

If there are parameters involved, this solution becomes a little
tackier. One way might be something like:

def dofns(key,**kws):
fd2 = {
0:'print "Key 0"',
1:'print "one"',
2:"\n".join(['n=kws["name"]','x=kws["x"]',
'y=kws["y"]','print "%s:"%n,x,y']),
3:"\n".join(['val=kws["x"]*7 + kws["y"]',
'print kws["x"],kws["y"],val']),
4:"\n".join(['for ix in range(kws["x"]):',
' print "%s%d" % (" "*ix,ix)']),
5:'exec(fd2[3])',
6:"\n".join(['print kws["z"],',
'dofns(3,x=13,y=22)']),
}
try:
exec(fd2[key])
except KeyError:
print 'Key',key,'not found'


# switch (key kwdparms)
for key in [0, 1,2,3,4,5,6,7]:
dofns(key,name='Gladys',y=50,x=8,z=34)

You could remove the function dictionary from the wrapper and use it
similarly to your example, but I find that less readable.
exec({
multi-line dictionary definition
}[key] parms) # what were we doing again? Oh! exec!

Anyway, for those who use lambdas, this approach is likely to be
unappealing. For those who find lambdas puzzling, it may be an
alternative, at least for a way to handle the switch equivalent.
 
S

Skip Montanaro

Keith> My personal gripe is this. I think the core language, as of 2.3
Keith> or 2.4 is very good, has more features than most people will ever
Keith> use, and they (Guido, et al.) can stop tinkering with it now and
Keith> concentrate more on the standard libraries.

What keeps you from being part of the "et al"? This is open source, after
all. Note that there's more to be done than simply writing code.
Documentation always needs attention. Bug reports and patches always need
to be verified and vetted. Even mundane stuff like managing mailing lists
detracts from the time the most experienced people could spend writing code
you might not be able to do. There's lots to do. Start here:

http://www.python.org/dev/

Go anywhere. <wink>

Skip
 
S

Skip Montanaro

Craig> IMO the reference behaviour of functions in the C API could be
Craig> clearer. One often has to simply know, or refer to the docs, to
Craig> tell whether a particular call steals a reference or is reference
Craig> neutral. Take, for example, PyDict_SetItemString vs
Craig> PyMapping_SetItemString . Is it obvious that one of those steals
Craig> a reference, and one is reference neutral? Is there any obvious
Craig> rationale behind this?

Sure. PyDict_SetItemString was first written very early on in Python's
development (actually, it was originally called something
namespace-ly-dangerous like dict_setstring). PyMapping_SetItemString (part
of the abstract objects api) was written later with an emphasis on the
consistency of behavior you desire. You're generally going to be better off
sticking with the abstract objects api. For obvious reasons of backward
compatibility, the concrete apis (PyDict_*, PyList_*, etc) must be retained.

Skip
 
S

Skip Montanaro

Paul> Actually it's the other way around: it's named functions that are
Paul> the syntactic sugar.

While I'm sure it can be done, I'd hate to see a non-trivial Python program
written with lambda instead of def. (Take a crack at pystone if you're
interested.)

Skip
 
F

Fredrik Lundh

Skip said:
Keith> My personal gripe is this. I think the core language, as of 2.3
Keith> or 2.4 is very good, has more features than most people will ever
Keith> use, and they (Guido, et al.) can stop tinkering with it now and
Keith> concentrate more on the standard libraries.

What keeps you from being part of the "et al"?

as I've proven from time to time, joining the "et al" and *not* tinkering with
the language doesn't mean that the language stays where it is.

(I've said it before, and I'll say it again: native unicode and generators are
the only essential additions I've seen since 1.5.2, with properties and sub-
classable C types sharing a distant third place. the rest of the stuff has had
zero impact on my ability to write solid code in no time at all, and negative
impact on my ability to download stuff that others have written and expect
it to work in any Python version but the latest...)

</F>
 
T

tanghaibao

I have this book called TEXT PROCESSING IN PYTHON by David Mertz on
hand, it is a good book and in the first chapter it is really a show
room for higher-order functions which I may now cite to remind you of
the FLEXIBILITY of this keyword.
''' combinatorial.py

from operator import mul, add, truth
apply_each = lambda funs, args = []: map(apply, fns, [args]*len(fns))
bools = lambda lst: mpa(truth, lst)
bool_each = lambda fns, args = []: bools(apply_each(fns, args))
conjoin = lambda fns, args = []: reduce(mul, bool_each(fns, args))
all = lambda fns: lambda arg, fns = fns: conjoin(fns, (arg,))
both = lambda f,g: all(f(f,g))
all3 = lambda f,g,h: all((f,g,h))
and_ = lambda f,g: lambda x, f=f, g=g: f(x) and g(x)
disjoin = lambda fns, args = []: reduce(add, bool_each(fns, args))
some = lambda fns: lambda arg, fns = fns: disjoin(fns, (arg,))
either = lambda f,g: some((f,g))
anyof3 = lambda f,g,h: some((f,g,h))
compose = lambda f,g: lambda x, f=f, g=g: f(g(x))
compose3 = lambda f,g,h: lambda x, f=f, g=g, h=j: f(g(h(x)))
ident = lambda x:x
'''
And some other lambda function usage is when they are treated like
objects, they can also fit in generators... THIS IS ART. Well, some may
argue that it is hard for people to maintain these codes, put the
problem to Haskell people and see how they respond(at least you don't
need to scroll up and down...) Oh! So when did python adopt simplicity
rather than verbosity?

Q: It simply doesn't FIT.
A: OK, OK, get all these map, filter stuff away, and go python, go and
get mixed with them.
 
S

Steven Bethard

I have this book called TEXT PROCESSING IN PYTHON by David Mertz on
hand, it is a good book and in the first chapter it is really a show
room for higher-order functions which I may now cite to remind you of
the FLEXIBILITY of this keyword.

I'm not exactly sure what you mean by "flexibility"; all of these
examples can be written without lambdas:
apply_each = lambda funs, args = []: map(apply, fns, [args]*len(fns))

def apply_each(fns, args=[]):
return [fn(*args) for fn in fns]
bools = lambda lst: mpa(truth, lst)

def bools(lst):
return [bool(x) for x in lst]
bool_each = lambda fns, args = []: bools(apply_each(fns, args))

def bool_each(fns, args=[]):
return bools(apply_each(fns, args))
conjoin = lambda fns, args = []: reduce(mul, bool_each(fns, args))

def conjoin(fns, args=[]):
reduce(mul, bool_each(fns, args))
all = lambda fns: lambda arg, fns = fns: conjoin(fns, (arg,))

def all(fns):
def _(arg):
return conjoin(fns, (arg,))
return _
both = lambda f,g: all(f(f,g))

def both(f, g):
return all(f(f,g))
all3 = lambda f,g,h: all((f,g,h))

def all3(f, g, h):
return all((f,g,h))
and_ = lambda f,g: lambda x, f=f, g=g: f(x) and g(x)

def and_(f, g):
def _(x):
return f(x) and g(x)
return _
disjoin = lambda fns, args = []: reduce(add, bool_each(fns, args))

def disjoin(fns, args=[]):
return reduce(add, bool_each(fns, args))
some = lambda fns: lambda arg, fns = fns: disjoin(fns, (arg,))

def some(fns):
def _(arg):
return disjoin(fns, (arg,))
return _
either = lambda f,g: some((f,g))

def either(f, g):
return some((f,g))
anyof3 = lambda f,g,h: some((f,g,h))

def anyof3(f, g, h):
return some((f,g,h))
compose = lambda f,g: lambda x, f=f, g=g: f(g(x))

def compose(f, g):
def _(x):
return f(g(x))
return _
compose3 = lambda f,g,h: lambda x, f=f, g=g, h=j: f(g(h(x)))

def compose3(f, g, h):
def _(x):
return f(g(h(x)))
return _
ident = lambda x:x

def ident(x):
return x


Steve
 
T

tanghaibao

Thanks. :) Two remarks.
o One-liner fits the eyes & brains of a portion of people.
o Why don't you just say all python can be written in equivalent java,
can I assert that Guido doesn't want to get mixed with those
mainstream>?
 
F

Fredrik Lundh

jfj said:
Personally I'm not a fan of functional programming but lambda *is* useful when I want to say for
example:

f (callback=lambda x, y: foo (y,x))

I don't believe it will ever disappear.

agreed. there's no reason to spend this christmas rewriting your programs, folks.
I'm sure you all have better things to do ;-)

cheers /F
 
F

Fernando Perez

Alex said:
I don't know what it IS about lambda that prompts so much dubious to
absurd use, but that's what I observed. I don't know if that plays any
role in Guido's current thinking, though -- I have no idea how much
"dubious Python" he's had to struggle with.

Just a side comment, unrelated to the lambda issue: it just occurred to me that
it might be very useful to have a collection of 'dubious python' available
somewhere. Just as it is great for everyone to see good code in action, it is
equally enlightening to see examples of bad practices (preferably with an
explanation of why they are bad and the good alternatives).

I suspect after your CB2 experience, you are in a uniquely well-qualified
position to have such a collection handy. Whether you feel inclined to spend
the necessary time assembling it for public consumption is a different
story :) But I think it would be a very valuable resource, and a great way to
point newbies to 'mandatory reading' before they travel down the same blind
alleys for the n-th time.

Cheers, and happy holidays,

f
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top