Fork me on GitHub
#meander
<
2022-02-07
>
jgdavey17:02:45

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]

Jimmy Miller17:02:02

[<pattern> ...]

jgdavey17:02:37

Awesome! And d’oh!

jgdavey17:02:32

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)

jgdavey17:02:51

Trying to test that all are keywords that would unify

jgdavey18:02:35

Perhaps something with guard?

(m/and [<pattern binding !xs> ...] (m/guard (apply = !xs)))

noprompt18:02:30

If a logic variable repeats you are saying “one or more”

[?x . ?x ...]

jgdavey18:02:06

Huzzah! That did it. Now I can use with for a more complicated pattern than just ?x

👍 1