hyperfiddle

oλv 2025-03-03T10:41:42.006259Z

I have a task which prints “Hello world!” (def hello-world-task (m/sp (println "Hello world!"))) . When I call this task with (e/Task hello-world-task) it works correctly on both the client and the server. If however I inline the definition of hello-world-task in e/Task like so: (e/Task (m/sp (println "Hello world!"))) it fails to compile.

xificurC 2025-03-03T11:43:33.608519Z

I cannot repro locally. But there's a long standing design issue wrt inlining m/sp, m/ap, m/cp in electric and would strongly advise to extract them into clj(s) definitions for now. The underlying reason is missionary generates cloroutine code using object arrays. These are always pointer equal, resulting in electric work skipping subsequent calls

🗒️ 3
oλv 2025-03-03T13:33:42.340309Z

Thank you

tobias 2025-03-03T11:41:00.228259Z

In the webview2 tutorial https://electric.hyperfiddle.net/tutorial/webview2 I understand that online 26 we need to use e/call because the return value of (get m k) is an Electric thunk. But why don't we need to use e/call on line 19 when we call (Query), when Query is also an Electric thunk?

xificurC 2025-03-03T11:46:01.915189Z

v3 adopts a new shorthand calling convention. In v2 we used (Query.) for the shorthand, or (new Query). In v3 if the symbol starts with an uppercase char we interpret that as an electric call.

;; v2
(Query.)
(new Query)

;; v3
(Query)
(e/call Query)

xificurC 2025-03-03T11:46:32.445509Z

as you pointed out this shorthand is not possible with dynamic lookups like (get m k), so there one has to fall back to e/call

tobias 2025-03-03T11:51:52.177799Z

Ah, that makes sense, thanks!

oλv 2025-03-03T13:42:51.615649Z

I have a task factory: (defn print-task [s] (m/sp (println s))) which is used by some Electric code:

(let [test {:foo :bar}]                 
  ;; This prints:                       
  (e/Task (print-task test))            
  ;; This does not print:               
  (e/server (e/Task (print-task test))))
How come the server-side task invocation does not print anything? There’s no errors.

xificurC 2025-03-03T13:46:59.932019Z

it should. What is the surrounding context?

oλv 2025-03-03T13:50:25.974399Z

(when-some [event (dom/On "keydown" identity nil)]
  (when-some [[t _err] (e/Token event)]           
    (when t                                       
      (when (= (.-key event) "Enter")             
        (let [test {:foo :bar}]                   
          ;; This prints:                         
          (e/Task (print-task test))              
          ;; This does not print:                 
          (e/server (e/Task (print-task test))))) 
      (t))))                                      

xificurC 2025-03-03T13:52:07.984089Z

calling (t) will turn the token nil and unmount the when branch before the server finishes it, cancelling it. Does that explanation make sense?

xificurC 2025-03-03T13:52:49.785199Z

you have 2 effects, (t) and (print-task test), and you need to sequence them. Electric is concurrent, so the 2 are currently racing

xificurC 2025-03-03T13:53:08.043169Z

since one of them is on the server, due to latency it loses the race and gets unmounted

xificurC 2025-03-03T13:53:51.263239Z

the simplest way to sequence is to use case

(case (e/server (e/Task (print-task test)))
  (t))

xificurC 2025-03-03T13:54:35.543279Z

this (ab?)uses the conditional, it will only run the default branch when the test value transfers

oλv 2025-03-03T13:55:44.513639Z

I see. I’ve usually tried to sequence things with (apply last <code>)

oλv 2025-03-03T13:56:30.573599Z

Although that causes unintended transfers I think. So I’ll try the case-approach. Then I would need to consume the token in each branch right?

xificurC 2025-03-03T13:56:40.554309Z

that is valid too, I often write the equivalent of ((fn [_] (t)) (e/server (print-task test)))

👍 1
xificurC 2025-03-03T14:10:36.982069Z

> Then I would need to consume the token in each branch right? I don't see branches in your sample, but sure. Depending on the structure you might be able to lift the case out, around the branches

alex 2025-03-05T11:05:54.039719Z

I often write the equivalent@xifi give me an example please. I have the following code and I want each action to be executed synchronously step by step. Now I see that (conn/init-conn) (connection to db) is ignored

(e/defn Main [ring-request]
  (e/client
    (binding [dom/node js/document.body
              e/http-request (e/server ring-request)]
       
      #?(:cljs (glogi-console/install!))
      
      (routes/init!)
      
      #?(:cljs auth/listen-auth-state)

      (e/server #?(:clj (conn/init-conn)))
      
      (sh/Shell))))

xificurC 2025-03-05T11:34:37.088349Z

reader conditionals in electric code will break. The electric compiler needs to see the whole definition on both peers in order to correctly orchestrate. I don't see why all steps need sequencing here, but if they really do I guess I'd write it as below

👍 1
alex 2025-03-05T11:37:21.113999Z

Thank you!:)

😉 1
Jim Duey 2025-03-03T13:44:18.827489Z

Good morning. Learning the simple stuff. How do I attach an onclick handler to a button that will print a message to the browser console? And then how would I extend that to manipulate the DOM? No reactive stuff, just DOM actions.

Dustin Getz (Hyperfiddle) 2025-03-03T13:52:44.666769Z

https://electric.hyperfiddle.net/tutorial/system_properties

Dustin Getz (Hyperfiddle) 2025-03-03T13:52:58.318159Z

recommend going through the tutorials one at a time and replicating them on your machine

Dustin Getz (Hyperfiddle) 2025-03-03T13:53:33.056519Z

https://electric.hyperfiddle.net/tutorial/token_explainer has a button

Dustin Getz (Hyperfiddle) 2025-03-03T13:53:47.704299Z

https://electric.hyperfiddle.net/tutorial/webview_column_picker has checkboxes

Jim Duey 2025-03-03T14:00:06.049849Z

Wild. I thought I'd tried the simplest possible way to do this and it didn't work. But now it does. I thought I must have missed something in the tutorial.

Jim Duey 2025-03-03T14:23:44.582789Z

Ah. It seems there's some real jankiness with shadow-cljs. I got it working, but then it stopped working with the exact same code. And I get "stale output" warning.

Dustin Getz (Hyperfiddle) 2025-03-03T14:28:37.789169Z

you may need to hard refresh. the shadow "stale output" warning can be trusted. Chrome disrespecting cache headers has historically been an issue (idk if still is) and also having dev tools open gives you more options when you right click on the refresh button, as if to say "I'm a developer and I really mean it"

Jim Duey 2025-03-03T14:33:04.645369Z

Using Brave. And things are totally horked. Going to have to come back to this later.

tobias 2025-03-03T06:41:24.809139Z

In webview2 tutorial https://electric.hyperfiddle.net/tutorial/webview2 why does the code use e/Partial on line 54?

(e/Partial Teeshirt-orders db search (e/client (e/watch !sort-key)))
It seems like we supplied all the arguments so we don't need partial? Is it just a shorthand way of writing the following?
(e/fn [] (Teeshirt-orders db search (e/client (e/watch !sort-key))))

xificurC 2025-03-03T08:35:39.379789Z

yes

🙏 1
tobias 2025-03-03T06:43:52.452729Z

Also in webview2 tutorial, on line 29, what does the ! signify in the naming of the variable !e? I'm used to seeing that naming convention for atoms but I think in this case !e is just a map?

xificurC 2025-03-03T08:37:44.127089Z

it's a datomic entity object. Calling (:foo !e) can invoke IO, i.e. the object is "impure" and doesn't serialize

tobias 2025-03-03T10:58:34.157089Z

Got it, thanks!

Dustin Getz (Hyperfiddle) 2025-03-03T12:16:33.053359Z

we generally use !e bang prefix to mean "reference" because in electric it's extra important to keep track of things that can't or shouldn't cross wire

👍 3
Vincent 2025-03-20T13:26:47.587269Z

Is there a way for the compiler to know when things are crossing the wire and mark them accordingly? Like with a little zigzag orange underline for example?

Vincent 2025-03-20T13:27:57.378139Z

I think because incremental compilation works, this can in theory be created/made. Thoughts?