2014-10-30 8 views
8

Rich Hickey's Strange Loop transducers presentation ci dice che ci sono due implementazioni di map in Clojure 1.6, una per le sequenze in clojure.core e una per i canali in core.async.Potrebbe core.async aver implementato le sue funzioni in termini di sequenze?

enter image description here

Ora sappiamo che in 1.7 abbiamo trasduttori, per i quali una funzione foldr (reduce) viene restituito da funzioni di ordine superiore come map e filter quando somministrato una funzione, ma non è una collezione.

Quello che sto cercando di articolare e in mancanza, è il motivo per cui le funzioni core.async non possono restituire una sequenza, o essere Seq -like. Ho la sensazione che le "interfacce" (protocolli) siano diverse ma non riesco a vedere come.

Sicuramente se stai togliendo il primo oggetto da un canale, puoi rappresentarlo come se togli il primo elemento da una sequenza?

La mia domanda è: Potrebbe core.async aver implementato le sue funzioni in termini di sequenze?

risposta

7

Sì, in un certo senso avrebbero potuto essere. Se si ignora andare blocchi (per il momento cerchiamo di farlo), allora non c'è davvero niente di sbagliato con qualcosa come il seguente:

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

Ma bando qui la chiamata <!!. Questo è chiamato "prendere il blocco": all'interno di questa funzione ci sono alcune promesse e blocchi che causano l'arresto del thread attualmente in esecuzione fino a quando un valore non è disponibile sul canale. Quindi funzionerebbe bene se non ti dispiace avere un thread Java seduto lì senza fare nulla.

L'idea che sta dietro i blocchi è rendere i processi logici molto più economici; per fare ciò, il blocco go riscrive il corpo del blocco in una serie di callback che sono collegati al canale, in modo che internamente una chiamata a <! all'interno di un blocco go venga trasformata in qualcosa come questo (take! c k) dove k è un callback al resto del blocco go.

Ora, se avessimo reali continuazioni o se la JVM supportava thread leggeri, allora sì, potremmo combinare go-block e blocking take. Ma questo attualmente richiede una profonda riscrittura del bytecode (come fa il progetto Pulsar/Quasar) o alcune funzionalità JVM non standard. Entrambe queste opzioni sono state escluse nella creazione di core.async in favore del molto più semplice da implementare (e si spera molto più semplice da ragionare) sulla trasformazione del blocco locale.

Problemi correlati