Fork me on GitHub
#hyperfiddle
<
2023-05-01
>
andersmurphy17:05:34

Which of the the models presented in this blog post if any best describes electrics rendering/state model? https://tonsky.me/blog/humble-state/ electric doesn’t have a vdom right? It’s reactive incremental computations?

Dustin Getz18:05:26

at a quick glance, we match the phrase “surgical point updates” and “incremental” - however i cannot endorse the accuracy of the post or any claims it makes or implies about Electric

🙏 1
markaddleman20:05:34

Are the semantics of Pending supposed to match a real exception? The following code produces non-intuitive results:

(try
      (new (e/fn [n]
             (let [n (e/server (Thread/sleep n) n)]
               (e/client (dom/text (str "loaded after " n "ms")))))
           1000)
      (println "loaded")
      (catch Pending _
        (println "waiting...")))

2
markaddleman20:05:23

On the console, I see “loaded” followed immediately by “waiting…”

markaddleman20:05:33

My desired behavior is for the catch block to be executed and, when e/fn completes, I’d see “loaded”

markaddleman20:05:50

Is there an idiomatic means to force the desired behavior?

noonian20:05:22

I'm not sure about idiomatic, but I think one way to do it is to make the expression that prints "loaded" use the return value of calling the photon fn. You could do this by writing a macro that just discards the first arg value and returns the second then use that to call println. I believe the behavior you are seeing is because the "println" expression and the "new" expression are effectively executing in parallel which is why you see "loaded" print immediately

markaddleman20:05:47

Yeah, I was just experimenting with a similar approach. In the real case, the e/fn can return a value or nil so I end up writing some silliness. Fortunately, the electric compiler does not try to short-circuit expressions :)

(try
      (let [v (new (e/fn [n]
                     (let [n (e/server (Thread/sleep n) n)]
                       (e/client (dom/text (str "loaded after " n "ms")))))
                   1000)]
        (when (or v (not v))
          (println "loaded")))
      (catch Pending _
        (println "waiting...")))

noonian20:05:40

Yeah similar idea. I'm curious, does it do what you want if you just have (do v (println "loaded"))? I suspect it tries to parallelize do blocks but I'm not sure. v won't have a value until the function executes but I'm not at my computer atm to check

xificurC20:05:21

do indeed runs the branches concurrently To wait for a Pending to resolve for now we sequence with case.

(case a b)
b will run when a won't be exceptional

💯 2
xificurC20:05:46

Thread.sleep blocks the main thread and therefore the whole graph. You can use a missionary sleep to wait and not block the world

(case (new (e/task->cp (m/sleep n)))
  b)

markaddleman21:05:56

Thanks. Of course, this was all for demo purposes but it’s good to know that m/sleep exists

Dustin Getz21:05:20

think of it this way - (do (dom/div) (dom/div)) will mount both divs. think of them as components not statements. if they contain reactive dependencies then they will be maintained concurrently. Note that (do (println 1) (println 2)) will mount the printlns in order (and then never touch them again as the exprs are constant), so this is backwards compatible with clojure

xificurC06:05:31

the ordering is not yet guaranteed btw. It works and probably won't change. Cancellation order we're discussing too

👍 2
xificurC06:05:24

re demo purpuses - sure. I just wanted to point it out since it can trip up demos where you expect some server reactivity

👍 2