This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-02-26
Channels
- # announcements (4)
- # beginners (160)
- # boot (2)
- # calva (40)
- # cider (41)
- # clara (24)
- # cljdoc (2)
- # cljs-dev (99)
- # clojars (4)
- # clojure (71)
- # clojure-dev (9)
- # clojure-europe (4)
- # clojure-italy (2)
- # clojure-nl (19)
- # clojure-spec (97)
- # clojure-uk (103)
- # clojurescript (57)
- # core-logic (1)
- # cursive (15)
- # data-science (31)
- # datomic (24)
- # duct (1)
- # emacs (39)
- # events (7)
- # figwheel-main (14)
- # fulcro (44)
- # garden (7)
- # jobs (13)
- # juxt (1)
- # leiningen (29)
- # music (2)
- # nyc (4)
- # off-topic (37)
- # pathom (12)
- # re-frame (26)
- # ring (1)
- # ring-swagger (10)
- # shadow-cljs (35)
- # spacemacs (2)
- # specter (4)
- # test-check (67)
Any reason why (s/explain-data a-spec a-value)
does exactly what is expected (and is correct) and given the exact same input (s/valid? a-spec a-value)
fails with a class cast exception? This is on 1.9
@favila doesn't look to be that (might be peripherally related). I think the issue is related to a misuse of s/merge
in my case. I have a set of predicates def'd to specs. None of these are map/key related (like with s/keys
) so none involve a map. Then I use s/merge
(because s/and
short circuits...) on these. Now, s/merge
is happy to do this. s/explain-data
is happy to do 'the right thing' and check all predicates of the merged spec. But s/valid?
has a bug as well, but instead of 'doing the right thing' it just blows up. I put 'right thing' in quotes because I suppose s/merge
should not allow this in the first place. All of this is a shame - s/and
should not be short circuiting in the first place. This is a logic system after all. If you are concerned about guarding flow through to other predicates then your predicates are what's broken. I suppose you could have a guard
operator for that sort of case, but IMO, that would still be bogus. ¯\(ツ)/¯
Because you are saying that the spec should satisfy all predicates. Like in propositional logic. Not programming languages
The reason this is really useful is because you would like to catch all the errors in one go - not get one report to user. fix that one, get the next, report to user, etc. That is really annoying and just wrong
@jsa-aerial s/and
flows data through all the specs so it must be short-circuiting -- it has an inherent order and you can't rely on being able to apply subsequent specs if an earlier spec fails. (and I feel we've had this conversation before)
It is what it is - I think if you wanted that 'guarded flow` capability that another name would have been far better. I don't really care TBH, I just think it was a poor choice.
Yeah, each next spec in s/and
receives conformed value from prior one. So if one step is invalid – next would just blow up with random noise instead of useful explain data.
otherwise how would you s/conform
to s/and
spec? conform only last step? none? Most of the s/and specs I saw – check fields first, and then some relation between them next (e.g. this id and that id are the same.), which is basically: 1st step is conforming, last is not
if s/and were restricted to predicates, and predicates were written defensively (which they should be IMO), then I think what @jsa-aerial proposes would be fine; order could be used for making generators, but all could be checked in parallel
I'm just talking about s/and. Maybe for clarity I should say this would not be s/and anymore. s/nonconforming-and or s/parallel-and
It is what it is - I think if you wanted that 'guarded flow` capability that another name would have been far better. I don't really care TBH, I just think it was a poor choice.
I'd call it s/every
or something. But "flowing" behavior was surprising to me back then, I agree
Not necessarily, could be anything. You just want to be able to report all findable problems at once - not piecemeal
Actually it works amazingly good when coupled with phrase
maybe build your tool on top of spec, but not use s/and to collect all the errors. just call s/explain for each field for example
Not necessarily, could be anything. You just want to be able to report all findable problems at once - not piecemeal
Actually it works amazingly good when coupled with phrase
ok, what if one of the items in s/every would be spec with s/and inside? it'll propagate conformed value, I think
It's worth pointing out that Spec2 draws a harder line between specs and predicates -- and s/and
accepts specs, not arbitrary predicates. See https://github.com/clojure/spec-alpha2/wiki/Differences-from-spec.alpha
(! 591)-> clj
Clojure 1.10.0
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/def ::foo (s/and int? (partial > 10)))
:user/foo
user=> (s/valid? ::foo 10)
false
user=> (s/valid? ::foo 1)
true
user=> ^D
Tue Feb 26 11:22:41
(sean)-(jobs:0)-(~/clojure)
(! 592)-> clj -A:spec2
Clojure 1.10.0
user=> (require '[clojure.spec-alpha2 :as s])
nil
user=> (s/def ::foo (s/and int? (partial > 10)))
:user/foo
user=> (s/valid? ::foo 10)
Execution error (IllegalArgumentException) at clojure.spec-alpha2/spec* (spec_alpha2.clj:197).
No method in multimethod 'create-spec' for dispatch value: clojure.core/partial
user=>
@seancorfield I don't see "not arbitrary predicates" there. It says "Qualified symbols (predicate function references)" are ok
@misha See the code I just posted above.
Yes, you can def
a predicate from (partial > 10)
and then it falls into the set of things that can be treated as a symbol spec. But the point I'm making is that s/and
isn't intended to operate on predicates, it's for specs.
We got our entire codebase up and running on Spec2 and we had several places where we had "mixed" specs and predicates and those were rejected and we had to rewrite things somewhat.
If you have s/keys you can use s/merge which does satisfy all semantics
@favila see above. anonymous functions are allowed, but you have to write them with fn
or #(… %)
that doesn't jive with the doc @seancorfield linked
It's an important (but subtle) distinction. Spec1 doesn't enforce it but Spec2 does.
What counter-example?
I see how spec2 could disallow fns returning fns as predicates (partial), but forbidding anonymous fns would be strange (and doing it only for few spec forms – just awkward)
If you have s/keys you can use s/merge which does satisfy all semantics
int?
is acceptable as a symbolic spec.
> Spec forms (lists/seqs), with spec op in function position, composed of other symbolic specs > Qualified keywords (names that can be looked up in the registry) > Qualified symbols (predicate function references) > Sets of constant values (an enumeration)
@jsa-aerial s/merge is for "map-validating specs", it's not for things like "also check that value in [:foo :bar] is the same as in [:baz]" but s/and - is exactly for that
Yes, I know that - just saying it does satisfy all semantics
He means "not short-circuiting"
If you merge a bunch of specs it check them all
keys-spec could be (s/merge keys-spec1 keys-spec2 ...), yes. but important part is a custom-pred, which is usually (for me) goes last, and does not conform anything, but often requires conformed input, in case there are branches with different "postvalidation" semantics required
a new guide on coercion with spec1 and spec-tools: https://cljdoc.org/d/metosin/spec-tools/0.9.0/doc/spec-coercion