clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
Amir Eldor 2020-05-13T06:38:42.394700Z

Thanks @seancorfield for the detailed answer and thanks @fmnoise for helping out too!

oskarkv 2020-05-13T14:09:16.396Z

(s/def ::fact
  (s/cat :var (s/? ::?symbol)
         :type (s/or :simple symbol? :acc ::acc-vec)
         :destruct (s/? vector?)
         :exprs (s/* list?)))

(s/def ::fact-without-var
  (s/cat :type (s/or :simple symbol? :acc ::acc-vec)
         :destruct (s/? vector?)
         :exprs (s/* list?)))
Is there a way to get rid of the repetition here without introducing more nesting and keywords in the conformed data?

oskarkv 2020-05-13T14:12:07.397400Z

There are always macros of course but I was hoping for something easier.

alexmiller 2020-05-13T14:13:03.397700Z

doesn't the first one include the second?

oskarkv 2020-05-13T14:16:32.399300Z

But I want a spec for data where a var is forbidden. And one where it's optional.

alexmiller 2020-05-13T14:16:45.399700Z

ah

oskarkv 2020-05-13T14:16:45.399800Z

I'm not sure I understand what you meant.

alexmiller 2020-05-13T14:17:16.400400Z

so, you can create a new spec that is an s/cat that just contains the common portions, then reference it in both ::fact specs

alexmiller 2020-05-13T14:18:47.401800Z

(s/def ::fact-without-var
  (s/cat :type (s/or :simple symbol? :acc ::acc-vec)
         :destruct (s/? vector?)
         :exprs (s/* list?)))

(s/def ::fact
  (s/cat :var (s/? ::?symbol)
         :tail ::fact-without-var))

alexmiller 2020-05-13T14:19:15.402400Z

that does introduce nesting in the conformed data so is not everything you want

oskarkv 2020-05-13T14:19:24.402600Z

Yeah 🙂

alexmiller 2020-05-13T14:20:18.402900Z

another way would be to restrict the bigger one

alexmiller 2020-05-13T14:21:54.404Z

maybe something like

(s/def ::fact
  (s/cat :var (s/? ::?symbol)
         :type (s/or :simple symbol? :acc ::acc-vec)
         :destruct (s/? vector?)
         :exprs (s/* list?)))

(s/def ::fact-without-var
  (s/& ::fact #(nil? (:var %))))

alexmiller 2020-05-13T14:22:41.404700Z

can't say I've done this before, might need to tweak that predicate more

oskarkv 2020-05-13T14:23:02.405Z

Hm, gotta read up on &. Thanks!

🥨 1
alexmiller 2020-05-13T14:24:16.405500Z

& just lets you and arbitrary predicates into the regex spec

oskarkv 2020-05-13T14:24:31.405800Z

Ah, I see. Could work. Thanks!