Error in Code Example: "Can only recur from tail position"

178 views Asked by At

The follwing function implements mapping functionality using channels, similar to the behavoiur of the normal clojure map

I got this code example from the book Seven concurrency models in seven weeks by Paul Butcher. It seems that this code is already outdated because when executing it, it throws the follwing error message. Does anyone know how to fix the function?

Error Message:

Can only recur from tail position {:exprs nil, :form (recur)

Code:

   (defn map-chan [f from]
    (let [to (chan)]
     (go-loop []
      (when-let [x (<! from)]
       (>! to (f x))
       (recur))
     (close! to))
    to))

My first fixing attempt: // same error as origin

(defn map-chan [f from]
  (go-loop []
         (do
          (let [to (chan)]
          (when-let [x (<! from)]
           (>! to (f x))
           (recur))))
          (close! to)
         )
 )
1

There are 1 answers

0
Aleph Aleph On BEST ANSWER

Indeed, it does not work; this is also mentioned in the errata to the book.

You can place the close! function call outside the loop to ensure that recur is in final position (note that you have to use go and loop instead of go-loop for that):

(defn map-chan [f from]
  (let [to (chan)]
    (go (loop []
          (when-let [x (<! from)]
            (>! to (f x))
            (recur)))
        (close! to))
    to))