Comments (8)
Ah, good point, that's not a great experience for someone working through the official docs 😞 . Thanks for pointing that out 😄
Certainly defaulting to normal output is one option I'm considering. I'm not sure if falling back on normal explain
should be the default or something you can opt into with a configuration. Before I realized that and
had this issue, I was leaning towards "you must opt in" since using specs for coercion was an advanced use case and not recommended for various reasons.
But given that this more common (and, as you point out, included in the official docs), it might make sense to make falling back to normal explain
the default. Or it might be possible to print a reasonable error in this case by looking for the the conformed value.
In any case, the workaround for now is to wrap the printer in a try/catch and default to s/explain-printer
e.g.
(require '[expound.alpha :as expound])
(defn safe-printer [explain-data]
(let [exp (expound/custom-printer {})]
(try
(exp explain-data)
(catch Exception e e
(s/explain-printer explain-data)))))
(set! s/*explain-out* safe-printer)
(s/def ::sorted-pair (s/and (s/cat :x int? :y int?) #(< (-> % :x) (-> % :y))))
;; Usually use expound
(s/explain int? "a")
;;-- Spec failed --------------------
;;
;; "a"
;;
;;should satisfy
;;
;; int?
;;
;;-------------------------
;;Detected 1 error
;; If there is an issue, fallback on s/explain-printer
(s/explain ::sorted-pair [0 0])
;; val: {:x 0, :y 0} fails spec: :expound.alpha/sorted-pair predicate: (< (-> % :x) (-> % :y))
from expound.
@bhb I think you can rely on both conform and unform working for a "pure" and
implementation since those are standard transformations: https://github.com/clojure/spec.alpha/blob/739c1af56dae621aedf1bb282025a0d676eff713/src/main/clojure/clojure/spec/alpha.clj#L1136
However, it is of course possible that a user just mixed conformer
s directly with an s/and
call; I am guilty of this btw 😅.
Generally I dont create an unform function for those cases but just put identity
to "get the job done". You would have a hard time getting back the values unformed.
So I guess that you would need some kind of heuristics to figure out if you are able to unform the values or if you just default to the classical output. Btw, if you default to the classical output, would it be possible to still have a warning printed before it mentioning that you are getting the default output due to the unform part? otherwise the user would be left wondering if expound is actually working or not.
Hope it helps
from expound.
@carocad Thanks very much for trying it out! I appreciate it.
I think there are some cases where the output could be slightly more accurate but those are pretty much nice to have
Yes, you're right: Expound could do more here, but since string parsing is advanced at best, and discouraged at worst, I'm not inclined to add much more here. I may change my mind in the future, but I think this is sufficient for now 😄
from expound.
Sadly, it means expound fails on the very first example of instrumentation in the official spec guide use s/def
(the ranged-rand
example). I wonder, would it be possible to drop back to the original explain
in cases where expound fails? That'd be better than just getting an exception.
from expound.
I wonder if I could look for both the conformed and unconformed value in the original data, then show both. Something like:
[1 2]
when conformed to
{:x 1 :y 2}
should satisfy
#(< (-> % :x) (-> % :y))
I this more about this.
from expound.
@carocad @jmlsf I've got a fix for this issue in 0.7.2-SNAPSHOT. If you have time to try it out, please let me know what you think!
from expound.
@bhb first of all, I have to say "Thanks a lot for putting the effort of figuring this out"
I tried the following cases and they all worked wonderfully.
I think there are some cases where the output could be slightly more accurate but those are pretty much nice to have; here I am referring to the first case 'string parsing', where it is clear from the output that there is a single value not a collection so the text part of the value
doesn't really fit. Unfortunately I have stopped using conformer since they were creating too many problems so I cannot test my previous errors anymore 😅
from expound.
Fixed in 0.7.2-SNAPSHOT (to be released soon)
from expound.
Related Issues (20)
- Error reports returned as :cause string in an exception when produced by instrumentation within generative testing HOT 11
- allow passing options map to expound/expound-str HOT 1
- Improve grouping of spec errors HOT 2
- Unnecessary dependency on `cider-nrepl` HOT 1
- Regression of #3 HOT 4
- Easier editing of error messages
- `printer` has invalid spec HOT 2
- "Cannot convert path" on instrumentation failures in the wild HOT 4
- (cljs.spec.test.alpha/instrument) breaks expound due to wrong arity HOT 4
- should expound work anywhere s/explain works? - clojurescript error HOT 7
- Error in :ret check when using with Orchestra 2020.07.12-1 HOT 5
- Internal error in `lift-singleton-groups` when having a datomic db value in fn args HOT 13
- Crash bug when printing, if a datomic db is present and the spec fails HOT 19
- Feature inquiry: a convenience function for validating a value against a spec HOT 4
- Wrapped `s/keys` does not properly display unqualified keyword specs HOT 5
- ClassCastException from `expound-str` when running in AWS Lambda HOT 9
- Small *print-length* and/or *print-level* sometimes yield NPE HOT 5
- PersistentList cannot be cast to class Named HOT 3
- proposal : defmsg equivalent for arbitrary predicates HOT 15
- optional include location of the spec error in the message. HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from expound.