[Sorry, I missed this one originally.]

David C. Ullrich wrote:
> On Tue, 09 May 2006 05:35:47 -0500, David C. Ullrich
> <[EMAIL PROTECTED]> wrote:
> 
> 
>>On Mon, 08 May 2006 18:46:57 -0400, Ken Tilton <[EMAIL PROTECTED]>
>>wrote:
>>[...]
>>
>>If you, um, look at the code you see that "cells.a = 42" triggers
>>cells.__setattr__, which fires a's callback; the callback then
>>reaches inside and sets the value of b _without_ going through
>>__setattr__, hence without triggering b's callback.
>>
>>In Cells you can't have A depend on B and also B depend on A?
>>That seems like an unfortunate restriction - I'd want to be
>>able to have Celsius and Farenheit, so that setting either
>>one sets the other.

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

> 
> 
> Realized later that I hadn't thought this through.
> 
> I'd been assuming that of course we should be allowed to
> have A and B depend on each other. Hence if a change in
> A propagates to a change in B that change in B has to
> be a non-propagating change - thought I was just so
> clever seeing a way to do that.

I think it could be arranged, if one were willing to tolerate a little 
fuzziness: no, there would be no strictly correct snapshot at which 
point everyone had their "right value". Instead, A changes so B 
recomputes, B changes so A recomputes... our model has now come to life, 
we just have to poll for OS events or socket data, and A and B never get 
to a point where they are self-consistent, because one or the other 
always needs to be recalculated.

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

[Cue Xah]


> 
> But duh, if that's how things are then we can't have 
> transitive dependencies working out right; surely we
> want to be able to have B depend on A and then C
> depend on B...
> 
> (And also if A and B are allowed to depend on each
> other then the programmer has to ensure that the
> two rules are inverses of each other, which seems
> like a bad constraint in general, something non-trivial
> that the programmer has to get right.)

Right, when I considered multi-way dependencies I realized I would have 
to figure out some new syntax to declare in one place the rules for two 
slots, and that would be weird because in Cells it is the instance that 
gets a rule at make-instance time, so i would really have to have some 
new make-instance-pair capability. Talk about a slippery slope. IMO, the 
big constraints research program kicked off by Steele's thesis withered 
into a niche technology because they sniffed at the "trivial" 
spreadsheet model of linear dataflow and tried to do partial and 
multi-way dependencies. I call it "a bridge too far", and in my 
experience of Cells (ten years of pretty intense use), guess what?, all 
we need as developers is one-way, linear, fully-specified dependencies.

> 
> So fine, no loops. If anything, if we know that
> there are no loops in the dependencies that simplifies
> the rest of the programming, no need for the sort of
> finagling described in the first paragraph above.

Actually, I do allow an on-change callback ("observer" in Cells 
parlance) to kick off a toplevel, imperative state change to the model. 
Two cells who do that to each other will run until one decides not to do 
so. I solve some GUI situations (the classic being a scrollbar thumb and 
the text offset, which each at different times control the other, by 
having them simply set the other in an observer. On the second 
iteration, B is setting A to the value A has already, so propagation 
stops (a longstanding Cells feature).

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


> But this raises a question:
> 
> Q: How do we ensure there are no loops in the dependencies?

Elsewhere I suggested the code was:

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

It is actually:

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

So /before/ that I can say:

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

> 
> Do we actually run the whole graph through some algorithm
> to verify there are no loops?
> 
> The simplest solution seems like adding the cells one
> at a time, and only allowing a cell to depend on 
> previously added cells. It's clear that that would
> prevent loops, but it's not clear to me whether or
> not that disallows some non-looping graphs.

As you can see, the looping is detected only when there is an actual 
circularity, defined as a computation requiring its own computation as 
an input.

btw, a rule /does/ have access to the prior value it computed, if any, 
so the cell can be value-reflective even though the rules cannot be 
reentrant.

> A
> math question the answer to which is not immediately
> clear to me (possibly trivial, the question just
> ocurred to me this second):
> 
> Say G is a (finite) directed graph with no loops. Is it always
> possible to order the vertices in such a way that
> every edge goes from a vertex to a _previous_ vertex?

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

kenny

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

"Have you ever been in a relationship?"
    Attorney for Mary Winkler, confessed killer of her
    minister husband, when asked if the couple had
    marital problems.
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to