This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-11-18
Channels
- # architecture (33)
- # asami (1)
- # aws (1)
- # babashka (19)
- # beginners (48)
- # bristol-clojurians (1)
- # calva (5)
- # cider (12)
- # cljdoc (15)
- # cljsrn (7)
- # clojure (151)
- # clojure-europe (19)
- # clojure-losangeles (1)
- # clojure-nl (2)
- # clojure-provo (4)
- # clojure-spec (9)
- # clojure-uk (21)
- # clojuredesign-podcast (28)
- # clojurescript (33)
- # core-typed (1)
- # cryogen (2)
- # css (6)
- # cursive (10)
- # data-science (1)
- # datomic (20)
- # events (3)
- # expound (72)
- # figwheel-main (5)
- # fulcro (43)
- # graalvm (6)
- # helix (1)
- # kaocha (13)
- # leiningen (2)
- # malli (1)
- # meander (93)
- # membrane (4)
- # off-topic (17)
- # pathom (6)
- # portland-or (5)
- # re-frame (25)
- # reagent (6)
- # reitit (7)
- # reveal (30)
- # shadow-cljs (25)
- # vim (2)
I'm having a really hard time getting Expound set up with ClojureScript in the browser. I've been at it for a couple hours and I haven't even seen an Expound error message yet.
That's what I started trying to do, instrumentation with Orchestra, setting up with something like:
(st/instrument)
(set! spec/*explain-out* expound/printer)
But reading through the docs more has suggested that instrumentation isn't completely ready to go in Expound... is that still the case?
If instrumentation isn't the solution for the browser, what's the suggested workflow?
What happens is that you instrument with spec or orchestra, but then you need to make sure Expound is used to actually print the instrumentation errors.
If you’re in a REPL, I would think the above would work. But in the browser, you may not be in the context of a REPL - it might just be that the errors are being thrown from your running program
This section of the README was be of help https://github.com/bhb/expound#clojurescript-considerations
Namely
> To format errors in the browser, you must set up some global handler to catch errors and call repl/error->str
.
I don't even think I have Expound messages appearing in the REPL. When I evaluate an expression (which I know has a spec error) in an Emacs buffer, I just get this in the minibuffer:
A little hard to read, especially because cider-inspect
doesn't work with ClojureScript..
So even without Expound, it looks like something is amiss because you might expect to see a normal spec message
That could be a clue, I'm also new to spec so I have no idea what I'm even looking for.
Yeah, normally a spec error would print like this https://clojure.org/guides/spec#_instrumentation
I might suggest starting without Orchestra or Expound and just get normal spec messages working first.
I don’t know the details of your CLJS REPL, but what I would expect to happen is 1. You instrument the function 2. You call the function 3. An error is thrown 4. The REPL catches the error, and then prints a string error message to the console
@neil.hansen.31 To get you started, here’s a simple example of how it might work in a bare-bones CLJS REPL
clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.764"}}}' -m cljs.main
ClojureScript 1.10.764
cljs.user=> (require '[clojure.spec.alpha :as s])
nil
cljs.user=> (require '[clojure.spec.test.alpha :as st])
nil
cljs.user=> (defn foo [x] x)
#'cljs.user/foo
cljs.user=> (s/fdef foo :args (s/cat :x int?))
cljs.user/foo
cljs.user=> (st/instrument foo)
Unexpected error macroexpanding cljs.spec.test.alpha/instrument at (<cljs repl>:1:1).
Unable to resolve symbol: foo in this context
cljs.user=> (st/instrument `foo)
[cljs.user/foo]
cljs.user=> (foo 1)
1
cljs.user=> (foo "")
Execution error - invalid arguments to cljs.user/foo at (<cljs repl>:1).
"" - failed: int? at: [:x]
You can compare that to what you’re seeing - I don’t know the details of the cider CLJS repl, but it could be configured in a way that it is not print spec errors as expected
This isn’t specific to Expound, but FWIW, if the cider CLJS repl is giving you issues, you could try the following if you happen to use Figwheel (I don’t know anything about shadow-cljs)
1. Start normal nrepl REPL
2. M-x cider-connect
3. `(use ’figwheel-sidecar.repl-api)
4. (start-figwheel!)
5. (cljs-repl)
Then open the browser e.g.
or whatever port figwheel is running on
My whole project is shadow-cljs at this point, so I'll have to google around by this. It's all pretty overwhelming... I really hope I finally get to use your tool at some point, I've heard so much about it!
Sigh... this is exhausting... I really want messages in my browser like the ones provided by Ghostwheel...
@neil.hansen.31 I’m certainly not an expert in Shadow-CLJS, so take this with a grain of salt, but it looks like we may be discussing two different issues at once 1. In a CLJS REPL, you’re not seeing spec errors printed 2. In a browser session, errors are being raised and not handled
For the latter, have you tried setting a global JS error handler e.g.
(ns app.core
(:require [cljs.spec.alpha :as s]
[expound.alpha :as expound]
[cljs.repl :as repl]))
(set! s/*explain-out* expound/printer)
(defn error-handler [message url line column e]
(js/console.error e)
(print (repl/error->str e))
true)
(set! (.-onerror js/window) error-handler)
source: https://github.com/bhb/expound/issues/152Also, I haven’t looked at the code, but either Ghostwheel or Guardrails may have some code that explains how they work https://github.com/fulcrologic/guardrails
@bbrinck thanks for hanging in with me, after doing some investigation all day I've uncovered some new mysteries, as well as a few of my own stupid mistakes.
1st dumb mistake... I was calling (set! s/*explain-out* expound/printer)
after the :require
calls to my other .cljs
files... so obviously my naive spec tests were running before I had even configured Expound properly.
So, with a minimal .cljs
file, I have now found ways to get three different outputs in the Chrome DevTools. I'll show you! First off, here's the minimal .cljs
file:
(ns cards.preload
(:require
[cljs.repl :as repl]
[expound.alpha :as expound]
[cljs.spec.test.alpha :as stest]
[cljs.spec.alpha :as spec]))
(set! spec/*explain-out* expound/printer)
(defn error-handler [message url line column e]
(js/console.error e)
(print (repl/error->str e))
true)
(set! (.-onerror js/window) error-handler)
(spec/fdef result
:args (spec/cat :m map?))
(defn result [m]
(merge m {:foo "bar"}))
(stest/instrument `result)
(result [:bar "baz"])
That last line is the incorrect call to the function result
. Here's what this outputs in the browser:
Now, after this has loaded, if I trigger a Hot Reload (by adding a newline, w.e.)... I get an additional error in the DevTools that looks different. This time, there's data attached to it:
Finally, I get a different output if I replace that the last line (the incorrect result
call) with this:
(.setTimeout js/window #(result [:bar "baz"]) 3)
... I realize when I say "Expound works!", I'm probably referring to any number of things that may have been set into place by this little ceremony... I'm sure Expound always works if all the other pieces are set up right, I mean to say "I'm finally getting beautiful error messages in DevTools".
Why this is happening is a total mystery to me. I imagine that in those 3 seconds that I'm waiting to call the result
function, something else is getting set up behind the scenes that is necessary for me to the correct error formatting. Do you have any ideas?
So one thing that jumps out (maybe a red herring, but just trying to make sure we’re looking at the same thing) is that cljs.spec
indicates a fairly old version of CLJS. What version are you on?
The reason I ask is because there were some changes to how errors were handled at some point, so what works on my version may not work on yours
I'm just using it because I don't know any better. What's the story there? Documentation everywhere seems to use it interchangeably with clojure.spec.alpha
I think that’s more idiomatic, but I actually don’t think it matters in this case (my mistake)