Lambda going out of fashion

A

Alex Martelli

Thanks. :) Two remarks.
o One-liner fits the eyes & brains of a portion of people.

True! So, personally, I'd rather code, e.g.,

def bools(lst): return map(bool, lst)

rather than breal this one-liner into two lines at the colon, as per
standard Python style. However, uniformity has its advantages, too; I'm
ready for the one-liner style to be outlawed in Python 3.0, purely in
the advantage of uniformity.

Note that lambda is utterly useless here, be it for one-liners or not.


Alex
 
J

jfj

Stephen said:
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.

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 :)

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.


G.
 
T

Terry Reedy

Well, you can say apply() is 'deprecated' now,

What is deprecated is the spelling, not the concept or functionality.
As far as I know, apply(func, args) is exactly equivalent to func(*args).
If the latter had been invented in the beginning and you had learned it as
Python's spelling of the apply concept, you might never miss the 'apply'
spelling.

Terry J. Reedy
 
B

Brian van den Broek

Fernando Perez said unto the world upon 2004-12-23 14:42:
Alex Martelli wrote:




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

Hi all,

+1

I would find this really useful!

I'm much more likely to be among the benefited than the benefactors.
This could be a lot of work for one person. Thus, it seems like a good
thing for a wiki, so as to spread the weight around. With that in mind,
I created <http://www.python.org/moin/DubiousPython>. I hope this seems
like a good idea to others, particularly those more able to extend it
than I. (I'd also be grateful if others could remove any feet than I
might have inadvertently put into my mouth on the wiki page.)

Best to all,

Brian vdB
 
A

Andrew Dalke

Terry said:
As far as I know, apply(func, args) is exactly equivalent to func(*args).

After playing around a bit I did find one difference in
the errors they can create.
.... yield 1
.... Traceback (most recent call last):
Traceback (most recent call last):

That led me to the following
.... def __len__(self):
.... return 10
.... def __getitem__(self, i):
.... if i == 0: return "Hello!"
.... raise IndexError, i
.... Traceback (most recent call last):

Is that difference a bug?

Andrew
(e-mail address removed)
 
M

Mike Meyer

Nick Coghlan said:
jfj wrote:
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.

Perl 6.0 is going to include even more drastic changes. It will also
include a Perl 5.x interpreter, and will have to be switched to 6.0
mode by a magic cookie of some kind in the source. Possibly Python 3.0
could do something similar. Use the same byte code engine, and a
compiler switch that enables the gotchas. Or maybe
"from __past__ import gotchas"

<mike
 
B

Benji York

Andrew said:
After playing around a bit I did find one difference in
the errors they can create.



... yield 1
...


Traceback (most recent call last):


Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: len() of unsized object

No question that they report different errors in the face of being given
unsupported input.

That led me to the following

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: len() takes exactly one argument (6 given)


Is that difference a bug?

They do two different things. I think you have a spurious * in the call
to apply. The apply above is equivalent to

Which gives the same error:

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: len() takes exactly one argument (6 given)

If the * is removed, it works correctly:
6
 
T

Terry Reedy

Andrew Dalke said:
After playing around a bit I did find one difference in
the errors they can create.

Ok, add 'assuming that func and args are a valid callable and sequence
respectively.' Error messages are not part of the specs, and may change
for the same code from version to version.
... yield 1
...
Traceback (most recent call last):

Traceback (most recent call last):


That led me to the following

... def __len__(self):
... return 10
... def __getitem__(self, i):
... if i == 0: return "Hello!"
... raise IndexError, i
...

To be equivalent to len(*blah), this should be apply(len, blah), no *.
6 #Py2.2
Traceback (most recent call last):


Is that difference a bug?

In your input, yes ;-)

Terry J. Reedy
 
S

Skip Montanaro

Mike> Perl 6.0 is going to include even more drastic changes. It will
Mike> also include a Perl 5.x interpreter, and will have to be switched
Mike> to 6.0 mode by a magic cookie of some kind in the source. Possibly
Mike> Python 3.0 could do something similar.

-1

Things are complex enough as it is. Maintaining two interpreters that have
to somehow comingle would be worse. Maintain Python 2.x as a separate
release for a period of time after Python 3.0 is released (a couple years,
anyway, maybe longer), but don't mix the two.

Skip
 
A

Andrew Dalke

Benji said:
They do two different things. I think you have a spurious * in the call
to apply. The apply above is equivalent to

D'oh! This cold has definitely made me error prone the last
couple of days. Yesterday I managed to leave my cell phone
in my pants pocket along with a couple pens. My new phone has
a color screen and a camera.

Andrew
(e-mail address removed)
 
A

Andrew Dalke

Terry said:
Ok, add 'assuming that func and args are a valid callable and sequence
respectively.' Error messages are not part of the specs, and may change
for the same code from version to version.

While true, the difference in error messages suggests that the
two approaches use slightly different and possibly exploitable
mechanisms.
To be equivalent to len(*blah), this should be apply(len, blah), no *.

Oops. Here's one that really works. I have an idea of why
there's a difference but would rather someone explain it to me.

import traceback

def YieldTest():
yield "Test"

class Blah:
__len__ = None
__iter__ = YieldTest().__iter__

func = len
args = Blah()

try:
print "apply", apply(func, args)
except TypeError, err:
print "does not work:", err
try:
print "call", func(*args)
except TypeError, err:
print "does not work:", err

The output from running it under Python 2.3 is

apply 4
call does not work: len() takes exactly one argument (0 given)

If I make Blah be a new-style class (ie "class Blah(object):")
I get the opposite success behavior:

apply does not work: apply() arg 2 expected sequence, found Blah
call 4



Andrew
(e-mail address removed)
 
N

Nick Coghlan

Python 2.4 interactive session:
Py> class Blah:
.... def __iter__(self):
.... yield "Test"
....
Py> args = Blah()
Py> apply(len, args)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: apply() arg 2 expected sequence, found instance
Py> len(*args)
4
Py> class Blah(object):
.... def __iter__(self):
.... yield "Test"
....
Py> args = Blah()
Py> apply(len, args)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: apply() arg 2 expected sequence, found Blah
Py> len(*args)
4


And you're right, there is a behavioural difference - apply() expects a real
sequence, whereas the extended function call syntax accepts any iterable.

However, there's also a bug in your demo code:

Py> def YieldTest():
.... yield "Test"
....
Py> x = YieldTest().__iter__
Py> list(x())
['Test']
Py> list(x())
[]

Your failing case with len(*args) was due to the iterator having already been
consumed :)

Cheers,
Nick.
 
A

Andrew Dalke

Nick said:
And you're right, there is a behavioural difference - apply() expects a real
sequence, whereas the extended function call syntax accepts any iterable.

However, there's also a bug in your demo code:

I guess I must be getting over this cold -- I'm only 1/2 wrong
this time. :)

Andrew
(e-mail address removed)
 
A

Aahz

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

Hmmm... I find code much more readable and writable now that apply() is
going away. And unless you mean "generator" to include iterators in
general, I believe that iterators are another critical addition.

I'm surprised that you don't include garbage collection and augmented
assignment, though. String methods have been a net gain, I think.

Reviewing the various What's New documents, it appears that we really
have been holding the line since 2.2 on language changes.
 
F

Fredrik Lundh

Aahz said:
Hmmm... I find code much more readable and writable now that apply() is
going away. And unless you mean "generator" to include iterators in
general, I believe that iterators are another critical addition.

I'm surprised that you don't include garbage collection and augmented
assignment, though. String methods have been a net gain, I think.

garbage collection is a CPython implementation detail, not a language
property (it's a nice implementation detail, sure).

and we had iterators before we got the iterator protocol; the protocol made
things slightly more convenient, but it didn't enable you to do anything you
couldn't do before (using __getitem__ instead of __next__). generators are
something entirely different. writing inverted code is hard; yielding is trivial.

func(*arg) instead of apply() is a step back -- it hides the fact that functions
are objects, and it confuses the heck out of both C/C++ programmers and
Python programmers that understand the "def func(*arg)" form, because it
looks like something it isn't (there's a false symmetry between the call-form
and the def-form).

and I still do enough 1.5.2-programming to use "x = x + y"; when I find
myself in a situation where my code would benefit a lot from being able to
write "x += y" instead, I go back and fix the design.

string methods are nice, but nothing groundbreaking, and their niceness is
almost entirely offset by the horrid "".join(seq) construct that keeps popping
up when people take the "the string module is deprecated" yada yada too
seriously. and what do the python-devers do? they add a "sum" built-in,
but no "join"? hello?

</F>
 
J

Just

"Fredrik Lundh said:
func(*arg) instead of apply() is a step back

Strongly disagree. I find func(*args) much more readable than
apply(func, args).
-- it hides the fact that functions are objects,

What does this have to do with anything?
and it confuses the heck out of both C/C++ programmers and
Python programmers that understand the "def func(*arg)" form, because it
looks like something it isn't (there's a false symmetry between the call-form
and the def-form).

What's false about the symmetry?

Call: you supply a sequence of args
Def: you receive a sequence of args

Lovely.
and I still do enough 1.5.2-programming to use "x = x + y"; when I find
myself in a situation where my code would benefit a lot from being able to
write "x += y" instead, I go back and fix the design.

string methods are nice, but nothing groundbreaking, and their niceness is
almost entirely offset by the horrid "".join(seq) construct that keeps
popping
up when people take the "the string module is deprecated" yada yada too
seriously. and what do the python-devers do? they add a "sum" built-in,
but no "join"? hello?

That's what you get for unsubscribing ;-)

Just
 
A

Aahz

func(*arg) instead of apply() is a step back -- it hides the fact
that functions are objects, and it confuses the heck out of both
C/C++ programmers and Python programmers that understand the "def
func(*arg)" form, because it looks like something it isn't (there's a
false symmetry between the call-form and the def-form).

For me, it works the other way around, but I can see how you perceive it
that way.
and I still do enough 1.5.2-programming to use "x = x + y"; when I find
myself in a situation where my code would benefit a lot from being able
to write "x += y" instead, I go back and fix the design.

Okay, it wasn't clear in your original post that you're still stuck with
1.5.2. That makes a huge difference in the convenience of newer
features.
string methods are nice, but nothing groundbreaking, and their niceness
is almost entirely offset by the horrid "".join(seq) construct that
keeps popping up when people take the "the string module is deprecated"
yada yada too seriously. and what do the python-devers do? they add a
"sum" built-in, but no "join"? hello?

While I'm in complete agreement about the "".join() construct on the
basis of looks, I have come to appreciate the fact that I *never* mess up
the order of arguments any more.
 
D

Dima Dorfman

string methods are nice, but nothing groundbreaking, and their niceness is
almost entirely offset by the horrid "".join(seq) construct that keeps popping
up when people take the "the string module is deprecated" yada yada too
seriously. and what do the python-devers do? they add a "sum" built-in,
but no "join"? hello?

I happen to not mind the ''.join syntax, but if I did, I would use

str.join('', seq)

which is just like a join builtin except that it's not as easy to make
it work on pre-string-method Pythons.
 
M

Mike Meyer

While I'm in complete agreement about the "".join() construct on the
basis of looks, I have come to appreciate the fact that I *never* mess up
the order of arguments any more.

Yeah. When I needed joinable arrays of strings in Eiffel, I added them
to the ARRAY[STRING] class. array.join("") is *much* saner looking.

<mike
 
F

Fredrik Lundh

Dima said:
I happen to not mind the ''.join syntax, but if I did, I would use

str.join('', seq)

which is just like a join builtin except that it's not as easy to make
it work on pre-string-method Pythons.

just like join, except that it isn't:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: descriptor 'join' requires a 'str' object but received a 'unicode'

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

Forum statistics

Threads
473,754
Messages
2,569,526
Members
44,997
Latest member
mileyka

Latest Threads

Top