Fork me on GitHub
braai engineer14:11:55

I get the following error when I attempt to compile my ClojureScript project for Release via shadow-cljs (running Node v16.16.0):

------ ERROR -------------------------------------------------------------------
 File: jar:file:/Users/petrus/.m2/repository/org/clojure/core.async/1.5.648/core.async-1.5.648.jar!/cljs/core/async.cljs:283:22
 280 |                        true)))]
 281 |        (dotimes [_ n]
 282 |          (case type
 283 |            :compute  (go-loop []
Syntax error macroexpanding cljs.core/==.
ClassCastException: clojure.lang.KeywordLookupSite$1 incompatible with clojure.lang.IFn
	clojure.spec.alpha/spec-impl/reify--2053 (alpha.clj:930)
	clojure.spec.alpha/conform (alpha.clj:171)
	clojure.spec.alpha/conform (alpha.clj:167)
	clojure.spec.alpha/macroexpand-check (alpha.clj:708)
	clojure.spec.alpha/macroexpand-check (alpha.clj:704)

braai engineer14:11:48

Solved: This seems to happen if you do shadow-cljs release while there is another shadow-cljs watch app instance running. Adding comment to GH issue here:

Alex Miller (Clojure team)14:11:30

fyi, this may be unrelated but there were some longstanding issues with using Clojure with OpenJ9 on older Clojure versions - that was addressed in Clojure 1.10.2 so you should make sure your use of Clojure is ≥ that version

braai engineer15:11:29

Thanks, @U064X3EF3. I’m running Clojure v1.11.1, ClojureScript v1.11.60 & core.async 1.5.648. This might be related to me defining the same Shadow-cljs release path as debug (watch) paths. Will try with different paths in case it’s clobbering something.

Daniel Gerson16:11:50

I'm busy reading and wishing I could name channels (chan :name :bob) even if the name would be 101:bob if it was instantiated repeatedly. Then I also wish I could enable trace logging for any time something went onto or came off all channels.

👍 1

Channels are not the thing to focus on there. Go blocks get translated into callbacks attached to go blocks or running on the go block pool, those callbacks are clojure function which end up with class names that reflect the current namespace when they were compiled


Ah, interesting, I thought the ask post was about blocking up the core.async threadpool

Daniel Gerson17:11:50

Nope, as you've figured out the question is about reasoning about the "state machine" of your channels. The dude in the video is thinking along exactly the same lines as I am.

Daniel Gerson17:11:01

Project doesn't look alive though :thinking_face:


channels don't have a state machine


go blocks do


the channel ops that block a real thread <!! >!!, etc use promises


so in your stack traces from thread dumps they will show up as a deref of a promise

Daniel Gerson17:11:15

I'm using the word to mean how ALL your channels changed across your various go blocks.

Daniel Gerson17:11:07

Happy to say log of your channels instead.


and stacktraces from the thread dump will have associated file and line information (which isn't always perfect)

Daniel Gerson17:11:15

I just want the history of what went into and out of all channels in order.


you may not want core.async then


channels have no order enforced between them


so if you want things in a global order, you would have to create one

Daniel Gerson17:11:36

I don't want it while my programming is running, I want it only as a debug tool.

Daniel Gerson17:11:55

Take a look at the video.

Daniel Gerson17:11:22

Even if not identical, it's angling at the same goal.


I might at some point, but scrubbing through, he has channel operations that are not ordered between them, so he makes up an order

Daniel Gerson17:11:59

Yeah, okay, he calls it a "step machine", so Freudian on my part. The output from a number of threads and 3 go blocks, multiple channels:

Daniel Gerson17:11:28

And it doesn't matter to me if it's non-deterministic provided if the visual aid is the same as how it ran. It's a tool for identifying issues. I'm just happy that there are others that have been thinking along same lines 🙂

Daniel Gerson17:11:20

(yes I saw he has some ways of trying to force determinism)


You may be interested in some of the jepsen libraries. They're built for analyzing the semantics of distributed databases, but I think some of the ideas can be applied to any asynchronous program:

👀 1