473,769 Members | 8,267 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 10829
Op 2006-05-09, Pisin Bootvong schreef <jo********@gma il.com>:

Joe Marshall wrote:
Alex Martelli wrote:
Most languages allow `unnamed numbers'. The `VAT_MULTIPLIER ' argument
is a
strawman. Would you want to have to use a special syntax to name the
increment
in loop?

defnumber zero 0
defnumber one { successor (zero); }

for (int i = zero; i < limit; i += one) { ...}

If you language allows unnamed integers, unnamed strings, unnamed
characters, unnamed arrays or aggregates, unnamed floats, unnamed
expressions, unnamed statements, unnamed argument lists, etc. why
*require* a name for trivial functions?
Wouldn't all the other constructs benefit by having a required name as
well?

Is this a Slippery Slope fallacious argument?
(http://c2.com/cgi/wiki?SlipperySlope)


No it is not.
"if python required you to name every function then soon it will
require you to name every number, every string, every immediate result,
etc. And we know that is bad. Therefore requiring you to name your
function is bad!!!! So Python is bad!!!!"


I think this is a strawman. IMO requiring to name a function can
make things cumbersome.

I don't suppose anyone thinks the following is good practice.

one = 1.
lst.append(one)
Yet this practice is forced upon you in a number of cases when
you require functions to be named. Look at the following:

def incr_cnt_by_one (obj):
obj.cnt += 1

treat_all(lst, incr_cnt_by_one )

So the question I have is: Why is requiring me to give this function
a name considered a good thing, when it leads to a situation that
is considered bad practice in case of a number.

--
Antoon Pardon
May 10 '06 #161
Pisin Bootvong <jo********@gma il.com> wrote:
+---------------
| No matter how scalable your language is, you cannot make a 100MHz/128MB
| server serve 100,000 client a second over the internet.
+---------------

Sure you can! That's ~1000 CPU cycles/request, which [assuming at least
a 100BASE-TX NIC] is plenty to service 100K *small* requests/s... ;-}

Of course, you might have to write it in assembler on bare metal,
but the good news is that with only a 1000 cycle budget, at least
the code won't be very large! ;-}
-Rob [someone who remembers 0.5 MIPS DEC PDP-10s being used
for >100 simultaneous commercial timesharing users]

-----
Rob Warnock <rp**@rpw3.or g>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

May 10 '06 #162

Rob Warnock wrote:
Pisin Bootvong <jo********@gma il.com> wrote:
+---------------
| No matter how scalable your language is, you cannot make a 100MHz/128MB
| server serve 100,000 client a second over the internet.
+---------------

Sure you can! That's ~1000 CPU cycles/request, which [assuming at least
a 100BASE-TX NIC] is plenty to service 100K *small* requests/s... ;-}

Of course, you might have to write it in assembler on bare metal,
but the good news is that with only a 1000 cycle budget, at least
the code won't be very large! ;-}

Well, I was really asking for a service that really service something
complicate and useful though :-D

And donot forget to account for OS CPU time (well may be you can write
your own OS for it too :-D )


-Rob [someone who remembers 0.5 MIPS DEC PDP-10s being used
for >100 simultaneous commercial timesharing users]

-----
Rob Warnock <rp**@rpw3.or g>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607


May 10 '06 #163
al***@mac.com (Alex Martelli) writes:
if anonymous functions are available, they're used in even more
cases where naming would help


Yes, you're right. But don't stop here. What about expressions? Many
people write very complex expression, that are hard to understand. A
good language should forbid these abuse and don't allow expressions
with more than 2 or maybe 3 operators!

Forbid everything that might be abused and you have a perfect
language?

I like Python and I teach Python, I'm also used to Java and C#. But
one of the best solutions to problems of beginners and not so
brilliant programmers is something like the Dr. Scheme enviroment:
Choose your language level yourself. Everyting (allowed constructs,
error messages,...) will be adjusted to your choosen level. And
experts have all at their fingertips they want and need. Code isn't
blowed up and screwed with workaround for language limitations (that
are aimed at beginners and less capable programmers).

Why only adjust to the less capable people? Give everyone what they
need and want! :)

--
Stefan.
May 10 '06 #164
Pisin Bootvong <jo********@gma il.com> wrote:
+---------------
| Rob Warnock wrote:
| > | No matter how scalable your language is, you cannot make a
| > | 100MHz/128MB server serve 100,000 client a second over the internet.
| > +---------------
| >
| > Sure you can! That's ~1000 CPU cycles/request, which [assuming at least
| > a 100BASE-TX NIC] is plenty to service 100K *small* requests/s... ;-}
|
| Well, I was really asking for a service that really service something
| complicate and useful though :-D
+---------------

If "only" being useful is enough, 100 cycles is enough for a DNS server,
or an NTP server, or even a stub HTTP server that delivers some small
piece of real-time data, like a few realtime environmental sensors
[temperature, voltages, etc.].

+---------------
| > Of course, you might have to write it in assembler on bare metal,
| > but the good news is that with only a 1000 cycle budget, at least
| > the code won't be very large! ;-}
|
| And donot forget to account for OS CPU time (well may be you can write
| your own OS for it too :-D )
+---------------

Uh... What I meant by "bare metal" is *no* "O/S" per se, only a
simple poll loop servicing the attention flags[1] of the various
I/O devices -- a common style in lightweight embedded systems.
-Rob

[1] a.k.a. "interrupt request" bits, except with interrupts not enabled.

-----
Rob Warnock <rp**@rpw3.or g>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

May 10 '06 #165

Antoon Pardon wrote:
Op 2006-05-09, Pisin Bootvong schreef <jo********@gma il.com>:
Is this a Slippery Slope fallacious argument?
(http://c2.com/cgi/wiki?SlipperySlope)
No it is not.

[...]

So the question I have is: Why is requiring me to give this function
a name considered a good thing, when it leads to a situation that
is considered bad practice in case of a number.

--


Slippery Slope::
"Argumentat ion that A is bad, because A might lead to B, and B
to C, and we all know C is very bad."
Why is requiring me to give this function
a name considered a good thing, when it leads to a situation that
is considered bad practice in case of a number.


A === "requiring me to give function a name"
no B
C === "requiring me to give number a name"

"Argumentat ion that requiring one to give function a name is bad,
because that might lead to requiring one to give number a name, and we
all know that that is very bad."
Now you tell me which part of that is not Slippery slope argument.

-- Or are you trying to make a sarcastic joke? I'm sorry if I didn't
get it. --

May 10 '06 #166
Alex Martelli wrote:
I think it's reasonable to make a name a part of functions, classes and
modules because they may often be involved in tracebacks (in case of
uncaught errors): to me, it makes sense to let an error-diagnosing
tracebacks display packages, modules, classes and functions/methods
involved in the chain of calls leading to the point of error _by name_.


It seems to me that there's something of a circularity here. Either in your
logic if applied to language design in general, or as a self-perpetuating habit
when applied to Python in particular.

The assumption is that functions are in some sense rather "big" things -- that
each function performs a well-defined action which can be understood in
isolation. That may well be true in idiomatically written Python (I've never
cared for the look of the language myself, so I don't know what's considered
"normal"), but it isn't true in general. With the assumption, it makes sense
to say that every function /could/ have a name, and so, why not /give/ it a
name ? But without the assumption, when many little anonymous functions are
used, the idea of giving them all names appears pettifogging to the point of
idiocy. If the language and/or culture expects that all/most functions will be
named, then "little" functions (in my sense) won't be used; hence the
self-perpetuating habit. But I don't think that the underlying logic supports
that habit independently of its own self-perpetuating nature.

E.g. consider the Smalltalk code (assumed to be the body of a method):

aCollection
do: [:each |
each > 0 ifTrue: [^ true]].
^ false.

which iterates over a collection checking to see if any element is > 0. If so
then the method answers true ("^" -- spelled "return" in Java), otherwise it
answers false. In that code,
[^ true]
is syntactically and semantically an anonymous function, which is only invoked
if the antecedent is true (in point of fact the compiler inlines that function
away but I don't think that's relevant here). The passage beginning
[:each | ...
and reaching to the matching ] is also an anonymous function with one parameter
(each) which is applied to each element of the collection in turn. (In this
case it really is an anonymous function, even at the implementation level.)
What "name" would you give to either of them ? I don't believe that /any/ name
is possible, and certainly that no name is desirable.

In my working Smalltalk environment today, there are 60099 methods defined
across 3369 classes. In that codebase there are 38112 anonymous functions. Do
you really want to have to find names for them all ?

-- chris
May 10 '06 #167
Op 2006-05-09, Pisin Bootvong schreef <jo********@gma il.com>:

Antoon Pardon wrote:
Op 2006-05-09, Pisin Bootvong schreef <jo********@gma il.com>:
> Is this a Slippery Slope fallacious argument?
> (http://c2.com/cgi/wiki?SlipperySlope)


No it is not.

[...]

So the question I have is: Why is requiring me to give this function
a name considered a good thing, when it leads to a situation that
is considered bad practice in case of a number.

--


Slippery Slope::
"Argumentat ion that A is bad, because A might lead to B, and B
to C, and we all know C is very bad."


But I have seen noone here argue that requiring functions to be named
leads to requiring all variables to be named.
Why is requiring me to give this function
a name considered a good thing, when it leads to a situation that
is considered bad practice in case of a number.


A === "requiring me to give function a name"
no B
C === "requiring me to give number a name"

"Argumentat ion that requiring one to give function a name is bad,
because that might lead to requiring one to give number a name, and we
all know that that is very bad."


That is not the arguement I'm making.

The argument is that a particular pratice is considered bad coding,
(with an example giving a number) and then showing that requiring
a name for a function, almost makes such a practice inevitable (for
certain functions used as parameters)

--
Antoon Pardon
May 10 '06 #168
Pisin Bootvong wrote:
Slippery Slope::
"Argumentat ion that A is bad, because A might lead to B, and B
to C, and we all know C is very bad."


For the Slippery Slope criticism to be applicable, there would have to be some
suggestion that removing anonymous functions /would actually/ (tend to) lead to
removing anonymous values in general. There was no such suggestion.

The form of the argument was more like reasoning by analogy: if context A has
features like context B, and in B some feature is known to be good (bad) then
the analogous feature in A is also good (bad). In that case an attack on the
validity of the argument would centre on the relevance and accuracy of the
analogy.

Alternatively the argument might be seen as a generalisation/specialisation
approach. Functions are special cases of the more general notion of values.
We all agree that anonymous values are a good thing, so anonymous functions
should be too. If you parse the argument like that, then the attack should
centre on showing that functions have relevant special features which are not
shared by values in general, and so that we cannot validly deduce that
anonymous functions are good.

-- chris
May 10 '06 #169
On Mon, 08 May 2006 18:46:57 -0400, Ken Tilton <ke*******@gmai l.com>
wrote:


David C. Ullrich wrote:
On 08 May 2006 12:53:09 -0700, tf*@conquest.OC F.Berkeley.EDU (Thomas
F. Burdick) wrote:

Ken Tilton <ke*******@gmai l.com> writes:
No, you do not want on-change handlers propagating data to other
slots, though that is a sound albeit primitive way of improving
self-consistency of data in big apps. The productivity win with
VisiCalc was that one simply writes rules that use other cells, and
the system keeps track of what to update as any cell changes for
you. You have that exactly backwards: every slot has to know what
other slots to update. Ick.

No no, that's fine and the way it should be: when you change a slot,
it should know who to update. And that's also the way it works in
Cells. The trick is that Cells takes care of that part for you:

I'm glad you said that - this may be what he meant, but it seems
more plausible than what he actually said.


There may be some confusion here because there are two places for code
being discussed at the same time, and two sense of propagation.

the two places for code are (1) the rule attached to A which is
responsible for computing a value for A and (2) a callback for A to be
invoked whenever A changes. Why the difference?

In Cells, A is a slot such as 'background-color'. Whenever that changes,
we have to do something more. On Mac OS9 it was "InvalidateRect " of the
widget. In Cells-Tk, it is:
(Tcl_interp "mywidget configure -background <new color>")

In my OpenGL GUI, it is to rebuild the display-list for the widget.

That is the same no matter what rule some instance has for the slot
background-color, and different instances will have different rules.

As for propagating, yes, Cells propagates automatically. More below on
that. What I saw in the example offered was a hardcoded on-change
callback that was doing /user/ propagation form B to A (and B to A! ...
doesn't that loop, btw?


No, there's no looping in the example. Yes, the code determining what
b returns should be attached to b instead of to a, but the code I
gave does work as advertised. (I mean give me a break - I provided
a sample use so you could simply run it. Installing Python is not
hard.)

If you, um, look at the code you see that "cells.a = 42" triggers
cells.__setattr __, which fires a's callback; the callback then
reaches inside and sets the value of b _without_ going through
__setattr__, hence without triggering b's callback.

In Cells you can't have A depend on B and also B depend on A?
That seems like an unfortunate restriction - I'd want to be
able to have Celsius and Farenheit, so that setting either
one sets the other.

Of course if there are no loops it's easier to see how
you managed to do the stuff you were talking about elsewhere,
(at least sometimes) delaying execution until needed.
Anyway...)

all
the *programmer* has to care about is what values a slot depends on --
Cells takes care of inverting that for you, which is important because
that's a job that a computer is much better at than a human.

Fine. I suppose that is better; if b is going to return a + 1
the fact that this is what b returns should belong to b, not
to a. So a has an update list including b, so when a's value
is set a tells b it needs to update itself.

If we're allowed to pass (at some point, to some constructor
or other) something like (b, a + 1, [a]), which sets up a
cell b that shall return a + 1, and where the [a] is used
in the constructor to tell a to add b to a's update list
then this seems like no big deal.

And doing that doesn't seem so bad - now when the programmer
is writing b he has to decide that it should return a + 1
and also explicitly state that b shall depend on a; this
is all nice and localized, it's still _b_ telling _a_ to
add b to a's update list, and the programmer only has
to figure out what _b_ depends on when he's writing _b_.
Doesn't seem so bad.

But of course it would be better to be able to pass just
something morally equivalent to (b, a + 1) to whatever
constructor and have the system figure out automatically
that since b returns a + 1 it has to add a to b's update
list. There must be some simple trick to accomplish that
(using Python, without parsing code).


Right, you do not want to parse code. It really would not work as
powerfully as Cells, which notice any dynamic access to another cell
while a rule is running. So my rule can call a function on "self" (the
instance that wons the slot being calculated, and since self can have
pointers to other instances, the algorithm can navigate high and low
calling other functions before finally reading another ruled slot. You
want to track those.
Exactly what the trick is I
don't see immediately.


To compute a value for a slot that happens to have a rule associated
with it, have a little cell datastructure that implements all this and
associate the cell with the slot and store a pointer to the rule in the
cell. Then have a global variable called *dependent* and locally:

currentdependen t = *dependent*
oldvalue = cell.value
newvalue = call cell.rule, passing it the self instance
*dependent* = currentvalue

if newvalue not = oldvalue
call on-change on the slot name, self, newvalue and oldvalue
(the on-chnage needs to dispatch on as many arguments as
the language allows. Lisp does it on them all)

In the reader on a slot (in your getattr) you need code that notices if
the value being read is mediated by a ruled cell, and if the global
*dependent* is non empty. If so, both cells get a record of the other
(for varying demands of the implementation) .

In Cells do we just pass a rule using other cells to
determine this cell's value, or do we also include
an explicit list of cells that this cell depends on?


Again, the former. Just write the rule, the above scheme dynamically
figures out the dependencies. Note then that dependencies vary over time
because of different branches a rule might take.

I want to reassure the community that this (nor the spreadsheet analogy
<g>) is not just my crazy idea. In 1992:

http://www.cs.utk.edu/~bvz/active-va...readsheet.html

"It is becoming increasingly evident that imperative languages are
unsuitable for supporting the complicated flow-of-control that arises in
interactive applications. This paper describes a declarative paradigm
for specifying interactive applications that is based on the spreadsheet
model of programing. This model includes multi-way constraints and
action procedures that can be triggered when constraints change the
values of variables."

Cells do not do multi-way constraints, btw.


My _guess_ is that a "multi-way constraint" is something like
what's above, where A depends on B and B depends on A?
Nor partial constraints. To
hard to program, because the system gets non-deterministic. That kinda
killed (well, left to a small niche) the whole research programme. I
have citations on that as well. :)

kenny

*************** *********

David C. Ullrich
May 10 '06 #170

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

Similar topics

181
8911
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
9589
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, well explore What is ONU, What Is Router, ONU & Routers main usage, and What is the difference between ONU and Router. Lets take a closer look ! Part I. Meaning of...
0
10216
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10049
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...
1
9997
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8873
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...
1
7413
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupr who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6675
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
5310
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...
0
5448
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.