Ошибка в примере кода: может повторяться только из хвостовой позиции

Следующая функция реализует функциональность сопоставления с использованием каналов, аналогично поведению обычной clojure map.

Я взял этот пример кода из книги Пола Батчера Семь моделей параллелизма за семь недель. Кажется, что этот код уже устарел, потому что при его выполнении выдается следующее сообщение об ошибке. Кто-нибудь знает, как исправить функцию?

Сообщение об ошибке:

Может повторяться только из хвостовой позиции {:exprs nil, :form (recur)

Код:

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

Моя первая попытка исправить: // та же ошибка, что и у источника

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

person TruckerCat    schedule 13.12.2016    source источник


Ответы (1)


Действительно, это не работает; это также упоминается в исправлениях к книге.

Вы можете поместить вызов функции close! вне цикла, чтобы убедиться, что recur находится в конечной позиции (обратите внимание, что для этого вам нужно использовать go и loop вместо go-loop):

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