code-reviews 2021-09-07

on the JVM where there is no real stack storage of data, "store the state of the function" would mean reifying the stack pointer (entrypoint) and call stack (what you return to) into something you can execute later by interpreting it, and storing all scoped heap references in a way you can later restore.

this is expensive, because as far as I know the only way to have a resumable continuation on the jvm is to use an interpreter (IOW use a reified stack for your code, and put an interpreter in the actual stack)

I'm basing what I'm saying on my understanding of the jvm - it can't do goto past method boundaries which is a pre-requisite for non-interpreted continuations

I'd be interested in being proved wrong actually

oh! you mean loom the jvm project

yes, that's awesome and up and coming, it totally changes what the jvm can do

I was thinking of loom the graph library lol

right, so continuations are coming... eventually

well for "fun" stuff i don't see a reason to wait to use the ea builds

rust people build companies on nightly

I'm a "Rust person" building a company on nightly. I wish I wasn't, but there's some embedded stuff that just can't be done on stable yet.

(import java.lang.Continuation)
=> java.lang.Continuation
(import java.lang.ContinuationScope)
=> java.lang.ContinuationScope
(ContinuationScope. "scope")
=> #object[java.lang.ContinuationScope 0x4356af7c "scope"]
(def default-scope (ContinuationScope. "scope"))
=> #'user/default-scope
(Continuation. default-scope (fn []
                               (println "A")
                               (Continuation/yield default-scope)
                               (println "B")))
=> #object[java.lang.Continuation 0x3a99c9b2 "java.lang.Continuation@3a99c9b2 scope: scope"]
(def cont (Continuation. default-scope (fn []
                                         (println "A")
                                         (Continuation/yield default-scope)
                                         (println "B"))))
=> #'user/cont
(.run cont)
A
=> nil
(.run cont)
B
=> nil
(.run cont)
Execution error (IllegalStateException) at java.lang.Continuation/run (Continuation.java:286).
Continuation terminated

(defn generator [f]
  (let [last-val (volatile! nil)
        scope (ContinuationScope. "generator")
        continuation (Continuation. scope (fn []
                                            (f (fn [v]
                                                 (vreset! last-val v)
                                                 (Continuation/yield scope)))))]
    (reify Iterator 
      (hasNext [_]
        (not (.isDone continuation)))
      (next [_]
        (.run continuation)
        @last-val))))
=> #'user/generator
(def gen (generator 
           (fn [yield]
             (doseq [x (range 10)]
               (yield x)))))
=> #'user/gen
(iterator-seq gen)
=> (0 1 2 3 4 5 6 7 8 9 9)

(defn generator [f]
  (let [no-yield (Object.)
        last-val (volatile! no-yield)
        scope (ContinuationScope. "generator")
        continuation (Continuation. scope (fn []
                                            (f (fn [v]
                                                 (vreset! last-val v)
                                                 (Continuation/yield scope)))))]
    (reify Iterator 
      (hasNext [_]
        (and (not (.isDone continuation))
             (do (.run continuation)
                 (not= @last-val no-yield))))
      (next [_]
        (when (and (not (.isDone continuation)) (= @last-val no-yield))
          (.run continuation))
        (let [val @last-val]
          (vreset! last-val no-yield)
          val)))))
=> #'user/generator
(def gen (generator 
           (fn [yield]
             (doseq [x (range 10)]
               (yield x)))))
=> #'user/gen
(iterator-seq gen)
=> (1 2 3 4 5 6 7 8 9)