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

Ken Tilton kentilton at gmail.com
Sun May 7 10:36:00 EDT 2006



Serge Orlov wrote:
> Bill Atkins wrote:
> 
>>"Serge Orlov" <Serge.Orlov at gmail.com> writes:
>>
>>
>>>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
>>>
>>
>>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.

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

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



More information about the Python-list mailing list