On Github dpp / clojurex2014
Clojure eXchange 2014 David Pollak / @dpp
Not Spike from My Little Pony
from How to Train Your Dragon (the book). The mark of those rebelling against Alvin the Treacherous.
Yes, this talk will contain a lot of seemingly random threads... I hope to pull it together in the end (and in under 50 minutes)
Spike sends messages from Ponyville to Princess Celstia in Equestria... across address spaces...
We can serialize Clojure data and send it to another address space such that it will have the same meaning when it's reified!
Thinking asynchronously...
Well...
Nothing is synchronous...
Exception some 'weird' quantum effects...
But...
We humans mostly gloss over asynchronousness.
core.async: linear instructions for non-linear execution
Spike: find the book Pinky: Find Applejack S&P: Look for gems
aka the gofor macro
(gofor [a (foo channel {:thing value :other_thing other_value})] :let [b (+ a 1)] [c (baz other_channel) d (moose third_channel {:p b} :timeout 45000] (println a b c) :error (println &err &at))
[a (foo channel {:thing value :other_thing other_value})]
sends a message to channel:
{:_cmd "foo" :thing value :other_thing other_value :_return a_created_channel}
Simultaneous dispatch & timeout
(def service-channel (dc/build-service ns))
In the namespace, we define functions:
(sc/defn ^:service get-42 :- sc/Num ([] 42) ([x :- sc/Num] (+ x 42))) (sc/defn ^:service plus-one :- sc/Num "Hello" [x :- sc/Num] (+ 1 x))
docs (_commands service)] :let [_ (println "Commands:\n" docs)
Commands: {get-42 Inputs: ([] [x :- sc/Num]) Returns: sc/Num Hello, plus-one Inputs: [x :- sc/Num] Returns: sc/Num}
(circ/gofor :let [other-root (circ/remote-root transport)] [the-chat-server (locate-service other-root {:service "chat"})] [_ (add-listener the-chat-server {:the-chan chat-listener})] (reset! chat-server the-chat-server) :error (.log js/console "Got error " &err " var " &var) )
(defn make-remote-calls [] (circ/gofor [answer (inc (circ/remote-root transport))] (do (swap! app-state assoc :text (str "Remote count: " answer)) (js/setTimeout make-remote-calls 1000) ) ))
root (circ/build-root-channel {"get" (fn [msg env] @count-atom) "inc" (fn [msg env] (swap! count-atom inc))}
{:_cmd "foo" :thing value :other_thing other_value :_return a_created_channel}
(defprotocol Transport "A transport to another address space" (remote-root "Returns a channel that is a way to send messages to the remote root" [this]) (close! "Close the transport" [this]) (proxy-info "GUID to Proxy functions" [this]) (serialize "Serialize a msg" [this info]) (deserialize "reify a msg" [this info]))
Dragonmark Repo: https://github.com/dragonmark