Ricerca…


operazioni di base del canale: creazione, inserimento, chiusura, chiusura e buffer.

core.async riguarda i processi che prendono valori e inseriscono valori nei canali .

(require [clojure.core.async :as a])

Creazione di canali con chan

Crei un canale usando la funzione chan :

(def chan-0 (a/chan)) ;; unbuffered channel: acts as a rendez-vous point.
(def chan-1 (a/chan 3)) ;; channel with a buffer of size 3. 
(def chan-2 (a/chan (a/dropping-buffer 3)) ;; channel with a *dropping* buffer of size 3
(def chan-3 (a/chan (a/sliding-buffer 3)) ;; channel with a *sliding* buffer of size 3

Mettere valori in canali con >!! e >!

Metti i valori in un canale con >!! :

(a/>!! my-channel :an-item)

Puoi inserire qualsiasi valore (stringhe, numeri, mappe, raccolte, oggetti, persino altri canali, ecc.) In un canale, tranne nil :

;; WON'T WORK
(a/>!! my-channel nil)
=> IllegalArgumentException Can't put nil on channel

A seconda del buffer del canale, >!! potrebbe bloccare il thread corrente.

(let [ch (a/chan)] ;; unbuffered channel
  (a/>!! ch :item) 
  ;; the above call blocks, until another process 
  ;; takes the item from the channel.
  )
(let [ch (a/chan 3)] ;; channel with 3-size buffer
  (a/>!! ch :item-1) ;; => true
  (a/>!! ch :item-2) ;; => true
  (a/>!! ch :item-3) ;; => true
  (a/>!! ch :item-4) 
  ;; now the buffer is full; blocks until :item-1 is taken from ch.
  )

Dall'interno di un blocco (go ...) , puoi - e dovresti - usare a/>! invece di a/>!! :

 (a/go (a/>! ch :item))

Il comportamento logico sarà lo stesso di a/>!! , ma solo il processo logico della goroutine bloccherà invece del thread effettivo del sistema operativo.

Usando a/>!! all'interno di un blocco (go ...) c'è un anti-pattern:

;; NEVER DO THIS
(a/go 
  (a/>!! ch :item))

Prendendo i valori dai canali con <!!

Prendi un valore da un canale usando <!! :

;; creating a channel
(def ch (a/chan 3))
;; putting some items in it
(do 
  (a/>!! ch :item-1)
  (a/>!! ch :item-2)
  (a/>!! ch :item-3))
;; taking a value
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2

Se nessun elemento è disponibile nel canale, a/<!! bloccherà il thread corrente fino a quando non viene inserito un valore nel canale (o il canale è chiuso, vedi dopo):

(def ch (a/chan))
(a/<!! ch) ;; blocks until another process puts something into ch or closes it

Dall'interno di un blocco (go ...) , puoi - e dovresti - usare a/<! invece di a/<!! :

 (a/go (let [x (a/<! ch)] ...))

Il comportamento logico sarà lo stesso di a/<!! , ma solo il processo logico della goroutine bloccherà invece del thread effettivo del sistema operativo.

Usando a/<!! all'interno di un blocco (go ...) c'è un anti-pattern:

;; NEVER DO THIS
(a/go 
  (a/<!! ch))

Canali di chiusura

Chiudi un canale con a/close! :

(a/close! ch)

Una volta che un canale è stato chiuso e tutti i dati nel canale sono stati esauriti, i nil restituiranno sempre nil :

(def ch (a/chan 5))

;; putting 2 values in the channel, then closing it
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/close! ch)

;; taking from ch will return the items that were put in it, then nil
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil

;; once the channel is closed, >!! will have no effect on the channel:
(a/>!! ch :item-3)
=> false ;; false means the put did not succeed
(a/<!! ch) ;; => nil

Mette asincrono con put!

In alternativa a a/>!! (che può bloccare), puoi chiamare a/put! inserire un valore in un canale in un altro thread, con un callback opzionale.

(a/put! ch :item)
(a/put! ch :item (fn once-put [closed?] ...)) ;; callback function, will receive 

In ClojureScript, poiché bloccare il thread corrente non è possibile, a/>!! non è supportato e put! è l'unico modo per mettere i dati in un canale al di fuori di un blocco (go) .

Asincrono prende con take!

In alternativa a a/<!! (che potrebbe bloccare il thread corrente), puoi usare a/take! per prendere un valore da un canale in modo asincrono, passandolo a un callback.

(a/take! ch (fn [x] (do something with x)))

Usando i buffers dropping e sliding

Con i buffer dropping e sliding, puts non blocca mai, tuttavia, quando il buffer è pieno, si perdono i dati. Il buffer in uscita perde gli ultimi dati aggiunti, mentre i buffer di scorrimento perdono i primi dati aggiunti.

Esempio di buffer di rilascio:

(def ch (a/chan (a/dropping-buffer 2)))

;; putting more items than buffer size
(a/>!! ch :item-1)
=> true ;; put succeeded
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> false ;; put failed

;; no we take from the channel
(a/<!! ch)
=> :item-1
(a/<!! ch)
=> :item-2
(a/<!! ch)
;; blocks! :item-3 is lost

Esempio di buffer scorrevole:

(def ch (a/chan (a/sliding-buffer 2)))

;; putting more items than buffer size
(a/>!! ch :item-1)
=> true
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> true

;; no when we take from the channel:
(a/<!! ch)
=> :item-2
(a/<!! ch)
=> :item-3
;; :item-1 was lost


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow