用clojure.spec解析

时间:2016-08-29 10:53:54

标签: clojure clojure.spec

(require '[clojure.spec :as s])

考虑以下数据:

(def data {:names [["Anna"      :lucky]
                   ["Peter"]
                   ["Jon"       :lucky]
                   ["Andre"     :lucky]]})

这是一个带有一个键的哈希映射:具有向量向量值的名称。内部向量必须包含一个字符串作为第一个元素,并且可以选择包含关键字:lucky作为第二个元素。

前两句应该用clojure.spec来描述 - 让我们从向量中的项目开始:

(s/def ::item (s/cat :name string? :lucky (s/? #(= :lucky %))))

(s/conform ::item ["Tom"])
;; {:name "Tom"}
(s/conform ::item ["Tom" :lucky])
;; {:name "Tom", :lucky :lucky}
(s/conform ::item ["Tom" :sad])
;; :clojure.spec/invalid

这很有效。但是,如果只有一个选项。解析后的结果不会像这样更好:

`{:name "Tom", :lucky true}` or `{:name "Tom", :lucky false}`

可以在clojure.spec中完成吗?

有了这个,就可以继续:

(s/def ::items (s/coll-of ::item '()))

(s/conform ::items [["Tom" :lucky] ["Tim"]])
[["Tom" :lucky] ["Tim"]]

然而,看起来它通过了测试,但为什么这些项目不再被解析?

编辑: 这可以通过从alpha7切换到alpha10版本来解决,其中coll-of只接受一个参数

最后我的规范看起来像是,有前面提到的警告:

(s/def ::my-spec (s/keys req-un [::items]))

1 个答案:

答案 0 :(得分:2)

spec不是为提供任意数据转换而设计的(可以使用Clojure的核心库)。

可以使用s/conformer实现此目的,但不建议将此功能用于此类任意转换(它更适合构建自定义规范之类的内容)。