This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-31
Channels
- # aleph (3)
- # aws (5)
- # beginners (65)
- # boot (17)
- # cljs-dev (112)
- # cljsrn (5)
- # clojure (146)
- # clojure-austin (3)
- # clojure-dusseldorf (3)
- # clojure-italy (18)
- # clojure-norway (13)
- # clojure-russia (84)
- # clojure-serbia (5)
- # clojure-spec (24)
- # clojure-uk (84)
- # clojurescript (204)
- # css (1)
- # cursive (21)
- # data-science (3)
- # datascript (21)
- # datomic (26)
- # emacs (5)
- # euroclojure (1)
- # hoplon (8)
- # jobs (7)
- # jobs-discuss (2)
- # keechma (35)
- # lumo (92)
- # mount (1)
- # nrepl (2)
- # numerical-computing (16)
- # off-topic (10)
- # om (58)
- # re-frame (13)
- # reagent (90)
- # remote-jobs (2)
- # ring-swagger (1)
- # spacemacs (9)
- # specter (6)
- # unrepl (17)
- # untangled (56)
- # yada (2)
is there a way to highjack a "bottom" component of composed spec to avoid manually writing 2 sets of specs? use case would be: a) spec for datomic entity with both temp and actual ids in refs; b) and the "same" spec, but with actual ids only?
(s/def :datomic/temp-id neg-int?)
(s/def :datomic/actual-id pos-int?)
(s/def :datomic/id (s/or
:actual-id :datomic/actual-id
:temp-id :datomic/temp-id))
(s/def :datomic/actual-ref (s/map-of #{:db/id} :datomic/actual-id))
(s/def :datomic/ref (s/map-of #{:db/id} :datomic/id))
(s/def :foo/bar :datomic/actual-ref) ;; actual goal is to replace `actual-ref` with `ref` here, and still be able to use both `:entity/foo` specs in different situations
(s/def :entity/foo (s/keys :req [:foo/bar]))
;; is there a way to re-use :entity/foo, and avoid writing following:
(s/def :foo/bar* :datomic/ref)
;^^^ I don't even know how to keep attribute name, but change underlying spec
(s/def :entity/tepm-foo (s/keys :req [:foo/bar*]))
Maybe you could use macros to generate both sorts of specs according to a macros convention
@danieleneal the fact, that you can't have same spec-name (:foo/bar above) with a 2 different specs under it at the same time, makes me think I need to somehow hot-swap the bottom (:datomic/ref <--> :datomic/actual-ref) spec definition on-demand. Which, given global nature of registry, might not behave/scale well in e.g. treaded env.
ah so you don't want :foo/bar* to exist ever, even if it is autogenerated
I'd want at least something like
(let [actual (with :entity/temp-foo {:datomic/ref :datomic/actual-ref})] ;; swaping `ref` with `actual-ref` inside :entity/temp-foo
(s/valid? actual {...}))
ah ok, I don't know how to do that
@danieleneal I don't know yet. But at least one of the problem with duplicating entire "tree" of :entity/tepm-foo
here, is you can't have 2 different specs for the same attribute at the same time (AFAIK), so you are forced to do s/or
, and then, in app code, go through conform data and see which or
branch attribute conformed to.
So you can't just use 2 simple (s/valid? :entity/maybe-temp-foo entity)
and (s/valid? :entity/only-actual-foo entity)
calls in different places.
You need to conform, and search for those or
branches with custom walkers.
+ this is a trivial example, spec tree might be tens of levels deep (imagine nested datomic pull result, where some nodes are pulled, and some are just {:db/id 9999})
but maybe (re-)defining specs on the fly on-demand is ok. Is it, @alexmiller?
I don't think it's a good idea
If you want non-conforming s/or, then wrap s/nonconforming around it
Or maybe it's s/non-conforming, can't remember
The best way to write a spec is to make true statements about your data
@alexmiller how would you go about speccing same entity for validating against these at the same time: a) being actual entity (containing no datomic temp ids), and b) being to-be-transacted entity (maybe containing some temp ids)?
@misha This feels to me like you might be over-specifying your data. If the difference between actual-ref and ref doesn’t matter in most cases, then don’t specify it at all. When and where it actually matters, have a separate spec that can validate you have the one you want.
Deeply nested specs feel like an anti-pattern to me (based on my usage of spec so far in production).
When we first got started with spec, I found myself trying to declare every aspect of every known key in a data structure and soon realized that got in the way of writing generic functions across variants of that data. It took a while to settle into a flow of only specifying what was important for the places where specs were being used to help drive the system.
@seancorfield @dpsutton yeah, I am sure such questions are a part of learning and calibration process, on the other hand, there might have been a "function for that" after all
Many of existing things still surprise me, and I'd like to avoid prematurely limit myself in approaches/tools – we are in lisp world after all! :)
if I have a set of possible usernames ["fred" "tom" "mary"]
and a set of possible mail host domains ["
, how do I combine them into a spec generator to make strings like <mailto:[email protected]|[email protected]>
@jjttjj clojure.test.check.generators/let
https://clojure.github.io/test.check/clojure.test.check.generators.html#var-let
@jjttjj Use generators of s/tuple to combine other generators into random combinations, then use s/fmap to apply a function to the combinations