473,757 Members | 10,263 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

A critic of Guido's blog on Python's lambda

Python, Lambda, and Guido van Rossum

Xah Lee, 2006-05-05

In this post, i'd like to deconstruct one of Guido's recent blog about
lambda in Python.

In Guido's blog written in 2006-02-10 at
http://www.artima.com/weblogs/viewpo...?thread=147358

is first of all, the title “Language Design Is Not Just Solving
Puzzles”. In the outset, and in between the lines, we are told that
“I'm the supreme intellect, and I created Python”.

This seems impressive, except that the tech geekers due to their
ignorance of sociology as well as lack of analytic abilities of the
mathematician, do not know that creating a language is a act that
requires little qualifications. However, creating a language that is
used by a lot people takes considerable skill, and a big part of that
skill is salesmanship. Guido seems to have done it well and seems to
continue selling it well, where, he can put up a title of belittlement
and get away with it too.

Gaudy title aside, let's look at the content of his say. If you peruse
the 700 words, you'll find that it amounts to that Guido does not like
the suggested lambda fix due to its multi-line nature, and says that he
don't think there could possibly be any proposal he'll like. The
reason? Not much! Zen is bantered about, mathematician's impractical
ways is waved, undefinable qualities are given, human's right brain is
mentioned for support (neuroscience!) , Rube Goldberg contrivance
phraseology is thrown, and coolness of Google Inc is reminded for the
tech geekers (in juxtaposition of a big notice that Guido works
there.).

If you are serious, doesn't this writing sounds bigger than its
content? Look at the gorgeous ending: “This is also the reason why
Python will never have continuations, and even why I'm uninterested in
optimizing tail recursion. But that's for another installment.” . This
benevolent geeker is gonna give us another INSTALLMENT!

There is a computer language leader by the name of Larry Wall, who said
that “The three chief virtues of a programmer are: Laziness,
Impatience and Hubris” among quite a lot of other ingenious
outpourings. It seems to me, the more i learn about Python and its
leader, the more similarities i see.

So Guido, i understand that selling oneself is a inherent and necessary
part of being a human animal. But i think the lesser beings should be
educated enough to know that fact. So that when minions follow a
leader, they have a clear understanding of why and what.

----

Regarding the lambda in Python situation... conceivably you are right
that Python lambda is perhaps at best left as it is crippled, or even
eliminated. However, this is what i want: I want Python literatures,
and also in Wikipedia, to cease and desist stating that Python supports
functional programing. (this is not necessarily a bad publicity) And, I
want the Perl literatures to cease and desist saying they support OOP.
But that's for another installment.

----
This post is archived at:
http://xahlee.org/UnixResource_dir/w...bda_guido.html

* * Xah
* * xa*@xahlee.org
http://xahlee.org/

May 6 '06
267 10820
<br***@sweetapp .com> wrote:
...
Being able to keep pass around state with functions is useful.
I agree and Python supports this. What is interesting is how
counter-intuitive many programmers find this. For example, one of my


Funny: I have taught/mentored large number of people in Python, people
coming from all different levels along the axis of "previous knowledge
of programming in general", and closures are not among the issues where
I ever noticed large number of people having problems.
So I try to use this sort of pattern sparingly because many programmers
don't think of closures as a way of saving state. That might be because
it is not possible to do so in most mainstream languages.
I don't normally frame it in terms of "saving" state, but rather of
"keeping some amount of state around" -- which means more or less the
same thing but may perhaps be easier to digest (just trying to see what
could explain the difference between my experience and yours).
There are already some people in the Python community who think that
Python has already gone too far in supporting "complex" language
features and now imposes two steep a learning curve i.e. you now have
to know a lot to be considered a Python expert. And there is a lot of
resistance to adding features that will raise the bar even higher.


I might conditionally underwrite this, myself, but I guess my emphasis
is different from that of the real "paladins" of this thesis (such as
Mark Shuttleworth, who gave us all an earful about this when he
delivered a Keynote at Europython 2004).

I'm all for removing _redundant_ features, but I don't think of many
things on the paladins' hitlist as such -- closures, itertools, genexps,
etc, all look just fine to me (and I have a good track record of
teaching them...). I _would_ love to push (for 3.0) further
simplifications , e.g., I do hate it that
[ x for x in container if predicate(x) ]
is an exact synonym of the more legible
list( x for x in container if predicate(x) )
and the proposed
{1, 2, 3}
is an exact synonym of
set((1, 2, 3))
just to focus on a couple of redundant syntax-sugar ideas (one in
today's Python but slated to remain in 3.0, one proposed for 3.0). It's
not really about there being anything deep or complex about this, but
each and every such redundancy _does_ "raise the bar" without any
commensurate return. Ah well.
Alex
May 7 '06 #101
<br***@sweetapp .com> wrote:
...
2. There has to be a mechanism where an organization can add
developers - even if it is only for new projects. Python advocates
Obviously.


It's good that you agree. I think that the ability to add new
productive developers to a project/team/organization is at least part
of what Alex means by "scaleabili ty". I'm sure that he will correct me
if I am wrong.


I agree with your formulation, just not with your spelling of
"scalabilit y";-).
[1] I'm considering introducing bugs or misdesigns that have to be
fixed
as part of training for the purposes of this discussion. Also the
Actually, doing it _deliberately_ (on "training projects" for new people
just coming onboard) might be a good training technique; what you learn
by finding and fixing bugs nicely complements what you learn by studying
"good" example code. I do not know of this technique being widely used
in real-life training, either by firms or universities, but I'd love to
learn about counterexamples .
time needed to learn to coordinate with the rest of the team.


Pair programming can help a lot with this (in any language, I believe)
if the pairing is carefully chosen and rotated for the purpose.
Alex
May 7 '06 #102
Carl Friedrich Bolz <cf****@gmx.d e> wrote:
...
an extension that allows the programmer to specify how the value of
some slot (Lisp lingo for "member variable") can be computed. It
frees the programmer from having to recompute slot values since Cells
... I have not looked at Cells at all, but what you are saying here sounds
amazingly like Python's properties to me. You specify a function that
calculates the value of an attribute (Python lingo for something like a


You're right that the above-quoted snipped does sound exactly like
Python's properties, but I suspect that's partly because it's a very
concise summary. A property, as such, recomputes the value each and
every time, whether the computation is necessary or not; in other words,
it performs no automatic caching/memoizing.

A more interesting project might therefore be a custom descriptor, one
that's property-like but also deals with "caching wherever that's
possible". This adds interesting layers of complexity, some of them not
too hard (auto-detecting dependencies by introspection), others really
challenging (reliably determining what attributes have changed since
last recomputation of a property). Intuition tells me that the latter
problem is equivalent to the Halting Problem -- if somewhere I "see" a
call to self.foo.zap(), even if I can reliably determine the leafmost
type of self.foo, I'm still left with the issue of analyzing the code
for method zap to find out if it changes self.foo on this occasion, or
not -- there being no constraint on that code, this may be too hard.

The practical problem of detecting alterations may be softened by
realizing that some false positives are probably OK -- if I know that
self.foo.zap() *MAY* alter self.foo, I might make my life simpler by
assuming that it *HAS* altered it. This will cause some recomputations
of property-like descriptors' values that might theoretically have been
avoided, "ah well", not a killer issue. Perhaps a more constructive
approach would be: start by assuming the pseudoproperty always
recomputes, like a real property would; then move toward avoiding SOME
needless recomputations when you can PROVE they're needless. You'll
never avoid ALL needless recomputations, but if you avoid enough of them
to pay for the needed introspection and analysis, it may still be a win.
As to whether it's enough of a real-world win to warrant the project, I
pass -- in a research setting it would surely be a worthwhile study, in
a production setting there are other optimizations that look like
lower-hanging fruits to me. But, I'm sure the Cells people will be back
with further illustrations of the power of their approach, beyond mere
"properties with _some_ automatic-caching abilities".
Alex
May 7 '06 #103
Tomasz Zielonka <to************ *@gmail.com> wrote:
Alex Martelli wrote:
Tomasz Zielonka <to************ *@gmail.com> wrote:
Alex Martelli wrote:
> Having to give functions a name places no "ceiling on expressiveness" ,
> any more than, say, having to give _macros_ a name.

And what about having to give numbers a name?
Excellent style, in most cases; I believe most sensible coding guides
recommend it for most numbers -- cfr
<http://en.wikipedia.or g/wiki/Magic_number_(p rogramming)> , section
"magic numbers in code".


I was a bit unclear. I didn't mean constants (I agree with you on
magic numbers), but results of computations, for example


Ah, good that we agree on _some_thing;-)

(x * 2) + (y * 3)

Here (x * 2), (y * 3) and (x * 2) + 3 are anonymous numbers ;-)

Would you like if you were forced to write it this way:

a = x * 2
b = y * 3
c = a * b

?

Thanks for your answers to my questions.


I do not think there would be added value in having to name every
intermediate result (as opposed to the starting "constants" , about which
we agree); it just "spreads things out". Fortunately, Python imposes no
such constraints on any type -- once you've written out the starting
"constants" (be they functions, numbers, classes, whatever), which may
require naming (either language-enforced, or just by good style),
instances of each type can be treated in perfectly analogous ways (e.g.,
calling callables that operate on them and return other instances) with
no need to name the intermediate results.

The Function type, by design choice, does not support any overloaded
operators, so the analogy of your example above (if x and y were
functions) would be using named higher-order-functions (or other
callables, of course), e.g.:

add_funcs( times_num(x, 2), times_num(y, 3) )

whatever HOF's add and times were doing, e.g.

def add_funcs(*fs):
def result(*a):
return sum(f(*a) for f in fs)
return result

def times_num(f, k):
def result(*a):
return k * f(*a)
return result

or, add polymorphism to taste, if you want to be able to use (e.g.) the
same named HOF to add a mix of functions and constants -- a side issue
that's quite separate from having or not having a name, but rather
connected with how wise it is to overload a single name for many
purposes (PEAK implements generic-functions and multimethods, and it or
something like it is scheduled for addition to Python 3.0; Python 2.*
has no built-in way to add such arbitrary overloads, and multi-dispatch
in particular, so you need to add a framework such as PEAK for that).
Alex
May 7 '06 #104
I V <wr******@gmail .com> wrote:
...
higher level languages. There are useful programming techniques, like
monadic programming, that are infeasible without anonymous functions.
Anonymous functions really add some power to the language.
Can you give me one example that would be feasible with anonymous
functions, but is made infeasible by the need to give names to
functions? In Python, specifically, extended with whatever fake syntax
you favour for producing unnamed functions?


Monads are one of those parts of functional programming I've never really
got my head around, but as I understand them, they're a way of
transforming what looks like a sequence of imperative programming
statements that operate on a global state into a sequence of function
calls that pass the state between them.


Looks like a fair enough summary to me (but, I'm also shaky on monads,
so we might want confirmation from somebody who isn't;-).
So, what would be a statement in an imperative language is an anonymous
function that gets added to the monad, and then, when the monad is run,
these functions get executed. The point being, that you have a lot of
small functions (one for each statement) which are likely not to be used
anywhere else, so defining them as named functions would be a bit of a
pain in the arse.


It seems to me that the difference between, say, a hypothetical:

monad.add( lambda state:
temp = zipper(state.wi dget, state.zrup)
return state.alteredco py(widget=temp)
)

and the you-can-use-it-right now alternative:

def zipperize_widge t(state):
temp = zipper(state.wi dget, state.zrup)
return state.alteredco py(widget=temp)
monad.add(zippe rize_widget)

is trivial to the point of evanescence. Worst case, you name all your
functions Beverly so you don't have to think about the naming; but you
also have a chance to use meaningful names (such as, presumably,
zipperize_widge t is supposed to be here) to help the reader.

IOW, monads appear to me to behave just about like any other kind of
HOFs (for a suitably lax interpretation of that "F") regarding the issue
of named vs unnamed functions -- i.e., just about like the difference
between:

def double(f):
return lambda *a: 2 * f(*a)

and

def double(f):
def doubled(*a): return 2 * f(*a)
return doubled

I have no real problem using the second form (with a name), and just
don't see it as important enough to warrant adding to the language (a
language that's designed to be *small*, and *simple*, so each addition
is to be seen as a *cost*) a whole new syntaxform 'lambda'.

((The "but you really want macros" debate is a separate one, which has
been held many times [mostly on comp.lang.pytho n] and I'd rather not
repeat at this time, focusing instead on named vs unnamed...))
Alex
May 7 '06 #105
Frank Buss <fb@frank-buss.de> wrote:
Alex Martelli wrote:
I cannot conceive of one. Wherever within a statement I could write the
expression
lambda <args>: body
I can *ALWAYS* obtain the identical effect by picking an otherwise
locally unused identifier X, writing the statement
def X(<args>): body
and using, as the expression, identifier X instead of the lambda.


This is true, but with lambda it is easier to read:

http://www.frank-buss.de/lisp/functional.html
http://www.frank-buss.de/lisp/texture.html

Would be interesting to see how this would look like in Python or some of
the other languages to which this troll thread was posted :-)


Sorry, but I just don't see what lambda is buying you here. Taking just
one simple example from the first page you quote, you have:

(defun blank ()
"a blank picture"
(lambda (a b c)
(declare (ignore a b c))
'()))

which in Python would be:

def blank():
" a blank picture "
return lambda a, b, c: []

while a named-function variant might be:

def blank():
def blank_picture(a , b, c): return []
return blank_picture

Where's the beef, really? I find the named-function variant somewhat
more readable than the lambda-based variant, but even if your
preferences are the opposite, this is really such a tiny difference that
I can't see why so many bits should gets wasted debating it (perhaps
it's one of Parkinson's Laws at work...).
Alex
May 7 '06 #106
<br***@sweetapp .com> wrote:
Patrick May wrote:
al*****@yahoo.c om (Alex Martelli) writes:
In my opinion (and that of several others), the best way for Python to
grow in this regard would be to _lose_ lambda altogether, since named
functions are preferable


Why? I find the ability to create unnamed functions on the fly
to be a significant benefit when coding in Common Lisp.


1. They don't add anything new to the language semantically i.e. you
can always used a named function to accomplish the same task
as an unnamed one.
2. Giving a function a name acts as documentation (and a named
function is more likely to be explicitly documented than an unnamed
one). This argument is pragmatic rather than theoretical.
3. It adds another construction to the language.


Creating *FUNCTIONS* on the fly is a very significant benefit, nobody on
the thread is disputing this, and nobody ever wanted to take that
feature away from Python -- it's the obsessive focus on the functions
needing to be *unnamed* ones, that's basically all the debate. I wonder
whether all debaters on the "unnamed is a MUST" side fully realize that
a Python's def statement creates a function on the fly, just as much as
a lambda form does. Or maybe the debate is really about the distinction
between statement and expression: Python does choose to draw that
distinction, and while one could certainly argue that a language might
be better without it, the distinction is deep enough that nothing really
interesting (IMHO) is to be gleaned by the debate, except perhaps as
pointers for designers of future languages (and there are enough
programming languages that I personally see designing yet more of them
as one of the least important tasks facing the programming community;-).
Alex
May 7 '06 #107
al*****@yahoo.c om (Alex Martelli) writes:
I do hate it that
[ x for x in container if predicate(x) ]
is an exact synonym of the more legible
list( x for x in container if predicate(x) )
Heh, I hate it that it's NOT an exact synonym (the listcomp leaves 'x'
polluting the namespace and clobbers any pre-existing 'x', but the
gencomp makes a new temporary scope).
and the proposed
{1, 2, 3}
is an exact synonym of
set((1, 2, 3))


There's one advantage that I can think of for the existing (and
proposed) list/dict/set literals, which is that they are literals and
can be treated as such by the parser. Remember a while back that we
had a discussion of reading expressions like
{'foo': (1,2,3),
'bar': 'file.txt'}
from configuration files without using (unsafe) eval. Aside from that
I like the idea of using constructor functions instead of special syntax.
May 7 '06 #108
Alex Martelli wrote:
Sorry, but I just don't see what lambda is buying you here. Taking just
one simple example from the first page you quote, you have:

(defun blank ()
"a blank picture"
(lambda (a b c)
(declare (ignore a b c))
'()))


You are right, for this example it is not useful. But I assume you need
something like lambda for closures, e.g. from the page
http://www.frank-buss.de/lisp/texture.html :

(defun black-white (&key function limit)
(lambda (x y)
(if (> (funcall function x y) limit)
1.0
0.0)))

This function returns a new function, which is parametrized with the
supplied arguments and can be used later as building blocks for other
functions and itself wraps input functions. I don't know Python good
enough, maybe closures are possible with locale named function definitions,
too.

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
May 7 '06 #109
Bill Atkins wrote:
[snip]
Here's how one of the cells examples might look in corrupted Python
(this is definitely not executable):

class FallingRock:
def __init__(self, pos):
define_slot( 'velocity', lambda: self.accel * self.elapsed )
define_slot( 'pos', lambda: self.accel * (self.elapsed ** 2) / 2,
initial_positio n = cell_initial_va lue( 100 ) )
self.accel = -9.8

rock = FallingRock(100 )
print rock.accel, rock.velocity, rock.pos
# -9.8, 0, 100

rock.elapsed = 1
print rock.accel, rock.velocity, rock.pos
# -9.8, -9.8, -9.8

rock.elapsed = 8
print rock.accel, rock.velocity, rock.pos
# -9.8, -78.4, -627.2

Make sense? The idea is to declare what a slot's value represents
(with code) and then to stop worrying about keeping different things
synchronize d.

Here's another of the examples, also translated into my horrific
rendition of Python (forgive me):

class Menu:
def __init__(self):
define_slot( 'enabled',
lambda: focused_object( self ).__class__ == TextEntry and
focused_object( self ).selection )

Now whenever the enabled slot is accessed, it will be calculated based
on what object has the focus. Again, it frees the programmer from
having to keep these different dependencies updated.

--
This is a song that took me ten years to live and two years to write.
- Bob Dylan

Oh dear, there were a few typos:

class FallingRock:
def __init__(self, pos):
define_slot( 'velocity', lambda: self.accel * self.elapsed )
define_slot( 'pos', lambda: self.accel * (self.elapsed ** 2) / 2,
initial_value = cell_initial_va lue( 100 ) )
self.accel = -9.8

rock = FallingRock(100 )
print rock.accel, rock.velocity, rock.pos
# -9.8, 0, 100

rock.elapsed = 1
print rock.accel, rock.velocity, rock.pos
# -9.8, -9.8, 90.2

rock.elapsed = 8
print rock.accel, rock.velocity, rock.pos
# -9.8, -78.4, -527.2


you mean something like this? (and yes, this is executable python):
class FallingRock(obj ect):
def __init__(self, startpos):
self.startpos = startpos
self.elapsed = 0
self.accel = -9.8

velocity = property(lambda self: self.accel * self.elapsed)
pos = property(lambda self: self.startpos + self.accel *
(self.elapsed ** 2) / 2)

rock = FallingRock(100 )
print rock.accel, rock.velocity, rock.pos
# -9.8, 0, 100

rock.elapsed = 1
print rock.accel, rock.velocity, rock.pos
# -9.8, -9.8, 95.1

rock.elapsed = 8
print rock.accel, rock.velocity, rock.pos
# -9.8, -78.4, -213.6
Cheers,

Carl Friedrich Bolz

May 7 '06 #110

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

181
8880
by: Tom Anderson | last post by:
Comrades, During our current discussion of the fate of functional constructs in python, someone brought up Guido's bull on the matter: http://www.artima.com/weblogs/viewpost.jsp?thread=98196 He says he's going to dispose of map, filter, reduce and lambda. He's going to give us product, any and all, though, which is nice of him.
30
2173
by: Mike Meyer | last post by:
I know, lambda bashing (and defending) in the group is one of the most popular ways to avoid writing code. However, while staring at some Oz code, I noticed a feature that would seem to make both groups happy - if we can figure out how to avoid the ugly syntax. This proposal does away with the well-known/obscure "lambda" keyword. It gives those who want a more functional lambda what they want. It doesn't add any new keywords. It doesn't...
0
9298
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9906
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9737
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8737
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development projectplanning, coding, testing, and deploymentwithout human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6562
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5172
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3829
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3399
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2698
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.