Clojurescript - Uncaught Error: <! используется не в (Go...) блок

Я в Clojurescript и пытаюсь использовать core.async чтобы получить результат от встроенной функции Javascript (я в браузере) и условно интегрировать ее в карту.

У меня есть функция для переноса нативного вызова браузера (вдохновленный выступлением Тимоти Болдриджа на core.async, примерно 34 минуты для заинтересованных):

(defn geolocation []
    (let [c (chan)
         cb (fn [e] (put! c (js->clj e)))]
     (if (exists? js/navigator.geolocation)
       (.getCurrentPosition js/navigator.geolocation. cb cb)
       (put! c {:error "Geolocation is not supported"}))
     c))

Я могу использовать это так:

   ;; this works
   (go (.log js/console "RES1 -"  (<! (geolocation))))

   ;; this too (not sure how to print it though)
   (go (println "RES2 - "  (-> {}
                            (assoc :test (<! (geolocation))))))

   ;; this fails... why ?
   (go (println "RES3 - "  (-> {}
                               (#(when true
                                   (assoc % :test (<! (geolocation))))))))

Последний пример завершается с ошибкой: Uncaught Error: <! used not in (go ...) block хотя я думал, что использую такую ​​же структуру.

Что я делаю неправильно?

Примечание: я требую это должным образом от :require-macro Директива, как описано здесь.

1 ответ

Решение

go макрос возьмет тело, которое ему дано, и преобразует все <! а также alt! а также >! звонки на конечный автомат. Однако это не будет входить в функции:

невозможно использовать для цикла в блоке go из core.async?

Под остановкой трансляции на границах функций я имею в виду следующее: блок go берет свое тело и переводит его в конечный автомат. Каждый звонок <!>! или же alts! (и несколько других) считаются переходами конечного автомата, в которых выполнение блока может приостанавливаться. В каждой из этих точек машина превращается в обратный вызов и подключается к каналу. Когда этот макрос достигает формы fn, он прекращает трансляцию. Так что вы можете звонить только <! изнутри блока go, а не внутри функции внутри блока кода.

Это часть магии core.async, Без go макрос, код core.async очень похож на callback-ад в других языках.

Другие вопросы по тегам