This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-07
Channels
- # 100-days-of-code (1)
- # announcements (10)
- # aws (2)
- # beginners (134)
- # calva (25)
- # cider (29)
- # cljs-dev (43)
- # clojure (130)
- # clojure-dusseldorf (3)
- # clojure-italy (27)
- # clojure-nl (48)
- # clojure-spec (32)
- # clojure-uk (63)
- # clojurescript (75)
- # core-logic (5)
- # cursive (18)
- # datascript (2)
- # datomic (37)
- # emacs (5)
- # figwheel (13)
- # figwheel-main (55)
- # graphql (1)
- # java (7)
- # jobs (11)
- # jobs-discuss (19)
- # juxt (1)
- # leiningen (16)
- # luminus (10)
- # mount (3)
- # off-topic (40)
- # om (1)
- # onyx (1)
- # pedestal (7)
- # re-frame (40)
- # reagent (81)
- # ring (2)
- # shadow-cljs (32)
- # spacemacs (5)
- # testing (1)
- # tools-deps (48)
In clojure.spec.alpha “0.2.176”, is there a new way to install a custom printer for macro-expansion errors?
There may be some subtlety of https://dev.clojure.org/jira/browse/CLJ-2373 that I’m not understanding
It's this patch https://dev.clojure.org/jira/secure/attachment/18391/clj-2373-spec-alpha-2.patch that removes the call to s/explain-out
as part of simplifying the error messages.
And specifically this part of the proposal: * stop printing data into message strings ExceptionInfo.toString should list keys, not entire map contents spec.alpha/macroexpand-check should stop including explain-out in message
@bbrinck Interesting. I can reproduce the behavior in a Boot repl but if I use clj
I get different behavior:
(! 504)-> clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.0-alpha7"}}}'
src/user.clj was loaded
Clojure 1.10.0-alpha7
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (set! s/*explain-out* (fn [ed] (println "failed")))
#object[user$eval5$fn__141 0x5b07730f "user$eval5$fn__141@5b07730f"]
user=> (let [x] 1)
Syntax error macroexpanding clojure.core/let at (3:1). Cause: Call to clojure.core/let did not conform to spec.
failed
user=>
@seancorfield Good to know - I am still using Clojure 1.9 in my repro. Maybe it’s an issue with using new clojure.spec without new clojure alpha?
Compared to alpha 6
(! 505)-> clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.0-alpha6"}}}'
src/user.clj was loaded
Clojure 1.10.0-alpha6
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (set! s/*explain-out* (fn [ed] (println "failed")))
#object[user$eval5$fn__140 0x502f1f4c "user$eval5$fn__140@502f1f4c"]
user=> (let [x] 1)
CompilerException clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
failed
#:clojure.spec.alpha{:problems [{:path [:args :bindings :init-expr], :reason "Insufficient input", :pred clojure.core/any?, :val (), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings], :in [0]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2499 0x5b07730f "clojure.spec.alpha$regex_spec_impl$reify__2499@5b07730f"], :value ([x] 1), :args ([x] 1)}, compiling:(NO_SOURCE_PATH:3:1)
user=>
The announcement for spec.alpha 0.2.176 and core.specs.alpha 0.2.44 says “these libraries can be used now with Clojure 1.9.0”, so I expected that to work
Confirmed, yes, the printing has changed:
(! 506)-> clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.9.0"} org.clojure/spec.alpha {:mvn/version "0.2.176"}}}'
src/user.clj was loaded
Clojure 1.9.0
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (set! s/*explain-out* (fn [ed] (println "failed")))
#object[user$eval15$fn__150 0x590c73d3 "user$eval15$fn__150@590c73d3"]
user=> (let [x] 1)
CompilerException clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec. #:clojure.spec.alpha{:problems [{:path [:bindings :init-expr], :reason "Insufficient input", :pred clojure.core/any?, :val (), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings], :in [0]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2509 0x55b5f5d2 "clojure.spec.alpha$regex_spec_impl$reify__2509@55b5f5d2"], :value ([x] 1), :args ([x] 1)}, compiling:(NO_SOURCE_PATH:3:1)
user=>
@seancorfield Thanks! Since it works in 1.10.0-alpha7, I may just add a note to Expound to suggest that people don’t upgrade to newest spec.alpha unless they also upgrade clojure. Or there may be a workaround
I am too tired to grok the issue - can you recap?
@alexmiller The change in 2373 that removes the explain-out
call from several spec failures (and instead adds that call to the default REPL?) means that The details of the spec failure aren't run through a custom printer now in Clojure 1.9 or Boot REPL (and probably not in Leiningen's REPL -- I think both lein
and boot
use REPL-y?).
(it's the right choice but it means that tools that print explain-data
in fancy ways now need to hook into the REPL instead of expecting to be invoking in the spec failures themselves)
It’s not that they aren’t run through a custom printer though, it’s that they’re not run through any printer, right?
Previously they were printed into the exception message and now they’re not
The hooking is still exactly the same, its just that repls need to be better about how they print. The 1.10 clojure.main has a new function exposed to help with this
> It’s not that they aren’t run through a custom printer though, it’s that they’re not run through any printer, right? Yes, right. I could have worded that better 🙂
> The hooking is still exactly the same, its just that repls need to be better about how they print. The 1.10 clojure.main has a new function exposed to help with this Boot and Leiningen have some work to do. Or REPL-y. 🙂
@alexmiller I suspect I’ll get questions about this for Expound, so I’d like to put a notice for anyone who upgrades clojure.spec.alpha to “0.2.176”. What would you suggest? Should I recommend not upgrading to 0.2.176 unless they also upgrade to clojure 1.10.0-alpha7? Or until they upgrade to a newer version of Lein or Boot that changes the REPL printing?
> The 1.10 clojure.main has a new function exposed to help with this which function is this? I’m toying around with a custom REPL built on top of rebel-readline
clojure.main/ex-str
that’s the function that builds the string to print in the repl
for the note, I think the key is to just be clear about the combination of circumstances you’re warning about
as those circumstances will change with subsequent releases of clojure, spec.alpha, and the tools involved
What do you want the spec to express? Have you read the spec guide? https://clojure.org/guides/spec
“how would you spec this map” is very subjective; it depends on what you need. For example, a perfectly valid spec is (s/def ::map-thing map?)
, if that is a robust enough spec for your particular problem.