Skip to content

Commit

Permalink
[runtime] lazy drain
Browse files Browse the repository at this point in the history
We experimented with eager drain. In `(do (a) (b))` we don't care about
the return value of `(a)` and with eager drain we can discard the return
value without notifying through the graph.

The problem is it introduces inconsistencies, e.g. in

    (when-let [x (e/watch !x)]
      (prn x)
      (do-something-with x))

the `(prn x)` form will run even when `x` turns falsy, because of its
over-eagerness.

This commit switches to a lazy drain implementation to fix the
inconsistencies at the cost of additional graph churn.
  • Loading branch information
xificurC committed Sep 16, 2024
1 parent 8f78d9e commit 75d0690
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
8 changes: 3 additions & 5 deletions src/hyperfiddle/electric/impl/runtime3.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
(:refer-clojure :exclude [resolve])
(:require [hyperfiddle.incseq :as i]
[missionary.core :as m]
[cognitect.transit :as t])
[cognitect.transit :as t]
[hyperfiddle.incseq.diff-impl :as d])
(:import missionary.Cancelled
#?(:clj (clojure.lang IFn IDeref))
#?(:clj (java.io ByteArrayInputStream ByteArrayOutputStream Writer))
Expand Down Expand Up @@ -223,10 +224,7 @@ T T T -> (EXPR T)
(defn drain "
(IS T) -> (IS VOID)
" [incseq]
(let [signal (m/signal i/combine incseq)]
(m/ap
(m/amb (i/empty-diff 0)
(do (m/?> signal) (m/amb))))))
(m/latest (constantly (d/empty-diff 0)) incseq))

(defn error [^String msg]
#?(:clj (Error. msg)
Expand Down
25 changes: 24 additions & 1 deletion test/hyperfiddle/electric3_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2287,4 +2287,27 @@
#_init % := :branch
(swap! !x not) % := :unmount
(swap! !x not) % := :branch
(swap! !x not) % := :unmount)))
(swap! !x not) % := :unmount)))

(tests
(let [!x (atom false)]
(with ((l/single {}
(when-let [x (e/watch !x)]
(tap x)
(e/OnUnmount #(tap :bye)))) {} {})
(reset! !x 1) % := 1
(swap! !x inc) % := 2
(swap! !x inc) % := 3
(reset! !x false) % := :bye)))

(tests
(let [!x (atom false)]
(with ((l/single {}
(if-let [x (e/watch !x)]
(tap x)
(tap :not))) {} {})
#_init % := :not
(reset! !x 1) % := 1
(swap! !x inc) % := 2
(swap! !x inc) % := 3
(reset! !x false) % := :not)))

0 comments on commit 75d0690

Please sign in to comment.