2017-08-31 1 views
3

J'essaie de comprendre core.async dans ma REPL et je suis complètement confus quant à la façon dont mon utilisation de (go-loop ...) ne parvient pas à se qualifier de "blocage" pour async />!Pourquoi "Assert failed:>! Used not in (go ...) block"

Mon go-boucle est comme ...

(async/go-loop [page (range 3)] 
    (if (empty? page) 
    (async/close! ch) 
    (dorun (map (fn [row] 
        (println row) 
        (async/>! ch row)) page))) 
    (recur (range (dec (count page))))) 

Mais le REPL est tout bouleversé ...

=> 
#object[clojure.core.async.impl.channels.ManyToManyChannel 
     0x23465937 
     "[email protected]"] 
0 
Exception in thread "async-dispatch-12" java.lang.AssertionError: Assert failed: >! used not in (go ...) block 
nil 
... 

Pourquoi pas la portée de cette (go-loop ...) suffisante pour l'appel (async/>! row) ?

Devrais-je même utiliser une boucle de déclenchement ici?

+0

double possible de [Clojurescript - Uncaught Erreur: OlegTheCat

+0

@OlegTheCat La réponse peut être la même, mais ce n'est pas exactement la même question. Tout comme 2 + 5 = 7 et 8 - 1 = 7 ne sont pas vraiment la même question même si la réponse est la même. Autrement dit, si quelqu'un connaît intimement core.async, cela peut ressembler à la même question mais à quelqu'un de nouveau ... disons googling pour ce message d'exception, vous n'arriveriez pas à cette question Clojurescript lorsque vous cherchez ce message d'exception. –

Répondre

7

>! et d'autres appels de stationnement ne peuvent pas être utilisés à l'intérieur de fonctions imbriquées à l'intérieur d'un go malheureusement.

go transforme le code que vous lui donnez en une machine d'état et recherche les appels de stationnement. Il ne regarde cependant pas à l'intérieur des fonctions imbriquées.

De Clojure.Asyncs Github best practice page:

Unsupported constructs and other limitations in go blocks

The go macro stops translating at function creation boundaries. This means the following code will fail to compile, or may just throw a runtime error stating that <! was used outside of a go block:

(go (let [my-fn (fn [] (<! c))] 
    (my-fn))) 

This is one thing to remember since many Clojure constructs create functions inside macros. The following are examples of code that will not work as one would expect:

(go (map <! some-chan)) 
(go (for [x xs] 
     (<! x))) 
+0

alors ... '' '(do-seq ...' '' au lieu de '' '(la tentative de dorun (map ...' '') me ferait sortir de mon anomalie de fonction imbriquée? Vous l'aurez deviné. ..Je suis un peu nouveau pour core.async –

+0

@BobKuhar Lire la nouvelle mise à jour Trouvé une source officielle Notez que de nombreuses macros produisent des fonctions, donc cela ne peut pas vous sauver non plus – Carcigenicate

+1

Yep ... '' '(doseq [page de la ligne] ... '' 'surmonte la fonction imbriquée et fonctionne très bien Merci –