Skip to content

Instantly share code, notes, and snippets.

Last active November 27, 2020 22:29
What would you like to do?
(java.lang Continuation ContinuationScope)))
(let [effect-scope (ContinuationScope. "effect")
state (atom 0)
;; track what effect is currently being performed,
;; and what we're going to return
effect-performing (atom nil)
effect-returning (atom nil)
;; this atom gets set any time we `perform`
;; if we do not `resume`, this is left as `false`
stopped? (atom false)
resume (fn resume
(resume nil))
(reset! effect-returning x)
(reset! stopped? false)
put-state (fn [x]
(reset! state x)
(resume x))
get-state (fn []
(resume @state))
stop (fn []
(prn "stopping"))
perform (fn [& args]
;; any time we perform an effect, we yield to the parent context
;; and set some state that declares what effect is currently
;; performed
(reset! effect-performing (vec args)) ; e.g. [:get], [:put 2]
(Continuation/yield effect-scope)
;; once we've resumed (if we do), capture the return value
;; passed into `resume` and clear the global state
(let [ret @effect-returning]
(reset! effect-performing nil)
(reset! effect-returning nil)
;; create a continuation wrapping our effect-ful function
c1 (Continuation.
(fn []
(println "-")
(prn :get (perform :get))
(println "--")
(perform :put 1)
#_(perform :stop)
(prn :get (perform :get))
(println "---")
(perform :put 2)
#_(perform :stop)
(prn :get (perform :get))))]
(while (and (not @stopped?) (not (.isDone c1)))
(.run c1)
(reset! stopped? true)
;; handle effects
;; e.g. [:get], [:put 2]
(case (first @effect-performing)
:get (get-state)
:put (put-state (second @effect-performing))
:stop (stop)
nil nil))
(prn @state @effect-performing @effect-returning @stopped?))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment