Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

287 views
Skip to first unread message

Xah Lee

unread,
May 5, 2006, 8:26:26 PM5/5/06
to
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/viewpost.jsp?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/writ/python_lambda_guido.html

    Xah
    x...@xahlee.org
http://xahlee.org/

Ken Tilton

unread,
May 5, 2006, 9:16:50 PM5/5/06
to

I think this is what you missed in your deconstruction. The upshot of
what he wrote is that it would be really hard to make semantically
meaningful indentation work with lambda. Guido did not mean it, but the
Rube Goldberg slam is actually against indentation as syntax. "Yes,
print statements in a while loop would be helpful, but..." it would be
so hard, let's go shopping. ie, GvR and Python have hit a ceiling.

That's OK, it was never meant to be anything more than a scripting
language anyway.

But the key in the whole thread is simply that indentation will not
scale. Nor will Python.

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

Oh, my, you are preaching to the herd (?!) of lemmings?! Please tell me
you are aware that lemmings do not have ears. You should just do Lisp
all day and add to the open source libraries to speed Lisp's ascendance.
The lemmings will be liberated the day Wired puts John McCarthy on the
cover, and not a day sooner anyway.

kenny (wondering what to call a flock (?!) of lemmings)

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

Alex Martelli

unread,
May 5, 2006, 9:53:53 PM5/5/06
to
Ken Tilton <kent...@gmail.com> wrote:
...

> But the key in the whole thread is simply that indentation will not
> scale. Nor will Python.

Absolutely. That's why firms who are interested in building *seriously*
large scale systems, like my employer (and supplier of your free mail
account), would never, EVER use Python, nor employ in prominent
positions such people as the language's inventor and BDFL, the author of
the most used checking tool for it, and the author of the best-selling
reference book about that language; and, for that matter, a Director of
Search Quality who, while personally a world-renowned expert of AI and
LISP, is on record as supporting Python very strongly, and publically
stating its importance to said employer.

Obviously will not scale. Never.

Well... hardly ever!


Alex

I V

unread,
May 5, 2006, 9:59:39 PM5/5/06
to
On Fri, 05 May 2006 17:26:26 -0700, Xah Lee wrote:
> 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

What does lambda have to do with supporting or not supporting functional
programming?

David Hopwood

unread,
May 5, 2006, 10:28:12 PM5/5/06
to
Ken Tilton wrote:
> [...] The upshot of what [Guido] wrote is that it would be really hard to make

> semantically meaningful indentation work with lambda.

Haskell manages it.

--
David Hopwood <david.nosp...@blueyonder.co.uk>

Ken Tilton

unread,
May 5, 2006, 10:44:59 PM5/5/06
to

You are talking about being incredibly popular. I was talking about
language expressivity. COBOL in its day was incredibly popular and
certainly the language of choice (hell, the only language) for the
biggest corporations you can imagine. But it did not scale as a
language. I hope there are no doubts on that score (and I actually am a
huge fan of COBOL).

The problem for Python is its success. meant to be a KISS scripting
language, it has caught on so well that people are asking it to be a
full-blown, OO, GC, reflexive, yada, yada, yada language. Tough to do
when all you wanted to be when you grew up was a scripting language.

kenny (who is old enough to have seen many a language come and go)

Ken Tilton

unread,
May 5, 2006, 10:50:53 PM5/5/06
to

David Hopwood wrote:
> Ken Tilton wrote:
>
>>[...] The upshot of what [Guido] wrote is that it would be really hard to make
>>semantically meaningful indentation work with lambda.
>
>
> Haskell manages it.
>

To be honest, I was having a hard time imagining precisely how
indentation broke down because of lambda. does text just sail out to the
right too fast?

kenny

Steve R. Hastings

unread,
May 5, 2006, 11:56:03 PM5/5/06
to
On Fri, 05 May 2006 21:16:50 -0400, Ken Tilton wrote:
> The upshot of
> what he wrote is that it would be really hard to make semantically
> meaningful indentation work with lambda.

Pretty much correct. The complete thought was that it would be painful
all out of proportion to the benefit.

See, you don't need multi-line lambda, because you can do this:


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

add5 = make_adder(5)
add7 = make_adder(7)

print add5(1) # prints 6
print add5(10) # prints 15
print add7(1) # prints 8


Note that make_adder() doesn't use lambda, and yet it makes a custom
function with more than one line. Indented, even.

You could also do this:


lst = [] # create empty list
def f(x):
return x + 5
lst.append(f)
del(f) # now that the function ref is in the list, clean up temp name

print lst[0](1) # prints 6


Is this as convenient as the lambda case?

lst.append(lambda x: x + 7)
print lst[1](1) # prints 8


No; lambda is a bit more convenient. But this doesn't seem like a very
big issue worth a flame war. If GvR says multi-line lambda would make
the lexer more complicated and he doesn't think it's worth all the effort,
I don't see any need to argue about it.

> But the key in the whole thread is simply that indentation will not
> scale. Nor will Python.

This is a curious statement, given that Python is famous for scaling well.

I won't say more, since Alex Martelli already pointed out that Google is
doing big things with Python and it seems to scale well for them.
--
Steve R. Hastings "Vita est"
st...@hastings.org http://www.blarg.net/~steveha

Rhino

unread,
May 5, 2006, 11:49:23 PM5/5/06
to

"I V" <wron...@gmail.com> wrote in message
news:pan.2006.05.06...@gmail.com...

What does any of this have to do with Java?

--
Rhino


Ken Tilton

unread,
May 6, 2006, 1:30:04 AM5/6/06
to

<g> Hopefully it can be a big issue and still not justify a flame war.

Mileages will always vary, but one reason for lambda is precisely not to
have to stop, go make a new function for this one very specific use,
come back and use it as the one lambda statement, or in C have an
address to pass. but, hey, what are editors for? :)

the bigger issue is the ability of a lambda to close over arbitrary
lexically visible variables. this is something the separate function
cannot see, so one has to have a function parameter for everything.

but is such lexical scoping even on the table when Ptyhon's lambda comes
up for periodic review?

> If GvR says multi-line lambda would make
> the lexer more complicated and he doesn't think it's worth all the effort,
> I don't see any need to argue about it.

Oh, no, this is just front porch rocking chair BS. But as an enthuiastic
developer I am sensitive to how design choices express themselves in
ways unanticipated. Did the neat idea of indentation-sensitivity doom
pythonistas to a life without the sour grapes of lambda?

If so, Xah's critique missed that issue and was unfair to GvR in
ascribing his resistance to multi-statement lamda to mere BDFLism.

kenny

John Bokma

unread,
May 6, 2006, 1:42:03 AM5/6/06
to
Reported for excessive crossposting.

--
John Bokma Freelance software developer
&
Experienced Perl programmer: http://castleamber.com/

John Bokma

unread,
May 6, 2006, 1:44:47 AM5/6/06
to
"Rhino" <no.offline.c...@nospam.com> wrote:

> What does any of this have to do with Java?

Xah Lee is well known for abusing Usenet for quite some time, report
his posts as excessive crossposts to:

abuse at bcglobal dot net
abuse at dreamhost dot com

IIRC this is his third ISP account in 2 weeks, so it *does* work.

Moreover, his current hosting provider, dreamhost, might drop him soon.

Glyn Millington

unread,
May 6, 2006, 1:10:43 AM5/6/06
to
Ken Tilton <kent...@gmail.com> writes:

> kenny (wondering what to call a flock (?!) of lemmings)

Couldn't find it here:-

http://ojohaven.com/collectives/

So I would propose a "leap" of lemmings :-)


WAY OT! Sorry.

atb

Glyn

Alex Martelli

unread,
May 6, 2006, 3:13:49 AM5/6/06
to
Ken Tilton <kent...@gmail.com> wrote:
...
> > Absolutely. That's why firms who are interested in building *seriously*
> > large scale systems, like my employer (and supplier of your free mail
...

> > Obviously will not scale. Never.
> >
> > Well... hardly ever!
>
> You are talking about being incredibly popular. I was talking about

Who, me? I'm talking about the deliberate, eyes-wide-open choice by
*ONE* firm -- one which happens to more or less *redefine* what "large
scale" computation *means*, along many axes. That's got nothing to do
with Python being "incredibly popular": it has everything to do with
scalability -- the choice was made in the late '90s (and, incidentally,
by people quite familiar with lisp... no less than the reddit.com guys,
you know, the ones who recently chose to rewrite their side from Lisp to
Python...?), based on scalability issues, definitely not "popularity"
(Python in the late '90s was a very obscure, little-known language).

> kenny (who is old enough to have seen many a language come and go)

See your "many a language" and raise you one penny -- besides sundry
Basic dialects, machine languages, and microcode[s], I started out with
Fortran IV and APL, and I have professionally programmed in Pascal (many
dialects), Rexx, Forth, PL/I, Cobol, Lisp before there was a "Common"
one, Prolog, Scheme, Icon, Tcl, Awk, EDL, and several proprietary 3rd
and 4th generation languages -- as well of course as C and its
descendants such as C++ and Java, and Perl. Many other languages I've
studied and played with, I've never programmed _professionally_ (i.e.,
been paid for programs in those languages), but I've written enough
"toy" programs to get some feeling for (Ruby, SML, O'CAML, Haskell,
Snobol, FP/1, Applescript, C#, Javascript, Erlang, Mozart, ...).

Out of all languages I know, I've deliberately chosen to specialize in
Python, *because it scales better* (yes, functional programming is
_conceptually_ perfect, but one can never find sufficiently large teams
of people with the right highly-abstract mathematical mindset and at the
same time with sufficiently down-to-earth pragmaticity -- so, for _real
world_ uses, Python scales better). When I was unable to convince top
management, at the firm at which I was the top programmer, that the firm
should move to Python (beyond the pilot projects which I led and gave
such stellar results), I quit, and for years I made a great living as a
freelance consultant (mostly in Python -- once in a while, a touch of
Pyrex, C or C++ as a vigorish;-).

That's how come I ended up working at the firm supplying your free mail
(as Uber Tech Lead) -- they reached across an ocean to lure me to move
from my native Italy to California, and my proven excellence in Python
was their prime motive. The terms of their offer were just too
incredible to pass by... so, I rapidly got my O1 visa ("alien of
exceptional skills"), and here I am, happily ubertechleading... and
enjoying Python and its incredibly good scalability every single day!


Alex

Alex Martelli

unread,
May 6, 2006, 3:21:03 AM5/6/06
to
Steve R. Hastings <st...@hastings.org> wrote:
...

> > But the key in the whole thread is simply that indentation will not
> > scale. Nor will Python.
>
> This is a curious statement, given that Python is famous for scaling well.

I think "ridiculous" is a better characterization than "curious", even
if you're seriously into understatement.


> I won't say more, since Alex Martelli already pointed out that Google is
> doing big things with Python and it seems to scale well for them.

And of course we're not the only ones. In fact, I believe that we're
not even among the firms which have reported their experiences in the
official "Python Success Stories" -- IBM, Industrial Light and Magic,
NASA, etc, etc, are there, but we arent. I guess we just prefer to play
our cards closer to our chest -- after all, if our competitors choose to
use inferior languages, it's hardly to our advantage to change that;-).


Alex

Kay Schluehr

unread,
May 6, 2006, 3:26:19 AM5/6/06
to
Ken Tilton wrote:

> Oh, my, you are preaching to the herd (?!) of lemmings?! Please tell me
> you are aware that lemmings do not have ears. You should just do Lisp
> all day and add to the open source libraries to speed Lisp's ascendance.
> The lemmings will be liberated the day Wired puts John McCarthy on the
> cover, and not a day sooner anyway.

And then the 12th vanished Lisper returns and Lispers are not
suppressed anymore and won't be loosers forever. The world will be
united in the name of Lisp and Lispers will be leaders and honorables.
People stop worrying about Lispers as psychpaths and do not consider
them as zealots, equipped with the character of suicide bombers. No,
Lisp means peace and paradise.

Bill Atkins

unread,
May 6, 2006, 4:14:28 AM5/6/06
to
"Kay Schluehr" <kay.sc...@gmx.net> writes:

> And then the 12th vanished Lisper returns and Lispers are not
> suppressed anymore and won't be loosers forever. The world will be

The mark of a true loser is the inability to spell 'loser.' Zing!

> them as zealots, equipped with the character of suicide bombers. No,

A very reasonable comparison. Yes, the more I think about it, we Lisp
programmers are a lot like suicide bombers.

Doofus.

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

Thomas F. Burdick

unread,
May 6, 2006, 4:22:41 AM5/6/06
to
Ken Tilton <kent...@gmail.com> writes:

> <g> Hopefully it can be a big issue and still not justify a flame war.
>
> Mileages will always vary, but one reason for lambda is precisely not
> to have to stop, go make a new function for this one very specific
> use, come back and use it as the one lambda statement, or in C have an
> address to pass. but, hey, what are editors for? :)
>
> the bigger issue is the ability of a lambda to close over arbitrary
> lexically visible variables. this is something the separate function
> cannot see, so one has to have a function parameter for everything.
>
> but is such lexical scoping even on the table when Ptyhon's lambda
> comes up for periodic review?

This is second-hand, as I don't actually follow Python closely, but
from what I've heard, they now have reasonable scoping rules (or maybe
they're about to, I'm not sure). And you can use def as a
Scheme-style inner define, so it's essentially a LABELS that gets the
indentation wrong. This means they have proper closures, just not
anonymous ones. And an egregiously misnamed lambda that should be
fixed or thrown out.

If Python gets proper macros it won't matter one bit that they only
have named closures, since you can macro that away in a blink of an
eye.

Bill Atkins

unread,
May 6, 2006, 4:22:02 AM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:

How do you define scalability?

Kay Schluehr

unread,
May 6, 2006, 5:12:49 AM5/6/06
to
Bill Atkins wrote:
> "Kay Schluehr" <kay.sc...@gmx.net> writes:
>
> > And then the 12th vanished Lisper returns and Lispers are not
> > suppressed anymore and won't be loosers forever. The world will be
>
> The mark of a true loser is the inability to spell 'loser.' Zing!

There is not much lost.

> > them as zealots, equipped with the character of suicide bombers. No,
>
> A very reasonable comparison. Yes, the more I think about it, we Lisp
> programmers are a lot like suicide bombers.

Allah Inschallah

Martin P. Hellwig

unread,
May 6, 2006, 6:24:03 AM5/6/06
to
Bill Atkins wrote:
<cut>

>
> How do you define scalability?
>
http://www.google.com/search?hl=en&q=define%3Ascalability&btnG=Google+Search

;-)

--
mph

Bill Atkins

unread,
May 6, 2006, 6:42:21 AM5/6/06
to

OK, my real question is: what features of Python make it "scalable"?

Tomasz Zielonka

unread,
May 6, 2006, 7:04:56 AM5/6/06
to
Bill Atkins wrote:
> OK, my real question is: what features of Python make it "scalable"?

Let me guess: Python makes it easier to scale the application on
the "features" axis, and the approach to large-scale computation
taken by google makes Python's poor raw performance not so big
an issue, so it doesn't prevent the application from scaling
on the "load" and "amount of data" axes. I also guess that python
is often used to control simple, fast C/C++ programs, or even
to generate such programs.

Best regards
Tomasz

Martin P. Hellwig

unread,
May 6, 2006, 7:27:02 AM5/6/06
to
Bill Atkins wrote:
> "Martin P. Hellwig" <mhel...@xs4all.nl> writes:
>
>> Bill Atkins wrote:
>> <cut>
>>> How do you define scalability?
>>>
>> http://www.google.com/search?hl=en&q=define%3Ascalability&btnG=Google+Search
>>
>> ;-)
>>
>> --
>> mph
>
> OK, my real question is: what features of Python make it "scalable"?
>
Well I'm no expert, but I guess the ease of creating network services
and clients make it quite scalable. For example, I'm creating a
xmlrpcserver that returns a randomized cardlist, but I because of
fail-over I needed some form of scalability , my solution was to first
randomize the deck then marshal it and dump the file on a ZFS partition,
giving back the client a ticket number, the client can then connect with
the ticket number to receive the cardlist (read the file - unmarshal it).

While this is overkill for 1 server, I needed multiple because of
fail-over and load-balancing, in this case I have 3 'crypto' boxes (with
hardware crypto engines using OpenBSD) doing only the randomizing and 4
solaris machines doing the zfs and distribution of the list.

By using xmlrpc and DNS round-robin, I can just add boxes and it scales
without any problem, The ZFS boxes are the front-end listening to the
name 'shuffle' and are connecting to a private network to my crypto
boxes listening to the name 'crypto'.

So as long as I make DNS aliases (I have a little script that hearbeats
the boxes and when not responding within 10 seconds removes it alias)
and install the right scripts on the box I can scale till I'm round the
earth. Of course when the machine amount gets over a certain degree I
have to add some management functionality.

Now I don't say that I handle this situation well and that its the right
solution, but it worked for me and it was easy and fun to do with
python, but I guess that any language in this sence should be 'scalable'
and perhaps other languages have even better built-in networking
libraries but I'm not a professional programmer and until I learn other
languages (and are comfortable enough to use it) I'll keep on using
python for my projects.

For me python is easy, scalable, fun and by this the 'best' but that is
personal and I simply don't know whether my opinion will change in the
future or not.

--
mph

Xah Lee

unread,
May 6, 2006, 9:15:26 AM5/6/06
to

Ken Tilton wrote:

> kenny (wondering what to call a flock (?!) of lemmings)

Rabble. A rabble of lemmings.

Xah
x...@xahlee.org
http://xahlee.org/

Paddy

unread,
May 6, 2006, 9:27:39 AM5/6/06
to
Also addressing the Python and scaling question is the
kamaelia.sourceforge.net project whos objective is to solve the
problems of putting the BBCs vast archives on the web, and who use
Python.
-- Pad.

Paul Rubin

unread,
May 6, 2006, 10:36:49 AM5/6/06
to
"Martin P. Hellwig" <mhel...@xs4all.nl> writes:
> and clients make it quite scalable. For example, I'm creating a
> xmlrpcserver that returns a randomized cardlist, but I because of
> fail-over I needed some form of scalability , my solution was to first
> randomize the deck then marshal it and dump the file on a ZFS
> partition, giving back the client a ticket number, the client can then
> connect with the ticket number to receive the cardlist (read the file
> - unmarshal it).

This is a weird approach. Why not let the "ticket" by the (maybe
encrypted) PRNG seed that generates the permutation?

> While this is overkill for 1 server, I needed multiple because of
> fail-over and load-balancing, in this case I have 3 'crypto' boxes
> (with hardware crypto engines using OpenBSD) doing only the
> randomizing and 4 solaris machines doing the zfs and distribution of
> the list.

I don't know what good that hardware crypto is doing you, if you're
then writing out the shuffled deck to disk in the clear.

Paul Rubin

unread,
May 6, 2006, 10:52:51 AM5/6/06
to
Paul Rubin <http://phr...@NOSPAM.invalid> writes:
> I don't know what good that hardware crypto is doing you, if you're
> then writing out the shuffled deck to disk in the clear.

Ehhh, I guess you want the crypto hardware to generate physical
randomness for each shuffle. I'm skeptical of the value of this since
a cryptographic PRNG seeded with good entropy is supposed to be
computationally indistinguishable from physical randomness, and if
it's not, we're all in big trouble; further, that hardware engine is
almost certainly doing some cryptographic whitening, which is a
problem if you don't think that cryptography works.

Anyway, if it's just a 52-card deck you're shuffling, there's only
about 226 bits of entropy per shuffle, or 52*6 = 312 bits if you write
out the permutation straightforwardly as a vector. You could use that
as the ticket but if you're generating it that way you may need to
save the shuffle for later auditing.

For practical security purposes I'd be happier generating the shuffles
entirely inside the crypto module (HSM) by cryptographic means, with
the "ticket" just being a label for a shuffle. E.g. let

K1, K2 = secret keys

T(n) = ticket #n = AES(K1, n) to prevent clients from guessing
ticket numbers

shuffle(n) = HMAC-SHA-384(K2, n) truncated to 312 bits, treated as
permutation on 52 cards

You could put some of the card dealing logic into the HSM to get the
cards dealt out only as the game as played, to decrease the likelihood
of any cards getting exposed prematurely.

Martin P. Hellwig

unread,
May 6, 2006, 10:55:23 AM5/6/06
to
Paul Rubin wrote:
> "Martin P. Hellwig" <mhel...@xs4all.nl> writes:
>> and clients make it quite scalable. For example, I'm creating a
>> xmlrpcserver that returns a randomized cardlist, but I because of
>> fail-over I needed some form of scalability , my solution was to first
>> randomize the deck then marshal it and dump the file on a ZFS
>> partition, giving back the client a ticket number, the client can then
>> connect with the ticket number to receive the cardlist (read the file
>> - unmarshal it).
>
> This is a weird approach. Why not let the "ticket" by the (maybe
> encrypted) PRNG seed that generates the permutation?

Because the server that handles the generate request doesn't need to be
the same as the one that handles the request to give the client that
deck. Even more, the server that handles the request calls the crypto
servers to actually do the shuffling. So when the server fails before it
has given the client the ticket, it could be possible that a deck is
already created but not used, no biggie there.
But if the ticket is given to the client, than any other server can
serve back that ticket to give the shuffled deck, unless the ZFS dies of
course but then again thats why I use ZFS so I can mirror them om 4
different machines in 2 different locations.


>
>> While this is overkill for 1 server, I needed multiple because of
>> fail-over and load-balancing, in this case I have 3 'crypto' boxes
>> (with hardware crypto engines using OpenBSD) doing only the
>> randomizing and 4 solaris machines doing the zfs and distribution of
>> the list.
>
> I don't know what good that hardware crypto is doing you, if you're
> then writing out the shuffled deck to disk in the clear.

It's not about access security it's more about the best possible
randomness to shuffle the deck.

--
mph

Ken Tilton

unread,
May 6, 2006, 10:56:28 AM5/6/06
to

Thomas F. Burdick wrote:
> Ken Tilton <kent...@gmail.com> writes:
>
>
>><g> Hopefully it can be a big issue and still not justify a flame war.
>>
>>Mileages will always vary, but one reason for lambda is precisely not
>>to have to stop, go make a new function for this one very specific
>>use, come back and use it as the one lambda statement, or in C have an
>>address to pass. but, hey, what are editors for? :)
>>
>>the bigger issue is the ability of a lambda to close over arbitrary
>>lexically visible variables. this is something the separate function
>>cannot see, so one has to have a function parameter for everything.
>>
>>but is such lexical scoping even on the table when Ptyhon's lambda
>>comes up for periodic review?
>
>
> This is second-hand, as I don't actually follow Python closely, but
> from what I've heard, they now have reasonable scoping rules (or maybe
> they're about to, I'm not sure). And you can use def as a
> Scheme-style inner define, so it's essentially a LABELS that gets the
> indentation wrong.

Cool. And I know how much you like labels/flet. :)

> This means they have proper closures, just not
> anonymous ones. And an egregiously misnamed lambda that should be
> fixed or thrown out.
>
> If Python gets proper macros it won't matter one bit that they only
> have named closures, since you can macro that away in a blink of an
> eye.

Ah, well, there we go again. Without sexpr notation, the lexer/parser
again will be "hard", and "hardly worth it": we get even more sour
grapes, this time about macros not being such a big deal.

One of the hardest things for a technologist to do is admit that a neat
idea has to be abandoned. Initial success creates a giddy
over-commitment to the design choice. After then all difficulties get
brushed aside or kludged.

This would not be a problem for Python if it had stayed a scripting
language... well, maybe "no Macro!s" and "no real lambda!" and "no
continuations!" are GvR's way of keeping Python just a scripting language.

:)

Ken Tilton

unread,
May 6, 2006, 11:04:15 AM5/6/06
to

Damn! Google can do that?! Omigod!!! Not joking, I never knew that,a
lways used dictionary.com. Thx! I meant:

> The ability to add power and capability to an existing system without significant expense or overhead.
> www.yipes.com/care/cc_glossary.shtml

The number of definitions explains why most respondents should save
their breath. Natural language is naturally ambiguous. Meanwhile Usenet
is the perfect place to grab one meaning out of a dozen and argue over
the implications of that one meaning which of course is never the one
originally intended, as any reasonable, good faith reader would admit.

kenny

Ken Tilton

unread,
May 6, 2006, 11:09:18 AM5/6/06
to

"The Twelfth Vanished Lisper"? I love it. Must start a secret society....

:)

Paul Rubin

unread,
May 6, 2006, 1:41:00 PM5/6/06
to
"Martin P. Hellwig" <mhel...@xs4all.nl> writes:
> > This is a weird approach. Why not let the "ticket" by the (maybe
> > encrypted) PRNG seed that generates the permutation?
>
> Because the server that handles the generate request doesn't need to
> be the same as the one that handles the request to give the client
> that deck.

Wait a sec, are you giving the entire shuffled deck to the client?
Can you describe the application? I was imagining an online card game
where clients are playing against each other. Letting any client see
the full shuffle is disastrous.

> But if the ticket is given to the client, than any other server can
> serve back that ticket to give the shuffled deck, unless the ZFS dies
> of course but then again thats why I use ZFS so I can mirror them om 4
> different machines in 2 different locations.

> > I don't know what good that hardware crypto is doing you, if you're


> > then writing out the shuffled deck to disk in the clear.
>
> It's not about access security it's more about the best possible
> randomness to shuffle the deck.

Depending on just what the server is for, access security may be a far
more important issue. If I'm playing cards online with someone, I'd
be WAY more concerned about the idea of my opponent being able to see
my cards by breaking into the server, than his being able to
cryptanalyze a well-designed PRNG based solely on its previous
outputs.

Martin P. Hellwig

unread,
May 6, 2006, 2:18:17 PM5/6/06
to
Paul Rubin wrote:
> "Martin P. Hellwig" <mhel...@xs4all.nl> writes:
>>> This is a weird approach. Why not let the "ticket" by the (maybe
>>> encrypted) PRNG seed that generates the permutation?
>> Because the server that handles the generate request doesn't need to
>> be the same as the one that handles the request to give the client
>> that deck.
>
> Wait a sec, are you giving the entire shuffled deck to the client?
> Can you describe the application? I was imagining an online card game
> where clients are playing against each other. Letting any client see
> the full shuffle is disastrous.

Nope I have a front end service that does the client bit, its about this
(in this context, there are more services of course):

crypto - ZFS - table servers - mirror dispatching - client xmlrpc access
- client ( last one has not been written yet )

<cut>


>
> Depending on just what the server is for, access security may be a far
> more important issue. If I'm playing cards online with someone, I'd
> be WAY more concerned about the idea of my opponent being able to see
> my cards by breaking into the server, than his being able to
> cryptanalyze a well-designed PRNG based solely on its previous
> outputs.

Only client xmlrpc access is (should be) accessible from the outside and
since this server is user session based they only see their own card.
However this project is still in it's early development, I'm doing now
initial alpha-tests (and stress testing) and after this I'm going to let
some audit bureau's check for security (probably Madison-Ghurka, but I
haven't asked them yet).

--
mph

Thomas F. Burdick

unread,
May 6, 2006, 3:02:26 PM5/6/06
to
[ I pruned the cross-posting down to a reasonable level ]

Ken Tilton <kent...@gmail.com> writes:

> Thomas F. Burdick wrote:
>
> > This is second-hand, as I don't actually follow Python closely, but
> > from what I've heard, they now have reasonable scoping rules (or maybe
> > they're about to, I'm not sure). And you can use def as a
> > Scheme-style inner define, so it's essentially a LABELS that gets the
> > indentation wrong.
>
> Cool. And I know how much you like labels/flet. :)

Well, I love LABELS but I hate inner defines with an equal passion --
so for me it's a wash :-)

As much as I like nice low-level, close-to-the-machine mechanisms as
labels and lambda, sometimes you just want the high-level
expressiveness of tagbody/go, which Python doesn't have ... which in
my opinion is quite a crime to readability and the ability to
transcribe Knuth algorithms, which any engineer should find offensive
to their sensibilities.

> > This means they have proper closures, just not
> > anonymous ones. And an egregiously misnamed lambda that should be
> > fixed or thrown out.
> > If Python gets proper macros it won't matter one bit that they only
> > have named closures, since you can macro that away in a blink of an
> > eye.
>
> Ah, well, there we go again. Without sexpr notation, the lexer/parser
> again will be "hard", and "hardly worth it": we get even more sour
> grapes, this time about macros not being such a big deal.
>
> One of the hardest things for a technologist to do is admit that a
> neat idea has to be abandoned. Initial success creates a giddy
> over-commitment to the design choice. After then all difficulties get
> brushed aside or kludged.

Y'never know, they could always Greenspun their way to almost-sexps.
What with the way that selective pressure works, it's gonna be that or
die, so it is a possibility.

Thomas F. Burdick

unread,
May 6, 2006, 3:06:00 PM5/6/06
to
Ken Tilton <kent...@gmail.com> writes:

> "The Twelfth Vanished Lisper"? I love it. Must start a secret society....

Cool, can I join? Are you going to announce things on Usenet, set up
a mailing list, use cliki, or use the LispNYC page, or what? Should we start a
common-lisp.net project?

The first project should be an Eco-Eliza, that would kill.

marc spitzer

unread,
May 6, 2006, 3:40:50 PM5/6/06
to

ok, you are a nail

marc

--
ms4...@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org

Alex Martelli

unread,
May 6, 2006, 3:43:02 PM5/6/06
to
Ken Tilton <kent...@gmail.com> wrote:

> Martin P. Hellwig wrote:
> > Bill Atkins wrote:
> > <cut>
> >
> >>
> >> How do you define scalability?
> >>
> > http://www.google.com/search?hl=en&q=define%3Ascalability&btnG=Google+Search
> >
>
> Damn! Google can do that?! Omigod!!! Not joking, I never knew that,a

You're welcome; we do have several little useful tricks like that.

> lways used dictionary.com. Thx! I meant:
>
> > The ability to add power and capability to an existing system without
> > significant expense or overhead. www.yipes.com/care/cc_glossary.shtml

Excellent -- just the definition of "scalability" that Google and its
competitor live and die by ((OK, OK, I'm _not_ implying that such issues
as usability &c don't matter, by no means -- but, I live mostly in the
world of infrastructure, where scalability and reliability reign)).


> The number of definitions explains why most respondents should save
> their breath. Natural language is naturally ambiguous. Meanwhile Usenet
> is the perfect place to grab one meaning out of a dozen and argue over
> the implications of that one meaning which of course is never the one
> originally intended, as any reasonable, good faith reader would admit.

However, you and I are/were discussing exactly the same nuance of
meaning, either by a funny quirk of fate or because it's the one that
really matters in large-scale programming (and more generally,
large-scale systems). E.g., if your existing system can gracefully
handle your current traffic of, say, a billion queries of complexity X,
you want to be able to rapidly add a feature that will increase the
average query's complexity to (X+dX) and attract 20% more users, so
you'll need to handle 1.2 billion queries just as gracefully: i.e., you
need to be able to add power and capability to your existing system,
rapidly and reliably, just as that definition says.

When this is the challenge, your choice of programming language is not
the first order of business, of course -- your hardware and network
architecture loom large, and so does the structuring of your
applications and infrastructure software across machines and networks.
Still, language does matter, at a "tertiary" level if you will. Among
the potential advantages of Lisp is the fact that you could use Lisp
across almost all semantic levels ("almost" because I don't think "Lisp
machines" are a realistic option nowadays, so lower levels of the stack
would remain in C and machine language -- but those levels may probably
be best handled by a specialized squad of kernel-level and device-driver
programmers, anyway); among the potential advantages of Python, the fact
that (while not as suited as Lisp to lower-level coding, partly because
of a lack of good solid compilers to make machine language out of it),
it brings a powerful drive to uniformity, rather than a drive towards a
host of "domain-specific" Little Languages as is encouraged by Lisp's
admirably-powerful macro system.

One key axis of scalability here is, how rapidly can you grow the teams
of people that develop and maintain your software base? To meet all the
challenges and grasp all the opportunities of an exploding market,
Google has had to almost-double its size, in terms of number of
engineers, every year for the last few years -- I believe that doing so
while keeping stellar quality and productivity is an unprecedented feat,
and while (again!) the choice of language(s) is not a primary factor
(most kudos must go to our management and its approaches and methods, of
course, and in particular to the strong corporate identity and culture
they managed to develop and maintain), it still does matter. The
uniformity of coding style and practices in our codebase is strong.

We don't demand Python knowledge from all the engineers we hire: for any
"engineering superstar" worth the adjective, Python is really easy and
fast to pick up and start using productively -- I've seen it happen
thousands of times, both in Google and in my previous career, and not
just for engineers with a strong software background, but also for those
whose specialties are hardware design, network operations, etc, etc. The
language's simplicity and versatility allow this. Python "fits people's
brains" to an unsurpassed extent -- in a way that, alas, languages
requiring major "paradigm shifts" (such as pure FP languages, or Common
Lisp, or even, say, Smalltalk, or Prolog...) just don't -- they really
require a certain kind of mathematical mindset or predisposition which
just isn't as widespread as you might hope. Myself, I do have more or
less that kind of mindset, please note: while my Lisp and scheme are
nowadays very rusty, proficiency with them was part of what landed me my
first job, over a quarter century ago (microchip designers with a good
grasp of lisp-ish languages being pretty rare, and TI being rather
hungry for them at the time) -- but I must acknowlegde I'm an exception.

Of course, the choice of Python does mean that, when we really truly
need a "domain specific little language", we have to implement it as a
language in its own right, rather than piggybacking it on top of a
general-purpose language as Lisp would no doubt afford; see
<http://labs.google.com/papers/sawzall.html> for such a DSLL developed
at Google. However, I think this tradeoff is worthwhile, and, in
particular, does not impede scaling.


Alex

Luc The Perverse

unread,
May 6, 2006, 4:10:19 PM5/6/06
to
"John Bokma" <jo...@castleamber.com> wrote in message
news:Xns97BB7216CA...@130.133.1.4...
> Reported for excessive crossposting.

Did u report yourself?

--
LTP

:)


Ken Tilton

unread,
May 6, 2006, 5:21:20 PM5/6/06
to

> the first order of business, of course ...

Looks like dictionaries are no match for the ambiguity of natural
language. :) Let me try again: it is Python itself that cannot scale, as
in gain "new power and capability", and at least in the case of lambda
it seems to be because of indentation-sensitivity.

Is that not what GvR said?

By contrast, in On Lisp we see Graham toss off Prolog in Chapter 22 and
an object system from scratch in Chapter 25. Lite versions, to be sure,
but you get the idea.

My sig has a link to a hack I developed after doing Lisp for less than a
month, and without lambda (and to a lesser degree macros) it would be
half the tool it is. It adds a declarative paradigm to the CL object
system, and is built on nothing but ansi standard Lisp. Yet it provides
new power and capability. And that by an application programmer just
working on a nasty problem, never mind the language developer.

I just find it interesting that sexpr notation (which McCarthy still
wants to toss!) is such a huge win, and that indentation seems to be so
limiting.


-- your hardware and network
> architecture loom large, and so does the structuring of your
> applications and infrastructure software across machines and networks.
> Still, language does matter, at a "tertiary" level if you will. Among
> the potential advantages of Lisp is the fact that you could use Lisp
> across almost all semantic levels ("almost" because I don't think "Lisp
> machines" are a realistic option nowadays, so lower levels of the stack
> would remain in C and machine language -- but those levels may probably
> be best handled by a specialized squad of kernel-level and device-driver
> programmers, anyway); among the potential advantages of Python, the fact
> that (while not as suited as Lisp to lower-level coding, partly because
> of a lack of good solid compilers to make machine language out of it),
> it brings a powerful drive to uniformity, rather than a drive towards a
> host of "domain-specific" Little Languages as is encouraged by Lisp's
> admirably-powerful macro system.
>
> One key axis of scalability here is, how rapidly can you grow the teams
> of people that develop and maintain your software base?

I am with Brooks on the Man-Month myth, so I am more interested in /not/
growing my team. If Lisp is <pick a number, any numer> times more
expressive than Python, you need exponentially fewer people.

In some parallel universe Norvig had the cojones to dictate Lisp to
Google and they listened, and in that universe... I don't know, maybe
GMail lets me click on the sender column to sort my mail? :)

> To meet all the
> challenges and grasp all the opportunities of an exploding market,
> Google has had to almost-double its size, in terms of number of
> engineers, every year for the last few years -- I believe that doing so
> while keeping stellar quality and productivity is an unprecedented feat,
> and while (again!) the choice of language(s) is not a primary factor
> (most kudos must go to our management and its approaches and methods, of
> course, and in particular to the strong corporate identity and culture
> they managed to develop and maintain), it still does matter. The
> uniformity of coding style and practices in our codebase is strong.

Well, you said it for me. Google hires the best and pays a lot. Hey, I
wrote great code in Cobol. So as much as you want to brag on yourself
and Google <g>, your success does not address:

Indentation-sensitivity: Is it holding Python back?

>
> We don't demand Python knowledge from all the engineers we hire: for any
> "engineering superstar" worth the adjective, Python is really easy and
> fast to pick up and start using productively -- I've seen it happen
> thousands of times, both in Google and in my previous career, and not
> just for engineers with a strong software background, but also for those
> whose specialties are hardware design, network operations, etc, etc. The
> language's simplicity and versatility allow this. Python "fits people's
> brains" to an unsurpassed extent -- in a way that, alas, languages
> requiring major "paradigm shifts" (such as pure FP languages, or Common
> Lisp, or even, say, Smalltalk, or Prolog...) just don't -- they really
> require a certain kind of mathematical mindset or predisposition which
> just isn't as widespread as you might hope.

Talk about Lisp myths. The better the language, the easier the language.
And the best programmers on a team get to develop tools and macrology
that empower the lesser lights, so (a) they have fun work that keeps
them entertained while (b) the drones who just want to get through the
day are insanely productive, too.

Another myth (or is this the same?) is this "pure FP" thing. Newbies can
and usually do code as imperatively as they wanna be. Until someone else
sees their code, tidies it up, and the light bulb goes on. But CL does
not force a sharp transition on anyone.


> Myself, I do have more or
> less that kind of mindset, please note: while my Lisp and scheme are
> nowadays very rusty, proficiency with them was part of what landed me my
> first job, over a quarter century ago (microchip designers with a good
> grasp of lisp-ish languages being pretty rare, and TI being rather
> hungry for them at the time) -- but I must acknowlegde I'm an exception.
>
> Of course, the choice of Python does mean that, when we really truly
> need a "domain specific little language", we have to implement it as a
> language in its own right, rather than piggybacking it on top of a
> general-purpose language as Lisp would no doubt afford; see
> <http://labs.google.com/papers/sawzall.html> for such a DSLL developed
> at Google.

No lambdas? Static typing?! eewwwewww. :) Loved the movie, tho.

Come on, try just one meaty Common Lisp project at Google. Have someone
port Cells to Python. I got halfway done but decided I would rather be
doing Lisp. uh-oh. Does Python have anything like special variables? :)

Kenny

Ken Tilton

unread,
May 6, 2006, 5:36:10 PM5/6/06
to

Ken Tilton wrote:
>
> Come on, try just one meaty Common Lisp project at Google. Have someone
> port Cells to Python. I got halfway done but decided I would rather be
> doing Lisp. uh-oh. Does Python have anything like special variables? :)

Omigod. I scare myself sometimes. This would be a great Summer of Code
project. Port Cells (see sig) to Python. Trust me, this is Silver Bullet
stuff. (Brooks was wrong on that.)

If a strong Pythonista wants to submit a proposal, er, move fast. I am
mentoring through LispNYC: http://www.lispnyc.org/soc.clp

Gotta be all over Python metaclasses, and everything else pure Python.
PyGtk would be a good idea for the demo, which will involve a GUI mini
app. Just gotta be able to /read/ Common Lisp.

kenny

Alex Martelli

unread,
May 6, 2006, 6:37:43 PM5/6/06
to
Ken Tilton <kent...@gmail.com> wrote:
...
> Looks like dictionaries are no match for the ambiguity of natural
> language. :) Let me try again: it is Python itself that cannot scale, as
> in gain "new power and capability", and at least in the case of lambda
> it seems to be because of indentation-sensitivity.

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 (and it's an acknowledged Python design
principle that there should ideally be just one obvious way to perform a
task); GvR used to hold the same opinion, but changed his mind recently,
alas, so we'll keep the wart.

But, quite apart from the whole issue of whether it's desirable to
languages to change massively ("add new power and capability" meaning
new enriched features in the language itself), your whole argument is
bogus: it's obvious that _any_ fundamental design choice in an artefact
will influence the feasibility and desirability of future design choices
in future releases of that same, identical artefact. At a syntax-sugar
level, for example, Lisp's choice to use parentheses as delimiter means
it's undesirable, even unfeasible, to use the single character '(' as an
ordinary identifier in a future release of the language. Considering
this to mean that Lisp "cannot scale" is just as ridiculous as
considering that Python "cannot scale" by not having an elegant way to
make lambdas heavier and richer -- totally laughable and idiotic. ``An
unneeded feature "cannot" be added (elegantly) in future releases of the
language'' is just as trivial and acceptable for the unneded feature
``allow ( as an ordinary single-character identifier'' as for the
unneded feature ``allow unnamed functions with all the flexibility of
named ones''.

> By contrast, in On Lisp we see Graham toss off Prolog in Chapter 22 and

Oh, is that the same Graham who writes:

"""
A friend of mine who knows nearly all the widely used languages uses
Python for most of his projects. He says the main reason is that he
likes the way source code looks. That may seem a frivolous reason to
choose one language over another. But it is not so frivolous as it
sounds: when you program, you spend more time reading code than writing
it. You push blobs of source code around the way a sculptor does blobs
of clay. So a language that makes source code ugly is maddening to an
exacting programmer, as clay full of lumps would be to a sculptor.
"""
...? [[ I suspect that friend is in fact a common friend of mine and
Graham's, the guy you also mention later in your post, and who
introduced Graham and me when G recently came talk at Google (we had
"brushed" before, speaking in the same sessions at conferences and the
like, but had never "met", as in, got introduced and _talked_...;-). ]]

But, no matter, let's get back to Graham's point: significant
indentation is a large part of what gives Python its own special beauty,
uncluttered by unneeded punctuation. And while you, I, Graham, and that
common friend of ours, might likely agree that Lisp, while entirely
different, has its own eerie beauty, most people's aesthetics are poles
apart from that (why else would major pure-FP languages such as *ML and
Haskell entirely reject Lisp's surface syntax, willingly dropping the
ease of macros, to introduce infix operator syntax etc...? obviously,
their designers' aesthetics weigh parenthesized prefixsyntax negatively,
despite said designers' undeniable depth, skill and excellence).


Alex

Bill Atkins

unread,
May 6, 2006, 7:27:07 PM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:

Not so infeasible:

(let ((|bizarrely(named()symbol| 3))
(+ |bizarrely(named()symbol| 4))

;; => 7

And in any case, enforced indentation is a policy with vastly more
serious consequences than the naming of identifiers.

--

Ken Tilton

unread,
May 6, 2006, 7:55:06 PM5/6/06
to

Alex Martelli wrote:
> Ken Tilton <kent...@gmail.com> wrote:
> ...
>
>>Looks like dictionaries are no match for the ambiguity of natural
>>language. :) Let me try again: it is Python itself that cannot scale, as
>>in gain "new power and capability", and at least in the case of lambda
>>it seems to be because of indentation-sensitivity.
>
>
> 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 (and it's an acknowledged Python design
> principle that there should ideally be just one obvious way to perform a
> task); GvR used to hold the same opinion, but changed his mind recently,
> alas, so we'll keep the wart.

Yes, I am enjoying watching lambda teetering on the brink. So it has
been re-upped for another tour? Go, lambda! Go, lambda!

>
> But, quite apart from the whole issue of whether it's desirable to
> languages to change massively ("add new power and capability" meaning
> new enriched features in the language itself), your whole argument is
> bogus: it's obvious that _any_ fundamental design choice in an artefact
> will influence the feasibility and desirability of future design choices
> in future releases of that same, identical artefact.

True but circular, because my very point is that () was a great design
choice in that it made macros possible and they made CL almost
infinitely extensible, while indentation-sensitivity was a mistaken
design choice because it makes for very clean code (I agree
wholeheartedly) but placed a ceiling on its expressiveness.

As for:

> At a syntax-sugar
> level, for example, Lisp's choice to use parentheses as delimiter means
> it's undesirable, even unfeasible, to use the single character '(' as an
> ordinary identifier in a future release of the language.

(defun |(| (aside) (format nil "Parenthetically speaking...~a." aside))
=> |(|
(|(| "your Lisp /is/ rusty.")
=> "Parenthetically speaking...your Lisp /is/ rusty.."

:) No, seriously, is that all you can come up with?

> Considering
> this to mean that Lisp "cannot scale" is just as ridiculous as
> considering that Python "cannot scale" by not having an elegant way to
> make lambdas heavier and richer -- totally laughable and idiotic.

Harsh. :) I demand satisfaction. See end of article.

> ``An
> unneeded feature "cannot" be added (elegantly) in future releases of the
> language'' is just as trivial and acceptable for the unneded feature
> ``allow ( as an ordinary single-character identifier'' as for the
> unneded feature ``allow unnamed functions with all the flexibility of
> named ones''.
>
>
>>By contrast, in On Lisp we see Graham toss off Prolog in Chapter 22 and
>
>
> Oh, is that the same Graham who writes:

So we are going to skip the point I was making about Common Lisp being
so insanely extensible? By /application/ programmers? Hell, for all we
know CL does have a BDFL, we just do not need their cooperation.

>
> """
> A friend of mine who knows nearly all the widely used languages uses
> Python for most of his projects. He says the main reason is that he
> likes the way source code looks.

No argument. The little Python I wrote while porting Cells to Python was
strikingly attractive. But it was a deal with the devil, unless Python
is content to be just a scripting language. (And it should be.)

OK, I propose a duel. We'll co-mentor this:

http://www.lispnyc.org/wiki.clp?page=PyCells

In the end Python will have a Silver Bullet, and only the syntax will
differ, because Python has a weak lambda, statements do not always
return values, it does not have macros, and I do not know if it has
special variables.

Then we can just eyeball the code and see if the difference is
interesting. These abstract discussions do tend to loop.

kenny

Alex Martelli

unread,
May 6, 2006, 7:57:12 PM5/6/06
to
Bill Atkins <NOatki...@rpi.edu> wrote:
...

> > ``allow ( as an ordinary single-character identifier'' as for the
> > unneded feature ``allow unnamed functions with all the flexibility of
> > named ones''.
>
> Not so infeasible:
>
> (let ((|bizarrely(named()symbol| 3))
> (+ |bizarrely(named()symbol| 4))
>
> ;; => 7

Read again what I wrote: I very specifically said "ordinary
*single-character* identifier" (as opposed to "one of many characters
inside a multi-character identifier"). Why do you think I said
otherwise, when you just quoted what I had written? (Even just a
_leading_ ( at the start of an identifier may be problematic -- and just
as trivial as having to give names to functions, of course, see below).


> And in any case, enforced indentation is a policy with vastly more
> serious consequences than the naming of identifiers.

So far, what was being discussed here isn't -- having to use an
identifier for an object, rather than keeping it anonymous -- trivial.
Python practically enforces names for several kinds of objects, such as
classes and modules as well as functions ("practically" because you CAN
call new.function(...), type(...), etc, where the name is still there
but might e.g. be empty -- not a very practical alternative, though) --
so what? Can you have an unnamed macro in Lisp? Is being "forced" to
name it a "serious consequence"? Pah.

Anyway, I repeat: *any* design choice (in a language, or for that matter
any other artefact) has consequences. As Paul Graham quotes and
supports his unnamed friend as saying, Python lets you easily write code
that *looks* good, and, as Graham argues, that's an important issue --
and, please note, a crucial consequence of using significant
indentation. Alien whitespace eating nanoviruses are no more of a worry
than alien parentheses eating nanoviruses, after all.


Alex

Bill Atkins

unread,
May 6, 2006, 8:16:19 PM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:

> Bill Atkins <NOatki...@rpi.edu> wrote:
> ...
>> > ``allow ( as an ordinary single-character identifier'' as for the
>> > unneded feature ``allow unnamed functions with all the flexibility of
>> > named ones''.
>>
>> Not so infeasible:
>>
>> (let ((|bizarrely(named()symbol| 3))
>> (+ |bizarrely(named()symbol| 4))
>>
>> ;; => 7
>
> Read again what I wrote: I very specifically said "ordinary
> *single-character* identifier" (as opposed to "one of many characters
> inside a multi-character identifier"). Why do you think I said
> otherwise, when you just quoted what I had written? (Even just a
> _leading_ ( at the start of an identifier may be problematic -- and just
> as trivial as having to give names to functions, of course, see below).

Well, the same technique can obviously be used for:

(let ((|(| 3)))
(+ |(| 4)))
;; => 7

The length of the identifier is irrelevant...

>> And in any case, enforced indentation is a policy with vastly more
>> serious consequences than the naming of identifiers.
>
> So far, what was being discussed here isn't -- having to use an
> identifier for an object, rather than keeping it anonymous -- trivial.
> Python practically enforces names for several kinds of objects, such as
> classes and modules as well as functions ("practically" because you CAN
> call new.function(...), type(...), etc, where the name is still there
> but might e.g. be empty -- not a very practical alternative, though) --
> so what? Can you have an unnamed macro in Lisp? Is being "forced" to
> name it a "serious consequence"? Pah.

Common Lisp does not support unnamed macros (how would these be
useful?), but nothing stops me from adding these. What use case do
you envision for anonymous macros?

> Anyway, I repeat: *any* design choice (in a language, or for that matter
> any other artefact) has consequences. As Paul Graham quotes and
> supports his unnamed friend as saying, Python lets you easily write code
> that *looks* good, and, as Graham argues, that's an important issue --
> and, please note, a crucial consequence of using significant
> indentation. Alien whitespace eating nanoviruses are no more of a worry
> than alien parentheses eating nanoviruses, after all.

It *is* an important issue, but it's also a subjective issue. I find
Lisp to be far prettier than any syntax-based language, so it's far
from an objective truth that Python code often looks good - or even at
all.

Plus, I can easily write code that looks good without using a language
that enforces indentation rules. Lisp's regular syntax lets Emacs do
it for me with a simple C-M-a C-M-q. What could be easier?

Alex Martelli

unread,
May 6, 2006, 8:34:31 PM5/6/06
to
Ken Tilton <kent...@gmail.com> wrote:
...
> True but circular, because my very point is that () was a great design
> choice in that it made macros possible and they made CL almost
> infinitely extensible, while indentation-sensitivity was a mistaken
> design choice because it makes for very clean code (I agree
> wholeheartedly) but placed a ceiling on its expressiveness.

Having to give functions a name places no "ceiling on expressiveness",
any more than, say, having to give _macros_ a name.


> As for:
>
> > At a syntax-sugar
> > level, for example, Lisp's choice to use parentheses as delimiter means
> > it's undesirable, even unfeasible, to use the single character '(' as an
> > ordinary identifier in a future release of the language.
>
> (defun |(| (aside) (format nil "Parenthetically speaking...~a." aside))
> => |(|
> (|(| "your Lisp /is/ rusty.")
> => "Parenthetically speaking...your Lisp /is/ rusty.."
>
> :) No, seriously, is that all you can come up with?

Interestingly, the SECOND lisper to prove himself unable to read the
very text he's quoting. Reread carefully, *USE THE ***SINGLE***
CHARACTER* ... *AS AN ORDINARY IDENTIFIER*. What makes you read a
``PART OF'' that I had never written? You've shown how to use the
characters as *PART* of an identifier [[and I believe it couldn't be the
very start]], and you appear to believe that this somehow refutes my
assertion?

Are you ready to admit you were utterly wrong, and (while it is indeed
true that my Lisp is rusty) there is nothing in this exchange to show
it, as opposed to showing rustiness in your ability to understand
English? Or shall we move from polite although total dissent right on
to flamewars and namecalling?

The point is, OF COURSE any design choice places limitations on future
design choices; but some limitations are even DESIRABLE (a language
where *every* single isolated character could mean anything whatsoever
would not be "expressive", but rather totally unreadable) or at least
utterly trivial (syntax-sugar level issues most typically are). Wilfully
distorting some such limitation as meaning that one language "can scale"
(when EVERY language inevitably has SOME such limitations) is not even
funny, and clearly characterizes a polemist who is intent on proving a
preconceived thesis, as opposed to an investigator with any real
interest in ascertaining the truth of the matter.

> > Oh, is that the same Graham who writes:
>
> So we are going to skip the point I was making about Common Lisp being
> so insanely extensible? By /application/ programmers? Hell, for all we
> know CL does have a BDFL, we just do not need their cooperation.

Yes, we are, because the debate about why it's better for Python (as a
language used in real-world production systems, *SCALABLE* to extremely
large-scale ones) to *NOT* be insanely extensible and mutable is a
separate one -- Python's uniformity of style allows SCALABILITY of
teams, and teams-of-teams, which is as crucial in the real world as
obviously not understood by you (the law you misquoted was about adding
personnel to a LATE project making it later -- nothing to do with how
desirable it can be to add personnel to a large and growing collection
of projects, scaling and growing in an agile, iterative way to meet
equally growing needs and market opportunities).

This specific debate grew from your misuse of "scalable" to mean or
imply "a bazillion feechurz can [[and, implicitly, should]] be added to
a language, and therefore anything that stands in the way of feechuritis
is somehow holding the language back". That's bad enough, even though
in its contextual misuse of "scalable" it breaks new ground, and I don't
want to waste even more time re-treading *old* ground as to whether the
"*insane* extensibility" afforded by macros is a good or a bad thing in
a language to be used for real-world software production (as opposed to
prototyping and research).


> > """
> > A friend of mine who knows nearly all the widely used languages uses
> > Python for most of his projects. He says the main reason is that he
> > likes the way source code looks.
>
> No argument. The little Python I wrote while porting Cells to Python was
> strikingly attractive. But it was a deal with the devil, unless Python
> is content to be just a scripting language. (And it should be.)

It's hard to attribute feelings to a programming language, but, if you
really must, I'd say Pyton aspires to be *useful* -- if all you need is
"just a scripting language", it will be content to be one for you, and
if your need SCALE, well then, PYTHON IS SCALABLE, and will remain a
*SIMPLE, CLEAN, LITTLE AND POWERFUL LANGUAGE* (letting nobody do
anything INSANE to it;-) while scaling up to whatever size of project(s)
you need (including systems so large that they redefine the very concept
of "large scale" -- believe me, once in a while at a conference I make
the mistake of going to some talk about "large scale" this or that, and
invariably stagger out once again with the realization that what's
"large scale" to the world tends to be a neat toy-sized throwaway little
experiment to my current employer).


> OK, I propose a duel. We'll co-mentor this:
>
> http://www.lispnyc.org/wiki.clp?page=PyCells
>
> In the end Python will have a Silver Bullet, and only the syntax will
> differ, because Python has a weak lambda, statements do not always
> return values, it does not have macros, and I do not know if it has
> special variables.
>
> Then we can just eyeball the code and see if the difference is
> interesting. These abstract discussions do tend to loop.

As a SummerOfCode mentor, I'm spoken for, and can't undertake to mentor
other projects. I do agree that these discussions can be sterile, and
I'll be glad to see what comes of your "pycells" project, but until then
there's little we can do except agree to disagree (save that I'd like
you to acknowledge my point above, regarding what exactly I had said and
the fact that your alleged counterexample doesn't address at all what I
had said -- but, I'll live even without such an acknowledgment).


Alex

Alex Martelli

unread,
May 6, 2006, 8:49:42 PM5/6/06
to
Bill Atkins <NOatki...@rpi.edu> wrote:
...
> >
> > Read again what I wrote: I very specifically said "ordinary
> > *single-character* identifier" (as opposed to "one of many characters
> > inside a multi-character identifier"). Why do you think I said
> > otherwise, when you just quoted what I had written? (Even just a
> > _leading_ ( at the start of an identifier may be problematic -- and just
> > as trivial as having to give names to functions, of course, see below).
>
> Well, the same technique can obviously be used for:
>
> (let ((|(| 3)))
> (+ |(| 4)))
> ;; => 7
>
> The length of the identifier is irrelevant...

But it cannot be a SINGLE CHARACTER, *just* the openparenthesis.

Wow, it's incredible to me that you STILL can't read, parse and
understand what I have so clearly expressed and repeated!


> Common Lisp does not support unnamed macros (how would these be
> useful?), but nothing stops me from adding these. What use case do
> you envision for anonymous macros?

None, just like there is none for anonymous functions -- there is
nothing useful I can do with anonymous functions that I cannot do with
named ones.


> > Anyway, I repeat: *any* design choice (in a language, or for that matter
> > any other artefact) has consequences. As Paul Graham quotes and
> > supports his unnamed friend as saying, Python lets you easily write code
> > that *looks* good, and, as Graham argues, that's an important issue --
> > and, please note, a crucial consequence of using significant
> > indentation. Alien whitespace eating nanoviruses are no more of a worry
> > than alien parentheses eating nanoviruses, after all.
>
> It *is* an important issue, but it's also a subjective issue. I find
> Lisp to be far prettier than any syntax-based language, so it's far
> from an objective truth that Python code often looks good - or even at
> all.

The undeniable truth, the objective fact, is that *to most programmers*
(including ones deeply enamored of Lisp, such as Graham, Tilton, Norvig,
...) Python code looks good; the Lisp code that looks good to YOU (and,
no doubt them), and palatable to me (I have spoken of "eerie beauty"),
just doesn't to most prospective readers. If you program on your own,
or just with a few people who share your tastes, then only your taste
matters; if you want to operate in the real world, maybe, as I've
already pointed out, to build up a successful firm faster than had ever
previously happened, this *DOESN'T SCALE*. Essentially the same issue
I'm explaining on the parallel subthread with Tilton, except that he
fully agrees with my aesthetic sense (quoting Tilton, "No argument. The


little Python I wrote while porting Cells to Python was strikingly

attractive") so this facet of the jewel needed no further belaboring
there.

>
> Plus, I can easily write code that looks good without using a language
> that enforces indentation rules. Lisp's regular syntax lets Emacs do
> it for me with a simple C-M-a C-M-q. What could be easier?

If you need to edit and reformat other people's code with Emacs to find
it "looks good", you've made my point: code exists to be read, far more
than it's written, and Python's design choice to keep punctuation scarce
and unobtrusive obviates the need to edit and reformat code that way.


Alex

Bill Atkins

unread,
May 6, 2006, 9:02:03 PM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:

Now I see what the problem is here - you just don't know what you're
talking about. The identifier in Ken's and my samples *is* a single
character identifier. The vertical bars tell the Lisp reader that
what's between them is exempt from other reading rules.

(symbol-name '|(| ) => "("

(length (symbol-name '|(| )) => 1

> Are you ready to admit you were utterly wrong, and (while it is indeed
> true that my Lisp is rusty) there is nothing in this exchange to show
> it, as opposed to showing rustiness in your ability to understand
> English? Or shall we move from polite although total dissent right on
> to flamewars and namecalling?

Believe it or not, _you_ got it wrong.

> The point is, OF COURSE any design choice places limitations on future
> design choices; but some limitations are even DESIRABLE (a language
> where *every* single isolated character could mean anything whatsoever
> would not be "expressive", but rather totally unreadable) or at least
> utterly trivial (syntax-sugar level issues most typically are). Wilfully
> distorting some such limitation as meaning that one language "can scale"
> (when EVERY language inevitably has SOME such limitations) is not even
> funny, and clearly characterizes a polemist who is intent on proving a
> preconceived thesis, as opposed to an investigator with any real
> interest in ascertaining the truth of the matter.

Having to name a variable "paren" instead of "(" is not a serious
restriction. I can't think of a single situation where being able to
do so would be useful.

That said, raw, out-of-the-box Common Lisp can accomodate you if you
both a) need variables named "(" and b) are unwilling to use the bar
syntax. Simply redefine the parenthesis characters in the readtable
(a matter of four function calls) and get this abomination:

{let {{( 3}}
{+ ( 5}}

Lisp places no restrictions on you, even when your goal is as silly as
this one.

>> > Oh, is that the same Graham who writes:
>>
>> So we are going to skip the point I was making about Common Lisp being
>> so insanely extensible? By /application/ programmers? Hell, for all we
>> know CL does have a BDFL, we just do not need their cooperation.
>
> Yes, we are, because the debate about why it's better for Python (as a
> language used in real-world production systems, *SCALABLE* to extremely
> large-scale ones) to *NOT* be insanely extensible and mutable is a
> separate one -- Python's uniformity of style allows SCALABILITY of
> teams, and teams-of-teams, which is as crucial in the real world as
> obviously not understood by you (the law you misquoted was about adding
> personnel to a LATE project making it later -- nothing to do with how
> desirable it can be to add personnel to a large and growing collection
> of projects, scaling and growing in an agile, iterative way to meet
> equally growing needs and market opportunities).

Buh? The project doesn't have to be late for Brooks's law to hold;
adding programmers, so goes Brooks reasoning, will always increase the
time required to complete the project because of various communication
issues.

You haven't given much justification for the claim that Python is a
particularly "scalable" language. Sure, Google uses it, Graham gave
it some props somewhere in the middle of his notoriously pro-Lisp
writings, and even Norvig has said good things about it.

Fair enough. But what does Python offer above any garbage-collected
language that makes it so scalable?

>
>> OK, I propose a duel. We'll co-mentor this:
>>
>> http://www.lispnyc.org/wiki.clp?page=PyCells
>>
>> In the end Python will have a Silver Bullet, and only the syntax will
>> differ, because Python has a weak lambda, statements do not always
>> return values, it does not have macros, and I do not know if it has
>> special variables.
>>
>> Then we can just eyeball the code and see if the difference is
>> interesting. These abstract discussions do tend to loop.
>
> As a SummerOfCode mentor, I'm spoken for, and can't undertake to mentor
> other projects. I do agree that these discussions can be sterile, and
> I'll be glad to see what comes of your "pycells" project, but until then
> there's little we can do except agree to disagree (save that I'd like
> you to acknowledge my point above, regarding what exactly I had said and
> the fact that your alleged counterexample doesn't address at all what I
> had said -- but, I'll live even without such an acknowledgment).
>
>
> Alex

--

Paul Rubin

unread,
May 6, 2006, 9:05:39 PM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:
> > (|(| "your Lisp /is/ rusty.")
>
> Interestingly, the SECOND lisper to prove himself unable to read the
> very text he's quoting. Reread carefully, *USE THE ***SINGLE***
> CHARACTER* ... *AS AN ORDINARY IDENTIFIER*. What makes you read a
> ``PART OF'' that I had never written? You've shown how to use the
> characters as *PART* of an identifier [[and I believe it couldn't be the
> very start]], and you appear to believe that this somehow refutes my
> assertion?

The identifier there is a single paren. The vertical bars are used to
escape the paren, so that the reader doesn't get confused. The Pythonic
equivalent would be something like

\( = 5

where the backslash escapes the paren. In real Python you could say:

locals()['('] = 5

In Lisp you could get rid of the need to escape the paren if you
wanted, using suitable read macros. Whether that's a good idea is of
course a different matter.

> Yes, we are, because the debate about why it's better for Python (as a
> language used in real-world production systems, *SCALABLE* to extremely
> large-scale ones) to *NOT* be insanely extensible and mutable is a
> separate one -- Python's uniformity of style allows SCALABILITY of

> teams, and teams-of-teams, which is as crucial in the real world ...

My current take on Lisp vs Python is pretty close to Peter Norvig's
(http://www.norvig.com/python-lisp.html):

Python has the philosophy of making sensible compromises that make
the easy things very easy, and don't preclude too many hard
things. In my opinion it does a very good job. The easy things are
easy, the harder things are progressively harder, and you tend not
to notice the inconsistencies. Lisp has the philosophy of making
fewer compromises: of providing a very powerful and totally
consistent core. This can make Lisp harder to learn because you
operate at a higher level of abstraction right from the start and
because you need to understand what you're doing, rather than just
relying on what feels or looks nice. But it also means that in
Lisp it is easier to add levels of abstraction and complexity;
Lisp makes the very hard things not too hard.


>
> It's hard to attribute feelings to a programming language, but, if you
> really must, I'd say Pyton aspires to be *useful* -- if all you need is
> "just a scripting language", it will be content to be one for you, and
> if your need SCALE, well then, PYTHON IS SCALABLE, and will remain a
> *SIMPLE, CLEAN, LITTLE AND POWERFUL LANGUAGE* (letting nobody do
> anything INSANE to it;-) while scaling up to whatever size of project(s)
> you need (including systems so large that they redefine the very concept
> of "large scale" -- believe me, once in a while at a conference I make
> the mistake of going to some talk about "large scale" this or that, and
> invariably stagger out once again with the realization that what's
> "large scale" to the world tends to be a neat toy-sized throwaway little
> experiment to my current employer).

I've heard many times that your current employer uses Python for all
kinds of internal tools; I hadn't heard that it was used in Very Large
projects over there. I'd be interested to hear how that's been
working out, since the biggest Python projects I'd heard of before
(e.g. Zope) are, as you say, toy-sized throwaways compared to the
stuff done regularly over there at G.

Paul Rubin

unread,
May 6, 2006, 9:10:57 PM5/6/06
to
Bill Atkins <NOatki...@rpi.edu> writes:
> Fair enough. But what does Python offer above any garbage-collected
> language that makes it so scalable?

I think what used to be Lisp culture now uses the *ML languages or
Haskell. It's only throwbacks (which includes me sometimes) who still
use Lisp. I've been wanting for a while to do something in ML but
just haven't worked up enough steam for it. Python really does make
small and medium-sized tasks easy, even compared with Lisp. I'm still
reserving judgement about how it is at large tasks.

Ken Tilton

unread,
May 6, 2006, 9:11:38 PM5/6/06
to

The function name here:

(|(| "Boy, your Lisp is rusty")
-> Boy, your Lisp is rusty.

...is exactly one (1) character long.

(length (symbol-name'|(|) -> 1

Why? (symbol-name '|(|) -> "(" (No, the "s are not part of the name!)

If you want to argue about that, I will have to bring up the Lisp
readtable. Or did you forget that, too?

:)

Bill Atkins

unread,
May 6, 2006, 9:19:58 PM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:

> Bill Atkins <NOatki...@rpi.edu> wrote:
> ...
>> >
>> > Read again what I wrote: I very specifically said "ordinary
>> > *single-character* identifier" (as opposed to "one of many characters
>> > inside a multi-character identifier"). Why do you think I said
>> > otherwise, when you just quoted what I had written? (Even just a
>> > _leading_ ( at the start of an identifier may be problematic -- and just
>> > as trivial as having to give names to functions, of course, see below).
>>
>> Well, the same technique can obviously be used for:
>>
>> (let ((|(| 3)))
>> (+ |(| 4)))
>> ;; => 7
>>
>> The length of the identifier is irrelevant...
>
> But it cannot be a SINGLE CHARACTER, *just* the openparenthesis.
>
> Wow, it's incredible to me that you STILL can't read, parse and
> understand what I have so clearly expressed and repeated!

Read my other post. It's incredible that you STILL haven't considered
the possibility that you're just wrong.

>
>> Common Lisp does not support unnamed macros (how would these be
>> useful?), but nothing stops me from adding these. What use case do
>> you envision for anonymous macros?
>
> None, just like there is none for anonymous functions -- there is
> nothing useful I can do with anonymous functions that I cannot do with
> named ones.

Sure there are.

Does Python have any support for closures? If so, ignore this point.
But if not, what about examples like this:

(defun make-window (window observer)
;; initialization code here
(add-handler window 'close
(lambda (event)
(notify observer event)))
;; more code)

Being able to keep pass around state with functions is useful.

There are also cases where a function is so trivial that the simplest
way to describe it is with its source code, where giving it a name and
putting it at the beginning of a function is just distracting and
time-consuming. E.g.:

(remove-if (lambda (name)
(find #\- name :test #'char=))
list-of-names)

What's the sense of giving that function its own name? It's much
clearer to simply write it in place. Yes, it's _possible_ to use
named functions, but in this case its functionality is so simple that
it's clearer to simply type it in place. Why is this expressiveness a
bad thing, aside from its power to wreck an indentation-significant
language?

And I'm sure Kelly Clarkson sounds better *to most listeners* but that
doesn't mean she's a better musician than Hendrix. The fact that most
people are used to ALGOL-like languages does not mean that ALGOL-like
languages are more aesthetically pleasing on their own merits.

>>
>> Plus, I can easily write code that looks good without using a language
>> that enforces indentation rules. Lisp's regular syntax lets Emacs do
>> it for me with a simple C-M-a C-M-q. What could be easier?
>
> If you need to edit and reformat other people's code with Emacs to find
> it "looks good", you've made my point: code exists to be read, far more
> than it's written, and Python's design choice to keep punctuation scarce
> and unobtrusive obviates the need to edit and reformat code that way.

That's not what I'm saying at all. My point is that I can write a
function, counting on Emacs to keep it indented for me, and then after
making a series of changes to it, a mere C-M-a C-M-q takes them into
account and bam, no-fuss indenting.

Paul Rubin

unread,
May 6, 2006, 9:29:35 PM5/6/06
to
Bill Atkins <NOatki...@rpi.edu> writes:
> Does Python have any support for closures? If so, ignore this point.
> But if not, what about examples like this:
>
> (defun make-window (window observer)
> ;; initialization code here
> (add-handler window 'close
> (lambda (event)
> (notify observer event)))
> ;; more code)

Python has closures but you can only read the closed variables, not
write them.

> Being able to keep pass around state with functions is useful.
>
> There are also cases where a function is so trivial that the simplest
> way to describe it is with its source code, where giving it a name and
> putting it at the beginning of a function is just distracting and
> time-consuming. E.g.:
>
> (remove-if (lambda (name)
> (find #\- name :test #'char=))
> list-of-names)

If I read that correctly, in Python you could use

filter(list_of_names, lambda name: '-' not in name)
or
[name for name in list_of_names if '-' not in name]

Both of these have become more natural for me than the Lisp version.

I V

unread,
May 6, 2006, 9:31:13 PM5/6/06
to
On Sat, 06 May 2006 21:19:58 -0400, Bill Atkins wrote:
> There are also cases where a function is so trivial that the simplest
> way to describe it is with its source code, where giving it a name and
> putting it at the beginning of a function is just distracting and
> time-consuming. E.g.:
>
> (remove-if (lambda (name)
> (find #\- name :test #'char=))
> list-of-names)
>
> What's the sense of giving that function its own name? It's much
> clearer to simply write it in place. Yes, it's _possible_ to use
> named functions, but in this case its functionality is so simple that
> it's clearer to simply type it in place. Why is this expressiveness a
> bad thing, aside from its power to wreck an indentation-significant
> language?

Well, you can do that with python's current,
non-indentation-significance-wrecking, lambda syntax, so I don't think
that's a particularly persuasive example. Note also that the only
limitation python has on where you can define functions is that you can't
define them inside expressions (they have to be statements), so you could
define a named function right before the call to remove-if, which removes
some of the advantage you get from the lambda (that is, the function
definition is not very far from when it's used).

Actually, I think the limitation on python that is operative here is not
significant whitespace, but the distinction between statements and
expressions.

(crossposts trimmed)

Cameron MacKinnon

unread,
May 6, 2006, 9:30:00 PM5/6/06
to
Alex Martelli wrote:
> Ken Tilton <kent...@gmail.com> wrote:
> ...
>
>>True but circular, because my very point is that () was a great design
>>choice in that it made macros possible and they made CL almost
>>infinitely extensible, while indentation-sensitivity was a mistaken
>>design choice because it makes for very clean code (I agree
>>wholeheartedly) but placed a ceiling on its expressiveness.
>
>
> Having to give functions a name places no "ceiling on expressiveness",
> any more than, say, having to give _macros_ a name.

As was pointed out, if a Lisper wants anonymous macros, it's a cinch to
create a scheme to allow this. Whether or not it's a good idea in
general, if someone feels they need it, they can do it. An attitude like
that beats "No you can't do that, but you shouldn't do it anyway."

>>(defun |(| (aside) (format nil "Parenthetically speaking...~a." aside))
>>=> |(|
>>(|(| "your Lisp /is/ rusty.")
>>=> "Parenthetically speaking...your Lisp /is/ rusty.."

> Interestingly, the SECOND lisper to prove himself unable to read the


> very text he's quoting. Reread carefully, *USE THE ***SINGLE***
> CHARACTER* ... *AS AN ORDINARY IDENTIFIER*. What makes you read a
> ``PART OF'' that I had never written? You've shown how to use the
> characters as *PART* of an identifier [[and I believe it couldn't be the
> very start]], and you appear to believe that this somehow refutes my
> assertion?

Those vertical bars are just quoting characters, rather like the quoting
characters you'd undoubtedly need in Python to create a variable name
with a space in it.

> The point is, OF COURSE any design choice places limitations on future
> design choices; but some limitations are even DESIRABLE (a language
> where *every* single isolated character could mean anything whatsoever
> would not be "expressive", but rather totally unreadable) or at least
> utterly trivial (syntax-sugar level issues most typically are).

Yeah, a language like that would probably have some strange name like
"TeX." But we'd never know, because nobody would ever use it.


> Yes, we are, because the debate about why it's better for Python (as a
> language used in real-world production systems, *SCALABLE* to extremely
> large-scale ones) to *NOT* be insanely extensible and mutable is a
> separate one -- Python's uniformity of style allows SCALABILITY of
> teams, and teams-of-teams, which is as crucial in the real world as
> obviously not understood by you (the law you misquoted was about adding
> personnel to a LATE project making it later -- nothing to do with how
> desirable it can be to add personnel to a large and growing collection
> of projects, scaling and growing in an agile, iterative way to meet
> equally growing needs and market opportunities).

You seem to be using the most primitive definition of scalable that
there is, viz, if one coder can write one one page program in a day, two
coders can write two (or more likely 1.8) one page programs in a day.
Lispers tend to the view that *OF COURSE* most other decent languages
scale linearly, but what we want is force multipliers and exponential
scaling, not "throw money at it" scaling. Thus program writing programs,
program analyzing programs, compiled domain specific languages and great
quotes like

"I'd rather write programs to write programs than write programs."

"Programs that write programs are the happiest programs in the world."

Bill Atkins

unread,
May 6, 2006, 9:43:03 PM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:

> Yes, we are, because the debate about why it's better for Python (as a
> language used in real-world production systems, *SCALABLE* to extremely
> large-scale ones) to *NOT* be insanely extensible and mutable is a
> separate one -- Python's uniformity of style allows SCALABILITY of
> teams, and teams-of-teams, which is as crucial in the real world as
> obviously not understood by you (the law you misquoted was about adding
> personnel to a LATE project making it later -- nothing to do with how
> desirable it can be to add personnel to a large and growing collection
> of projects, scaling and growing in an agile, iterative way to meet
> equally growing needs and market opportunities).
>
> This specific debate grew from your misuse of "scalable" to mean or
> imply "a bazillion feechurz can [[and, implicitly, should]] be added to
> a language, and therefore anything that stands in the way of feechuritis
> is somehow holding the language back". That's bad enough, even though
> in its contextual misuse of "scalable" it breaks new ground, and I don't
> want to waste even more time re-treading *old* ground as to whether the
> "*insane* extensibility" afforded by macros is a good or a bad thing in
> a language to be used for real-world software production (as opposed to
> prototyping and research).

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*"ly
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.

For example, at work I recently had to generate PDF reports in PHP.
Certain sections would need to be indented, and then once they were
done, I wanted to move back out to the previous level of indentation.
I ended up with stuff like this (totally made up on the spot, but
conveys the general idea):

function out_main_text( ) {
$old_indent = $pdf->indentation;
$pdf->indent_to( $pdf->indentation + 4 );

out_header();
out_facts();

$pdf->set_indentation( $old_indent );
}

function out_header() {
$old_indent = $pdf->indentation;
$pdf->indent_to( $pdf->indentation + 4 );

$pdf->write( "some text" );

$pdf->set_indentation( $old_indent );
}

function out_facts() {
$old_indent = $pdf->indentation;
$pdf->indent_to( $pdf->indentation + 4 );

out_some_subsection();
out_another_subsection();

$pdf->set_indentation( $old_indent );
}


Obviously, this is very much pseudocode. The point is that managing
indentation was a hassle, because each of these subfunctions indents
to a new position. This can pretty clearly get tedious, and is
definitely error-prone, especially when you consider that different
groups of functions are called depending upon the input and that some
of the functions might return early.

But why should I have to worry about any of this? Why can't I do:

(with-indentation (pdf (+ (indentation pdf) 4))
(out-header)
(out-facts))

and then within, say out-facts:

(with-indentation (pdf (+ (indentation pdf) 4))
(write pdf "some text"))

More readable, and no bookkeeping to worry about. This is great! And
here's the macro:

(defmacro with-indentation (pdf new-value &body body)
(let ((old-indent (gensym)))
`(let ((,old-indent (indentation pdf)))
(unwind-protect (progn ,@body)
(setf (indentation pdf) ,old-indent)))))

Bam, all of that bookkeeping, all of those potential errors have taken
care of themselves. WITH-INDENTATION will expand into code that uses
UNWIND-PROTECT to ensure that the indentation always gets returned to
its previous value, even if an exception occurs or the code within
calls RETURN. The WITH-INDENTATION call sets up an environment where
there is a new indentation level in effect, and then cleans it up when
it's done. I can nest these to my heart's content.

Obviously, to someone totally unfamiliar with Lisp, the contents of
that macro are pretty daunting. But you're crazy if you argue that
having WITH-INDENTATION around isn't an improvement over manually
ensuring that indentation gets saved and restored for every function
call.

I could even generalize this (as CLISP does) to this:

(letf (((indentation pdf) (+ 4 (indentation pdf))))
(write "some text"))

Now I can use LETF to temporarily set any value at all for as long as
the code inside is running, and to restore it when it's done.

Macros rock.

Bill Atkins

unread,
May 6, 2006, 9:49:19 PM5/6/06
to
I V <wron...@gmail.com> writes:

You're right, I was replying to Alex's assertion that "there is


nothing useful I can do with anonymous functions that I cannot do with
named ones."

--

Alex Martelli

unread,
May 6, 2006, 10:23:11 PM5/6/06
to
Bill Atkins <NOatki...@rpi.edu> wrote:
...
> Believe it or not, _you_ got it wrong.

Acknowledged: Common Lisp is even MORE insane (note that the quote
"INSANELY extensible" is from Tilton) than I believed -- I'm pretty sure
that the Lisp dialects I used in 1979-1981 didn't go to such crazy
extremes, and neither did Scheme.

> Buh? The project doesn't have to be late for Brooks's law to hold;
> adding programmers, so goes Brooks reasoning, will always increase the
> time required to complete the project because of various communication
> issues.

And here is where we check if you're as gracious about admitting your
errors, as I am about mine. Brooks' law is:

"""Adding manpower to a late software project makes it later."""

These are Brooks' words, literally. OK so far?

Your claim, that adding programmers will ALWAYS increase the time, is
not just wrong, but utterly ridiculous. I can't put it better than the
wikipedia:
"""
Misconceptions

A commonly understood implication of Brooks' law is that it will be more
productive to employ a smaller number of very talented (and highly paid)
programmers on a project than to employ a larger number of less talented
programmers, since individual programmer productivity can vary greatly
between highly talented and efficient programmers and less talented
programmers. However, Brooks' law does not mean that starving a project
of resources by employing fewer programmers beyond a certain point will
get it done faster.
"""

Moreover, check out the research on Pair Programming: it scientifically,
empirically confirms that "two heads are better than one", which should
surprise nobody. Does this mean that there aren't "various
communication issues"? Of course there are, but there's no implied
weighting of these factors wrt the _advantages_ of having that second
person on the team (check the Pair Programming literature for long lists
of those advantages).

Only empirical research can tell us where the boundary is -- when
productivity is decreased by going from N to N+1. A lot depends on
imponderable issues such as personality meshes or clashes, leadership
abilities at hands, methodology used, etc. All of this is pretty
obvious, making your assertion that Brooks held otherwise actionable (as
libel, by Brooks) in many legislations.

As it happens, I also have examples in which adding (a few carefully
selected) people to a software project that WAS (slightly) late put that
project back on track and made it deliver successfully on schedule.
Definitely not the "pointy-haired boss" management style of "throwing
warm bodies at the problem" that Brooks was fighting against, but,
consider: the project's velocity has suffered because [a] the tech lead
has his personal (usually phenomenal) productivity hampered by a painful
condition requiring elective surgery to abate, and [b] nobody on the
team is really super-experienced in the intricacies of cryptography, yes
some very subtle cryptographic work turns out to be necessary. One day,
the tech lead calls in -- the pain has gotten just too bad, he's going
for surgery, and will be out of the fray for at least one week.

I still remember with admiration how my Director reacted to the
emergency: he suspended two other projects, deciding that, if THEIR
deadlines were broken, that would be a lesser damage to the company than
if this one slipped any further; and cherrypicked exactly two people --
one incredibly flexible "jack of all trades" was tasked with getting up
to speed on the project and becoming the acting TL for it, and an
excellent cryptography specialist was tasked to dig deep into the
project's cryptography needs and solve them pronto.

So, We Broke Brooks' Law -- the cryptographer did his magic, and
meanwhile the JOAT ramped up instantly and took the lead (kudos to the
Jack's skills, to the clarity and transparency of the previous TL's
work, to the agile methodologies employed throughout, AND to the
uniformity of style of one language which will stay unnamed here)... and
the project delivered on time and within budget. We had one extra
person (two "replacements" for one TL's absence), yet it didn't make the
late software project even later -- it brought it back on track
perfectly well.

I have many other experiences where _I_ was that JOAT (and slightly
fewer ones where I was the specialist -- broadly speaking, I'm more of a
generalist, but, as needs drive, sometimes I do of necessity become the
specialist in some obscure yet necessary technology... must have
happened a dozen times over the 30 years of my careers, counting
graduate school...).

This set of experiences in no way tarnishes the value of Brooks' Law,
but it does *put it into perspective*: done JUST RIGHT, by sufficiently
brilliant management, adding A FEW people with exactly the right mix of
skills and personality to a late software project CAN save the bacon,


> Fair enough. But what does Python offer above any garbage-collected
> language that makes it so scalable?

Uniformity of style, facilitating egoless programming; a strong cultural
bias for simplicity and clarity, and against cleverness and obscurity;
"just the right constraints" (well, mostly;-), such as immutability at
more or less the right spots (FP languages, with _everything_ immutable,
have an edge there IN THEORY... but in practice, using them most
effectively requires a rare mindset/skillset, making it hard to "scale
up" teams due to the extra difficulty of finding the right people).


Alex

Alex Martelli

unread,
May 6, 2006, 10:23:10 PM5/6/06
to
Bill Atkins <NOatki...@rpi.edu> wrote:
...
> Does Python have any support for closures? If so, ignore this point.

Ignored, since closures are there.

> Being able to keep pass around state with functions is useful.

Sure, but naming the functions doesn't hamper that.

> There are also cases where a function is so trivial that the simplest
> way to describe it is with its source code, where giving it a name and
> putting it at the beginning of a function is just distracting and
> time-consuming. E.g.:
>
> (remove-if (lambda (name)
> (find #\- name :test #'char=))
> list-of-names)
>
> What's the sense of giving that function its own name? It's much
> clearer to simply write it in place. Yes, it's _possible_ to use
> named functions, but in this case its functionality is so simple that
> it's clearer to simply type it in place. Why is this expressiveness a
> bad thing, aside from its power to wreck an indentation-significant
> language?

Offering several "equivalently obvious" approaches to performing just
one same task is bad for many reasons: you end up with a bigger language
(with all the attending ills) with no extra power, and you diminish the
style uniformity of programs written in the language, hampering the
ability of many people to work in the same codebase with no "ownership".

Like most all design principles, "there should be one, and preferably
only one, obvious way to perform a task" is an _ideal_, unattainable in
its perfect form in this sublunar world; but I find it an extremely
helpful guideline to design, and it does pervade Python (many of the
planned improvements for the future Python 3.0, which will be allowed to
be backwards-incompatible with 2.*, involve *removing* old features
made, in this sense, redundant by enhancements in recent versions; my
only beef here is that _not enough_ is scheduled for removal, alas).


> people are used to ALGOL-like languages does not mean that ALGOL-like
> languages are more aesthetically pleasing on their own merits.

"on their own merits" can't be the case -- as Wittgenstein pointed out,
we ARE talking about the natural history of human beings. A frequently
observed aestethic preference for X over Y says nothing about X and Y
``on their own merits'' (if such noumena could even be envisaged), but
it's empirically important about X and Y _when many human beings must
interact with them_.

Being "used to" some kinds of languages has nothing to do with it: when
I met Python I was most "used to" perl (and cognizant of Forth, scheme,
pre-common Lisp, sh, APL, ...), nevertheless Python immediately struck
me as allowing particularly beautiful coding. And I specifically named
many Lisp experts as acknowledging exacty the same thing, further
demolishing your "used to" strawman...


Alex

Alex Martelli

unread,
May 6, 2006, 10:23:12 PM5/6/06
to
Paul Rubin <http://phr...@NOSPAM.invalid> wrote:
...

> > Yes, we are, because the debate about why it's better for Python (as a
> > language used in real-world production systems, *SCALABLE* to extremely
> > large-scale ones) to *NOT* be insanely extensible and mutable is a
> > separate one -- Python's uniformity of style allows SCALABILITY of
> > teams, and teams-of-teams, which is as crucial in the real world ...
>
> My current take on Lisp vs Python is pretty close to Peter Norvig's
> (http://www.norvig.com/python-lisp.html):
>
> Python has the philosophy of making sensible compromises that make
> the easy things very easy, and don't preclude too many hard
> things. In my opinion it does a very good job. The easy things are
> easy, the harder things are progressively harder, and you tend not
> to notice the inconsistencies. Lisp has the philosophy of making
> fewer compromises: of providing a very powerful and totally
> consistent core. This can make Lisp harder to learn because you
> operate at a higher level of abstraction right from the start and
> because you need to understand what you're doing, rather than just
> relying on what feels or looks nice. But it also means that in
> Lisp it is easier to add levels of abstraction and complexity;
> Lisp makes the very hard things not too hard.

Sure -- however, Python makes them not all that hard either. Peter and
I have uncannily similar tastes -- just last month we happened to meet
at the same Arizona Pueblo-ancestral-people ruins-cum-museum (we both
independently chose to take vacation during spring break week to take
the kids along, we both love the Grand Canyon region, we both love
dwelling on ancient cultures, etc -- so I guess the coincidence wasn't
TOO crazy -- but it still WAS a shock to see Peter walk into the museum
at the same time I was walking out of it!-). Yes, it IS easier to add
complexity in Lisp; that's a good summary of why I prefer Python.


> I've heard many times that your current employer uses Python for all
> kinds of internal tools; I hadn't heard that it was used in Very Large
> projects over there. I'd be interested to hear how that's been
> working out, since the biggest Python projects I'd heard of before
> (e.g. Zope) are, as you say, toy-sized throwaways compared to the
> stuff done regularly over there at G.

Sorry, but I'm not authorized to speak for my employer nor to reveal
details of our internal systems -- hey, I cannot even say how many
servers we have; the "corporate approved metrics" is ``several
thousands''...;-). The most that managed to get approved for external
communication you'll find in the "Python at Google" presentation that
Chris di Bona and Greg Stein hold at times in various venues, and that's
not saying much -- good thing I'm not the one giving those
presentations, as I might find hard to stick to the approved line;-)


Alex

Alex Martelli

unread,
May 6, 2006, 10:23:12 PM5/6/06
to
Ken Tilton <kent...@gmail.com> wrote:
...
> Why? (symbol-name '|(|) -> "(" (No, the "s are not part of the name!)
>
> If you want to argue about that, I will have to bring up the Lisp
> readtable. Or did you forget that, too?

Mea culpa -- it wasn't in the Lisp(s) I used 25+ years ago, nor in
Scheme; I've never used Common Lisp in anger, and obviously "just
dabbling" gives one no good feel for how *INSANELY COMPLICATED* (or, if
you prefer, "insanely extensible") it truly is.

I personally think these gyrations are a good example of why Python, the
language that "fits your brain" and has simplicity among its goals, is
vastly superior for production purposes. Nevertheless, I admit I was
wrong!


Alex

Bill Atkins

unread,
May 6, 2006, 10:41:56 PM5/6/06
to
ale...@yahoo.com (Alex Martelli) writes:

> Bill Atkins <NOatki...@rpi.edu> wrote:
> ...
>> Believe it or not, _you_ got it wrong.
>
> Acknowledged: Common Lisp is even MORE insane (note that the quote
> "INSANELY extensible" is from Tilton) than I believed -- I'm pretty sure
> that the Lisp dialects I used in 1979-1981 didn't go to such crazy
> extremes, and neither did Scheme.
>
>> Buh? The project doesn't have to be late for Brooks's law to hold;
>> adding programmers, so goes Brooks reasoning, will always increase the
>> time required to complete the project because of various communication
>> issues.
>
> And here is where we check if you're as gracious about admitting your
> errors, as I am about mine. Brooks' law is:
>
> """Adding manpower to a late software project makes it later."""
>
> These are Brooks' words, literally. OK so far?

You are correct.

I posted too hastily. Here is what my paragraph ought to have said:

Buh? The project doesn't have to be late for Brooks's law to hold;

adding programmers *in the middle of a project*, so goes Brooks


reasoning, will always increase the time required to complete the
project because of various communication issues.

Agree?

Hahaha.

--

David Steuber

unread,
May 6, 2006, 10:57:23 PM5/6/06
to
"Xah Lee" <x...@xahlee.org> writes:

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

Why couldn't you keep this to comp.lang.python where it would almost
be relevant? Before I pulled down the headers, I thought maybe
something interesting was posted to comp.lang.lisp.

Followups set.

--
http://www.david-steuber.com/
1998 Subaru Impreza Outback Sport
2006 Honda 599 Hornet (CB600F) x 2 Crash & Slider
It's OK. You only broke your leg in three places. Walk it off.

Ken Tilton

unread,
May 6, 2006, 11:56:55 PM5/6/06
to

Alex Martelli wrote:
> Ken Tilton <kent...@gmail.com> wrote:
> ...
>
>>Why? (symbol-name '|(|) -> "(" (No, the "s are not part of the name!)
>>
>>If you want to argue about that, I will have to bring up the Lisp
>>readtable. Or did you forget that, too?
>
>
> Mea culpa -- it wasn't in the Lisp(s) I used 25+ years ago, nor in
> Scheme; I've never used Common Lisp in anger, and obviously "just
> dabbling" gives one no good feel for how *INSANELY COMPLICATED* (or, if
> you prefer, "insanely extensible") it truly is.
>

> I personally think these gyrations...

Please. You are the only one gyrating. I was joking with both |(| and
the fact that its length is one, no matter what our eyes tell us.

And I hope to god you were joking with the objection that a Lisper could
not name a variable "(". You would not say something that daft just to
win a Usenet debate, would you? Omigod...I think you did! I mean, look
at the way you were jumping up and down and shouting and accusing Bill
and me of not understanding English and... well, you are an uber tech
geek, what did i expect? All is forgiven. But...

It is vastly more disappointing that an alleged tech genius would sniff
at the chance to take undeserved credit for PyCells, something probably
better than a similar project on which Adobe (your superiors at
software, right?) has bet the ranch. This is the Grail, dude, Brooks's
long lost Silver Bullet. And you want to pass?????

C'mon, Alex, I just want you as co-mentor for your star quality. Of
course you won't have to do a thing, just identify for me a True Python
Geek and she and I will take it from there.

Here's the link in case you lost it:

http://www.lispnyc.org/wiki.clp?page=PyCells

:)

peace, kenny

ps. flaming aside, PyCells really would be amazingly good for Python.
And so Google. (Now your job is on the line. <g>) k

Tomasz Zielonka

unread,
May 7, 2006, 12:16:13 AM5/7/06
to
Alex Martelli wrote:
> ``An unneeded feature "cannot" be added (elegantly) in future releases
> of the language'' is just as trivial and acceptable for the unneded
> feature ``allow ( as an ordinary single-character identifier'' as for
> the unneded feature ``allow unnamed functions with all the flexibility
> of named ones''.

You can't be seriously claiming that these two features are equally
(un)needed. Anonymous functions come from the foundations of computer
science - Lamda Calculus. They are just a natural step on the road to
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.

On the other hand, what do you get by allowing ( as an indentifier?

Significant whitespace is a good thing, but the way it is designed in
Python it has some costs. Can't you simply acknowledge that?

Best regards
Tomasz

Alex Martelli

unread,
May 7, 2006, 12:18:00 AM5/7/06
to
Bill Atkins <NOatki...@rpi.edu> wrote:
...
> > And here is where we check if you're as gracious about admitting your
> > errors, as I am about mine. Brooks' law is:
> >
> > """Adding manpower to a late software project makes it later."""
> >
> > These are Brooks' words, literally. OK so far?
>
> You are correct.
>
> I posted too hastily. Here is what my paragraph ought to have said:
>
> Buh? The project doesn't have to be late for Brooks's law to hold;
> adding programmers *in the middle of a project*, so goes Brooks
> reasoning, will always increase the time required to complete the
> project because of various communication issues.
>
> Agree?

"What does one do when an essential software project is behind schedule?
Add manpower, naturally. As Figs 2.1 through 2.4 suggest, this may or
may not help".

How do you translate "may or may not help" into "will always increase
the time required", and manage to impute that translation to "Brooks
reasoning"? It *MAY* help -- Brooks says so very explicitly, and from
the Fig 2.4 he quotes just as explicitly you may infer he has in mind
that the cases in which it may help are those in which the project was
badly understaffed to begin with (a very common case, as the rest of the
early parts of chapter 2 explains quite adequately).

I could further critique Brooks for his ignoring specific personal
factors -- some extremely rare guys are able to get up to speed on an
existing project in less time, and requiring less time from those
already on board, than 99.9% of the human race (the JOAT in my previous
example); and, another crucial issue is that sometimes the key reason a
project is late is due to lack of skill on some crucial _specialty_, in
which case, while adding more "generic" programmers "may or may not
help" (in Brooks' words), adding just the right specialist (such as, the
cryptography expert in my previous example) can help a LOT. But, it
would be uncourteous to critique a seminal work in the field for not
anticipating such detailed, nuanced discussion (besides, in the next
chapter Brooks does mention teams including specialists, although if I
recall correctly he does not touch on the issue of a project which finds
out the need for a specialist _late_, as in this case). I'm still more
interested in critiquing your overgeneralization of Brooks' assertions
and reasoning.


Alex


Tomasz Zielonka

unread,
May 7, 2006, 12:36:08 AM5/7/06
to
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?

> Yes, we are, because the debate about why it's better for Python (as a
> language used in real-world production systems, *SCALABLE* to extremely
> large-scale ones) to *NOT* be insanely extensible and mutable is a
> separate one -- Python's uniformity of style allows SCALABILITY of
> teams, and teams-of-teams

I think this kind of language scalability is most important for Google,
see below.

> if your need SCALE, well then, PYTHON IS SCALABLE, and will remain a
> *SIMPLE, CLEAN, LITTLE AND POWERFUL LANGUAGE* (letting nobody do
> anything INSANE to it;-) while scaling up to whatever size of project(s)

> you need (including systems so large...

But honestly, isn't this scalability a result of the data processing
model you use, which is language independent? My point is that when you
have such a well scaling data processing model, most languages scale
well on the "data" and "load" axes, so you pick your language based on
how well it scales on the "teams" and "features" axes.

You seem to claim that there is something in Python that lets it scale
well on "data" and "load", and is not related to "teams" and "features",
and also not related to Google's data processing model. Can you tell
me what it is?

Best regards
Tomasz

Alex Martelli

unread,
May 7, 2006, 2:05:58 AM5/7/06
to
Tomasz Zielonka <tomasz....@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.org/wiki/Magic_number_(programming)> , section
"magic numbers in code".

> > Yes, we are, because the debate about why it's better for Python (as a
> > language used in real-world production systems, *SCALABLE* to extremely
> > large-scale ones) to *NOT* be insanely extensible and mutable is a
> > separate one -- Python's uniformity of style allows SCALABILITY of
> > teams, and teams-of-teams
>
> I think this kind of language scalability is most important for Google,
> see below.

It's definitely very important for Google, just as for most organization
doing software development on a large scale.


> > if your need SCALE, well then, PYTHON IS SCALABLE, and will remain a
> > *SIMPLE, CLEAN, LITTLE AND POWERFUL LANGUAGE* (letting nobody do
> > anything INSANE to it;-) while scaling up to whatever size of project(s)
> > you need (including systems so large...
>
> But honestly, isn't this scalability a result of the data processing
> model you use, which is language independent? My point is that when you
> have such a well scaling data processing model, most languages scale
> well on the "data" and "load" axes, so you pick your language based on
> how well it scales on the "teams" and "features" axes.

There's one more axis, the "size of software project" one (in some unit
of measure such as function points). That is partly related to
"language level", but it's not _just_ about that -- e.g., Ruby's
language level is basically the same as Python, but (in my modest
experience) it doesn't scale up quite as well to very large software
projects, as it's more prone to subtle coupling between modules (as it
makes it easy for one module to affect others indirectly, by making
modifications to fundamental globals such as "Object" and other built-in
types).


> You seem to claim that there is something in Python that lets it scale
> well on "data" and "load", and is not related to "teams" and "features",
> and also not related to Google's data processing model. Can you tell
> me what it is?

I don't think that (apart from whatever infrastructure Google may have
developed, and partly published in various whitepapers while partly
deciding to not discuss it publically) Python's scaling on "data" and
"load", to use your terminology, should be intrinsically different
(i.e., due to language differences) from that of other languages with
similar characteristics, such as, say, Ruby or Smalltalk.


Alex

Alex Martelli

unread,
May 7, 2006, 2:05:59 AM5/7/06
to
Tomasz Zielonka <tomasz....@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?

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.


> On the other hand, what do you get by allowing ( as an indentifier?

Nothing useful -- the parallel is exact.


> Significant whitespace is a good thing, but the way it is designed in
> Python it has some costs. Can't you simply acknowledge that?

I would have no problem "acknowledging" problems if I agreed that any
exist, but I do not agree that any exist. Please put your coding where
your mouth is, and show me ONE example that would be feasible in a
Python enriched by unlimited unnamed functions but is not feasible just
because Python requires naming such "unlimited" functions.


Alex

Tomasz Zielonka

unread,
May 7, 2006, 2:17:14 AM5/7/06
to
Alex Martelli wrote:
> Tomasz Zielonka <tomasz....@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.org/wiki/Magic_number_(programming)> , 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

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

Best regards
Tomasz

Serge Orlov

unread,
May 7, 2006, 2:17:34 AM5/7/06
to
Ken Tilton wrote:
> It is vastly more disappointing that an alleged tech genius would sniff
> at the chance to take undeserved credit for PyCells, something probably
> better than a similar project on which Adobe (your superiors at
> software, right?) has bet the ranch. This is the Grail, dude, Brooks's
> long lost Silver Bullet. And you want to pass?????
>
> C'mon, Alex, I just want you as co-mentor for your star quality. Of
> course you won't have to do a thing, just identify for me a True Python
> Geek and she and I will take it from there.
>
> Here's the link in case you lost it:
>
> http://www.lispnyc.org/wiki.clp?page=PyCells
>
> :)
>
> peace, kenny
>
> ps. flaming aside, PyCells really would be amazingly good for Python.
> And so Google. (Now your job is on the line. <g>) k

Perhaps I'm missing something but what's the big deal about PyCells?
Here is 22-lines barebones implementation of spreadsheet in Python,
later I create 2 cells "a" and "b", "b" depends on a and evaluate all
the cells. The output is

a = negate(sin(pi/2)+one) = -2.0
b = negate(a)*10 = 20.0

=================== spreadsheet.py ==================
class Spreadsheet(dict):
def __init__(self, **kwd):
self.namespace = kwd
def __getitem__(self, cell_name):
item = self.namespace[cell_name]
if hasattr(item, "formula"):
return item()
return item
def evaluate(self, formula):
return eval(formula, self)
def cell(self, cell_name, formula):
"Create a cell defined by formula"
def evaluate_cell():
return self.evaluate(formula)
evaluate_cell.formula = formula
self.namespace[cell_name] = evaluate_cell
def cells(self):
"Yield all cells of the spreadsheet along with current values
and formulas"
for cell_name, value in self.namespace.items():
if not hasattr(value, "formula"):
continue
yield cell_name, self[cell_name], value.formula

import math
def negate(x):
return -x
sheet1 = Spreadsheet(one=1, sin=math.sin, pi=math.pi, negate=negate)
sheet1.cell("a", "negate(sin(pi/2)+one)")
sheet1.cell("b", "negate(a)*10")
for name, value, formula in sheet1.cells():
print name, "=", formula, "=", value

Bill Atkins

unread,
May 7, 2006, 3:02:17 AM5/7/06
to
"Serge Orlov" <Serge...@gmail.com> writes:

I hope Ken doesn't mind me answering for him, but Cells is not a
spreadsheet (where did you get that idea?). It does apply the basic
idea of a spreadsheet to software - that is, instead of updating value
when some event occurs, you specify in advance how that value can be
computed and then you stop worrying about keeping it updated.

Incidentally, is this supposed to be an example of Python's supposed
"aesthetic pleasantness"? I find it a little hideous, even giving you
the benefit of the doubt and pretending there are newlines between
each function. There's nothing like a word wrapped in pairs of
underscores to totally ruin an aesthetic experience.

P.S. Is this really a spreadsheet? It looks like it's a flat
hashtable...

Bill Atkins

unread,
May 7, 2006, 3:07:37 AM5/7/06
to
Bill Atkins <NOatki...@rpi.edu> writes:

> Incidentally, is this supposed to be an example of Python's supposed
> "aesthetic pleasantness"? I find it a little hideous, even giving you
> the benefit of the doubt and pretending there are newlines between
> each function. There's nothing like a word wrapped in pairs of
> underscores to totally ruin an aesthetic experience.

I don't mean to suggest that your code in particular is hideous -
sorry if it came off that way. It's just that Python code seems a
disappointingly un-pretty after all the discussion about its beauty in
this thread.

Kay Schluehr

unread,
May 7, 2006, 3:29:57 AM5/7/06
to
Tomasz Zielonka wrote:

> On the other hand, what do you get by allowing ( as an indentifier?
>
> Significant whitespace is a good thing, but the way it is designed in
> Python it has some costs. Can't you simply acknowledge that?

One can admit this but what is it worth or how should those costs be
evaluated? This problem is unsolvable because we cannot agree on a
common standard of the value of PL design. All we can do is making the
decisions more visible. Obviously Lispers want the boundary between
application-level and interpreter-level programming as low as possible.
It is still present but making it invisible and expressing language
semantics through the language is regarded of high value. This makes
application level meta-programming as simple as it could be. Others
tend to separate the concerns/boundaries more strictly and standardize
the language while implementing all features regarded necessary for
application-level programming in a huge opaque runtime and a vast
amount of libraries. Application level metaprogramming is restricted to
runtime-reflection, metaclass-protocols, annotations etc. From this
point of view a programming language is basically an interface to a
virtual machine that is much like an operating system i.e. it supports
basic functions and hides complexity. This is the way Java and Python
have gone. The benefit of the latter approach lies not so much in
creating new language capabilities but considering the language as just
another application where requirement engineering and carefull design
can be done without sprawling in every possible direction ( see Forth
as an example for this tendency ). This way standard libraries (
"batteries included" ) become almost equal important and
"language-designer" is a job that is not once be done. This is roughly
my interpretation of GvRs "design view" on PLs that Xah Lee obviously
doesn't get - Xah is not important here, because he never gets anything
right but here are enough Lispers with quite some working brain cells
who seem to think that the best thing to do is giving a programmer
unlimited programming power.

Concluding remark: I'm not sure I want to defend one point of view all
the way long. Although not being a Lisper myself I can clearly see that
the DSL topic is hot these days and the pendulum oscillates into the
direction of more liberty. I have mixed feelings about this but I have
my own strong opinion of how those *can* fit into the CPython design
space and a working model that is to be published soon. As with the
dialectic double negation there is no return to a former position.

br...@sweetapp.com

unread,
May 7, 2006, 3:54:48 AM5/7/06
to
Bill Atkins wrote:
> Does Python have any support for closures? If so, ignore this point.
> But if not, what about examples like this:
>
> (defun make-window (window observer)
> ;; initialization code here
> (add-handler window 'close
> (lambda (event)
> (notify observer event)))
> ;; more code)
>
> 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
colleges (who is a reasonably average programmer), was completely
stumped by this:

>>> def right_partial(fn, *args):
... def inner(*innerargs):
... return fn(*(innerargs + args))
... return inner
...
>>> square = right_partial(pow, 2)
>>> square(5)
25
>>> cube = right_partial(pow, 3)
>>> cube(5)
125

(for those of you unfamiliar with Python, the '>>>' and '...' means
that I typed this in the interactive shell)

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.

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.

> There are also cases where a function is so trivial that the simplest
> way to describe it is with its source code, where giving it a name and
> putting it at the beginning of a function is just distracting and
> time-consuming. E.g.:
>
> (remove-if (lambda (name)
> (find #\- name :test #'char=))
> list-of-names)

There are some ways to write it in Python (if I understand the code):

# prefered


[name for name in list_of_names if '-' not in name]

OR:

# 2nd choice
def contains_no_dash(name):
return '-' not in name

filter(contains_no_dash, list_of_names)

# not recommended
filter(lambda name: return '-' not in name, list_of_names)


> What's the sense of giving that function its own name? It's much
> clearer to simply write it in place. Yes, it's _possible_ to use
> named functions, but in this case its functionality is so simple that
> it's clearer to simply type it in place. Why is this expressiveness a
> bad thing, aside from its power to wreck an indentation-significant
> language?

There are a few people in the Python community who think that unnamed
functions are inherently inferior to named ones because the name
provides documentation. The majority probably just don't care about the
issue at all. I will say that I am not sure that I know what your LISP
code does. However, even if you didn't understand the Python code in my
named-function version, the name "contains_no_dash" might provide you
with a small clue.

Cheers,
Brian

Serge Orlov

unread,
May 7, 2006, 4:08:23 AM5/7/06
to

It's written on the page linked above, second sentence: "Think of the
slots as cells in a spreadsheet, and you've got the right idea". I'm
not claiming that my code is full PyCell implementation.


> It does apply the basic
> idea of a spreadsheet to software - that is, instead of updating value
> when some event occurs, you specify in advance how that value can be
> computed and then you stop worrying about keeping it updated.

The result is the same. Of course, I don't track dependances in such a
tiny barebones example. But when you retrieve a cell you will get the
same value as with dependances. Adding dependances is left as an
exercise.

>
> Incidentally, is this supposed to be an example of Python's supposed
> "aesthetic pleasantness"?

Nope. This is an example that you don't need macros and
multi-statements. Ken writes: "While the absence of macros and
multi-statement lambda in Python will make coding more cumbersome". I'd
like to see Python code doing the same if the language had macros and
multi-statement lambda. Will it be more simple? More expressive?

> I find it a little hideous, even giving you
> the benefit of the doubt and pretending there are newlines between
> each function. There's nothing like a word wrapped in pairs of
> underscores to totally ruin an aesthetic experience.

I don't think anyone who is not a master of a language can judge
readability. You're just distracted by insignificant details, they
don't matter if you code in that language for many years. I'm not going
to tell you how Lisp Cell code looks to me ;)

> P.S. Is this really a spreadsheet? It looks like it's a flat
> hashtable...

Does it matter if it's flat or 2D?

br...@sweetapp.com

unread,
May 7, 2006, 4:21:11 AM5/7/06
to
Bill Atkins wrote:
> Buh? The project doesn't have to be late for Brooks's law to hold;
> adding programmers, so goes Brooks reasoning, will always increase the

> time required to complete the project because of various communication
> issues.

1. This is not what Brooks says. Brooks was talking about late
projects. Please provide a supporting quote if you wish to continue
to claim that "adding programmers will always increase the time
required to complete the project".
2. There has to be a mechanism where an organization can add
developers - even if it is only for new projects. Python advocates
would say that getting developers up to speed on Python is easy
because:

- it fits most programmers brains i.e. it is similar enough to
languages that most programmers have experience with and the
differences are usually perceived to beneficial (exception:
people from a Java/C/C++ background often perceive dynamic
typing as a misfeature and have to struggle with it)
- the language is small and simple
- "magic" is somewhat frowned upon in the Python community i.e.
most code can be taken at face value without needing to learn a
framework, mini-language, etc. (but I think that the Python
community could do better on this point)

I'm sure that smarter people can think of more points.

> Fair enough. But what does Python offer above any garbage-collected
> language that makes it so scalable?

See above point - you can more easily bring programmers online in your
organization because most programmers find Python easily learnable.
And, as a bonus, it is actually a pretty flexible, powerful language.

Cheers,
Brian

I V

unread,
May 7, 2006, 4:35:07 AM5/7/06
to
On Sat, 06 May 2006 23:05:59 -0700, Alex Martelli wrote:
> Tomasz Zielonka <tomasz....@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.

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.

Actually, defining them as unnamed functions via lambdas would be annoying
too, although not as annoying as using named functions - what you really
want is macros, so that what looks like a statement can be interpreted is
a piece of code to be executed later.

Here, for instance, is an article about using scheme (and, in particular,
macros), to produce a fairly elegant monad implementation:

http://okmij.org/ftp/Scheme/monad-in-Scheme.html

Bill Atkins

unread,
May 7, 2006, 4:53:20 AM5/7/06
to
"Serge Orlov" <Serge...@gmail.com> writes:

Unfortunately, it's *nothing* like a full PyCell implementation. I
explained what Cells is above. It is not merely a spreadsheet - it is
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
can transparently update them. It has to do with extending the object
system, not with merely setting tables in a hash and then retrieving
them.

>> It does apply the basic
>> idea of a spreadsheet to software - that is, instead of updating value
>> when some event occurs, you specify in advance how that value can be
>> computed and then you stop worrying about keeping it updated.
>
> The result is the same. Of course, I don't track dependances in such a
> tiny barebones example. But when you retrieve a cell you will get the
> same value as with dependances. Adding dependances is left as an
> exercise.
>
>>
>> Incidentally, is this supposed to be an example of Python's supposed
>> "aesthetic pleasantness"?
>
> Nope. This is an example that you don't need macros and
> multi-statements. Ken writes: "While the absence of macros and
> multi-statement lambda in Python will make coding more cumbersome". I'd
> like to see Python code doing the same if the language had macros and
> multi-statement lambda. Will it be more simple? More expressive?

FWIW (absolutely nothing, I imagine), here is my take on your
spreadsheet:

http://paste.lisp.org/display/19766

It is longer, for sure, but it does more and I haven't made any
attempt to stick to some minimum number of lines.

>> I find it a little hideous, even giving you
>> the benefit of the doubt and pretending there are newlines between
>> each function. There's nothing like a word wrapped in pairs of
>> underscores to totally ruin an aesthetic experience.
>
> I don't think anyone who is not a master of a language can judge
> readability. You're just distracted by insignificant details, they
> don't matter if you code in that language for many years. I'm not going
> to tell you how Lisp Cell code looks to me ;)
>
>> P.S. Is this really a spreadsheet? It looks like it's a flat
>> hashtable...
>
> Does it matter if it's flat or 2D?
>

Not really, because this is not Cells.

Frank Buss

unread,
May 7, 2006, 4:58:17 AM5/7/06
to
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 :-)

--
Frank Buss, f...@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de

Bill Atkins

unread,
May 7, 2006, 5:05:11 AM5/7/06
to
br...@sweetapp.com writes:

> Bill Atkins wrote:
>> Buh? The project doesn't have to be late for Brooks's law to hold;
>> adding programmers, so goes Brooks reasoning, will always increase the
>> time required to complete the project because of various communication
>> issues.
>
> 1. This is not what Brooks says. Brooks was talking about late
> projects. Please provide a supporting quote if you wish to continue
> to claim that "adding programmers will always increase the time
> required to complete the project".

The "always" in my claim should not be there, I admit. Brooks didn't
claim that.

I refer you to pages 17 - 18 of The Mythical Man-Month:

Since software construction is inherently a systems effort - an
exercise in complex interrelationships - communication effort is
great...Adding more men then lengthens, not shortens, the schedule.

It is totally absurd to assume that, simply because a project has not
yet passed its deadline, it will somehow become immune to the kinds of
things Brooks is talking about. His thesis is that adding programmers
to an already-in-progress project will cause a delay, because the new
programmers must be brought up to speed. It does not matter if the
project is eight weeks late or has only been active for a month. This
issue still remains:

The two new men, however competent and however quickly trained, will
require training in the task by one of the experienced men. If this
takes a month, 3 man-months will have been devoted to work not in
the original estimate. (p. 24, TMM-M)

Brooks's Law mentions only late projects, but the rest of his
discussion applies to adding programmers in the middle of *any*
project.

Is this really so radical an idea?

> 2. There has to be a mechanism where an organization can add
> developers - even if it is only for new projects. Python advocates

Obviously.

> would say that getting developers up to speed on Python is easy
> because:
>
> - it fits most programmers brains i.e. it is similar enough to
> languages that most programmers have experience with and the
> differences are usually perceived to beneficial (exception:
> people from a Java/C/C++ background often perceive dynamic
> typing as a misfeature and have to struggle with it)
> - the language is small and simple
> - "magic" is somewhat frowned upon in the Python community i.e.
> most code can be taken at face value without needing to learn a
> framework, mini-language, etc. (but I think that the Python
> community could do better on this point)

These are not things I look for in a programming language.

>
> I'm sure that smarter people can think of more points.
>
>> Fair enough. But what does Python offer above any garbage-collected
>> language that makes it so scalable?
>
> See above point - you can more easily bring programmers online in your
> organization because most programmers find Python easily learnable.
> And, as a bonus, it is actually a pretty flexible, powerful language.
>
> Cheers,
> Brian
>

--

Dr.Ruud

unread,
May 7, 2006, 5:20:02 AM5/7/06
to
Paul Rubin schreef:

> a cryptographic PRNG seeded with good entropy is supposed to be
> computationally indistinguishable from physical randomness

Doesn't your "good entropy" include "physical randomness"?

--
Affijn, Ruud

"Gewoon is een tijger."


Chris Uppal

unread,
May 7, 2006, 5:35:15 AM5/7/06
to
Bill Atkins wrote:

> But why should I have to worry about any of this? Why can't I do:
>
> (with-indentation (pdf (+ (indentation pdf) 4))
> (out-header)
> (out-facts))
>
> and then within, say out-facts:
>
> (with-indentation (pdf (+ (indentation pdf) 4))
> (write pdf "some text"))
>
> More readable, and no bookkeeping to worry about. This is great! And
> here's the macro:
. [...]

Can you explain to a non-Lisper why macros are needed for this ? I'm a
Smalltalker, and Smalltalk has no macros, nor anything like 'em, but the
equivalent of the above in Smalltalk is perfectly feasible, and does not
require a separate layer of semantics (which is how I think of true macros).

aPdf
withAdditionalIndent: 4
do: [ aPdf writeHeader; writeFacts ].

and

aPdf
withAdditionalIndent: 4
do: [ aPdf write: '... some text...' ].

Readers unfamiliar with Smalltalk may not find this any easier to read that
your Lisp code, but I can assure them that to any Smalltalker that code would
be both completely idiomatic and completely transparent. (Although I think a
fair number of Smalltalkers would choose to use a slightly different way of
expressing this -- which I've avoided here only in order to keep things
simple).


> Macros rock.

I have yet to be persuaded of this ;-)

-- chris


Patrick May

unread,
May 7, 2006, 5:59:04 AM5/7/06
to
ale...@yahoo.com (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.

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc. | The experts in large scale distributed OO
| systems design and implementation.
p...@spe.com | (C++, Java, Common Lisp, Jini, CORBA, UML)

br...@sweetapp.com

unread,
May 7, 2006, 6:04:00 AM5/7/06
to
Bill Atkins wrote:
> br...@sweetapp.com writes:
>
>> Bill Atkins wrote:
>>> Buh? The project doesn't have to be late for Brooks's law to hold;
>>> adding programmers, so goes Brooks reasoning, will always increase the
>>> time required to complete the project because of various communication
>>> issues.
>> 1. This is not what Brooks says. Brooks was talking about late
>> projects. Please provide a supporting quote if you wish to continue
>> to claim that "adding programmers will always increase the time
>> required to complete the project".
>
> The "always" in my claim should not be there, I admit. Brooks didn't
> claim that.
>
> I refer you to pages 17 - 18 of The Mythical Man-Month:
>
> Since software construction is inherently a systems effort - an
> exercise in complex interrelationships - communication effort is
> great...Adding more men then lengthens, not shortens, the schedule.
>
> It is totally absurd to assume that, simply because a project has not
> yet passed its deadline, it will somehow become immune to the kinds of
> things Brooks is talking about.

Right. But only when a project is late does Brooks say that adding
programmers will always make it later (the claim that you made). In
other cases he says "Add manpower, ..., this may or may not help". That
seems intuitively obvious to me. If the programmers being added require
extensive training [1] by the team to become productive, and their
contribution to the project will be smaller than that amount (e.g. it
is a small or nearly completed project) then their net impact on the
project will be negative. If, OTOH, the new programmers are able to
quickly understand the project/organization/technologies and almost
immediately make useful contributions, then they are likely to have a
net positive impact.

>> 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 "scaleability". I'm sure that he will correct me
if I am wrong.

>> [list of proposed Python advantages snipped]


> These are not things I look for in a programming language.

Fair enough. That doesn't mean that these advantages aren't important
to others or, in some situations, objectively important in the survival
of a project/organization.

For example, imagine that Google had used language X instead of Python
to develop their tools (assume they started with 10 expert X
programmers). Expert X programmers are Y percent more productive than
expert Python programmers. Now Google wants to grow aggressively and
needs 100 times more developer productivity (and expects to need even
more productivity in the future). If it is harder to find/hire/create
experts in language X than Python, then Y will have to be large to make
language X a better choice than Python. Also, if non-expert Python
programmers can be more productive than non-expert X programmers, then
Python also has an advantage. Eric Raymond claims that Python has very
high initial productivity and that becoming an expert is fairly easy.

BTW, I'm not saying that Common Lisp fits X in this example.

Cheers,
Brian

[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
time needed to learn to coordinate with the rest of the team.

br...@sweetapp.com

unread,
May 7, 2006, 6:10:26 AM5/7/06
to
Patrick May wrote:
> ale...@yahoo.com (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.

Cheers,
Brian

Bill Atkins

unread,
May 7, 2006, 6:39:40 AM5/7/06
to
br...@sweetapp.com writes:

There is another essay in TMM-M that discusses the difference between
essential complexity and accidental complexity. You might think
Python is really swell, and I might think Common Lisp is really swell,
but at the heart of it there is still what Brooks calls "essential
complexity" - the difficulty of mapping a complicated real-world
situation into a model a computer can handle. So I think using Python
or Lisp will help get rid of a lot of the accidental complexity that
would arise from using C or C++, but it can only do so much; there is
still a lot of complexity involved even in projects that are written
in very high-level languages. IMHO.

>>> 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 "scaleability". I'm sure that he will correct me
> if I am wrong.
>
>>> [list of proposed Python advantages snipped]
>> These are not things I look for in a programming language.
>
> Fair enough. That doesn't mean that these advantages aren't important
> to others or, in some situations, objectively important in the survival
> of a project/organization.

Sure, agreed.

> For example, imagine that Google had used language X instead of Python
> to develop their tools (assume they started with 10 expert X
> programmers). Expert X programmers are Y percent more productive than
> expert Python programmers. Now Google wants to grow aggressively and
> needs 100 times more developer productivity (and expects to need even
> more productivity in the future). If it is harder to find/hire/create
> experts in language X than Python, then Y will have to be large to make
> language X a better choice than Python. Also, if non-expert Python
> programmers can be more productive than non-expert X programmers, then
> Python also has an advantage. Eric Raymond claims that Python has very
> high initial productivity and that becoming an expert is fairly easy.
>
> BTW, I'm not saying that Common Lisp fits X in this example.
>
> Cheers,
> Brian
>
> [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
> time needed to learn to coordinate with the rest of the team.
>

--

Bill Atkins

unread,
May 7, 2006, 6:38:34 AM5/7/06
to
"Chris Uppal" <chris...@metagnostic.REMOVE-THIS.org> writes:

To be honest, all I know about Smalltalk are the parts of it that were
grafted onto Ruby. But if your example is doing the same as my code,
then I can't say that there's much of an advantage to using a macro
over this.

>
>> Macros rock.
>
> I have yet to be persuaded of this ;-)

My favorite macro is ITERATE, which was written at MIT to add a
looping mini-language to CL. There is a macro called LOOP that is
part of Common Lisp, but ITERATE improves upon it in lots of ways.

The cool thing about ITERATE is that it lets you express looping
concepts in a language designed explicitly for such a purpose, e.g.

(iter (for x in '(1 3 3))
(summing x)) => 7

(iter (for x in '(1 -3 2))
(finding x maximizing (abs x))) => -3

(iter (for x in '(a b c 1 d 3 e))
(when (symbolp x)
(collect x))) => (a b c d e)

This is a tiny, tiny chunk of what ITERATE offers and of the various
ways these clauses can be combined. But it should be obvious that
being able to express loops this way is going to make your code much
more concise and more readable.

But it gets even better: since ITERATE is a macro, the code passed to
it is error-checked and analyzed at compile-time, and then converted
to primitive Lisp forms - also at compile-time. What this means is
you get all this extra expressive power at absolutely no runtime cost.

At the risk of causing brains to explode, here is what the third ITER
form expands into:

(LET* ((#:LIST17 NIL)
(X NIL)
(#:RESULT16 NIL)
(#:END-POINTER18 NIL)
(#:TEMP19 NIL))
(BLOCK NIL
(TAGBODY
(SETQ #:LIST17 '(A B C 1 D 3 E))
LOOP-TOP-NIL
(IF (ATOM #:LIST17) (GO LOOP-END-NIL))
(SETQ X (CAR #:LIST17))
(SETQ #:LIST17 (CDR #:LIST17))
(IF (SYMBOLP X)
(PROGN
NIL
(PROGN
(SETQ #:TEMP19 (LIST X))
(SETQ #:END-POINTER18
(IF #:RESULT16
(SETF (CDR #:END-POINTER18) #:TEMP19)
(SETQ #:RESULT16 #:TEMP19)))
#:RESULT16))
NIL)
(GO LOOP-TOP-NIL)
LOOP-END-NIL)
#:RESULT16))

This is obviously not something any sane programmer would sit down and
write just to get an efficient loop. But this code is highly tuned;
for instance, it tracks the end of the list it's building up to save
time. I, as a programmer, get all this expressiveness and efficiency
for free. I think that's awesome.

There are lots more examples of macros. My second favorite macro to
use as an example are Peter Seibel's macros for processing binary files:

http://gigamonkeys.com/book/practical-parsing-binary-files.html

He builds a set of macros so that in the next chapter he can define an
ID3 tag reader and writer with:

(define-tagged-binary-class id3v2.3-frame ()
((id (frame-id :length 4))
(size u4)
(flags u2)
(decompressed-size (optional :type 'u4 :if (frame-compressed-p flags)))
(encryption-scheme (optional :type 'u1 :if (frame-encrypted-p flags)))
(grouping-identity (optional :type 'u1 :if (frame-grouped-p flags))))
(:dispatch (find-frame-class id)))

The macro generates code for methods that let you read and write ID3
files in a structured way - and it can of course be used for any other
kind of binary file. The :dispatch parameter at the end will jump to
a different class to parse the rest based on the result of executing
the expression attached to it.

There are lots more, too. Lispers and their environments are often
much more proficient at writing and modifying s-expressions than HTML,
so there are neat HTML generation macros like:

(<:html (<:head (<:title "foo"))
(<:body (<:b :style "font-color: orange" "hello!")))

This example uses Marco Baringer's YACLML package. Again, we get this
expressiveness (no need to use closing tags, the ability to let our
editor indent or transpose tags and so on) for free. At compile-time,
these macros all get parsed down to much, much simpler code:

(PROGN
(WRITE-STRING "<html>
<head>
<title>
foo</title>
</head>
<body>
<b style=\"font-color: orange\">
"
*YACLML-STREAM*)
SOME-VARIABLE
(WRITE-STRING "</b>
</body>
</html>
"
*YACLML-STREAM*))

All of the tags have been streamlined down to a single stream
constant. Again we get more expressiveness but still keep killer
efficiency.

There are still more! _On Lisp_ has a lot of interesting ones, like
an embedded Prolog interpreter and compiler:

(<-- (father billsr billjr))
(?- (father billsr ?))

? = billjr

We have Marco Baringer's ARNESI package, which adds continuations to
Common Lisp through macros, even though Common Lisp does not include
them. The Common Lisp Object System (CLOS), although now part of
Common Lisp, could be (and originally was) built entirely from macros
[1]. That should give a rough idea of their power.

There are macros like DESTRUCTURING-BIND, which is part of Common
Lisp, but could just as easily have been written by you or me. It
handles destructuring of lists. A very simple case:

(destructuring-bind (a b c) '(1 2 3)
(+ a b c)) => 6

I hope this gives you a general idea of the coolness of macros.

[1] Strictly speaking, there are a couple of things that the Lisp
implementation has to take care of, but they are not absolutely
essential features.

Bill Atkins

unread,
May 7, 2006, 6:45:51 AM5/7/06
to
Bill Atkins <NOatki...@rpi.edu> writes:

> There are still more! _On Lisp_ has a lot of interesting ones, like
> an embedded Prolog interpreter and compiler:
>
> (<-- (father billsr billjr))
> (?- (father billsr ?))
>
> ? = billjr

Actually, these might not be implemented as macros.

Thomas F. Burdick

unread,
May 7, 2006, 6:55:50 AM5/7/06
to
Ken Tilton <kent...@gmail.com> writes:

> As for:
>
> > At a syntax-sugar
> > level, for example, Lisp's choice to use parentheses as delimiter means
> > it's undesirable, even unfeasible, to use the single character '(' as an
> > ordinary identifier in a future release of the language.
>
> (defun |(| (aside) (format nil "Parenthetically speaking...~a." aside))
> => |(|
> (|(| "your Lisp /is/ rusty.")
> => "Parenthetically speaking...your Lisp /is/ rusty.."
>
> :) No, seriously, is that all you can come up with?

Well, you have to quote your (s-as-identifiers. I tried a goofy hack
of a reader macro for ( to make this parse:

(let (( ( 10))) ( ))

[The spaces are just for readability, not necessary]

Alas, short of cps-transforming the whole reader, I can't see a
reasonable way to get that to parse as a single sexp that, when
evaluated, returns 10. What my reader macro gave me was five sexps:

\(, LET, \(, ((10)), NIL

I'll follow up with the Lisp code (on c.l.l only), in case I'm missing
something simple.

> OK, I propose a duel. We'll co-mentor this:
>
> http://www.lispnyc.org/wiki.clp?page=PyCells
>
> In the end Python will have a Silver Bullet, and only the syntax will
> differ, because Python has a weak lambda, statements do not always
> return values, it does not have macros, and I do not know if it has
> special variables.

I have no idea what the big problem with a multi-line lambda is in
Python, but I wonder if Cells wouldn't run against the same thing. I
often pass around anonymous formulas that eventually get installed in
a slot. Seems annoying to have to name every formula with a
labels-like mechanism.

Thomas F. Burdick

unread,
May 7, 2006, 7:03:51 AM5/7/06
to
t...@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> Well, you have to quote your (s-as-identifiers. I tried a goofy hack
> of a reader macro for ( to make this parse:
>
> (let (( ( 10))) ( ))
>
> [The spaces are just for readability, not necessary]
>
> Alas, short of cps-transforming the whole reader, I can't see a
> reasonable way to get that to parse as a single sexp that, when
> evaluated, returns 10. What my reader macro gave me was five sexps:
>
> \(, LET, \(, ((10)), NIL
>
> I'll follow up with the Lisp code (on c.l.l only), in case I'm missing
> something simple.

And here it is. To keep it minimally simple, it doesn't handle dotted
pair notation. Also, unread-string is an ugly sbcl-specific hack that
causes this code to only work there, on string-streams. Whatever,
those are things that can easily be solved if someone can see how to
make this read the "right" parens as symbols.

(defun \(-reader (stream char)
(declare (ignore char))
(let ((contents (slurp stream)))
(unread-string stream contents)
(labels ((eof (error)
(when (eql (stream-error-stream error) stream)
(unread-string stream contents)
(return-from \(-reader (intern "(")))))
(handler-bind ((end-of-file #'eof))
(loop for next-char = (next-nonwhite-char stream)
until (char= next-char #\))
do (unread-string stream (string next-char))
collect (read stream t nil t))))))

(defun make-kwazy-readtable ()
(let ((rt (with-standard-io-syntax (copy-readtable))))
(set-macro-character #\( #'\(-reader nil rt)
(set-macro-character #\) #'\)-reader nil rt)
rt))

(defvar *kwazy-readtable* (make-kwazy-readtable))

(defun slurp (stream)
(with-output-to-string (out)
(loop for c = (read-char stream nil nil t)
while c
do (write-char c out))))

(defun next-nonwhite-char (stream)
(loop for c = (read-char stream t nil t)
unless (find c #(#\Space #\Tab #\Newline #\Return))
return c))

;; Evil hack -- the correct way to do this is with a gray stream or
;; simple stream, but this is easier for a simple prototype, at least
;; on SBCL ;-)
(defun unread-string (stream string)
(declare (type sb-impl::string-input-stream stream))
(macrolet ((get-string (&rest r) (cons 'sb-impl::string-input-stream-string r))
(get-current (&rest r) (cons 'sb-impl::string-input-stream-current r))
(get-end (&rest r) (cons 'sb-impl::string-input-stream-end r)))
(let ((left (subseq (get-string stream)
(get-current stream)
(get-end stream))))
(setf (get-string stream) (concatenate 'string string left)
(get-current stream) 0
(get-end stream) (+ (length string) (length left)))
stream)))

Ken Tilton

unread,
May 7, 2006, 10:05:12 AM5/7/06
to

Serge Orlov wrote:
> Ken Tilton wrote:
>
>>It is vastly more disappointing that an alleged tech genius would sniff
>>at the chance to take undeserved credit for PyCells, something probably
>>better than a similar project on which Adobe (your superiors at
>>software, right?) has bet the ranch. This is the Grail, dude, Brooks's
>>long lost Silver Bullet. And you want to pass?????
>>
>>C'mon, Alex, I just want you as co-mentor for your star quality. Of
>>course you won't have to do a thing, just identify for me a True Python
>>Geek and she and I will take it from there.
>>
>>Here's the link in case you lost it:
>>
>> http://www.lispnyc.org/wiki.clp?page=PyCells
>>
>>:)
>>
>>peace, kenny
>>
>>ps. flaming aside, PyCells really would be amazingly good for Python.
>>And so Google. (Now your job is on the line. <g>) k
>
>

> Perhaps I'm missing something...

yes, but do not feel bad, everyone gets confused by the /analogy/ to
spreadsheets into thinking Cells /is/ a spreadsheet. In fact, for a
brief period I swore off the analogy because it was so invariably
misunderstood. Even Graham misunderstood it.

But it is such a great analogy! <sigh>

> but what's the big deal about PyCells?
> Here is 22-lines barebones implementation of spreadsheet in Python,
> later I create 2 cells "a" and "b", "b" depends on a and evaluate all
> the cells. The output is
>
> a = negate(sin(pi/2)+one) = -2.0
> b = negate(a)*10 = 20.0

Very roughly speaking, that is supposed to be the code, not the output.
So you would start with (just guessing at the Python, it has been years
since I did half a port to Python):

v1 = one
a = determined_by(negate(sin(pi/2)+v1)
b = determined_by(negate(a)*10)
print(a) -> -2.0 ;; this and the next are easy
print(b) -> 20
v1 = two ;; fun part starts here
print(b) -> 40 ;; of course a got updated, too

The other thing we want is (really inventing syntax here):

on_change(a,new,old,old-bound?) print(list(new, old, old-bound?)

Then the print statements Just Happen. ie, It is not as if we are just
hiding computed variables behind syntax and computations get kicked off
when a value is read. Instead, an underlying engine propagates any
assignment throughout the dependency graph before the assignment returns.

My Cells hack does the above, not with global variables, but with slots
(data members?) of instances in the CL object system. I have thought
about doing it with global variables such as a and b above, but never
really seen much of need, maybe because I like OO and can always think
of a class to create of which the value should be just one attribute.

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.

Ken Tilton

unread,
May 7, 2006, 10:36:00 AM5/7/06
to

Well it's the Miller Analogy Test, isn't it? <g> Very easy to leave out
a level of abstraction. Like I said in my other reply, /everyone/ leaves
this level out.

Your spreadsheet does not have slots ruled by functions, it has one slot
for a dictionary where you store names and values/formulas.

Go back to your example and arrange it so a and b are actual slots (data
members? fields?) of the spreadsheet class. You can just stuff numbers in a:

sheet1.a = 42

but b should be somehow associated with a rule when sheet1 is created.
As I said in the other post, also associate an on-change callback with
slots a and b.

When you create sheet1:

sheet1 = Spreadsheet(a=42,b=pow(self.a,2))

You should see the callbacks for a and b fire. Then when you:

sheet1.a = 7

You should see them fire again (and each should see old and new values
as one would hope).

The fun part is when the rule associated with b is just:

self.b = somefunction(self)

and somefunction happens to access slot a and it all still works.

One important feature above is that the rule is associated with the slot
when the instance is created, and different instances can have different
ruls for the same slot. In effect, classes become programmable, hence
more reusable -- without this one is forever subclassing to satisfy
different functional requirements.

>
>
>
>>It does apply the basic
>>idea of a spreadsheet to software - that is, instead of updating value
>>when some event occurs, you specify in advance how that value can be
>>computed and then you stop worrying about keeping it updated.
>
>
> The result is the same.

Hopefully I have made clear the different levels. With your example, all
variables exist only in the universe of the Spreadsheet class. So you
have a good start on an /interpreter/ that works like the /extension/
Cells provide to Common Lisp.

Do you see the difference?

Apologies for all the pseudo-Python above, btw.

btw, I am not saying Python cannot do PyCells. I got pretty far on a
port from CL to Python before losing interest. You just take your code
above and move it to the metaclass level and, yes, track dependencies,
etc etc etc.

When that is done we can look at a working example and see how well
Python fared without macros and full-blown lambda.


hth, kenny

Ken Tilton

unread,
May 7, 2006, 11:18:43 AM5/7/06
to

Thomas F. Burdick wrote:
> Ken Tilton <kent...@gmail.com> writes:
>
>
>>As for:
>>
>>
>>> At a syntax-sugar
>>>level, for example, Lisp's choice to use parentheses as delimiter means
>>>it's undesirable, even unfeasible, to use the single character '(' as an
>>>ordinary identifier in a future release of the language.
>>
>>(defun |(| (aside) (format nil "Parenthetically speaking...~a." aside))
>>=> |(|
>>(|(| "your Lisp /is/ rusty.")
>>=> "Parenthetically speaking...your Lisp /is/ rusty.."
>>
>>:) No, seriously, is that all you can come up with?
>
>
> Well, you have to quote your (s-as-identifiers. I tried a goofy hack
> of a reader macro for ( to make this parse:
>
> (let (( ( 10))) ( ))
>
> [The spaces are just for readability, not necessary]
>
> Alas, short of cps-transforming the whole reader, I can't see a
> reasonable way to get that to parse as a single sexp that, when
> evaluated, returns 10. What my reader macro gave me was five sexps:
>
> \(, LET, \(, ((10)), NIL
>
> I'll follow up with the Lisp code (on c.l.l only), in case I'm missing
> something simple.

Stop, you are scaring the pythonistas. Even Alex thought I was serious
with (|(| "Hi mom"). Ouch that is hard to type.


>
>
>>OK, I propose a duel. We'll co-mentor this:
>>
>> http://www.lispnyc.org/wiki.clp?page=PyCells
>>
>>In the end Python will have a Silver Bullet, and only the syntax will
>>differ, because Python has a weak lambda, statements do not always
>>return values, it does not have macros, and I do not know if it has
>>special variables.
>
>
> I have no idea what the big problem with a multi-line lambda is in
> Python, but I wonder if Cells wouldn't run against the same thing. I
> often pass around anonymous formulas that eventually get installed in
> a slot. Seems annoying to have to name every formula with a
> labels-like mechanism.

(a) Right.

(b) Bloated syntax will hurt in a linear way. the decomposition of
application complexity into so many tractable small rules is a nonlinear
win. (ok, painful coding of X does diminish ones use of X, but Cells
force one to use Cells everywhere or not at all, so it comes with its
own press gang, er, discipline.)

(c) (b) might convince GvR to fix (a)

Ken Tilton

unread,
May 7, 2006, 11:37:13 AM5/7/06
to

Ken Tilton wrote:
>
>>
>> a = negate(sin(pi/2)+one) = -2.0
>> b = negate(a)*10 = 20.0
>
>
> Very roughly speaking, that is supposed to be the code, not the output.
> So you would start with (just guessing at the Python, it has been years
> since I did half a port to Python):
>
> v1 = one

Sorry, only later did I realize "one" was going in as a named
spreadsheet Cell. I thought maybe Python was a bit of a super-cobol and
had one as a keyword. <g>

kenny

Ken Tilton

unread,
May 7, 2006, 12:36:12 PM5/7/06
to

here it is:

(in-package :cells)

(defmodel useless () ;; defmodel is CLOS defclass plus Cells wiring
((one :initform nil :accessor one :initarg :one)
(a :initform nil :accessor a :initarg :a)
(b :initform nil :accessor b :initarg :b)))

;; defobserver defines a CLOS method just the right way

(defobserver one (self new-value old-value old-value-bound-p)
(print (list :observing-one new-value old-value old-value-bound-p)))

(defobserver a (self new-value old-value old-value-bound-p)
(print (list :observing-a new-value old-value old-value-bound-p)))

(defobserver b (self new-value old-value old-value-bound-p)
(print (list :observing-b new-value old-value old-value-bound-p)))

;; c-in and c? hide more Cells wiring. The long names are c-input and
c-formula, btw

(progn
(print :first-we-make-a-useless-instance)
(let ((u (make-instance 'useless
:one (c-in 1) ;; we want to change it later, so wrap as
input value
:a (c? (- (+ (sin (/ pi 2)) (one self)))) ;;
negate(sin(pi/2)+one)
:b (c? (* (- (a self) 10)))))) ;; negate(a)*10
(print :now-we-change-one-to-ten)
(setf (one u) 10)))

#| output of the above

:first-we-make-a-useless-instance
(:observing-one 1 nil nil)
(:observing-a -2.0d0 nil nil)
(:observing-b -12.0d0 nil nil)
:now-we-change-one-to-ten
(:observing-one 10 1 t)
(:observing-a -11.0d0 -2.0d0 t)
(:observing-b -21.0d0 -12.0d0 t)

|#

Alexander Schmolck

unread,
May 7, 2006, 12:45:24 PM5/7/06
to
[trimmed groups]

Ken Tilton <kent...@gmail.com> writes:

> yes, but do not feel bad, everyone gets confused by the /analogy/ to
> spreadsheets into thinking Cells /is/ a spreadsheet. In fact, for a brief
> period I swore off the analogy because it was so invariably misunderstood.
> Even Graham misunderstood it.

Count me in.

>
> But it is such a great analogy! <sigh>
>
> > but what's the big deal about PyCells?
> > Here is 22-lines barebones implementation of spreadsheet in Python,
> > later I create 2 cells "a" and "b", "b" depends on a and evaluate all
> > the cells. The output is
> > a = negate(sin(pi/2)+one) = -2.0
>
> > b = negate(a)*10 = 20.0
>
> Very roughly speaking, that is supposed to be the code, not the output. So you
> would start with (just guessing at the Python, it has been years since I did
> half a port to Python):
>
>
> v1 = one
> a = determined_by(negate(sin(pi/2)+v1)
> b = determined_by(negate(a)*10)
> print(a) -> -2.0 ;; this and the next are easy
> print(b) -> 20
> v1 = two ;; fun part starts here
> print(b) -> 40 ;; of course a got updated, too
>

do you mean 30?

I've translated my interpretation of the above to this actual python code:

from math import sin, pi
v1 = cell(lambda: 1)
a = cell(lambda:-(sin(pi/2)+v1.val), dependsOn=[v1])
b = cell(lambda: -a.val*10, dependsOn=[a],
onChange=lambda *args: printChangeBlurp(name='b',*args))
print 'v1 is', v1
print 'a is', a # -2.0 ;; this and the next are easy
print 'b is', b # 20
v1.val = 2 # ;; fun part starts here
print 'v1 now is', v1
print 'b now is', b # 30 ;; of course a got updated, too


I get the following printout:

v1 is 1
a is -2.0
b is [cell 'b' changed from <__main__.unbound object at 0xb4e2472c> to 20.0,
it was not bound]20.0
[cell 'b' changed from 20.0 to 30.0, it was bound ] v1 now is 2
b now is 30.0

Does that seem vaguely right?

> The other thing we want is (really inventing syntax here):
>
> on_change(a,new,old,old-bound?) print(list(new, old, old-bound?)

Is the above what you want (you can also dynamically assign onChange later
on, as required or have a list of procedures instead)?

>
> Then the print statements Just Happen. ie, It is not as if we are just hiding
> computed variables behind syntax and computations get kicked off when a value
> is read. Instead, an underlying engine propagates any assignment throughout
> the dependency graph before the assignment returns.

Updating on write rather than recalculating on read does in itself not seem
particularly complicated.

> My Cells hack does the above, not with global variables, but with slots (data
> members?) of instances in the CL object system. I have thought about doing it
> with global variables such as a and b above, but never really seen much of
> need, maybe because I like OO and can always think of a class to create of
> which the value should be just one attribute.

OK, so in what way does the quick 35 line hack below also completely miss your
point?


# (NB. for lispers: 'is' == EQ; '==' is sort of like EQUAL)

def printChangeBlurp(someCell, oldVal, newVal, bound, name=''):
print '[cell %r changed from %r to %r, it was %s]' % (
name, oldVal, newVal, ['not bound', 'bound '][bound]),

_unbound = type('unbound', (), {})() # just an unique dummy value
def updateDependents(dependents):
seen = {}
for dependent in dependents:
if dependent not in seen:
seen[dependent] = True
dependent.recalculate()
updateDependents(dependent._dependents)
class cell(object):
def __init__(self, formula, dependsOn=(), onChange=None):
self.formula = formula
self.dependencies = dependsOn
self.onChange = onChange
self._val = _unbound
for dependency in self.dependencies:
if self not in dependency._dependents:
dependency._dependents.append(self)
self._dependents = []
def __str__(self):
return str(self.val)
def recalculate(self):
newVal = self.formula()
if self.onChange is not None:
oldVal = self._val
self.onChange(self, oldVal, newVal, oldVal is not _unbound)
self._val = newVal
def getVal(self):
if self._val is _unbound:
self.recalculate()
return self._val
def setVal(self, value):
self._val = value
updateDependents(self._dependents)
val = property(getVal, setVal)

'as

Bill Atkins

unread,
May 7, 2006, 2:30:26 PM5/7/06
to
Alexander Schmolck <a.sch...@gmail.com> writes:

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_position = cell_initial_value( 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
synchronized.

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.

Bill Atkins

unread,
May 7, 2006, 2:34:14 PM5/7/06
to
Bill Atkins <NOatki...@rpi.edu> writes:

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_value( 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

It is loading more messages.
0 new messages