clojureplumatic-schema

Check specifically for vector in a matrix Clojure's Schema


In my program, I'm using a kind of matrix (as a vector of vectors) like this one:

[[:lt :lt :gt :eq]
 [:eq :lt :gt :eq]
 [:eq :eq :gt :gt]
 [:un :eq :lt :lt]]

I have a schema for it, declared as:

(def OrderMatrix [[(s/enum :lt :eq :gt :un)]]

What I'd like to do is further restrict the schema so it makes sure my matrix is a vector of clojure.lang.PersistentVector, or even better (if possible), a structure that supports random access. It seems that using [ ] in schema only tests for sequence, so a list of lists would pass the schema as well.

How do I express this constraint with schema?


Solution

  • You may use combination of schema/both and schema/pred. Here's an example:

    (defn Vector [inner-schema]
      (schema/both (schema/pred vector? "vector")
                   [inner-schema]))
    
    (defn RandomAccess [inner-schema]
      (schema/both
       (schema/pred
        (partial instance? java.util.RandomAccess)
        "random access")
       [inner-schema]))
    
    (def OrderMatrix (Vector (Vector (schema/enum :lt :eq :gt :un))))
    ;; or (def OrderMatrix (RandomAccess (RandomAccess (schema/enum :lt :eq :gt :un))))
    

    and then:

    user> (schema/check OrderMatrix ['(:lt)])
    [(not ("vector" (:lt)))]