This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-07
Channels
- # announcements (4)
- # babashka (20)
- # beginners (167)
- # calva (1)
- # cider (18)
- # circleci (10)
- # clara (45)
- # clojure (85)
- # clojure-argentina (1)
- # clojure-europe (3)
- # clojure-finland (3)
- # clojure-greece (2)
- # clojure-italy (9)
- # clojure-nl (30)
- # clojure-spec (32)
- # clojure-survey (39)
- # clojure-uk (72)
- # clojurescript (12)
- # core-async (4)
- # data-science (3)
- # emacs (10)
- # figwheel-main (9)
- # fulcro (44)
- # graalvm (3)
- # jobs (12)
- # jobs-discuss (6)
- # joker (3)
- # juxt (1)
- # leiningen (4)
- # off-topic (23)
- # planck (5)
- # re-frame (4)
- # reitit (2)
- # remote-jobs (1)
- # shadow-cljs (43)
- # spacemacs (8)
- # test-check (19)
- # tools-deps (21)
I’ve got a spec(ish) design question that I’ve been thinking about for a while. I finally decided to throw it in a gist: https://gist.github.com/telekid/0f276bfa3b3f0d395a7a71158adbb35d I’m curious to know how other people approach this problem?
In a given (ns models.geography.continent)
, I tend to solve this with:
(spec/def :models.geography.continent.penguins/animals ...)
(spec/def :models.geography.continent.lions/animals ...)
i.e. I don't use ::
syntax for these cases, and I don't create additional Clojure namespaces (files).
I call it the "synthetic ns pattern"
It's a bit verbose, and losing the 1:1 mapping between cljs namespaces and spec namespaces isn't ideal either.
But it's fairly occasional so I've been happy to use these for a couple yearsbtw, not sure if this solution is already described in your gist. sometimes I'm impatient 🙃
I’ve experimented with that a bit in a few places (but I forgot about it when I was writing the gist - thanks for bringing it up)
✌️! I realised, a more accurate nickname would be "synthetic sub-ns pattern". so, while it's not a 1:1 mapping, one is still reasonably close to that ideal
funnily enough, I’ve been using the same name: https://ask.clojure.org/index.php/2817/lighter-weight-aliasing-for-keywords?show=8918#a8918
@jake142 If EDIT: Gist has been updated. Disregard! :)::animals/penguins
is defined as a count (perhaps s/def ::penguins nat-int?
) then I do not see a problem with reusing it.
Why were multi-specs implemented using multi-methods? I have never found the dynamism of multimethods useful in defining multi-specs. In fact, I think I'd prefer all of the multi-spec types to be declared statically.
Right. At least interally, I've never found that useful. All type->keys are declared upfront. Multimethods make it hard to determine the input data.
For a particular entity, I know it has types A, B, C. It can never and should never be extended except directly in the definition.
You might not be the one defining the multispecs, the users of your library may be.
https://github.com/clojure/tools.deps.alpha/blob/master/src/main/clojure/clojure/tools/deps/alpha/extensions.clj look at t.d.a.extensions ^
Oh right, I see the use for libs. This internal use case is much different. Perhaps some sort of new macro is what we need:
(multi-spec2 {:type1 (s/keys :opt [])
:type2 (s/keys :opt [])})
For those interested...
(defmacro closed-multi-spec
[name dispatch-key dispatch->spec]
(let [defmethods (map (fn [[dispatch spec-form]]
`(defmethod ~name ~dispatch
[~'_]
~spec-form))
dispatch->spec)]
`(do
(defmulti ~name ~dispatch-key)
~@defmethods
(s/multi-spec ~name ~dispatch-key))))
Don't know if this is where it'll land but it's a start.