This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-05-25
Channels
- # beginners (27)
- # boot (49)
- # cider (51)
- # cljs-dev (29)
- # cljsjs (1)
- # cljsrn (19)
- # clojure (59)
- # clojure-austin (2)
- # clojure-belgium (19)
- # clojure-china (1)
- # clojure-dev (14)
- # clojure-dusseldorf (7)
- # clojure-russia (8)
- # clojure-spec (115)
- # clojure-uk (45)
- # clojurescript (118)
- # css (6)
- # cursive (8)
- # datascript (20)
- # datomic (32)
- # emacs (5)
- # events (2)
- # flambo (21)
- # hoplon (58)
- # incanter (8)
- # jobs-rus (1)
- # jobs_rus (1)
- # off-topic (3)
- # om (22)
- # om-next (9)
- # onyx (5)
- # other-languages (79)
- # re-frame (126)
- # reagent (6)
- # ring (7)
- # specter (1)
- # untangled (119)
- # yada (38)
@sveri: not yet. Obviously there are several more useful predicates that could go into core. Considering which ones now
@richhickey: Yea, it would be nice to be consistent, much less work for the brain then 🙂
(spec/def ::foo (spec/cat :kw keyword? :int integer?))
(spec/def ::bar (spec/coll-of ::foo []))
(spec/explain ::bar [[:a 10] [:b 20] [:c "30"]])
;; => val: [[:a 10] [:b 20] [:c "30"]] fails predicate: (coll-checker :spec/foo)
Why doesn't the error reporting go into detail (like: val "30" fails predicate: integer?
) Is this intentional?Hm, is it ok to use ::spec/name for my own specs? Also I have not found the source for ::spec/string, neither by searching github (which is a bit harder, because it ignores "::", nor by looking at the api.
@alexmiller: About a week ago you hinted on Reddit at improved error messages for Clojure. Don’t think anyone’s said that here but it seems like we just got a peek into how that might be accomplished if all of Clojure.core implements specs.
What's the best way to have fdefs be checked during lein test? Instrument all works at the repl, but seems to not during test.
@mjhamrick: what I’ve done is (clojure.spec.test/check-var #’fn-speced-with-fdef)
@anmonteiro: are you just putting that in each test?
so far, yes
the project where I tried it was pretty small
@mjhamrick: I did put (s/instrument-all)
at the top of each test namespace
@kingoftheknoll: yes, I have done additional work in this area
@sveri ::spec/name and ::spec/string don't exist - what is that from?
@alexmiller: Thats why I have not found it in the code. Not sure where exactly it came from, its just that cursive offered it via code completion. Maybe I typed it in a different namespace or whatever. Anyway, good to know.
@richhickey @alexmiller: I have another proposed enhancement to explain-data
. Several predicates, such as keyword?
, or integer?
are programmatically easily recognizable via :pred
for non-conforming values. It's a straightforward equality check (e.g. (= 'keyword? (:pred error-map))
). Other predicates are, to my understanding, more difficult to recognize. Take s/keys
and s/tuple
for example. In the former, keys
yields a predicate when a required key is missing. While the predicate is somewhat understandable when you eye ball it, picking it out programmatically has been error-prone. The same goes for s/tuple
when the number of arguments is incorrect.
an example would help make this specific
Those functions have privileged access to which predicates are failing. It might be helpful to provide named predicates in those cases so that consumers of explain-data
could be more intelligent. See - https://gist.github.com/MichaelDrogalis/016ac62cf3f1e899fb89fd79f2de2277
thx for the example! :)
oh the contains stuff that's inside keys
I'll have to defer that to Rich, I think he's not around atm
It seems to me that inner conformed values are lost when using coll-of
or map-of
. Example:
(spec/conform (spec/coll-of (spec/and integer?
(spec/conformer (constantly nil)))
[])
[1 2 3])
returns [1 2 3]
instead of [nil nil nil]
. Meanwhile, cat
and keys
preserves them. How come?@alexmiller: Sure 🙂 Ill be back later.
@moxaj Rich said above "currently conform doesn't flow into coll-of, so the value is never conformed, only checked" which I think is likely related to this
@alexmiller alright, thanks!
I am converting a lib from schema to spec and in schema I was able to inline define the return values / args. Is there a way to do that in spec too? The alternative in this case is a lot more code.
for map keys, no - that's the whole point of the map / attributes split
the benefit is that you are creating named reusable semantics for ::entityname, ::ns, etc etc
so you can use those elsewhere too
@alexmiller: Yea, I understand the benefits, just wanted to make sure I did not miss anything
Is it possible to hook ones own error message if a predicate fails? Ex we have schemas that takes a string that should be a valid parse of our internal query language, and if fails should return a nicely structured error with line/col num and a human readable message. With prismatic Schema it is possible to do with our own schema type extending a protocol for explain/spec.
Correct me if I am wrong, but I think so far I can only get a generic "predicate foo? failed" type of message
there is not currently a way to provide a custom error for a failing predicate
you can use explain-data to detect problems and produce a custom error message
but @richhickey can comment on whether that might be something we could do
why not explain-data for that?
or maybe I misunderstand the suggestion
that's what instrument does on a failing function spec
hmm I am not sure that's really equivalent. I would have to wrap all schemas that contains these values with a special validation fn I think. I would like to have my own datastructure returned by explain-data (or something else) when the predicate fails. I am not sure that's doable with the current approach where predicates return just a potentially truthy value.
this might sound like a small concern, but in a larger context it's very useful: we have a whole api around the manipulation of data containing such queries, being able to use the same schema type and framework and not wrap the whole thing because of a single type in a potentially nested Schema is a nice feature, in our case it also integrates for free with frameworks that just follow this Schema format (rest server, swagger etc).
@eraserhd: @richhickey said they consider adding this and some more core types (I felt the need for it too :-))
I’m still playing with it, but the second thing I’m working through is the repetition, especially for function arguments.
@eraserhd: we have boolean? in almost every example namespace we wrote. so, agreed. :) definitely near the top of the wanted-predicates list.
@alexmiller: cool 🙂
Another interesting problem I encountered: I used a set for boolean: #{true false}. But sets aren’t treated differently in this context, although I might expect that they are. Namely #(#{true false} false) ;=> false. So having a set in a spec which contains nil or false is awkward.
yeah, don't do that :)
it is kind of an interesting wrinkle though that the obvious way to write boolean? is with #(instance? Boolean %)
Also, a lot of things seem to leak their internal implementations wrt error messages.
but Clojure uses (only) canonical boolean values
@eraserhd: prob better for a mention in the ref doc (which isn't there yet)
@eraserhd: example re errors?
@alexmiller: I encountered a couple. Just a minute and I’ll paste.
Anyone else seeing problems with reloading test namespaces in the REPL (cursive)?
I just commented out some tests, reloaded the test ns in the REPL, hit run-tests, but still, all tests were run.
I noticed something similar with test-refresh not recognizing commented fdef
s.
I cannot point at anything right now, but, there seems to be something broken
@cfleming: are there gonna be slick Cursive toolips for providing associated specs when editing functions arguments?
I imagine I'm editing the arg to some function that takes a big map, and as I'm filling in the components of the map its telling me what each piece should conform to
What is the spec for ‘map? i.e. in core.typed, I’d write something like (t/ann map [ [ X -> Y] [X] -> [Y] ). i.e. it takes a collection of X, and a function of X->Y, and returns a collection of Y. Is there a way to do that in spec?
I’m missing something related to recursive specs. I want to define a vaguely hiccup-like structure where the first element is the name, followed by some attributes, followed by a vector of children. What am I doing wrong here? https://gist.github.com/bhb/6cfcb3b38757442aec4ba5db46148699
if you add another (s/spec ....) around the ::tag I get a success, but I am not sure why
I guess you are in the regex context that matches the outer vector, so you need another s/spec to create a new regex context for the list of child vectors, then you need another s/spec to get out of the regex context of the vector of children and specify an individual child
I’d also be interested to see the spec for clojure.core/map
Ok, I dont understand how to use instrument
. My guess was, that if I put (s/instrument-all)
into a namespace all functions are instrumented whenever I load the file into the REPL. But thats not the case, instead I have to execute that function everytime after I loaded a namespace.
Hi all, first I want to thank Rich&Co for this awesome innovation 👍 And I have a question:
(s/def ::even-big-or-small (s/and (s/or :very-big #(> % 1000)
:very-small #(< % 1))
even?))
(s/valid? ::even-big-or-small 10000)
;; throws CompilerException java.lang.IllegalArgumentException: Argument must be an integer: [:very-big 10000]
what am I doing wrong?just noticed, works fine the other way around:
(s/def ::even-big-or-small (s/and even?
(s/or :very-big #(> % 1000)
:very-small #(< % 1))))
@dryewo: in the first case, it’ll conform to :very-big
and output [:very-big 1000]
(s/def ::even-big-or-small (s/and (s/or :very-big #(> % 1000)
:very-small #(< % 1))
#(even? (second %))))
this works
even?
gets [:very-big 1000]
so we are interested in the second element
that’s the explanation, but I’m also unsure if it’s expected
I’ve read somewhere that it’s not, by design
but I can’t recall the reason
I’m reading the guide: http://clojure.org/guides/spec maybe I should first read it to the end before asking more questions 🙂
@dryewo: Look into http://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec/conformer
Is there a pattern for whether you spec functions or use spec for validation (pre/post-conditions)? There doesn't seem to be a reason for pre/post-conditions if you spec a function.
I dont understand that, I have the code in the following snippet, and it fails with:
(remove-autoinc-columns [{:foo "some_t"}])
ExceptionInfo Call to #'de.sveri.clospcrud.s-play/remove-autoinc-columns did not conform to spec:
At: [:args] val: ([{:foo "some_t"}]) fails predicate: (cat :cols :de.sveri.clospcrud.s-play/columns), Extra input
:clojure.spec/args ([{:foo "some_t"}])
clojure.core/ex-info (core.clj:4617)
@sveri: you need to wrap ::column
in s/spec
like this: (s/def ::columns (s/cat :col (s/* (s/spec ::column))))
@arohner: @anmonteiro here's a spec for map
(assumes a seqable? predicate like the one in core.incubator)
(s/fdef clojure.core/map
:args (s/cat :f ifn?
:colls (s/* seqable?))
:ret (s/or :seq seqable? :transducer ifn?))
simpler than I imagined
I've left off :fn because I'm lazy but you could also verify some additional things
like :f / :transducer or :colls / :seq are the valid combos and even things like whether the :ret cardinality is minimum of the input colls cardinality
but that's enough to detect things like (map inc 100)
which is the kind of thing that normally leads to IllegalArgumentException Don't know how to create ISeq from: java.lang.Long
which, if it's occurring in a nested context can be pretty confusing
Anyone given the test namespace a try yet? I’m trying to figure out how check-var
works. It appears to be hanging half the time I try it and passing tests the other half.
@alexmiller: is it possible to check that f’s input matches the coll?
you would have to use a custom predicate to do so
the :args spec could be (s/and <current> #(custom predicate on the args))
I guess you might need to describe :f with an fspec to get the right parts to work with
I haven't done it!
I’ve created a gist with my attempt to try and use check-var
it is returning nil, is that expected behavior? https://gist.github.com/tvanhens/28b7f744d799910750d8ae3942680997
@tyler: there is a bug there, I hit it too
I think it is fixed on master
@alexmiller An example wrt errors: (spec/explain (spec/tuple number?) []) gives an error about #(clojure.core/= (clojure.core/count %) 2).
@eraserhd: "val: [] fails spec: _ predicate: (clojure.core/= (clojure.core/count %) 1)” says the collection should have count == 1