This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
Electric + electron apps are gonna be fire. I threw this together in ~30m. https://github.com/JJ-Atkinson/electric-starter-app/tree/54c6f63c44cfe214b20efc133e8996653c5803a0
yes!!!!!
I get Missing client program manifest
any idea why?
oh, missing package.json
also missing file-information.edn
what is this?
bin/kondo: line 2: clj-kondo: command not found
Ah, so clj kondo the linter. Im Surprised you don’t have it. I can put that file here temporarily. I’ll be back with it in 10m
it's integrated with vscode
I jsut don't want to guess what your dev setup might be
i will run `
brew install borkdude/brew/clj-kondo
`i have the app partially up now, there are compile time errors such as
Can you commit and push the version that ran?
I must've renamed the var just before pushing and not got an error, or I didn't see it.
it builds now but with javascript errors in console, do you have them also?
main.js:1426 TypeError: add[0].set is not a function
also i get
core.cljs:3953 Cannot read properties of undefined (reading 'cljs$lang$applyTo')
in ( contrib.electric-codemirror/codemirror {:parent #object[HTMLDivElement [object HTMLDivElement]]} ) in contrib/electric_codemirror.cljc
when i click on a var to try to trigger "open files"
re. package.json yeah that's my fault. I pulled a stupid and didn't add it to git. I'm clearing my node-modules now and restarting
we might have mismatched package.json
i dont understand the cm error
its probably caused by the js error prior, which is in codemirror stack frame
is nix managing package.json?
or npm or yarn ?
no worries
do you know why Kondo doesn't see the vars in the todo-app ns?
app.todo-list
take 5
It's been a wacky couple months, but I think I've got time again to try out the pathom + electric stuff. will report back soon I hope with something interesting on that front
looking forward to that!
Lol you caught me scrolling Twitter. Btw the reason the defn line wasn’t visible in one of the boxes is that you hadn’t rerun kondo and re loaded the slurped def
oh did i f up the video
i hadnn't, damn
Up to you if ya wanna change it. I only noticed cuz I did the same thing a couple times last night.
will you put this code in the public domain, i might run with it
the whole repo, i have to be careful with licenses
the UI and source-parser
we already have something similar I am just dotting is and crossing ts
thanks
If it weren't such a dead end time sink, this would be pretty fun to turn into the lighttable code bubbles thing that never was implemented.
ha yeah
Warning -- New Electric User I'm seeing errors like below. I thought that they were from me using try/catch but it is something different. Ideas?
clj -A:dev -X user/main
Starting Electric compiler and server...
shadow-cljs - server version: 2.20.1 running at
shadow-cljs - nREPL server started on port 9001
[:dev] Configuring build.
[:dev] Compiling ...
[:dev] Build failure:
------ ERROR -------------------------------------------------------------------
File: /src/user.cljs:8:3
--------------------------------------------------------------------------------
5 | hyperfiddle.electric-dom2))
6 |
7 | (def electric-main
8 | (hyperfiddle.electric/boot ; Electric macroexpansion - Clojure to signals compiler
---------^----------------------------------------------------------------------
Encountered error when macroexpanding hyperfiddle.electric/boot.
Unable to resolve symbol: e/*http-request*
{:file "app/dashboard.cljc", :in [e/*http-request*]}
ExceptionInfo: Unable to resolve symbol: e/*http-request*
hyperfiddle.electric.impl.compiler/analyze-form (compiler.clj:647)
hyperfiddle.electric.impl.compiler/analyze-form (compiler.clj:632)
hyperfiddle.electric.impl.compiler/eval30807/analyze--30813/fn--30818/fn--30819 (compiler.clj:700)
hyperfiddle.electric.impl.compiler/eval30807/analyze--30813/fn--30818 (compiler.clj:699)
hyperfiddle.electric.impl.compiler/eval30807/analyze--30813 (compiler.clj:688)
hyperfiddle.electric/boot (electric.cljc:378)
hyperfiddle.electric/boot (electric.cljc:373)
...
try wrapping e/http-request in e/server
Cool -- Will do.
Something like this from the starter app? If that is correct, then II still have the problem
(let [session-id
(e/server (get-in e/*http-request* [:headers "sec-websocket-key"]))
api-key
(e/server (get-in e/*http-request* [:cookies "username" :value]))
]
...
I think that I see the problem in my code. Let me try a few more things...
Stupid typo in a :require
file (misnamed variable).
I want to supply a callback to cytoscape and I get an error when clicking (invoking e/fn callback):
n.call is not a function
My code:
(dom/div (dom/props {:id "cy"
:class "cy"})
(let [container (.getElementById js/document "cy")
opts (get-cy-opts nodes edges container)]
(.use cytoscape cy-elk)
(let [cy (cytoscape (clj->js opts))]
;; I guess error is in this callback
(.on cy "tap" "node" (e/fn [e]
(let [node-id (-> e .-target .id)]
(println "clicked" node-id)
(e/server (println "clicked" node-id)))))))
nil)
Is e/fn
not interchangeable with functions (specifically for callbacks)?
How would I update the server that a selection was made? Specifically I want to update my db but I can't access it for updates (`!conn`) on the client afaict.
For now it just attempts to print what node was clicked on the client and switch to the server and print there as well.yes e/fn and clojure.core/fn are different types
the quick dirty way forward is to swap an atom in a clojure callback and then watch the atom from electric - this is the side effect way
the better way is to adapt the event emitter into a missionary flow with m/observe and then use ‘new’ to await the missionary flow from electric - this is the functional way. search m/observe for several examples
I thought about an atom side effect but was wondering if there is something simpler. I will search m/observe but I don't know anything about it.
atom way is 100% ok
actually I don't know how to do it. I know how to use an atom on the backend and watch
it on the front end, but I don't know how to pass values the other way without an e/server
block (which is basically the network).
I'll have to think about it.
you need an atom on the frontend in local scope to mediate the bridge
callback swaps local atom
watch atom to get electric reactive value
now you can use e/server on that value
I can watch client atoms? I thought it only works the other way around. Let me mess with it for a bit see if I understand
(when-some [x (e/watch !mediator)] (e/server (println x)))
that’s a “callback”
maybe you need to reset atom to nil after it depends on your use case
I understand the other stuff, just the fact you can e/watch
on the client was missing to me
it is probably worth reading about the m/observe approach too even if you don’t use it, because you’ll end up there eventually it just might take a couple tries for it to “click”
yeah it feels kind of familiar jargon-wise because I used to use rx-java a lot (even contributed an zip operator a long time ago)
but I don't know if it's actually the same
one day I'll have a big enough commitment to read about missionary 🙂
oh ok great yeah missionary is like that
it’s learned best by example
atom works btw! I was just missing that I can (e/client (e/watch some-atom))
and not just (e/server (e/watch some-atom))
If cc/let
implies a do
, and do
is parallel in Electric, what is the execution order of let
in Electric? Do the let-clauses execute sequentially or in order of topological dependence if a subsequent clause depends on the one above, or is there an m/sp
in there somewhere?
the let bindings evaluate sequentially when the let boots, the do is implicit only in the let body
any unused let binding will still be evaluated for effect (same as clojure)
even when we say do is parallel, it still is touched left to right on first render
Your question is great – let may indeed match semantics of do in terms of what happens if an exception is thrown (e.g. pending) in an intermediate let binding – i think the rest of the let bindings will still evaluate
If one of the let bindings changes, do all the let-clauses evaluate in lexical order?
e.g.
(let [a X
_ (prn "thing")
b Y ;; e.g. if Y changes
c Z]
(+ a b c))
reactive updates are fine-grained, only the expression whose input changed will rerun
so put the prn last, if Y changes the prn should not "reboot" because it's argument is constant
@U09FL65DK is this correct have I made any mistake?
so prn won't rerun unless it touches Y?
prn has invariable arguments (the string literal is constant), wrt updates the topographical ordering is irrelevant
so my understanding of Electric today is that the prn will only run on boot (in order of let-clauses) unless prn touches a binding that changed, in which case it will rerun in...unspecified order?
e.g. if there are two prns that touch Y
(let [a X
b Y ;; e.g. if Y changes
_ (prn :first Y) ;; are order of prn effects defined?
_ (prn :second Y)
c Z]
(+ a b c))
here, ummm i think when Y updates the two prns will be touched in lexical order (left to right) though technically this may be undefined behavior today
they will absolutely be touched in the same reactive propagation frame, you'll see neither or both, never inconsistent
asking because you can imagine clojure peeps expect let to be ordered, so if two effects depend on Y (and only Y), you might expect both effects to run in the order they are defined. I don't have a concrete case, but you could imagine transacting something and then blocking on the tx.
i think we currently satisfy that
note it's complicated, if instead of prn
we have more Electric components (deeper DAG), inside that DAG may be more latency
ordering is largely UB (undefined behavior) and subject to change. Today those 2 prns will run in program order. Order of them re-running when Y changes is also UB. If you have a specific case where ordering is necessary we can take a look
@U09FL65DK i think we intended to lock this down (as the impl currently does the desired thing despite not being formally guaranteed), right? Subject to any larger design changes the future might hold
we discussed ordering guarantees but that issue is on the backlog. So yes, I don't see any changes happening to that anytime soon
No specific cases right now - just trying to understand Electric's behaviour. Anytime I need to think about order I just put it in a cc/defn
outside e-fn.