Dopo aver scritto this answer, mi sono ispirato per cercare di specificare Clojure's destructuring language utilizzando spec
:Come specificare una mappa ibrida?
(require '[clojure.spec :as s])
(s/def ::binding (s/or :sym ::sym :assoc ::assoc :seq ::seq))
(s/def ::sym (s/and simple-symbol? (complement #{'&})))
La parte destrutturazione sequenziale è facile a spec con una regex (così sto ignorando qui), ma mi sono bloccato a destrutturazione associativa. Il caso più semplice è una mappa da forme di legame alle espressioni chiave:
(s/def ::mappings (s/map-of ::binding ::s/any :conform-keys true))
Ma Clojure fornisce diversi tasti speciali come pure:
(s/def ::as ::sym)
(s/def ::or ::mappings)
(s/def ::ident-vec (s/coll-of ident? :kind vector?))
(s/def ::keys ::ident-vec)
(s/def ::strs ::ident-vec)
(s/def ::syms ::ident-vec)
(s/def ::opts (s/keys :opt-un [::as ::or ::keys ::strs ::syms]))
Come posso creare un ::assoc
spec per le mappe che possono essere creati unendo una mappa conforme a ::mappings
e una mappa conforme a ::opts
? So che c'è merge
:
(s/def ::assoc (s/merge ::opts ::mappings))
Ma questo non funziona, perché merge
è fondamentalmente un analogo del and
. Sto cercando qualcosa di analogo a or
, ma per le mappe.
Grazie! Ero sicuro che ci fosse qualcosa di simile che potesse essere usato. Sembra piuttosto brutto, però; Spero che una soluzione più elegante venga aggiunta in futuro. –