2014-10-30 34 views
8

Rich Hickey's Strange Loop transducers presentation informuje, że istnieją dwie implementacje map w Clojure 1.6, jedna dla sekwencji w clojure.core i jedna dla kanałów w core.async.Czy core.async może implementować swoje funkcje pod względem sekwencji?

enter image description here

Teraz wiemy, że mamy w 1,7 przetworniki, dla których funkcja foldr (reduce) jest zwracany z funkcja wyższego rzędu jak map i filter gdy dana funkcja ale nie zbiór.

Co staram się artykułować i nie, dlatego funkcje core.async nie mogą zwrócić sekwencji lub być podobne do Seq. Mam wrażenie, że "interfejsy" (protokoły) są różne, ale nie widzę jak.

Z pewnością, jeśli zabierasz pierwszy element z kanału, możesz go przedstawić jako pierwszy element z sekwencji?

Moje pytanie brzmi: Czy core.async może zaimplementować swoje funkcje pod względem sekwencji?

Odpowiedz

7

Tak, w pewnym sensie mogły być. Jeśli zignorujesz przejść bloki (na razie zróbmy tak), to nie ma naprawdę nic złego w czymś takim, co następuje:

(defn chan-seq [ch] 
    (when-some [v (<!! c)] 
    (cons v (lazy-seq (chan-seq ch))))) 

jednak zauważyć tutaj połączenie <!!. Nazywa się to "weź blokowanie": wewnątrz tej funkcji są pewne obietnice i blokady, które spowodują zatrzymanie aktualnie wykonywanego wątku, dopóki wartość nie będzie dostępna na kanale. Tak więc działałoby to dobrze, jeśli nie masz nic przeciwko temu, aby wątek w języku Java działał bezczynnie.

Ideą bloków go jest uczynienie procesów logicznych znacznie tańszymi; Aby to osiągnąć, blok go przepisuje bryłę bloku na serię wywołań zwrotnych, które są dołączone do kanału, dzięki czemu wewnętrznie wywołanie <! wewnątrz bloku go zostaje przekształcone w coś podobnego do tego (take! c k), gdzie k jest wywołaniem resztę bloku go.

Gdybyśmy mieli prawdziwe kontynuacje lub gdyby JVM obsługiwała lekkie wątki, to tak, moglibyśmy łączyć go-bloki i blokować. Ale obecnie obejmuje to przepisanie głębokiego kodu bajtowego (jak robi to projekt Pulsar/Quasar) lub niestandardową funkcję JVM. Obie te opcje zostały wykluczone podczas tworzenia core.async na rzecz znacznie prostszego w implementacji (i mam nadzieję, że znacznie łatwiejsze do zrozumienia) lokalnej transformacji blokowej.