package react import "log" const testVersion = 4 type react struct { } type inputCell struct { cell } type compuCell struct { cell cb map[CallbackHandle]func(int) } type com struct { eval, ok chan bool } type cell struct { value int observer []com } func New() Reactor { return &react{} } func newCom() com { return com{ eval: make(chan bool), ok: make(chan bool), } } func (r *react) CreateCompute1(c Cell, f func(int) int) ComputeCell { com := newCom() cc := &compuCell{ cb: make(map[CallbackHandle]func(int)), } cc.value = f(c.Value()) Register(c, com) go func() { for range com.eval { log.Println("got", c.Value()) old := cc.value cc.value = f(c.Value()) if old != cc.value { for _, ch := range cc.observer { log.Println("notify #1") ch.eval <- true <-ch.ok } for _, cb := range cc.cb { log.Println("cb #1", cb) cb(cc.value) } } com.ok <- true } }() return cc } func (r *react) CreateCompute2(c1, c2 Cell, f func(int, int) int) ComputeCell { com := newCom() cc := &compuCell{ cb: make(map[CallbackHandle]func(int)), } cc.value = f(c1.Value(), c2.Value()) Register(c1, com) Register(c2, com) go func() { for range com.eval { old := cc.value cc.value = f(c1.Value(), c2.Value()) if old != cc.value { for _, ch := range cc.observer { log.Println("notify #2") ch.eval <- true <-ch.ok } for _, cb := range cc.cb { log.Println("cb #2", cb, cc.value) cb(cc.value) } } com.ok <- true } }() return cc } func (r *react) CreateInput(i int) InputCell { return &inputCell{ cell: cell{value: i}, } } func (c *compuCell) AddCallback(f func(int)) CallbackHandle { c.cb[&f] = f return &f } func (c *compuCell) RemoveCallback(h CallbackHandle) { delete(c.cb, h) } func (c *inputCell) SetValue(i int) { old := c.value c.value = i if old != c.value { for _, ch := range c.observer { log.Println("notify", i) ch.eval <- true <-ch.ok } } } func (c *cell) Value() int { v := c.value log.Println("report", v) return v } func Register(c Cell, ch com) { switch v := c.(type) { case *compuCell: v.observer = append(v.observer, ch) case *inputCell: v.observer = append(v.observer, ch) } }