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

A

Alex Martelli

Ken Tilton said:
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
 
B

Bill Atkins

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.


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

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

David Steuber

Xah Lee said:
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.
 
K

Ken Tilton

Alex said:
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

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

Tomasz Zielonka

Alex said:
``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
 
A

Alex Martelli

Bill Atkins said:
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
 
T

Tomasz Zielonka

Alex said:
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
 
R

Robert Kern

Ken said:
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?????

Looking at the description, Cells looks a lot like one of our internal Python
libraries at Enthought. It's quite useful. Not worldchanging, not a silver
bullet, but useful.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
A

Alex Martelli

Tomasz Zielonka said:
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
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.

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
 
A

Alex Martelli

Tomasz Zielonka said:
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
 
T

Tomasz Zielonka

Alex said:
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
 
S

Serge Orlov

Ken said:
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
 
T

Tomasz Zielonka

Alex said:
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?

Perhaps you were speaking more about Python, and I was speaking more
generally. There are useful programming techniques that require using
many functions, preferably anonymous ones, but these techniques probably
won't fit Python very well anyway.

In Haskell when I write IO intensive programs, when I use monadic
parsing libraries, etc. I use many lambdas, sometimes disguised as a
do-notation bind syntax (do x <- a; ...). I wouldn't want to name
all those functions.

Here is the random page with Haskell code I found on haskell.org
http://haskell.org/haskellwiki/Sudoku
See how many are there uses of lambdas:
\... ->
and do-bindings, which are basically a syntactic sugar for lambdas
and monadic bind operations:
do
x <- something ...
Also, there are many anonymous functions created by using higher
order functions or by partial application.

I want to make it clear that monadic programming in Haskell is not only
something that we *have* to do in order to perform IO in a purely
functional program, but it's often something we *can* and *want* to do,
because it's powerful, convenient, etc.

Haskell programs without many monadic programming also contain many
anonymous functions.

Of course I wouldn't use monadic programming too often in Python, mostly
because I wouldn't have to (eg. for IO), but also because it would be
inconvenient and difficult in Python.
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.

I know that. But the more such functions you use, the more cumbersome it
gets. Note also that I could use your reasoning to show that support
for expressions in the language is not neccessary.
Nothing useful -- the parallel is exact.

What we are discussing here is language expressivity and power,
something very subtle and hard to measure. I think your logical
reasoning proves nothing here. After all, what is really needed
in a programming language? Certainly not indentation sensitivity :)
0s and 1s should be enough.
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.

You got me, monadic programming is infeasible in Python even with
lambdas ;-)

Best regards
Tomasz
 
T

Tomasz Zielonka

Alex said:
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?

Perhaps you were speaking more about Python, and I was speaking more
generally. There are useful programming techniques that require using
many functions, preferably anonymous ones, but these techniques probably
won't fit Python very well anyway.

In Haskell when I write IO intensive programs, when I use monadic
parsing libraries, etc. I use many lambdas, sometimes disguised as a
do-notation bind syntax (do x <- a; ...). I wouldn't want to name
all those functions.

Here is the random page with Haskell code I found on haskell.org
http://haskell.org/haskellwiki/Sudoku
See how many are there uses of lambdas:
\... ->
and do-bindings, which are basically a syntactic sugar for lambdas
and monadic bind operations:
do
x <- something ...
Also, there are many anonymous functions created by using higher
order functions or by partial application.

I want to make it clear that monadic programming in Haskell is not only
something that we *have* to do in order to perform IO in a purely
functional program, but it's often something we *can* and *want* to do,
because it's powerful, convenient, etc.

Haskell programs without many monadic programming also contain many
anonymous functions.

Of course I wouldn't use monadic programming too often in Python, mostly
because I wouldn't have to (eg. for IO), but also because it would be
inconvenient and difficult in Python.
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.

I know that. But the more such functions you use, the more cumbersome it
gets. Note also that I could use your reasoning to show that support
for expressions in the language is not neccessary.
Nothing useful -- the parallel is exact.

What we are discussing here is language expressivity and power,
something very subtle and hard to measure. I think your logical
reasoning proves nothing here. After all, what is really needed
in a programming language? Certainly not indentation sensitivity :)
0s and 1s should be enough.
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.

You got me, monadic programming is infeasible in Python even with
lambdas ;-)

Best regards
Tomasz
 
T

Tomasz Zielonka

Tomasz said:
(x * 2) + (y * 3)

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

Of course it should be (x * 2) + (y * 3).

Best regards
Tomasz
 
B

Bill Atkins

Serge Orlov said:
Ken said:
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

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

Bill Atkins

Bill Atkins said:
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.
 
K

Kay Schluehr

Tomasz said:
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.
 
B

brian

Bill said:
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 inner(*innerargs):
.... return fn(*(innerargs + args))
.... return inner
....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
 
S

Serge Orlov

Bill said:
Serge Orlov said:
Ken said:
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

I hope Ken doesn't mind me answering for him, but Cells is not a
spreadsheet (where did you get that idea?).

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?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,775
Messages
2,569,601
Members
45,182
Latest member
BettinaPol

Latest Threads

Top