hyperfiddle

2025-04-19T10:26:10.895349Z

Does Electric have a way to create dynamic bindings that I only know about at runtime? (`binding` is a compile-time thing — I need to mention the things I want to bind in the source code. If I try with-bindings or with-bindings* I get an “Electric code inside a Clojure function” error.)

2025-04-19T10:31:18.527509Z

I’ve implemented a replacement for Electric v2's e/def that seems to work reasonably well. It’s a macro that defines a bunch of things, and there’s a need to bind dynamic vars at the app’s top level. And those vars are only known about at run time.

2025-04-19T10:34:08.304919Z

Currently I have to touch the top-level namespace to get it to recompile every time I add a new one of these vars, because the binding thing only knows what vars to bind at compile time.

2025-04-19T10:36:30.366489Z

Actually, ignore this. I think it can’t work. The thing that contains the list of things to bind isn’t and probably can’t be an Electric value, so no.

henrik 2025-04-19T11:22:09.817549Z

Does dynamic bindings not exist in v3?

2025-04-19T11:22:52.783779Z

bindings works fine, but you need to mention the things to bind in your source code.

henrik 2025-04-19T11:23:40.846179Z

Ah, so you essentially want a dynamic set of vars in the binding vector?

2025-04-19T11:23:49.980449Z

Yes, exactly

henrik 2025-04-19T11:24:24.525309Z

Why not just bind a well-known var to a map with dynamic vars as keys?

👍 1
henrik 2025-04-19T11:24:50.470059Z

Or an atom, if you want it to have mutable semantics.

2025-04-19T11:25:06.991309Z

I think because of grain size of updates

2025-04-19T11:25:16.199649Z

Reactive updates

henrik 2025-04-19T11:26:56.600589Z

If you let a get into a map then, sure, the get will rerun every time the map changes, but that’s very cheap. Whatever depends on the get will not rerun unless its return value changes.

henrik 2025-04-19T11:28:04.193299Z

Although this is from kind of a Big-O perspective, maybe there are subtleties to v3 here.

2025-04-19T11:29:12.835699Z

Hmmm, yes. I will give that a go. Thanks. (I now have the thing that contains the list of things to bind as an Electric value, so I can try this.)

Dustin Getz (Hyperfiddle) 2025-04-19T11:55:07.433669Z

i am very confused, please post code

Dustin Getz (Hyperfiddle) 2025-04-19T11:56:41.445429Z

a clojure map has a dynamic keyset, this implies looping over the present keyset since your code has no static knowledge of the keyset is that correct?

Dustin Getz (Hyperfiddle) 2025-04-19T11:58:35.627829Z

you'd use e/diff-by over the keyset in order to get downstream reactive updates. you'll pay the diff-by each time the keyset changes. I think we can assume the keyset is small enough to pay the O(n) diff-by, because if you were writing clojure you would similarly be using O(n) operators such as reduce over the map and not be too worried about it

Dustin Getz (Hyperfiddle) 2025-04-19T12:00:08.875449Z

the next level up would be to represent the keyset natively in e/amb (at least until we use e/amb and e/fn to implement an electric-native ReactiveMap datatype giving you the usual get/assoc APIs but reactive)

Dustin Getz (Hyperfiddle) 2025-04-19T12:01:07.933469Z

if you experience performance issues, it may not be the O(n) e/diff-by that is the problem, it may be something else, like accidental roundtrips or accidental transfer of the whole collection inside a loop, stuff like that

2025-04-19T15:42:04.969879Z

Thanks for all that. I need to have a think about all this. I won’t post code for now, but I might at some later point after I have thought more.

Dustin Getz (Hyperfiddle) 2025-04-19T01:45:01.364619Z

Cool demo from Geoffrey and Peter, using Electric process supervision to terminate a server query that is taking too long. The thread/sleep is L58

👍 4
👌🏼 1
henrik 2025-04-19T07:09:02.750869Z

How does this not block the server thread? Is it running on virtual threads?

henrik 2025-04-19T08:56:13.447449Z

Nvm, offload

Dustin Getz (Hyperfiddle) 2025-04-19T01:47:38.324829Z

this one is for the datomic users 😉

1
⚡ 1