What’s an idiomatic way to express “all elements of this vector match this pattern”? For sets and maps, there’s the built-in map-of and set-of, but I don’t see something like seq-of or vec-of. It’s trivial to implement with defsyntax, but feels like I’m missing something more fundamental.
Example:
(m/defsyntax vec-of
"Pattern matching and substitution operator.
When used as a pattern matching operator, matches a vector where all
the entries have keys which match `pattern`.
When used as a pattern substitution operator, constructs a vector where
all entries are constructed with `pattern`."
[pattern]
(cond
(m/match-syntax? &env)
`(m/with [%coll# (m/or [~pattern & %coll#]
'[])]
%coll#)
(m/subst-syntax? &env)
`[~pattern ...]
:else
&form))
(m/rewrite [:a :b]
(vec-of (m/and (m/keyword _) !x))
(vec-of !x)
?a :wrong) ;; => [:a :b][<pattern> ...]
Awesome! And d’oh!
Next issue: How can I specify that a logic variable repeats? That is, repetition of :a keyword in the following example:
(m/rewrite [:a :a]
[(m/and (m/keyword ?n) !x) ...]
[!x ...]
?a :wrong)
(This doesn’t compile because of unbound logic var error)Trying to test that all are keywords that would unify
Perhaps something with guard?
(m/and [<pattern binding !xs> ...] (m/guard (apply = !xs)))If a logic variable repeats you are saying “one or more”
[?x . ?x ...]
Huzzah! That did it. Now I can use with for a more complicated pattern than just ?x