hyperfiddle

henrik 2025-04-26T12:23:45.461259Z

v3 question. In Chrome, I get the following. Not in Safari or Firefox. Is it normal, or have I likely misconfigured something?

Connecting...
14:19:04.779 electric.cljs:35 Reactor failure: missionary.Cancelled {message: undefined}
It seems to work fine.

Dustin Getz (Hyperfiddle) 2025-04-26T12:43:04.058719Z

you're not the first to report, i have escalated it internally we will clean this up

🙏 1
euccastro 2025-04-26T17:56:22.312259Z

For me it only happens when I live-reload code. Also (perhaps unrelated) some interactions freeze for about 1sec when I have Chrome developer tools open, but are instantaneous otherwise. I can publish the repo where this happens if it helps

henrik 2025-04-26T21:15:07.602919Z

Chrome dev tools is a real resource hog, it slows things down enormously in our app. But yeah, I think you’re right, it’s possibly a live reload thing. Maybe “cosmetic” in the grand scheme of things even, seeing as the other two browser don’t have a problem, and I’m not seeing any particular problems that I would suspect to be Chrome-only.

henrik 2025-04-26T12:44:20.610459Z

Another question as I’m slowly requiring some existing files. How should I approach this interaction with Encore (via Telemere, Nippy, etc.)?

cannot-expand [co.multiply.client co.multiply.module.agent.query co.multiply.app.util.anomaly taoensso.telemere taoensso.encore] (#'taoensso.encore/defalias get-truss-data taoensso.truss/get-data nil nil)
:failed-to-analyze [co.multiply.client co.multiply.module.agent.query co.multiply.app.util.anomaly taoensso.telemere taoensso.encore]
:failed-to-analyze [co.multiply.client co.multiply.module.agent.query co.multiply.app.util.anomaly taoensso.telemere]
:failed-to-analyze [co.multiply.client co.multiply.module.agent.query co.multiply.app.util.anomaly]
:failed-to-analyze [co.multiply.client co.multiply.module.agent.query]
:failed-to-analyze [co.multiply.client]
Unexpected error (NullPointerException) macroexpanding e/defn at (co/multiply/client.cljc:24:1).
Cannot invoke "java.util.concurrent.Future.get()" because "fut" is null

2025-07-07T02:46:50.798919Z

subscribing to updates as well. @henrik were you able to find a workaround with telemere?

xificurC 2025-04-29T14:49:48.358789Z

I'm looking into this, if I require malli.core and use it as e.g. (malli.core/validate [:map] {}) in electric I don't see the failure you did. Do you have a more specific repro?

henrik 2025-04-29T15:02:40.705639Z

For Malli, it’s specifically malli.core/=> it complains about, ie., spec for IO to functions. For Telemere, it’s basically anything, since it’s all macros that expand into something straight out of the Egyptian Book of the Dead. In v2, the workaround was basically something like (#(te/log! …)) rather than te/log! directly from Electric. I’ll try to produce something that’ll trigger it predictably.

xificurC 2025-04-29T15:08:01.082889Z

what changed since v2 is we ship our custom cljs analyzer and it deep analyzes requires from your electric namespaces. The workaround Dustin explained is to not require the problematic namespaces in electric namespaces, i.e. if you have foo.cljc with malli and electric code, split it in 2 namespaces foo_with_malli.cljc and foo_with_electric.cljc and don't require malli in the electric ns. This is a quick fix until we figure out all the kinks. At the same time I do want to fix the bugs so if you have good repros of common libraries those are very helpful

henrik 2025-04-29T15:09:54.846319Z

Right, I’m not calling Malli or Telemere directly from an Electric NS, but I do reach into another NS which does, where there’s no Electric to be found.

henrik 2025-04-29T15:10:38.050779Z

Or rather it’s foo_with_electric -> foo_without_anything -> foo_with_malli .

xificurC 2025-04-29T15:12:12.327739Z

I dropped this from the malli readme into an electric file and did not trigger the bug

xificurC 2025-04-29T15:12:47.870769Z

yes, the analysis is transitive

xificurC 2025-04-29T15:20:12.051939Z

ok encore crashes immediately 😉

henrik 2025-04-29T15:27:28.789149Z

This is the cascade of imports from the three files. The problem occurs when I uncomment the #_[co.multiply.module.agent.query :as agent.q] line in the Electric NS. Perhaps pertinent to this is that I can do this with hot reload, and it seems to work, but booting from scratch with [co.multiply.module.agent.query :as agent.q] uncommented results in the error above.

xificurC 2025-04-29T15:28:59.873179Z

encore

(defmacro when
     "Supersets `core/when
` 🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

💀 1
henrik 2025-04-29T15:30:02.855469Z

Encore is the bane of my existence; full of black magic, backwards incompatible, and pervasively used throughout the Clojure community.

Dustin Getz (Hyperfiddle) 2025-04-29T15:35:33.383519Z

Why do we analyze transitive modules? I thought we just need to inspect defs visible from an Electric scope

xificurC 2025-04-29T15:39:59.755349Z

if an electric code calls foo/bar we need to know whether that's a macro or a defn (or both). If foo/bar is defined as (taoensso.core/defalias bar ...) we need to know what taoensso.core/defalias is and possibly expand it to figure out if bar will be a macro or a defn

Dustin Getz (Hyperfiddle) 2025-04-29T15:47:43.355369Z

Is there a clear example of why this absolutely has to be done, rather than just forcing unusual library bullshit to be wrapped in ((fn [] ...))

xificurC 2025-04-29T15:52:46.827009Z

cljs core functions often have a function and a macro definition at the same time. E.g. + might compile to a cljs + function call, or to (js* "+ {} {}" a b) (pseudo-coding here), to produce tighter js that can be better optimized. We want the opposite, we prefer to compile to function calls because a) it's more generic, i.e. will more likely work on both peers and b) the macroexpanded code is usually larger (inlining calls for speed) which for us means a larger DAG that is actually slower. So it boils down to cljs prefering macros while we prefer functions. We used the stock cljs analyzer but had to fight against it because of this difference. Today we have a small analyzer catered to our use cases that is easier to maintain than using the cljs one. But it's not mature yet, we need more real world code to train it on. There's also room for improvement in the analyzer, maybe it could be lazier, short-circuit sooner etc.

👍 1
xificurC 2025-04-29T15:54:28.807089Z

I certainly don't want users to wrap in IIFEs, we should increase our compat

👍 1
henrik 2025-04-29T15:57:10.184409Z

I’m talking out of my ass about things I don’t understand here, but I remember Alex saying that for the core.async IOC macro, they basically reimplemented the Clojure(non-script) analyzer from Java to plain Clojure. Perhaps there’s something, analyzer-wise, to get from there.

Dustin Getz (Hyperfiddle) 2025-04-29T16:10:09.200859Z

my question is specifically about the transitive case, + in an electric block is a direct refer not transitive

Dustin Getz (Hyperfiddle) 2025-04-29T16:10:51.420959Z

its clear that we need to analyze the first breadth level of :require statements because their definitions can appear in an electric block directly

xificurC 2025-04-30T06:37:49.566269Z

I understand the problem with encore. I cannot hit the malli error. Could you share which version are you using? The "fut" is null error comes from macros that try to read cljs internal compiler state (at macroexpansion time). You don't happen to do that in your code, do you? I'd expect some malli internals to fiddle with it but did not find the culprit yet

henrik 2025-04-30T06:47:44.083299Z

Amazing. No, not intentionally at least. We’re using the malli.experimental Prismatic function schema lookalike, and it looks like it’s reacting to that callsite in particular.

henrik 2025-04-30T06:53:00.094249Z

I.e., this syntax:

(mx/defn hello :- string?
  [name :- string?]
  (str "Hello " name "!"))


(hello "Peter")
(hello :peter)

xificurC 2025-04-30T07:33:29.336159Z

Thanks. Can you also paste the lib version from your deps.edn

henrik 2025-04-30T07:37:32.616259Z

metosin/malli {:mvn/version "0.17.0"}

slurpbarf 2025-04-30T11:37:15.544379Z

Inserting myself just to get updates. And hi Peter, hope you’re well!

👋 2
xificurC 2025-07-09T07:42:46.560399Z

tested both on server and client, telemere will work with the next snapshot release. No wrapper tricks needed

🙏 1
xificurC 2025-07-07T07:25:50.833119Z

I did not report but I fixed the issues for encore (transitively telemere) and malli. Latest should just work

2025-07-07T07:44:48.526819Z

fixed for the transitive case right? i can't log from within electric code? the v2 wrapper trick (#(te/log! …)) is still giving me this error: IllegalArgumentException: No matching ctor found for class taoensso.telemere.impl.Signal

2025-07-07T07:45:02.405479Z

at any rate, thank you for the workaround

henrik 2025-07-07T07:50:48.832979Z

I didn’t know that Peter had fixed it, so I haven’t retried. I’ll give it another go.

xificurC 2025-07-07T08:44:35.122969Z

I see, I will check telemere directly , didn't do that tbh

xificurC 2025-07-07T11:02:26.329779Z

I can repro the telemere Signal ctor bug

henrik 2025-04-26T12:46:19.939969Z

Looking at defalias, it’s a macro:

"Defines a local alias for the var identified by given qualified
 source symbol: (defalias my-map clojure.core/map), etc.

 Source var's metadata will be preserved (docstring, arglists, etc.).
 Changes to Clj source var's value will also be applied to alias.
 See also `defaliases`."

henrik 2025-04-26T12:46:44.879999Z

Barely a day goes by where Encore isn’t causing me one headache or another.

henrik 2025-04-26T12:57:07.631709Z

Could it be that it’s behind a :clj -scope?

#?(:clj
   (defmacro defalias

henrik 2025-04-26T13:01:52.852009Z

Actually, same for Malli:

:cannot-expand [co.multiply.client co.multiply.module.agent.query co.multiply.app.util.anomaly] (#'malli.core/=> new-anomaly [:function [:=> [:cat anomaly-categories-spec] anomaly-spec] [:=> [:cat anomaly-categories-spec string?] anomaly-spec] [:=> [:cat anomaly-categories-spec string? [:or nil? map?]] anomaly-spec]])
:failed-to-analyze [co.multiply.client co.multiply.module.agent.query co.multiply.app.util.anomaly]
:failed-to-analyze [co.multiply.client co.multiply.module.agent.query]
:failed-to-analyze [co.multiply.client]
Unexpected error (NullPointerException) macroexpanding e/defn at (co/multiply/client.cljc:23:1).
Cannot invoke "java.util.concurrent.Future.get()" because "fut" is null

Dustin Getz (Hyperfiddle) 2025-04-26T16:05:36.924139Z

probably electric compiler issues, here is an explanation with workaround:

Dustin Getz (Hyperfiddle) 2025-04-26T16:07:02.481389Z

in any file with an e/defn, the Electric compiler will analyze the namespace and further analyze all dependencies in the :require statement in order to understand any definitions referenced in an e/defn body. If you need to prevent that (e.g. due to the above issues), you can isolate electric code into smaller namespaces, rather than for example putting an e/defn (or e/boot!) in your Big Dependency Injection Server File that contains 1000 :require statements

Dustin Getz (Hyperfiddle) 2025-04-26T16:08:17.167739Z

so like, have a tight electric entrypoint namespace that injects the minimum dependencies (or takes them as parameter), and then your electric views only :require things they actually need

Dustin Getz (Hyperfiddle) 2025-04-26T16:08:46.924519Z

in the case of Malli and Encore, they are common enough that Electric will need to be fixed, we may not have seen those dependencies before

henrik 2025-04-26T21:10:58.597679Z

In this case it’s a CLJC file, but it has no Electric forms in it. In fact, it’s a CLJC file which requires another CLJC file which requires Malli, so I’m hesitant to think that moving it one step further away yet would make any difference.

henrik 2025-04-26T21:13:34.254429Z

I.e., co.multiply.app.util.anomaly uses Malli. It’s required by co.multiply.module.agent.query, which originally had Electric code in it in v2 to colocate with their CLJ counterparts, but which I’ve now all deleted in order to put back piecemeal, which is required from co.multiply.client which does have Electric forms.

Dustin Getz (Hyperfiddle) 2025-04-28T11:45:36.955889Z

update: we're working on it this week

henrik 2025-04-28T11:47:02.704419Z

Oh, I was sketching out workarounds, but that’s fantastic to hear. Thanks!

Dustin Getz (Hyperfiddle) 2025-04-26T20:00:28.575409Z

Lightning talk: https://share.descript.com/view/nJkFVXo15lM

👏 9
🔥 6
Tommy Jolly 2025-04-26T20:48:56.720029Z

Very well presented! I never noticed that "with lambda you can build an OS, or Emacs" is a puchline before

👍 1
🙂 1
Dustin Getz (Hyperfiddle) 2025-04-26T20:00:53.616519Z

(Nothing new here, it's from last summer)