Hi, I am trying to code an observer pattern or a publish/submit pattern for a sort of cellular automaton.
The classical observer pattern does not to the trick because if a cell A subscribes to changes in a cell B and vice-versa, the application will run out of stack owing to the recursive approach (B.update() will call A.update() and so on and the app will run out of stack). So I though about using a publish/subscribe pattern where respective cells pass each other messages, rather than calling each other's update() methods. Here is a simple example with two cells A and B: ``` package main import ( "fmt" ps "publish/pubsub" ) func main() { fmt.Printf("Starting\n") chEnd := make(chan int) // initialize a := ps.NewNode(1, 0) b := ps.NewNode(2, 0) // connect nodes a.Connect(b.ChOut) b.Connect(a.ChOut) // Start listening a.Listen() b.Listen() // Start sending data on one arbitrary node // to start the process. a.ChIn <- 10 <-chEnd } ``` and the corresponding lib ```package lib import ( "fmt" ) type Node struct { Id int State int ChOut chan int ChIn chan int } func NewNode(id int, state int) Node { chout := make(chan int) var chin chan int return Node{id, state, chout, chin} } func (p *Node) Broadcast(inItem int) { p.ChOut <- inItem + 1 //time.Sleep(100 * time.Millisecond) } func (p *Node) Listen() { go func() { for { select { case inItem := <-p.ChIn: fmt.Printf("%d: %d\n", p.Id, inItem) p.Broadcast(inItem) } } }() } func (p *Node) Connect(ch chan int) { p.ChIn = ch } ``` Each node has a input and an output channe. The input channel of B is the output channel of A and vice-versa. Every update consists merely of incrementing the data passed by the other cell. It seems to work. So far, so good. I tried to with a set of 4 cells A, B, C, D, in order to simulate a one dimensional cellular automaton of sorts. In this second attempt, - each cell has two input channels (let and right) to listen to its closest left- and right-hand neighbour, respectively (ChinL and ChinR). - each cell has to output channels to communicate its latest updated state to its closest neighbours (ChoutL and ChoutR). I must have done something wrong in the implementation of that scheme with 4 cells, because it yields odd results : the values passed back and forth between the 4 cells seem to hit a threshold instead of increasing at every consecutive step: here is the code: ``` package main import ( "fmt" ps "publish/pubsub" ) func main() { fmt.Printf("Starting\n") chEnd := make(chan int) // initialize a := ps.NewNode(1, 0) b := ps.NewNode(2, 0) c := ps.NewNode(3, 0) d := ps.NewNode(4, 0) // connect nodes a.ChInL = d.ChOutR a.ChInR = b.ChOutL b.ChInL = a.ChOutR b.ChInR = c.ChOutL c.ChInL = b.ChOutR c.ChInR = d.ChOutL d.ChInL = c.ChOutR d.ChInR = a.ChOutL // Start listening go a.Listen() go b.Listen() go c.Listen() go d.Listen() go a.Broadcast() go b.Broadcast() go c.Broadcast() go d.Broadcast() // Start sending data on one arbitrary node // to start the process. a.ChInL <- 1 // Dummy read on channel to make main() wait <-chEnd } /* A B C D LR LR LR LR */ ``` and the corresponding lib ``` package main import ( "fmt" ps "publish/pubsub" ) func main() { fmt.Printf("Starting\n") chEnd := make(chan int) // initialize a := ps.NewNode(1, 0) b := ps.NewNode(2, 0) c := ps.NewNode(3, 0) d := ps.NewNode(4, 0) // connect nodes a.ChInL = d.ChOutR a.ChInR = b.ChOutL b.ChInL = a.ChOutR b.ChInR = c.ChOutL c.ChInL = b.ChOutR c.ChInR = d.ChOutL d.ChInL = c.ChOutR d.ChInR = a.ChOutL // Start listening go a.Listen() go b.Listen() go c.Listen() go d.Listen() go a.Broadcast() go b.Broadcast() go c.Broadcast() go d.Broadcast() // Start sending data on one arbitrary node // to start the process. a.ChInL <- 1 // Dummy read on channel to make main() wait <-chEnd } /* A B C D LR LR LR LR */ ``` package pubsub import ( "fmt" "strings" ) type Node struct { Id int State int ChOutL chan int ChOutR chan int ChInL chan int ChInR chan int ChIO chan int } func NewNode(id int, state int) Node { choutL := make(chan int) choutR := make(chan int) var chinL chan int var chinR chan int chIO := make(chan int) return Node{id, state, choutL, choutR, chinL, chinR, chIO} } func (p *Node) Broadcast() { for item := range p.ChIO { p.ChOutL <- item + 1 p.ChOutR <- item + 1 fmt.Printf("%d: %d %s\n", p.Id, item, strings.Repeat("*", item)) } } func (p *Node) Listen() { for { //time.Sleep(100 * time.Millisecond) select { case inItem := <-p.ChInL: go func() { p.ChIO <- inItem }() case inItem := <-p.ChInR: go func() { p.ChIO <- inItem }() } } } ``` -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/0eecb599-2827-40e6-881b-affeb41962fcn%40googlegroups.com.