beatngu13
beatngu13

Reputation: 9423

How to handle infinite go-loops

As a hobby project, I am working on an alternate futures and promises implementation based on "From Events to Futures and Promises and back". The original author uses channels/events under the hood, which is why I am using core.async. A future, expressed in pseudo Go syntax, looks as follows:

func future(func f() (T, bool)) Future <T> {
    ch = newChannel ()
    spawn(func() {
        x := f()
        for { syncEvt(sndEvt(ch, x)) }
    })
    return rcvEvt(ch)
}

Using valid Go syntax, type definitions and a get function:

type Comp struct {
    value interface{}
    ok    bool
}

type Future chan Comp

func future(f func() (interface{}, bool)) Future {
    future := make(chan Comp)

    go func() {
        v, o := f()
        c := Comp{v, o}
        for {
            future <- c
        }
    }()

    return future
}

func (ft Future) get() (interface{}, bool) {
    c := <-ft
    return c.value, c.ok
}

Now, when I port this to Clojure, I was thinking to implement it as followed:

(defrecord Comp [value ok])

(defn future [f]
  (let [future (chan)]
    (go-loop [comp (f)]
      (>! future comp)
      (recur comp))
    future))

(defn get [future]
  (<!! future))

Since I'm pretty new to Clojure (and core.async), I worry about the infinite go-loop. Will the IOC thread ever be released? Should I provide some kind of poison pill to stop the loop (though I think this would be pretty error-prone)? Any suggestions?

Upvotes: 1

Views: 861

Answers (1)

Timothy Baldridge
Timothy Baldridge

Reputation: 10683

Go blocks in Clojure are not like they are in Go. In core.async go blocks exist as callbacks attached onto channels, and as such they live as long as the channel itself lives. So think of go blocks as being syntactic sugar over callbacks and it'll all star to make sense.

This video tutorial goes into a bit more detail: https://www.youtube.com/watch?v=VrwVc-saWLw

Upvotes: 4

Related Questions