Add the following dependency to your
Reagi introduces two new reference types, behaviors and event streams, which are collectively known as signals.
user=> (require '[reagi.core :as r]) nil
A behavior models continuous change, and is evaluated each time you dereference it.
user=> (def t (r/behavior (System/currentTimeMillis))) #'user/t user=> @t 1380475144266 user=> @t 1380475175587
An event stream models a series of discrete changes. Events must be expicitly delivered to the stream. Dereferencing the event stream returns the last value pushed onto the stream.
user=> (def e (r/events)) #'user/e user=> (r/deliver e 1) #<Events@66d278af: 1> user=> @e 1
If the event stream is empty (i.e. unrealized), dereferencing it will block the running thread, much like a promise.
Unlike promises, event streams can have more than one value delivered to them, and may be constructed with an initial value:
user=> (def e (r/events 1)) #'user/e user=> @e 1
Reagi provides a number of functions for transforming event streams, which mimic many of the standard Clojure functions for dealing with seqs:
user=> (def incremented (r/map inc e)) #'user/m user=> (r/deliver e 2) #<Events@66d278af: 2> user=> @incremented 3
For a full list, see the API docs.
Event streams can interoperate with core.async channels using
port function returns a write-only stream that
will deliver values to the stream:
user=> (>!! (r/port e) 3) true user=> @e 3
subscribe function allows an existing channel to be registered
as an output for the stream.
user=> (def ch (async/chan 1)) #'user/ch user=> (r/subscribe e ch) #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@3b4df45f> user=> (r/deliver e 4) #<Events@66d278af: 4> user=> (<!! ch) 4
Note that this may cause the source stream to block if you don't consume the items in the channel, or provide a sufficient buffer.
Behaviors can be converted to event streams by sampling them at a specified interval in milliseconds:
user=> (def et (r/sample 1000 t)) #'user/et user=> @et 1380475969885
Signals can be completed with the
completed function, which acts in
a similar fashion to
clojure.core/reduced. Signals that are
completed will always deref to the same value. Any values pushed to a
completed event stream will be ignored.
user=> (def e (r/events)) #'user/e user=> (r/deliver e (r/completed 1)) #<Events@66d278af: 1> user=> (r/deliver e 2) #<Events@66d278af: 1> user=> @e 1 user=> (r/complete? e) true
Differences in ClojureScript version
The ClojureScript version of Reagi has two main differences from the Clojure version:
Trying to deref an unrealized stream blocks the current thread in Clojure, but returned js/undefined in ClojureScript.
Event streams that fall out of scope in Clojure are automatically cleaned up. In ClojureScript, the
reagi.core/disposefunction must be manually called on streams before they fall out of scope.
Copyright © 2014 James Reeves
Distributed under the Eclipse Public License, the same as Clojure.