让我们来看一下与Leiningen项目映射相关的现实世界例子:
:global-vars
: ;; Sets the values of global vars within Clojure. This example
;; disables all pre- and post-conditions and emits warnings on
;; reflective calls. See the Clojure documentation for the list of
;; valid global variables to set (and their meaningful values).
:global-vars {*warn-on-reflection* true
*assert* false}
它允许leiningen的用户重新定义其项目范围内Clojure全局变量的默认值。
现在,如果这个映射的键由关键字组成,我们将使用clojure.spec/keys
来首先指定哪些键可以成为映射的一部分,然后单独定义这些键下预期的值。但是,由于clojure.spec/keys
在:req
和:req-un
中静默忽略非关键字,并在:opt
和:opt-un
中抛出异常(截至alpha15),因此我们需要以某种方式解决这个问题。
我们可以通过以下方式获取大多数这些全局变量的类型:
(for [[sym varr] (ns-publics 'clojure.core)
:when (re-matches #"\*.+\*" (name sym))]
[varr (type @varr)])
=>
[*print-namespace-maps* java.lang.Boolean]
[*source-path* java.lang.String]
[*command-line-args* clojure.lang.ArraySeq]
[*read-eval* java.lang.Boolean]
[*verbose-defrecords* java.lang.Boolean]
[*print-level* nil]
[*suppress-read* nil]
[*print-length* nil]
[*file* java.lang.String]
[*use-context-classloader* java.lang.Boolean]
[*err* java.io.PrintWriter]
[*default-data-reader-fn* nil]
[*allow-unresolved-vars* java.lang.Boolean]
[*print-meta* java.lang.Boolean]
[*compile-files* java.lang.Boolean]
[*math-context* nil]
[*data-readers* clojure.lang.PersistentArrayMap]
[*clojure-version* clojure.lang.PersistentArrayMap]
[*unchecked-math* java.lang.Boolean]
[*out* java.io.PrintWriter]
[*warn-on-reflection* nil]
[*compile-path* java.lang.String]
[*in* clojure.lang.LineNumberingPushbackReader]
[*ns* clojure.lang.Namespace]
[*assert* java.lang.Boolean]
[*print-readably* java.lang.Boolean]
[*flush-on-newline* java.lang.Boolean]
[*agent* nil]
[*fn-loader* nil]
[*compiler-options* nil]
[*print-dup* java.lang.Boolean]
其他的内容我们可以通过阅读文档来填写。但我想问你的是:我们如何编写一个规范,以确保如果映射包含键'*assert*'
,它仅包含布尔值?