Thanks @seancorfield for the detailed answer and thanks @fmnoise for helping out too!
(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?There are always macros of course but I was hoping for something easier.
doesn't the first one include the second?
But I want a spec for data where a var is forbidden. And one where it's optional.
ah
I'm not sure I understand what you meant.
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
(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))
that does introduce nesting in the conformed data so is not everything you want
Yeah 🙂
another way would be to restrict the bigger one
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 %))))
can't say I've done this before, might need to tweak that predicate more
Hm, gotta read up on &
. Thanks!
& just lets you and arbitrary predicates into the regex spec
Ah, I see. Could work. Thanks!