Sam*_*tep 8 clojure destructuring clojure.spec
写完这个答案之后,我受到启发,尝试使用以下方法指定Clojure的解构语言spec
:
(require '[clojure.spec :as s])
(s/def ::binding (s/or :sym ::sym :assoc ::assoc :seq ::seq))
(s/def ::sym (s/and simple-symbol? (complement #{'&})))
Run Code Online (Sandbox Code Playgroud)
顺序解构部分很容易用正则表达式进行规范(所以我在这里忽略它),但我陷入了联想解构.最基本的情况是从绑定表单到键表达式的映射:
(s/def ::mappings (s/map-of ::binding ::s/any :conform-keys true))
Run Code Online (Sandbox Code Playgroud)
但Clojure也提供了几个特殊键:
(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]))
Run Code Online (Sandbox Code Playgroud)
如何::assoc
为可以通过将符合::mappings
的地图和符合的地图合并在一起创建的地图创建规范::opts
?我知道有merge
:
(s/def ::assoc (s/merge ::opts ::mappings))
Run Code Online (Sandbox Code Playgroud)
您可以使用地图s/merge
的s/keys
和s/every
作为元组来定义混合地图.这是一个更简单的例子:
(s/def ::a keyword?)
(s/def ::b string?)
(s/def ::m
(s/merge (s/keys :opt-un [::a ::b])
(s/every (s/or :int (s/tuple int? int?)
:option (s/tuple keyword? any?))
:into {})))
(s/valid? ::m {1 2, 3 4, :a :foo, :b "abc"}) ;; true
Run Code Online (Sandbox Code Playgroud)
与配方器方法相比,这种更简单的配方具有几个优点.最重要的是,它说明了事实.此外,它应该生成,符合和不成形,而无需进一步努力.
归档时间: |
|
查看次数: |
333 次 |
最近记录: |