This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-02
Channels
- # announcements (3)
- # aws (3)
- # bangalore-clj (1)
- # beginners (88)
- # boot (7)
- # braveandtrue (10)
- # cider (6)
- # cljdoc (8)
- # cljsrn (3)
- # clojure (33)
- # clojure-germany (2)
- # clojure-italy (1)
- # clojure-spec (44)
- # clojure-uk (8)
- # clojurescript (14)
- # datomic (5)
- # emacs (6)
- # events (1)
- # figwheel-main (8)
- # fulcro (9)
- # leiningen (11)
- # lumo (3)
- # off-topic (119)
- # parinfer (2)
- # pedestal (1)
- # re-frame (11)
- # reagent (12)
- # shadow-cljs (162)
- # unrepl (4)
what do people do when you have different keys for different specs, but want to handle them generically? do you just use an extra key to index back in to that map? for example, i’m trying to model a WebAssembly AST, which has “modules” which are made up of “sections” and each section has a vector of “fields”. but while fields have common structure across types of sections, i’d like to have ::funcs and ::types and ::imports instead of just ::fields — my least bad idea is to add (s/def ::fields-key #{::funcs ::types …}) and then indirect through that
the two other more bad ideas are 1) just use the abstract name ::fields and rely on the spec’s global name validation. This isn’t ideal because (A) it fails to spec the fact that fields in the funcs section must conform to ::func and (B) precludes unname-spaced keys, which is what i’m actually doing & would have to do a much bigger refactor for that
and 2) just copy the fields to the other name like (let [{:keys [fields]} ast, ast (assoc ast ::funcs fields)]
is this problem explanation clear? if not, why not? if so, what do you guys do about this sort of problem?
> what do people do when you have different keys for different specs, but want to handle them generically?
We'll define it somewhere common, like (s/def ::field blah?)
and then alias it to match the expected keys where it's used like (s/def ::my-field ::common/field)
.
> ... while fields have common structure across types of sections
Depending on how common they are, you may define a (s/def ::base-field (s/keys :req [...]))
and then do a (s/def ::field (s/merge ::common/base-field (s/keys :req [...])))
in the namespace tied to that specific field.
yeah - so that much i’ve mastered. the tricky part is the collection of these things. for example:
my idea is to do: (s/def ::section (s/keys :req [::fields-key]))
and then indirect through that key
What about: (s/def ::funcs-section (s/merge (make-section-spec ::my-field-1 ::my-field-2) (s/keys :req [::funcs]))
where visit effectively does something like: (update-in section [:fields] #(mapv f %))
Yeah, that's beyond me. spec-tools allows for better introspection though. Might be of help.
there’s a bunch of different designs i’m experimenting with, but it basically is something like:
{:type-section {....}, :funcs-section {....}, :exports-section {....}}
where each of those are something like {:env {$someid 0} :funcs [....
@malch the logic for visit-section-fields is trivially monomorphic if a section is defined as {:env ..., :fields [...]}
honestly, i don’t want different field names at all - i’m happy to have them all called :fields
, but that makes the specs less strict
if unqualified – you just need the same (name kw) for those different specs: :foo/bar :baz/bar
i have no need for extensibility, so i was hoping to use unqualified keys to just avoid that entire syntactic headache
there is also (s/keys :req [(or :foo/bar :baz/bar])
, but I am not really sure what the behavior contract there
> :wasm.type/fields, :wasm.funcs/fields i don’t understand what you’re trying to say with this
ok - new least-bad idea: don’t try to spec my whole AST - just spec pieces of it on an ad-hoc as needed basis ¯\(ツ)/¯ take advantage of a-la-cart, i guess