Clojure。在地图中使用动态名称关键字创建规范
Clojure. Create a Spec with dynamic name keywords in a map
我有这张地图:
{:60 {:id 60, :quote "Lorem ipsum doloret sit anem", :author "foo name", :total 61}
:72 {:id 72, :quote "Excepteur sint occaecat cupidatat non", :author "Nietzsche", :total 61}
:56 {:id 56, :quote "Ut enim ad minim veniam, quis nostrud ", :author "O. Wilde", :total 61}
:58 {:id 58, :quote "Duis aute irure dolor in reprehenderit", :author "your mama", :total 61}}
我正在尝试创建它的规范,我想我有地图 "inner part":
(s/def ::id (s/and int? pos?))
(s/def ::quote (s/and string? #(>= (count %) 8)))
(s/def ::author (s/and string? #(>= (count %) 6)))
(s/def ::total (s/and int? pos?))
(s/def ::quotes (s/and
(s/map-of ::id ::quote ::author ::total)
#(instance? PersistentTreeMap %) ;; is a sorted-map (not just a map)
))
但是地图关键字是动态创建的,所以它们没有名称,我如何定义这些关键字的规范并将其添加到 (s/map-of 函数 ?
map-of takes a key predicate, a value predicate, and optional arguments — not a list of keywords. To define the list of keywords in a map you can use the keys 带有 :req-un
参数的函数,因为您使用的是不合格的键。
由于您没有指定要如何限制地图关键字,我假设它们可以是任何关键字。如果是这样,那么您可以更改以下内容,
(s/def ::key keyword?)
(s/def ::quotes (s/and
(s/map-of ::key (s/keys :req-un [::id
::quote
::author
::total]))
#(instance? clojure.lang.PersistentTreeMap %)))
使用上面的示例地图,我们可以看到此规范定义是对应的。
user=> (s/valid? ::quotes
#=> (into (sorted-map)
#=> {:60 {:id 60
#=> :quote "Lorem ipsum doloret sit anem"
#=> :author "foo name"
#=> :total 61}
#=> :72 {:id 72
#=> :quote "Excepteur sint occaecat cupidatat non"
#=> :author "Nietzsche"
#=> :total 61}
#=> :56 {:id 56
#=> :quote "Ut enim ad minim veniam, quis nostrud "
#=> :author "O. Wilde"
#=> :total 61}
#=> :58 {:id 58
#=> :quote "Duis aute irure dolor in reprehenderit"
#=> :author "your mama"
#=> :total 61}}))
true
只需使用整数作为您的地图键。对任意字符串进行关键字化 通常 是错误的;关键字化数字是一种特别明显的反模式。然后规范很简单:它只是一个带有 int 键的映射。
我有这张地图:
{:60 {:id 60, :quote "Lorem ipsum doloret sit anem", :author "foo name", :total 61}
:72 {:id 72, :quote "Excepteur sint occaecat cupidatat non", :author "Nietzsche", :total 61}
:56 {:id 56, :quote "Ut enim ad minim veniam, quis nostrud ", :author "O. Wilde", :total 61}
:58 {:id 58, :quote "Duis aute irure dolor in reprehenderit", :author "your mama", :total 61}}
我正在尝试创建它的规范,我想我有地图 "inner part":
(s/def ::id (s/and int? pos?))
(s/def ::quote (s/and string? #(>= (count %) 8)))
(s/def ::author (s/and string? #(>= (count %) 6)))
(s/def ::total (s/and int? pos?))
(s/def ::quotes (s/and
(s/map-of ::id ::quote ::author ::total)
#(instance? PersistentTreeMap %) ;; is a sorted-map (not just a map)
))
但是地图关键字是动态创建的,所以它们没有名称,我如何定义这些关键字的规范并将其添加到 (s/map-of 函数 ?
map-of takes a key predicate, a value predicate, and optional arguments — not a list of keywords. To define the list of keywords in a map you can use the keys 带有 :req-un
参数的函数,因为您使用的是不合格的键。
由于您没有指定要如何限制地图关键字,我假设它们可以是任何关键字。如果是这样,那么您可以更改以下内容,
(s/def ::key keyword?)
(s/def ::quotes (s/and
(s/map-of ::key (s/keys :req-un [::id
::quote
::author
::total]))
#(instance? clojure.lang.PersistentTreeMap %)))
使用上面的示例地图,我们可以看到此规范定义是对应的。
user=> (s/valid? ::quotes
#=> (into (sorted-map)
#=> {:60 {:id 60
#=> :quote "Lorem ipsum doloret sit anem"
#=> :author "foo name"
#=> :total 61}
#=> :72 {:id 72
#=> :quote "Excepteur sint occaecat cupidatat non"
#=> :author "Nietzsche"
#=> :total 61}
#=> :56 {:id 56
#=> :quote "Ut enim ad minim veniam, quis nostrud "
#=> :author "O. Wilde"
#=> :total 61}
#=> :58 {:id 58
#=> :quote "Duis aute irure dolor in reprehenderit"
#=> :author "your mama"
#=> :total 61}}))
true
只需使用整数作为您的地图键。对任意字符串进行关键字化 通常 是错误的;关键字化数字是一种特别明显的反模式。然后规范很简单:它只是一个带有 int 键的映射。