Working through the https://gorgeous-sorbet-a5a2bf.netlify.app/continuous-time.html, I have a total FRP-newb question:
If latest and signal are "fan-in and fan-out", then why do we need the extra signal in <diamond?
(def !input (atom 0))
(def <input (m/signal (m/watch !input)))
(def <diamond (m/signal (m/latest = <input <input)))
At the repl I can see that there'll be intermediate values without it, but can't wrap my head around why. I naively assumed (a single) signal would be some kind of a "sync point through memoization". Thanks!Thats what I did at the repl:
(defn flow-printer [<f]
((m/reduce (fn [_ v] (println :flow-state v)) nil <f)
(partial println :task-success)
(fn [e] (println :task-failure (.getMessage e)))))
(let [!x (atom 0)
<x (m/signal (m/watch !x))
task (flow-printer (m/latest = <x <x))] ; <== missing m/signal
(swap! !x inc)
(task))
;; :flow-state true
;; :flow-state false
;; :flow-state true
;; :task-failure Flow publisher cancelled.Yes, the second signal has no other purpose than controlling the timing of effects. m/reduce transfers synchronously, so you need an additional signal to delay the sampling until all upstream dependencies have updated, otherwise glitches can be observed - as you noticed.
Perfect, thank you!
Thank you!
(1) did I understand correctly that
• latest by itself returns a flow, not a publisher
• only publishers get pushed to the priority queue of the two-pass algorithm described in https://youtu.be/xtTCdT6e9-0?feature=shared&t=1577
• thus, if I fan-out with signal, I need another publisher somewhere down the chain,
• or the outcome will be the same as having no publisher at all
• this materializes, when the composed flow is syncronously reduced in a task [aside: are there other ways to "realize" a flow?]
(2) with cp/forking I can get a similar result (shown below)
• how should I decide which approach to use?
(let [!x (atom 0)
(1) Yes, correct (2) If you can solve your problem without signals, don't use them. Start without, the need will arise when the graph becomes more complex and requires to reuse intermediate computations