This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-02-06
Channels
- # bangalore-clj (2)
- # beginners (55)
- # boot (32)
- # bristol-clojurians (4)
- # cider (16)
- # clara (13)
- # cljsrn (6)
- # clojure (110)
- # clojure-india (1)
- # clojure-italy (69)
- # clojure-spec (32)
- # clojure-uk (15)
- # clojurescript (102)
- # community-development (6)
- # cursive (1)
- # datomic (9)
- # docs (2)
- # duct (1)
- # emacs (39)
- # events (3)
- # fulcro (131)
- # garden (1)
- # immutant (4)
- # jobs (1)
- # jobs-discuss (5)
- # keechma (1)
- # lein-figwheel (6)
- # leiningen (6)
- # mount (6)
- # nrepl (2)
- # off-topic (69)
- # om (54)
- # parinfer (7)
- # re-frame (63)
- # reagent (13)
- # remote-jobs (1)
- # shadow-cljs (90)
- # spacemacs (8)
- # specter (6)
- # sql (16)
- # testing (1)
- # unrepl (3)
- # vim (4)
- # yada (1)
I would expect it to fail in both, surprised it doesn’t in clojure
Hmm, what am I missing here?
cljs.user> (require '[cljs.spec.alpha :as s])
nil
cljs.user> (require '[cljs.spec.gen.alpha :as gen])
nil
cljs.user> (gen/generate (s/gen int?))
#object[Error Error: Var clojure.test.check.generators/simple-type-printable does not exist, clojure.test.check.generators never required]
Is there somewhere I should be looking for an example of how to do this in cljs? I couldn't find anything on http://clojurescript.org or in the official spec guide.Oh, and here's part of my :dependencies
:
[org.clojure/clojure "1.9.0"]
[org.clojure/clojurescript "1.9.946"]
[org.clojure/test.check "0.9.0"]
>>>Can be disabled at either compile time or runtime: If \compile-asserts\ is false at compile time, compiles to x. Defaults to value of 'clojure.spec.compile-asserts' system property, or true if not set. If (check-asserts?) is false at runtime, always returns x. Defaults to value of 'clojure.spec.check-asserts' system property, or false if not set. You can toggle check-asserts? with (check-asserts bool)
@alexmiller: are you sure? In my example, the ::t
spec, (s/keys :req [:ns/y]))
does not specify anything about the :ns/x
key. But it seems to be applying it anyways, simply by virtue of it being defined globally. This would seem to defy the point of :req
. Maybe I'm misunderstanding how keys
was meant to be used, but I would have thought the clojure version to be correct.
s/keys is intended to check all registered keys in the map, regardless of whether they are listed in the spec
ah, thanks for clarifying, but then what is the point of :req
? Shouldn't you only need :opt
?
req defines the keys that are required (must be present)
req is about membership
so it’s really checking a property of the containing map
hmm, but if all keys are just going to be globally applied whether they are in the spec or not, wouldn't that mean all keys a implicit req, unless specified by :opt?
validating values according to keys is about checking properties of attributes
no, it does not mean that
they’re not required, but if they are present, they are checked
Hmm, ok, thanks for the clarification. Is the design assumption that entity attributes should conform the same properties in all contexts? You should never have an entity attribute conform one way in one context, and another way in another context?
@alexmiller: thanks for the responses, the doc was very helpful. My use case was that I was playing with a simple FSM that brought an entity map through one or more workflows. At first spec seemed to lend itself well to defining the transitions in the FSM. For example, an entity with any number of votes is a valid entity, but once it gets a certain number of votes, it transitions to another state in the FSM. Unfortunately having one valid global definition for an attribute seems to place significant restrictions on defining multiple validity states for an entity. Am I missing an easier way to do this with spec, or is it just that spec is not the right tool for this job?
I find it’s always useful to go back to: what is the truth about this attribute? if I see it in data, what does it mean?
if it has several possible kinds of values, you can use s/or to specify those alternatives - then you’re stating the truth
s/multi-spec can be used to choose different combinations of attributes at different points in the fsm
or perhaps you may want to reconsider whether it’s really the same attribute at every step
and in that case, maybe the attribute should change
to be clearer, maybe there is really more than one kind of attribute
or another option is don’t spec that attribute - you’re expecting it to change over time
you can still spec functions that operate on that attribute more precisely
Yeah, I was thinking the same thing about the attribute, there are probably times where it indicates that it is really two attributes. However this isn't always the case. The simple example I gave above with the voting is probably a case where splitting would unnecessarily complicating the data model because of an assumptions in the implementation.
I think you're suggestion to not spec the attribute via the entity model, and just spec it separately using custom primitives (at least that is how interpreted your last sentence) is probably the one that makes the most sense . Unfortunately you lose some of the great higher order features of the entity model, like being able to define one transition as a merge of previous transitions and some new criteria.
One final question: do you think that allowing local bindings in keys
would break spec's entity model significantly? Something like:
(s/def ::entity
(s/keys :req [::attr]
:let [::attr #(<= 10 (count %))]))
yes and you don’t need it
(s/and (s/keys :req [::attr]) #(<= 10 (count (::attr %))