Anyway...)
all
the *programmer* has to care about is what values a slot depends on --
Cells takes care of inverting that for you, which is important because
that's a job that a computer is much better at than a human.
Fine. I suppose that is better; if b is going to return a + 1
the fact that this is what b returns should belong to b, not
to a. So a has an update list including b, so when a's value
is set a tells b it needs to update itself.
If we're allowed to pass (at some point, to some constructor
or other) something like (b, a + 1, [a]), which sets up a
cell b that shall return a + 1, and where the [a] is used
in the constructor to tell a to add b to a's update list
then this seems like no big deal.
And doing that doesn't seem so bad - now when the programmer
is writing b he has to decide that it should return a + 1
and also explicitly state that b shall depend on a; this
is all nice and localized, it's still _b_ telling _a_ to
add b to a's update list, and the programmer only has
to figure out what _b_ depends on when he's writing _b_.
Doesn't seem so bad.
But of course it would be better to be able to pass just
something morally equivalent to (b, a + 1) to whatever
constructor and have the system figure out automatically
that since b returns a + 1 it has to add a to b's update
list. There must be some simple trick to accomplish that
(using Python, without parsing code).
Right, you do not want to parse code. It really would not work as
powerfully as Cells, which notice any dynamic access to another cell
while a rule is running. So my rule can call a function on "self" (the
instance that wons the slot being calculated, and since self can have
pointers to other instances, the algorithm can navigate high and low
calling other functions before finally reading another ruled slot. You
want to track those.
Exactly what the trick is I
don't see immediately.
To compute a value for a slot that happens to have a rule associated
with it, have a little cell datastructure that implements all this and
associate the cell with the slot and store a pointer to the rule in the
cell. Then have a global variable called *dependent* and locally:
currentdependent = *dependent*
oldvalue = cell.value
newvalue = call cell.rule, passing it the self instance
*dependent* = currentvalue
if newvalue not = oldvalue
call on-change on the slot name, self, newvalue and oldvalue
(the on-chnage needs to dispatch on as many arguments as
the language allows. Lisp does it on them all)
In the reader on a slot (in your getattr) you need code that notices if
the value being read is mediated by a ruled cell, and if the global
*dependent* is non empty. If so, both cells get a record of the other
(for varying demands of the implementation).
In Cells do we just pass a rule using other cells to
determine this cell's value, or do we also include
an explicit list of cells that this cell depends on?
Again, the former. Just write the rule, the above scheme dynamically
figures out the dependencies. Note then that dependencies vary over time
because of different branches a rule might take.
I want to reassure the community that this (nor the spreadsheet analogy
<g>) is not just my crazy idea. In 1992:
http://www.cs.utk.edu/~bvz/active-value-spreadsheet.html
"It is becoming increasingly evident that imperative languages are
unsuitable for supporting the complicated flow-of-control that arises in
interactive applications. This paper describes a declarative paradigm
for specifying interactive applications that is based on the spreadsheet
model of programing. This model includes multi-way constraints and
action procedures that can be triggered when constraints change the
values of variables."
Cells do not do multi-way constraints, btw.