hyperfiddle

braai engineer 2025-10-29T12:37:29.745339Z

wd guys I'm seeing a significant performance boost with the new lockless impl., with no regressions so far. General Electric performance question: given a nested tree of Electric component nodes and a global atom containing expansion data (e.g. (let [expand? (boolean (get (e/watch !state) node-id))] ...), is it faster to (e/watch !state) the state in the top-level / root component and pass the value down the tree as a component argument, or to (e/watch !state) in each node?

xificurC 2025-10-29T12:44:24.585999Z

one should e/watch an atom only once, multiple watches can cause glitches

xificurC 2025-10-29T12:47:01.560069Z

if there's a perf diff idk

braai engineer 2025-10-29T12:48:45.813359Z

oh dear, I didn't know that. I have e/watch all over the place, and I can confirm the state glitches. Resolved by e/watch in root and passing down as arg.

braai engineer 2025-10-29T12:50:04.425009Z

can you safely e/watch the same atom multiple times in distinct, non-nested, components?

xificurC 2025-10-29T12:58:43.794119Z

it is always safe but glitch-prone. I'd either pass it to all components or bind in a binding

braai engineer 2025-10-29T12:59:06.799659Z

Perf. difference between passing down vs dynamic binding?

leonoel 2025-10-29T13:21:39.939239Z

> Perf. difference between passing down vs dynamic binding? argument passing is implemented with dynamic bindings, there should be no difference

Dustin Getz (Hyperfiddle) 2025-10-29T14:48:18.224829Z

the lockfree release does contain an optimization which is unrelated to the removal of the locks

👍 1
braai engineer 2025-10-29T13:11:56.286129Z

https://github.com/henryw374/time-literals for data readers like #time/date "2025-10-29" works in dev but fails in uberjar production compilation:

165 | (e/defn MyComponent [data {:keys [width height
-------^------------------------------------------------------------------------
Encountered error when macroexpanding hyperfiddle.electric3/defn.
IllegalStateException: Attempting to call unbound fn: #'time-literals.data-readers/date
	clojure.lang.Var$Unbound.throwArity (Var.java:47)
despite #time/date not used in that component (only in caller). Is there a trick to get custom data readers working with Electric v3, or is this not an Electric issue? btw. I don't think this is new i.e. not related to lockless impl.

xificurC 2025-10-29T13:42:36.474769Z

does the literal work if you put it in clojure defn? Don't put a reader conditional around that defn. Electric compiles on clj and cljs so this will test if both are correctly set up. For the same reason #js doesn't work in electric code. If the reader works in a defn then it's an electric bug

braai engineer 2025-10-29T13:44:01.230859Z

by the last defn, do you e/defn or clj defn? #time/date works in an e/defn in dev build

xificurC 2025-10-29T14:45:44.535989Z

if it works in cc/defn it's an electric bug

2025-10-29T22:30:53.257169Z

i'm trying to troubleshoot a simple e/fn handler

(e/defn InvokeChild [on-trigger]
  (dom/div
    (dom/button
     (dom/text "press me")
     (let [[ack err] (e/Token (dom/On "click" identity nil))] 
          (when ack
            (println "CLIENT")
            (if (= (on-trigger (rand-int 10)) ::handled)
              (ack)
              (ack "error")))))))

(e/defn Demo []
  (dom/div
   (InvokeChild
    (e/fn [v]
      (e/client (println "CLIENT HANDLER" v))
      (e/server (println "SERVER HANDLER" v)
                ::handled))))) 
when i click the button, i see CLIENT but not CLIENT HANDLER or SERVER HANDLER in the logs. what gives?

Hendrik 2025-10-30T10:13:43.909949Z

The call convention for electric functions is, that these must begin with a capital letter or explicitly called as an electric function. In your example electric tries to call on-trigger as a normal clojure function. Change on-trigger to On-trigger .

👍 1
🙏 1