Po napisaniu this answer byłem inspirowany spróbować określić Clojure's destructuring language użyciu spec
:Jak mogę określić mapę hybrydową?
(require '[clojure.spec :as s])
(s/def ::binding (s/or :sym ::sym :assoc ::assoc :seq ::seq))
(s/def ::sym (s/and simple-symbol? (complement #{'&})))
Sekwencyjna część rozpad jest łatwy do spec z regex (więc jestem ignorując go tutaj), ale utknąłem w asocjacyjna destrukcja. Najbardziej podstawowa sprawa jest mapa z obowiązujących formularzy do kluczowych wyrażeń:
(s/def ::mappings (s/map-of ::binding ::s/any :conform-keys true))
Ale Clojure oferuje kilka klawiszy specjalnych, a także:
(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]))
W jaki sposób można utworzyć ::assoc
specyfikację dla map, które mogą być tworzone łącząc mapę zgodną z ::mappings
i mapę zgodną z ::opts
? Wiem, że istnieje merge
:
(s/def ::assoc (s/merge ::opts ::mappings))
Ale to nie działa, ponieważ merge
jest w zasadzie analogiem and
. Szukam czegoś podobnego do or
, ale do map.
Dzięki! Byłem pewien, że było coś takiego, co można by wykorzystać. Wydaje się jednak dość brzydka; Mam nadzieję, że w przyszłości dodane zostanie bardziej eleganckie rozwiązanie. –