On Mon, 2006-09-11 at 15:33 -0400, Ken Tilton wrote:
kt wrote:
If A is eager and depends on B and A has an observer that really really wants to stay on top of reality....
I just had Cells4 kinda thought: what if all Cells are (in some new respect) lazy unless observed (directly or indirectly thru someone that is observed)?
I was using Cells4 today :)
So, all cells are lazy. Check. Unless observed. Check. Observed = I ask for a cells value explicitly (in which case it is transiently observed,) or a GUI, etc, subscribes to it.
This makes the implementation really easy:
class Cell: def invalidate( self ): if self.state != INVALID: if self.subscibed(): invalidationSet.add( self ) self.state = INVALID for x in self.dependents: x.invalidate()
def set( self, v ): self.invalidate() self.val = v # dispatch invalidateSet stuff at some transactional boundary
btw, as radical as that change sounds, I am not sure it really rises to the level of "Cells4" -- I am suggesting this only because I think it is equivalent to Cells3 (assuming one is sane enough not to have side-effects inside rules) and merely automates the identification of which cells can be lazy (or looked at another way, automates the detection of the need for eagerness.
Yep. No side-effects, and life is simple. Eagerness is just:
class Cell: def value( self ): inputs = [ x.value() for x in self.inputs ] self.val = self.calc( *inputs ) self.state = VALID return self.val
Then the explicit thing becomes supporting a new class of much rarer (methinks) "lazy" observer whose existence would not trigger eagerness.
Ah, but once you've eliminated side-effects, lazy observers become easy to write and really useful. Consider a tabbed panel GUI on an object with same panel 1 = basic info, and panel 2 = expensive to compute stuff. The panels subscribe to the cells they care about, but when the observer callbacks are called, they do something like:
class GuiElem: def myVal( self ): return self.myCell.value()
def draw( self ): self.widget.draw( self.myVal() )
def callback( self, aCell ): if self.isVisible(): self.draw()
def onActivate( self ): self.draw()
Lovely, no? Maximal laziness - the only cost is establishing the cell dependencies.
It would be interesting to see how much laziness ends up being deduced by this approach. The indirect eagerness (I am not observed, but I am called/used by someone who is) could get interesting.
Jes thinkin out loud.
You just keep thinking, Butch. That's what you're good at.
-- mmn