@seancorfield I spent some time today with spec 2. It seems like it's design goals are exactly what I need. I attempted to migrate and it was pretty rough (not complaining, I totally understand that it is still in development and also a new major version so I expected many breaking changes). I am not sure if we will be jumping on board with spec 2 yet, but thank you for the pointer!
There are a few things that we are doing in spec 1 that I cannot figure out how to recreate in spec 2, even though it smells like it should be possible.
For example, I would like to implement a custom generator that simply pulls a random element from a set.
I can get this to work if the set satisfies (every? constant-val? ...)
but otherwise, I cannot.
are you using a set spec?
user=> (s/def ::s #{1 2 3})
:user/s
user=> (gen/sample (s/gen ::s))
(2 1 3 2 2 1 1 1 2 2)
if you're trying to do this outside s/def (which has some magic), you can do something like
user=> (gen/sample (s/gen (s/resolve-spec #{1 2 3})))
(1 2 1 1 3 1 3 3 1 1)
one of the caveats you might be seeing is that set specs are constrained to constant values only which is part of the new symbolic spec direction
there are a couple of options but you can just use the built-in generators directly if you have something else
Thank you! gen/elements
is exactly what I was looking for.
However I am running into some strange behavior on the with-gen
.
user=> (s/with-gen (s/spec int?)
(fn [] (gen/elements [-1 0 1])))
Execution error (IllegalArgumentException) at clojure.alpha.spec.protocols/eval190$fn$G (protocols.clj:11).
No implementation of method: :with-gen* of protocol: #'clojure.alpha.spec.protocols/Spec found for class: clojure.lang.PersistentList
user=> (s/exercise (s/with-gen int? (fn [] (gen/elements [-1 0 1])))
10)
([-1 -1] [0 0] [1 1] [-1 -1] [-1 -1] [-1 -1] [0 0] [1 1] [-1 -1] [1 1])
Neither of those seem right to me. Am I missing a change from Spec 1?yeah, seems fishy. I'd expect the first one to work
user=> (def a 1) (def b 2)
#'user/a
#'user/b
user=> (gen/sample (gen/elements [a b]))
(1 2 2 2 1 2 2 2 2 2)
hello! it seems like @rafael and I ran into the same issue. I posted about it in the google group: https://groups.google.com/d/topic/clojure/rcuWmqyGWzs/discussion my specs:
(s/def ::id int?)
(s/def ::tag-id ::id)
(s/def ::child-tag ::tag-id)
(s/conform ::child-tag 22)
;; 22
(s/conform ::child-tag "a")
;; :clojure.alpha.spec/invalid
(s/conform (s/schema [::child-tag]) {::child-tag 22})
;; Execution error (IllegalArgumentException) at clojure.alpha.spec.protocols/eval1458$fn$G (protocols.clj:11).
;; No implementation of method: :conform* of protocol: #'clojure.alpha.spec.protocols/Spec found for class: clojure.lang.Keyword
(s/conform (s/schema [::tag-id]) {::tag-id 22})
;; Execution error (IllegalArgumentException) at clojure.alpha.spec.protocols/eval1458$fn$G (protocols.clj:11).
;; No implementation of method: :conform* of protocol: #'clojure.alpha.spec.protocols/Spec found for class: clojure.lang.Keyword
(s/conform (s/schema [::id]) {::id 22})
;; #:foo{:id 22}
and the stack trace, just in case that’s useful:
(clojure.repl/pst)
IllegalArgumentException No implementation of method: :conform* of protocol: #'clojure.alpha.spec.protocols/Spec found for class: clojure.lang.Keyword
clojure.core/-cache-protocol-fn (core_deftype.clj:583)
clojure.core/-cache-protocol-fn (core_deftype.clj:575)
clojure.alpha.spec.protocols/eval1458/fn--1556/G--1439--1567 (protocols.clj:11)
clojure.alpha.spec.impl/schema-impl/reify--2753 (impl.clj:435)
clojure.alpha.spec/conform (spec.clj:245)
clojure.alpha.spec/conform (spec.clj:237)
clojure.alpha.spec/conform (spec.clj:241)
clojure.alpha.spec/conform (spec.clj:237)
foo/eval6028 (form-init13722384443750232197.clj:1)
foo/eval6028 (form-init13722384443750232197.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7132)
yeah, this is just a bug in spec
whew