サーチ…


基本的なチャネル操作:作成、パッティング、テイク、クローズ、およびバッファー

core.asyncは、値を取得して値をチャネルに入れるプロセスのことです。

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

chanチャンネルを作成する

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

>!!チャンネルに値を入れる>!!>!

>!!使って値をチャンネルに入れます>!!

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

nil以外の任意の値(文字列、数値、地図、コレクション、オブジェクト、他のチャンネルなど)をチャンネルに入れることができます:

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

チャネルのバッファに応じて、 >!!現在のスレッドをブロックする可能性があります。

(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.
  )

内側から(go ...)ブロック、あなたができる-とすべきである-使用a/>! a/>!!代わりにa/>!!

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

論理的な振る舞いはa/>!!と同じですa/>!!実際のOSスレッドの代わりに、ゴルーチンの論理プロセスだけがブロックされます。

a/>!!を使うa/>!! (go ...)ブロックの内側はアンチパターンです:

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

<!!チャンネルから値を取る

あなたは<!!を使用してチャンネルから価値を得ています<!!

;; 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

チャンネルに項目がない場合はa/<!!値がチャンネルに入れられるまで(またはチャンネルが閉じられるまで、現在のスレッドをブロックします(後で参照してください):

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

内側から(go ...)ブロック、次のことができます-とすべきである-使用しますa/<! a/<!!代わりにa/<!!

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

論理的な振る舞いはa/<!!と同じになりますa/<!!実際のOSスレッドの代わりに、ゴルーチンの論理プロセスだけがブロックされます。

a/<!!を使用a/<!! (go ...)ブロックの内側はアンチパターンです:

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

チャネルをクローズする

あなたがチャネルをクローズ a/close!

(a/close! ch)

一度チャネルが閉じられ、そのチャネルのすべてのデータが使い果たされると、takeは常に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

非同期にput!put!

a/>!!代わりにa/>!! (ブロックするかもしれません)、あなたはa/put!呼び出すことができますa/put!オプションのコールバックを使用して、別のスレッドのチャネルに値を設定します。

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

ClojureScriptでは、現在のスレッドをブロックすることはできないのでa/>!!サポートされていませんput! (go)ブロックの外側からチャンネルにデータを入れる唯一の方法です。

非同期でテイクしtake!

a/<!!代わりにa/<!! (現在のスレッドをブロックする可能性があります)、 a/take!使うことができますa/take!チャネルから値を非同期的に取得し、コールバックに渡します。

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

ドロップおよびスライディングバッファの使用

ドロップやスライディングバッファでは、putはブロックされませんが、バッファがいっぱいになるとデータが失われます。スライディングバッファは追加された最初のデータを失うのに対して、ドロップバッファは最後に追加されたデータを失います。

ドロップバッファの例:

(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

スライディングバッファの例:

(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
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow