Joh*_*son 11 clojure clojure.spec
我正在关注clojure.spec指南.我知道在使用clojure.spec/keys时可以声明必需和可选属性.
我不明白可选的意思.对我来说:opt不做任何事情.
(s/valid? (s/keys :req [:my/a]) {:my/a 1 :my/b 2}) ;=> true
(s/valid? (s/keys :req [:my/a] :opt []) {:my/a 1 :my/b 2}) ;=> true
Run Code Online (Sandbox Code Playgroud)
指南承诺向我解释这个问题,"我们稍后会看到可选属性可能有用",但我找不到解释.我可以申报禁用钥匙吗?或者以某种方式声明有效键的集合等于以下键:req和:opt?
Jos*_*osh 10
这是一个非常好的问题,而clojure.spec API给出了(授予的,简短的和不满意的)答案:
:opt键用作文档,可以由生成器使用.
我不认为你可以使地图失效,如果它包含一个额外的(这是你所说的"禁止"我认为)密钥使用这种方法.但是,您可以使用此规范来确保:: bad-key不存在:
(s/def ::m (s/and (s/keys :req [::a]) #(not (contains? % ::bad-key))))
(s/valid? ::m {::a "required!"}) ; => true
(s/valid? ::m {::a "required!" ::b "optional!"}) ; => true
(s/valid? ::m {::a "required!" ::bad-key "no good!"}) ; => false
Run Code Online (Sandbox Code Playgroud)
您可以使用此规范将键的数量限制为您想要的设置:
(s/def ::r (s/and (s/keys :req [::reqd1 ::reqd2]) #(= (count %) 2)))
(s/valid? ::r {::reqd1 "abc" ::reqd2 "xyz"}) ; => true
(s/valid? ::r {::reqd1 "abc" ::reqd2 "xyz" ::extra 123}) ; => false
Run Code Online (Sandbox Code Playgroud)
尽管如此,处理这个IMO的最好方法是忽略一个你不关心的关键礼物.
希望随着规范的成熟,这些美好的东西将被添加.或者,也许它们已经存在(它正在快速变化)而我根本就不知道它.这是clojure中一个非常新的概念,所以我们大多数人都有很多需要了解它.
更新 - 2016年12月我只是想在写这篇文章后的6个月内再次访问.看起来我最初的评论忽略了你不关心的键是首选的方法.事实上,在我两周前参加的clojure/conj会议上,Rich的主题演讲特别针对各级软件的版本控制概念,从功能级到应用级.他甚至特别提到了禁止在谈话中使用键的概念,这可以在youtube上找到.他说这是故意设计的,所以只能指定所需的键.禁止使用钥匙确实没有任何好处,应该谨慎行事.
关于:opt密钥,我认为原始答案仍然很好 - 它是文档,实际上,它允许生成这些可选的指定密钥:
(s/def ::name #{"Bob" "Josh" "Mary" "Susan"})
(s/def ::height-inches (s/int-in 48 90))
(s/def ::person (s/keys :req-un [::name] :opt-un [::height-inches]))
(map first (s/exercise ::person))
; some generated data have :height-inches, some do not
({:name "Susan"}
{:name "Mary", :height-inches 48}
{:name "Bob", :height-inches 49}
{:name "Josh"}
Run Code Online (Sandbox Code Playgroud)