meander

jgdavey 2022-02-07T17:32:45.797449Z

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 Miller 2022-02-07T17:35:02.544949Z

[<pattern> ...]

jgdavey 2022-02-07T17:49:37.853139Z

Awesome! And d’oh!

jgdavey 2022-02-07T17:50:32.240259Z

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)

jgdavey 2022-02-07T17:50:51.408289Z

Trying to test that all are keywords that would unify

jgdavey 2022-02-07T18:08:35.824819Z

Perhaps something with guard?

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

noprompt 2022-02-07T18:19:30.061019Z

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

[?x . ?x ...]

jgdavey 2022-02-07T18:42:06.841029Z

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

👍 1