Fork me on GitHub
#clojure-spec
<
2018-05-18
>
vlad02:05:05

is it possible to evaluate spec description?

vlad02:05:30

(def big-integer 1000)
(s/def ::small-integer {:spec (fn [n] (n < big-integer)) :description (str "Smaller than " big-integer)})

vlad02:05:39

(s/explain-data ::small-integer 5000)

vlad02:05:41

produces

vlad02:05:05

#:clojure.spec.alpha{:problems [{:path [],
                                 :pred {:spec (fn [n] (n < big-integer)),
                                        :description (str "Smaller than " big-integer)},
                                 :val 5000,
                                 :via [:xxx.spec/small-integer],
                                 :in []}],
                     :spec :xxx.spec/small-integer,
                     :value 5000}

vlad02:05:26

I woud expect Smaller than 1000 in the description instead

vlad02:05:03

the following one works, but I want to see this in the explanation

vlad02:05:07

(-> (s/form ::small-integer) :description eval)

mpenet05:05:22

It's easy to hack a (simple) meta registry to do that without abusing the internals of clj.spec.

mpenet05:05:01

I did that and a few other horrors here if you re looking for inspiration https://github.com/mpenet/spex

mpenet05:05:59

Look for spex/with-doc in the readme

mpenet07:05:09

gist of it:

(-> (s/def ::foo any?)
    (spex/with-doc "That's a foo"))

(spex/doc ::foo) => "That's a foo"

sundarj13:05:11

there's a coll-of but no corresponding one-of; i can go from a scalar spec to a collection spec, but i don't think i can go from a collection spec to an element spec. is that intentional? i'm wondering because i'm currently speccing a text editor, and it's going to have a collection of working documents as well an active document, which would naturally be one of the working documents

mpenet13:05:20

seems like you just need a set

mpenet13:05:31

or I am misunderstanding

sundarj14:05:11

i presently have this:

(s/def :world.sometimes.nota.editor/working-notes
  (s/coll-of :world.sometimes.nota.app/note
             :kind vector?
             :distinct true))

(s/def :world.sometimes.nota.editor/active-note
  :world.sometimes.nota.app/note)

(s/def :world.sometimes.nota.app/editor
  (s/keys :req [:world.sometimes.nota.editor/working-notes
                :world.sometimes.nota.editor/active-note]))

sundarj14:05:32

but it feels wrong because active-note isn't just a random note, it's only ever going to be one of the working notes

Alex Miller (Clojure team)14:05:44

this would be easier if the working-notes was a set (not sure why it isn’t) but you could s/and an additional check into editor that working-notes contains active-note

sundarj14:05:51

it's not a set because the active-note is going to be pulled from the working-notes, and sets would be the wrong data structure for that, right? sets are just about membership, as far as i know

sundarj14:05:38

i hadn't thought about putting an s/and on editor, that makes a lot of sense. thanks 🙂

Alex Miller (Clojure team)14:05:24

you’re declaring in working-notes that its elements are distinct. that’s the same guarantee sets give you but they can check membership in (near) constant time rather than via a linear search

sundarj14:05:41

yeah, i know. i had the :kind as set? before, but then i realised you couldn't pull arbitrary members out of a set; there's going to be a UI that lists all the working notes, and then you click on one to open it. i think a vector is a better choice given that use-case. i suppose i could have a vector and a set, but then i'd have to keep them in sync

Alex Miller (Clojure team)14:05:33

what do you mean by “you couldn’t pull arbitrary members out of a set” ? it seems like you can do exactly that

Alex Miller (Clojure team)14:05:51

do you mean you need to retain ordering?

sundarj14:05:46

i meant that to pull an item out of a set you need the item itself; i thought you couldn't iterate over a set, but i realise i was mistaken. in any case, i think i do need to retain ordering

Alex Miller (Clojure team)14:05:38

and that’s a good reason to use a vector, not trying to necessarily change your mind, just probing

sundarj14:05:12

i understand; i appreciate the questions. it did make me more fully analyse why i wanted it to be a vector, so thanks 🙂