Fork me on GitHub

@rmuslimov perhaps structure it as a list of strings? That approach is simpler for the programmer, and easier to maintain


If my code accepts JS values at the boundary of the system, what’s the preferred way to use spec to validate it? AIUI, s/keys only works with keywords. Is it common practice to convert all string keys to keyword keys when converting to CLJS in order to use spec? e.g. (js->clj input :keywordize-keys true)


@tbaldridge yes it is dead simple, however spec is longer that data it describes. I was wondering if I’m missing some nice shortcut macro for that


@rmuslimov no, I'm saying that this is the better approach:

(s/def ::email string?)
(s/def ::emails (s/coll-of ::email))

(s/def ::item (s/keys :req-un [::emails ::data]))


@tbaldridge it wasn’t real world example, I just created the most trivial example of the problem. Real world example would be something like:

(s/def ::original_currency ::currency-type)
(s/def ::currency ::currency-type)
(s/def ::original_total (s/and double? pos?))
(s/def ::original_taxes (s/and double? pos?))
(s/def ::taxes (s/and double? pos?))
(s/def ::total (s/and double? pos?))
(s/def ::original_total (s/and double? pos?))
(s/def ::rate (s/keys :req-un [::rate_key ::original_currency ::currency ::original_total
                               ::original_taxes ::taxes ::total ::original_total]))


so, I thought why not something like:

  ::rate {::taxes ::money
          ::original_taxes ::money
          ::total ::money
          ::original_total ::money

Oliver George03:05:28

@gfredericks Thinking more about defn+spec made me explore why i wanted it and alternative ways to get the the same result.

Oliver George03:05:02

One key thing spec gives me is protection from "garbage in garbage out" errors while I'm hacking up new features. Colocating the spec with the defn is helpful during this phase because I'm refactoring heavily as I go - if the s/fdef specs were in another file they're more likely to get stale.

Oliver George03:05:05

I can do this by adding s/assert statements in my defn.

Oliver George03:05:37

Later when code stabilises I see the logic of specs living in a different namespace so they are out of the way but still available to reference.

Oliver George03:05:48

As an aside, IDE support to allow hiding of spec statements would make that less important. #cursive

Oliver George03:05:17

But I appreciate the idea that separate namespaces for specs also allow for different specs to be applied to the same code depending on need.

Oliver George03:05:07

@gfredericks defn+spec would benefit from the s/assert flag so that it can have no impact on prod performance.


@rmuslimov that's covered in some of the spec docs


I did actually, as far as I can see: only s/keys is given for building spec for maps. I cannot do something close to way I proposed. Developer should always define explicitly keys like (s/def ::total ::money) and then build spec for map with s/keys.

Alex Miller (Clojure team)12:05:10

It's quite intentional that information maps are built as sets of attributes. This is a key design principle in spec - the semantics belong to the attribute, not to the map.


is there any context-independent benefit/downside of defining intermediate predicate fn over inline spec definition?

(defn nsless-keyword? [k]
  (and (keyword? k) (nil? (namespace k))))

(defn ::nsless-keyword nsless-keyword?)
(defn ::nsless-keyword (s/and keyword? (complement namespace)))

Alex Miller (Clojure team)17:05:04

Well it affects automatic generator capability

Alex Miller (Clojure team)17:05:33

But you should really use simple-keyword? rather than either of those

Alex Miller (Clojure team)17:05:47

Which has a built in generator


I would like to be able to attach a docstring to a spec. Has there been an progress on