This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-11-28
Channels
- # admin-announcements (1)
- # aleph (3)
- # bangalore-clj (4)
- # beginners (167)
- # boot (14)
- # cider (4)
- # cljs-dev (24)
- # cljsjs (21)
- # cljsrn (33)
- # clojure (214)
- # clojure-greece (2)
- # clojure-italy (2)
- # clojure-korea (16)
- # clojure-russia (29)
- # clojure-spec (31)
- # clojure-uk (86)
- # clojurescript (144)
- # core-matrix (2)
- # cursive (37)
- # datascript (5)
- # datomic (104)
- # devcards (2)
- # events (2)
- # jobs (2)
- # luminus (8)
- # midje (1)
- # nyc (4)
- # off-topic (1)
- # om (39)
- # om-next (1)
- # onyx (47)
- # perun (1)
- # planck (6)
- # proton (2)
- # re-frame (25)
- # reagent (40)
- # spacemacs (9)
- # vim (71)
- # yada (3)
Hmm, I have an issue with generating data for a multi-spec. It works fine for testing with s/valid?
but not when using (gen/generate (s/gen ::myspec))
. I have the following setup:
(defmulti myspec first)
(defmethod myspec :option/a [_] (s/cat :opt #{:option/a} :val boolean?))
(defmethod myspec :option/b [_] (s/cat :opt #{:option/b} :val string?))
(s/def ::myspec (s/multi-spec myspec first))
Then the following crashes:
(gen/generate (s/gen ::myspec))
;; #object[Error Error: :option/b is not ISeqable]
I’m on cljs FYI.the problem is your retag function (first)
re the docs "retag is used during generation to retag generated values with matching tags. retag can either be a keyword, at which key the dispatch-tag will be assoc'ed, or a fn of generated value and dispatch-tag that should return an appropriately retagged value."
in this case, I think the value generated by each method spec is probably fine without modification, so you can just use (fn [val tag] val)
note that you can’t easily use the anon function syntax here as it must be a function with arity 2
you could sneakily use it via something like #(first %&)
but I find the fn
version to communicate much better
@alexmiller Awesome, honestly I read the docs but did not quite understand the retagging part… Now it works as expected.
Specs are re-added to the registry when you use c.t.n.r/refresh
and the like, but any deleted specs will not be removed from the registry.
Is this a bug? s/merge
specs are not conforming in this case:
(s/def ::status (s/conformer (fn [x] (or (keyword x) ::s/invalid))))
=> :dev/status
(s/def ::a (s/keys :req-un [::status]))
=> :dev/a
(s/def ::b (s/merge ::a (s/keys :req-un [::id])))
=> :dev/b
(s/conform ::b {:id 1 :status "hi"})
=> {:id 1, :status "hi"}
(s/conform ::a {:id 1 :status "hi"})
=> {:id 1, :status :hi}
Merge does not flow conformed values like and
You'll get the conformed value of the last spec
Each spec basically has to independently conform for the merge to succeed
If you swap the order in your merge you should get what you want
Don't you want the behavior to be more like map merge? First determine the keys and then conform them.
That's not what merge is
I wonder how clear these things should be in the docs or if I'm pushing it too far.
Is there a way to spec a multimethod where you can add to the spec in an open-ended way?
I had an idea to define a spec, ::item, that specifies that a thing either has an :id key or that it can have a function called id
called on it. I'm not sure, though, if that's a job for protocols instead of specs.
The other thing I'm struggling with is, I can use specs when I define them in the namespace in which I want to use them, but I don't understand how to require them from another namespace. I gathered that spec/def
registered them globally somehow, but other-name-space/foo
does not seem available.
@mathpunk re the first question - you could do that but you would need some way to tell that a function can do that (and protocols is maybe the best way) - something like (s/def ::item (s/or :has-key (s/keys :req-un [:id]) :has-fn #(satisfies? HasId %)))
where HasId is (defprotocol HasId (id [x]))
re the second, as hiredman said, they are registered globally and can be referred to by (qualified-keyword) name, assuming you loaded the code that registered them