Fork me on GitHub
#clojure-spec
<
2020-05-13
>
oskarkv14:05:16

(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?

oskarkv14:05:07

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

Alex Miller (Clojure team)14:05:03

doesn't the first one include the second?

oskarkv14:05:32

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

oskarkv14:05:45

I'm not sure I understand what you meant.

Alex Miller (Clojure team)14:05:16

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

Alex Miller (Clojure team)14:05:47

(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))

Alex Miller (Clojure team)14:05:15

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

oskarkv14:05:24

Yeah 🙂

Alex Miller (Clojure team)14:05:18

another way would be to restrict the bigger one

Alex Miller (Clojure team)14:05:54

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 %))))

Alex Miller (Clojure team)14:05:41

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

oskarkv14:05:02

Hm, gotta read up on &. Thanks!

🥨 4
Alex Miller (Clojure team)14:05:16

& just lets you and arbitrary predicates into the regex spec

oskarkv14:05:31

Ah, I see. Could work. Thanks!