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


Boris Borcic wrote:
Bill Atkins wrote:

It's interesting how much people who don't have macros like to put
them down and treat them as some arcane art that are too "*insane*"l y
powerful to be used well.

They're actually very straightforward and can often (shock of shocks!)
make your code more readable, without your efficiency taking a hit.

Not even efficiency of debugging ? A real problem with macros is that
run-time tracebacks etc, list macro outputs and not your macro'ed source
code. And that becomes an acute problem if you leave code for somebody
else to update. Or did lisp IDEs make progress on that front ?


AllegroCL now shows macros in the stack frame. Relatively recent
feature, and their IDE really stands out above the rest.

kenny

--
Cells: http://common-lisp.net/project/cells/

"Have you ever been in a relationship?"
Attorney for Mary Winkler, confessed killer of her
minister husband, when asked if the couple had
marital problems.
May 10 '06 #201
[Sorry, I missed this one originally.]
David C. Ullrich wrote:
On Tue, 09 May 2006 05:35:47 -0500, David C. Ullrich
<ul*****@math.o kstate.edu> wrote:

On Mon, 08 May 2006 18:46:57 -0400, Ken Tilton <ke*******@gmai l.com>
wrote:
[...]

If you, um, look at the code you see that "cells.a = 42" triggers
cells.__setat tr__, 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.

Set Kelvin, and make Celsius and Fahrneheit functions of that. ie, There
is only one datapoint, the temperature. No conflict unless one creates one.


Realized later that I hadn't thought this through.

I'd been assuming that of course we should be allowed to
have A and B depend on each other. Hence if a change in
A propagates to a change in B that change in B has to
be a non-propagating change - thought I was just so
clever seeing a way to do that.
I think it could be arranged, if one were willing to tolerate a little
fuzziness: no, there would be no strictly correct snapshot at which
point everyone had their "right value". Instead, A changes so B
recomputes, B changes so A recomputes... our model has now come to life,
we just have to poll for OS events or socket data, and A and B never get
to a point where they are self-consistent, because one or the other
always needs to be recalculated.

I sometimes wonder if the physical universe is like that, explaining why
gravity slows time: it is not the gravity, it is the mass and we are
seeing system degradation as the matrix gets bogged down recomputing all
that matter.

[Cue Xah]


But duh, if that's how things are then we can't have
transitive dependencies working out right; surely we
want to be able to have B depend on A and then C
depend on B...

(And also if A and B are allowed to depend on each
other then the programmer has to ensure that the
two rules are inverses of each other, which seems
like a bad constraint in general, something non-trivial
that the programmer has to get right.)
Right, when I considered multi-way dependencies I realized I would have
to figure out some new syntax to declare in one place the rules for two
slots, and that would be weird because in Cells it is the instance that
gets a rule at make-instance time, so i would really have to have some
new make-instance-pair capability. Talk about a slippery slope. IMO, the
big constraints research program kicked off by Steele's thesis withered
into a niche technology because they sniffed at the "trivial"
spreadsheet model of linear dataflow and tried to do partial and
multi-way dependencies. I call it "a bridge too far", and in my
experience of Cells (ten years of pretty intense use), guess what?, all
we need as developers is one-way, linear, fully-specified dependencies.

So fine, no loops. If anything, if we know that
there are no loops in the dependencies that simplifies
the rest of the programming, no need for the sort of
finagling described in the first paragraph above.
Actually, I do allow an on-change callback ("observer" in Cells
parlance) to kick off a toplevel, imperative state change to the model.
Two cells who do that to each other will run until one decides not to do
so. I solve some GUI situations (the classic being a scrollbar thumb and
the text offset, which each at different times control the other, by
having them simply set the other in an observer. On the second
iteration, B is setting A to the value A has already, so propagation
stops (a longstanding Cells feature).

These feel like GOTOs, by the way, and are definitely to be avoided
because they break the declarative paradigm of Cells in which I can
always look at one (anonymous!) rule and see without question from where
any value it might hold comes. (And observers define where they take
effect outside the model, but those I have to track down by slot name
using OO browsing tools.)

But this raises a question:

Q: How do we ensure there are no loops in the dependencies?
Elsewhere I suggested the code was:

(let ((*dependent* this-cell))
(funcall (rule this-cell) (object this-cell)))

It is actually:

(let ((*dependents* (list* this-cell *dependents*)))
(funcall (rule this-cell) (object this-cell)))

So /before/ that I can say:

(assert (not (find this-cell *dependents*)))

Do we actually run the whole graph through some algorithm
to verify there are no loops?

The simplest solution seems like adding the cells one
at a time, and only allowing a cell to depend on
previously added cells. It's clear that that would
prevent loops, but it's not clear to me whether or
not that disallows some non-looping graphs.
As you can see, the looping is detected only when there is an actual
circularity, defined as a computation requiring its own computation as
an input.

btw, a rule /does/ have access to the prior value it computed, if any,
so the cell can be value-reflective even though the rules cannot be
reentrant.
A
math question the answer to which is not immediately
clear to me (possibly trivial, the question just
ocurred to me this second):

Say G is a (finite) directed graph with no loops. Is it always
possible to order the vertices in such a way that
every edge goes from a vertex to a _previous_ vertex?


I am just a simple application programmer, so I just wait till Cells
breaks and then I fix that. :)

kenny

--
Cells: http://common-lisp.net/project/cells/

"Have you ever been in a relationship?"
Attorney for Mary Winkler, confessed killer of her
minister husband, when asked if the couple had
marital problems.
May 10 '06 #202
"Michele Simionato" <mi************ ***@gmail.com> writes:
Ken Tilton wrote:
I was not thinking about the thread issue (of which I know little). The
big deal for Cells is the dynamic bit:

(let ((*dependent* me))
(funcall (rule me) me))

Then if a rule forces another cell to recalculate itself, *dependent*
gets rebound and (the fun part) reverts back to the original dependent
as soon as the scope of the let is exited.


Python 2.5 has a "with" statement (yes, the name is Lispish on purpose)
that could be used to implement this. See
http://www.python.org/dev/peps/pep-0343


You are mistaken. In particular, VAR doesn't have dynamic scope.
/Jon

--
'j' - a n t h o n y at romeo/charley/november com
May 10 '06 #203
Randal L. Schwartz wrote:
>> "Alex" == Alex Martelli <al***@mac.co m> writes:


Alex> The difference, if any, is that gurus of Java, C++ and Python get to
Alex> practice and/or keep developing their respectively favorite languages
Alex> (since those three are the "blessed" general purpose languages for
Alex> Google - I say "general purpose" to avoid listing javascript for
Alex> within-browser interactivity, SQL for databases, XML for data
Alex> interchange, HTML for web output, &c, &c), while the gurus of Lisp,
Alex> Limbo, Dylan and Smalltalk don't (Rob Pike, for example, is one of the
Alex> architects of sawzall -- I already pointed to the whitepaper on that
Alex> special-purpose language, and he co-authored that paper, too).

That's crazy. Some of the key developers of Smalltalk continue to work
on the Squeak project (Alan Kay, Dan Ingalls, and I'm leaving someone
out, I know it...). So please remove Smalltalk from that list.


I thought it was clear that Alex was talking about "smalltalk gurus who
work for Google."

-Jonathan

May 10 '06 #204


Chris F Clark wrote:
David C Ullrich asked:
Q: How do we ensure there are no loops in the dependencies?

Do we actually run the whole graph through some algorithm
to verify there are no loops?

The question you are asking is the dependency graph a "directed
acyclic graph" (commonly called a DAG)? One algorithm to determine if
it is, is called "topologica l sort". That algorithm tells you where
there are cyclces in your graph,


Yep. But with Cells the dependency graph is just a shifting record of
who asked who, shifting because all of a sudden some outlier data will
enter the system and a rule will branch to code for the first time, and
suddenly "depend on" on some new other cell (new as in never before used
by this cell). This is not subject to static analysis because, in fact,
lexically everyone can get to everything else, what with closures,
first-class functions, runtime branching we cannot predict... fuggedaboutit.

So we cannot say, OK, here is "the graph" of our application model. All
we can do is let her rip and cross our fingers. :)

kenny
May 10 '06 #205
jayessay wrote:
"Michele Simionato" <mi************ ***@gmail.com> writes:
Ken Tilton wrote:
I was not thinking about the thread issue (of which I know little). The
big deal for Cells is the dynamic bit:

(let ((*dependent* me))
(funcall (rule me) me))

Then if a rule forces another cell to recalculate itself, *dependent*
gets rebound and (the fun part) reverts back to the original dependent
as soon as the scope of the let is exited.


Python 2.5 has a "with" statement (yes, the name is Lispish on purpose)
that could be used to implement this. See
http://www.python.org/dev/peps/pep-0343


You are mistaken. In particular, VAR doesn't have dynamic scope.


I said "it could be used to implement this", and since in a previous
post on mine in this
same thread I have shown how to implement thread local variables in
Python I figured
out people would be able to do the exercise for themselves.

Michele Simionato

May 10 '06 #206


Ketil Malde wrote:

Sometimes the best documentation is the code itself. Sometimes the
best name for a function is the code itself.


Absolutely. When I take over someone else's code I begin by deleting all
the comments. Then I read the code. If a variable or function name makes
no sense (once I have figured out what they /really/ do) I do a global
change. Pretty soon the system is "documented ". And I usually find a
couple of bugs as the renaming produces things like:

count = count + weight

I think one good argument for anonymous functions is a hefty Cells
application, with literally hundreds of rules. The context is set by the
instance and slot name, and as you say, the rule speaks for itself:

(make-instance 'frame-widget
:bounds (c? (apply 'rect-union (all-bounds (subwidgets self)))))

Why do I have to give that a name? And if the algorithm gets hairier,
well, why is the reader looking at my code? If the reader is debugging
or intending to modify the rule, they damn well better be looking at the
code, not the name and not the comments. (Never a problem with my code. <g>)

kenny

--
Cells: http://common-lisp.net/project/cells/

"Have you ever been in a relationship?"
Attorney for Mary Winkler, confessed killer of her
minister husband, when asked if the couple had
marital problems.
May 10 '06 #207
Ken Tilton wrote:


Boris Borcic wrote:
Ken Tilton wrote:
"Now if you are like most people, you think that means X. It does not."

As far as natural language and understanding are concerned, "to mean"
means conformity to what most people understand, Humpty Dumpties
notwithstanding .


Nonsense.


:)
You are confusing that quality of natural language with most
people's quality of being sloppy readers, or in your case, a sloppy
thinker. Misapplying an analogy is not a question of usage -- when I
said spreadsheet and they thought of spreadsheets, so far so good,
right?
No, as Adam Jones pointed out. Like Bush speaking of "crUSAde" after 9/11.
-- it just sloppiness and laziness.

I do it, too, all the time. :)


Right.
May 10 '06 #208

Alex Martelli wrote:
Joe Marshall <ev********@gma il.com> wrote:
...
The problem is that a `name' is a mapping from a symbolic identifier to
an object and that this mapping must either be global (with the
attendant name collision issues) or within a context (with the
attendant question of `in which context').
Why is that a problem? Even for so-called "global" names, Python
supports a structured, hierarchical namespace, so there can never be any
collision betwen the "globals" of distinct modules (including modules
which happen to have the same name but live in distinct packages or
subpackages) -- I did mention that names could usefully be displayed in
some strcutured form such as apackage.somemo dule.thefunctio n but perhaps
I was too tangential about it;-).


Can you refer to inner functions from the global context? Suppose I
have this Python code:

def make_adder(x):
def adder_func(y):
sum = x + y
return sum
return adder_func

Can I refer to the inner adder_func in any meaningful way?


Matthias Felleisen once suggested that *every* internal function should
be named. I just said `continuations' . He immediately amended his
statement with `except those'.


If I used continuations (I assume you mean in the call/cc sense rather
than some in which I'm not familiar?) I might feel the same way, or not,
but I don't (alas), so I can't really argue the point either way for
lack of real-world experience.


I meant continuations as in the receiver function in
continuation-passing-style. If you have a function that has to act
differently in response to certain conditions, and you want to
parameterize the behavior, then one possibility is to pass one or more
thunks to the function in addition to the normal arguments. The
function acts by selecting and invoking one of the thunks. A classic
example is table lookup. It is often the case you wish to proceed
differently depending upon whether a key exists in a table or not.
There are several ways to provide this functionality. One is to have a
separate `key-exists?' predicate. Another is to have a special return
value for `key not found'. Another is to throw an exception when a key
is not found. There are obvious advantages and drawbacks to all of
these methods. By using continuation-passing-style, we can
parameterize how the table lookup proceeds once it determines whether
or not the key is found. We have the lookup procedure take two thunks
in addition to the key. If the key is found, the first thunk is
invoked on the associated value. If the key is not found, the second
thunk is invoked. We can subsume all the previous behaviors:

(define (key-exists? key table)
(lookup key table
(lambda (value) #t) ;; if found, ignore value, return true
(lambda () #f))) ;; if not found, return false.

(define (option1 key table)
(lookup key table
(lambda (value) value)
(lambda () 'key-not-found)))

(define (option2 key table)
(lookup key table
(lambda (value) value)
(lambda () (raise 'key-not-found-exception))))

(define (option3 key table default-value)
(lookup key table
(lambda (value) value)
(lambda () default-value)))

The unnamed functions act in this regard much like a `local label'. We
wrap two chunks of code in a lambda and the lookup function `jumps' to
the appropriate chunk. (If the compiler knows about thunks, the
generated assembly code really will have local labels and jump
instructions. It can be quite efficient.)

This may look odd and cumbersome, but with a little practice the
lambdas fade into the background and it becomes easy to read.

My point with Matthias, however, was that defining all these
continuations (the thunks) as named internal functions was not only
cumbersome, but it obscured the control flow. Notice:

(define (named-option3 key table default-value)
(define (if-found value)
value)
(define (if-not-found)
default-value)
(lookup key table if-found if-not-found))

When we enter the function, we skip down to the bottom (past the
internal definitions) to run lookup, which transfers control to a
function defined earlier in the code.

There are many reasons to avoid this style in Python, so this probably
won't win you over, but my point is that there are times where
anonymous functions have an advantage over the named alternative and
that disallowing anonymous functions can be as cumbersome as
disallowing anonymous integers.

May 10 '06 #209
"Michele Simionato" <mi************ ***@gmail.com> writes:
jayessay wrote:
"Michele Simionato" <mi************ ***@gmail.com> writes:
Ken Tilton wrote:
> I was not thinking about the thread issue (of which I know little). The
> big deal for Cells is the dynamic bit:
>
> (let ((*dependent* me))
> (funcall (rule me) me))
>
> Then if a rule forces another cell to recalculate itself, *dependent*
> gets rebound and (the fun part) reverts back to the original dependent
> as soon as the scope of the let is exited.

Python 2.5 has a "with" statement (yes, the name is Lispish on purpose)
that could be used to implement this. See
http://www.python.org/dev/peps/pep-0343


You are mistaken. In particular, VAR doesn't have dynamic scope.


I said "it could be used to implement this", and since in a previous
post on mine in this
same thread I have shown how to implement thread local variables in
Python I figured
out people would be able to do the exercise for themselves.


I was saying that you are mistaken in that pep-0343 could be used to
implement dynamically scoped variables. That stands.
/Jon

--
'j' - a n t h o n y at romeo/charley/november com
May 10 '06 #210

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
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...
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
9865
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
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
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?
2
3565
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2815
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.