This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-04-23
Channels
- # aws (38)
- # babashka (3)
- # beginners (27)
- # calva (47)
- # clj-otel (14)
- # clojure (90)
- # clojure-brasil (9)
- # clojure-europe (36)
- # clojure-nl (1)
- # clojure-norway (17)
- # clojure-uk (6)
- # clojurescript (9)
- # docker (1)
- # emacs (8)
- # fulcro (14)
- # funcool (2)
- # graalvm (6)
- # graphql (5)
- # gratitude (1)
- # holy-lambda (11)
- # honeysql (12)
- # lingy (2)
- # malli (4)
- # missionary (3)
- # off-topic (2)
- # overtone (3)
- # pathom (2)
- # pedestal (20)
- # polylith (2)
- # re-frame (2)
- # remote-jobs (1)
- # shadow-cljs (76)
- # testify (4)
Is there any easy way to compare in REPL that the function returns the same results for CLJ and CLJS? Basically something like (= (run-in-shadow-cljs (cljc-ns/fun data)) (run-in-clj (cljc-ns/fun data))
?
I am not aware of one. Less-than-easy ways include (a) "shelling out" from a CLJ REPL to a CLJS REPL, or vice versa, or (b) running a CLJ program that prints output to a file, and a similar CLJS program that also prints output to a file, and then comparing those output files to each other. Because of things like map keys or set elements being printed in possibly different orders between CLJ and CLJS, you would probably want a more "intelligent" difference detector than command line diff
if you connect to the nrepl server that shadow-cljs starts you can then call shadow.cljs.devtools.api/cljs-eval
so you should be able to eval (foo 5)
on the repl, and also eval (shadow.cljs.devtools.api/cljs-eval :app-build-id "(foo 5)" {:ns 'some-ns})
on the same repl. The first one will run it in Clojure world while the second one will do it in ClojureScript
like this, assuming you have shadow-cljs with a build id of :dev-test
listening for nrepl connections on port 7123
:
clj -Sdeps '{:deps {nrepl/nrepl {:mvn/version "1.1.1"}}}'
Clojure 1.11.1
user=> (require '[nrepl.core :as nrepl])
nil
user=> (def conn (nrepl/connect :port 7123))
#'user/conn
user=> (def cli (nrepl/client conn 1000))
#'user/cli
user=> (nrepl/response-values (nrepl/message cli {:op "eval" :code "(+ 1 2)"}))
[3]
user=> (nrepl/response-values (nrepl/message cli {:op "eval" :code "(-> ((requiring-resolve 'shadow.cljs.devtools.api/cljs-eval) :dev-test \"js/window\" {}) :results first)"}))
["#object[Window [object Window]]"]
your function could be :
(defn same? [code build-id]
(= (-> (nrepl/response-values (nrepl/message cli {:op "eval" :code code}))
first)
(-> (nrepl/response-values (nrepl/message cli
{:op "eval"
:code (format "(-> ((requiring-resolve 'shadow.cljs.devtools.api/cljs-eval) %s %s {}) :results first)"
build-id
(pr-str code))}))
first
read-string)))
user=> (same? "(+ 1 2)" :dev-test)
true
@U0739PUFQ Thanks, that’s exactly what I needed. I didn’t find such a quick todo anywhere :-). Thanks a lot!

@U0739PUFQ Do you know how to call a function in a specific namespace? I have no problem with core functions...
yes, in cljs land the last argument to shadow.cljs.devtools.api/cljs-eval
is a map, and can be like {:ns "com.your-ns"}
and for the Clojure part you can do (nrepl/message cli {:op "eval" :code code :ns "com.your-ns"})
for some reason no other namespace than user I have trieed used so far works…
(nrepl/response-values (nrepl/message cli {:op "eval" :code "(+ 1 2)" :ns (str *ns*)}))
=> nil
does that ns exists in the remote runtime? this seams to work
user=> (nrepl/response-values (nrepl/message cli {:op "eval" :code "(str *ns*)"}))
["shadow.user"]
user=> (nrepl/response-values (nrepl/message cli {:op "eval" :code "(str *ns*)" :ns "user"}))
["user"]
but if you eval in a non-existing ns it will return nil
user=> (nrepl/response-values (nrepl/message cli {:op "eval" :code "(str *ns*)" :ns "foo"}))
nil
I would guess that the ns you are sending in your :ns key hasn't been required/created on the remote process yet
Yes. After I require it in a message, I can use it. I mistakenly thought I could use everything that is returned by (all-ns)
.
you don't need to call everything through the nrepl client, you can also connect a clj repl with npx shadow-cljs clj-repl :your-build-id
Does it make sense?
Thank you. So I can find pure CLJC files, but if anything contains CLJ / CLJS, it is not to be found.
> (require '[pure-cljc-namespace])
nil
> (require '[cljc-namespace-requiring-clj-and-cljs])
Execution error (FileNotFoundException) at ….
Could not locate ….
are the "Could not locate ..." on the classpath?
also you can't require a .cljs file from a clj repl
It fails on :clj dependencies (I use reader macro in cljc files). I guess that classpath must be configured somewhere outside of deps.edn in this case?
who is creating your classpath? shadow-cljs via its :source-paths
and :dependencies
or deps.edn via :deps
and :paths
?