将宏与 doseq 一起使用以生成规范
Use macros with doseq to generate spec
我发现自己写了很多这样的规范:
(s/def ::name string?)
(s/def ::logUri string?)
(s/def ::subnet (s/and string? #(> (count %) 5)))
(s/def ::instanceType string?)
...
(s/def ::key (s/and string? #(> (count %) 5)))
(s/def ::instanceCount string?)
(s/def ::bidPct string?)
即很多 s/and
和 s/def
。这似乎是一种浪费。所以我决定写一个宏来为我做这件事。类似于:
(defmacro and-spec [validations]
(doseq [[keyname & funcs] validations]
`(s/def ~keyname (s/and ~@funcs))))
所以我可以这样做:
(and-spec [[::name1 [string?]]
[::name2 [string? #(> (count %) 5)]]])
这会为我做所有 s/def
的事情。不幸的是,上面的宏不起作用,但我不确定为什么。
(s/valid? ::name1 "asdf")
Execution error at emr-cli.utils/eval6038 (form-init17784784591561795514.clj:1).
Unable to resolve spec: :emr-cli.utils/name1
这项工作的较小版本:
(defmacro small-and-spec-works [key-name validations]
`(s/def ~key-name (s/and ~@validations)))
=> #'emr-cli.utils/tsmall
(and-spec-small-works ::mykey [string?])
=> :emr-cli.utils/mykey
(s/valid? ::mykey "asdf")
=> true
但是第二个我介绍了让绑定的东西开始变得奇怪:
(defmacro small-and-spec [validation]
(let [[key-name & valids] validation]
`(s/def ~key-name (s/and ~@valids))))
=> #'emr-cli.utils/small-and-spec
(small-and-spec [::mykey2 [string?]])
=> :emr-cli.utils/mykey2
(s/valid? ::mykey2 "asdf")
Execution error (IllegalArgumentException) at emr-cli.utils/eval6012 (form-init17784784591561795514.clj:1).
Key must be integer
- 如何使
doseq
宏起作用?
- 造成
Key must be integer
错误的 small-and-spec
出了什么问题?
(defmacro and-spec [defs]
`(do
~@(map (fn [[name rest]]
`(s/def ~name (s/and ~@rest))) defs)))
doseq
用于副作用。它总是 returns nil
.
我发现自己写了很多这样的规范:
(s/def ::name string?)
(s/def ::logUri string?)
(s/def ::subnet (s/and string? #(> (count %) 5)))
(s/def ::instanceType string?)
...
(s/def ::key (s/and string? #(> (count %) 5)))
(s/def ::instanceCount string?)
(s/def ::bidPct string?)
即很多 s/and
和 s/def
。这似乎是一种浪费。所以我决定写一个宏来为我做这件事。类似于:
(defmacro and-spec [validations]
(doseq [[keyname & funcs] validations]
`(s/def ~keyname (s/and ~@funcs))))
所以我可以这样做:
(and-spec [[::name1 [string?]]
[::name2 [string? #(> (count %) 5)]]])
这会为我做所有 s/def
的事情。不幸的是,上面的宏不起作用,但我不确定为什么。
(s/valid? ::name1 "asdf")
Execution error at emr-cli.utils/eval6038 (form-init17784784591561795514.clj:1).
Unable to resolve spec: :emr-cli.utils/name1
这项工作的较小版本:
(defmacro small-and-spec-works [key-name validations]
`(s/def ~key-name (s/and ~@validations)))
=> #'emr-cli.utils/tsmall
(and-spec-small-works ::mykey [string?])
=> :emr-cli.utils/mykey
(s/valid? ::mykey "asdf")
=> true
但是第二个我介绍了让绑定的东西开始变得奇怪:
(defmacro small-and-spec [validation]
(let [[key-name & valids] validation]
`(s/def ~key-name (s/and ~@valids))))
=> #'emr-cli.utils/small-and-spec
(small-and-spec [::mykey2 [string?]])
=> :emr-cli.utils/mykey2
(s/valid? ::mykey2 "asdf")
Execution error (IllegalArgumentException) at emr-cli.utils/eval6012 (form-init17784784591561795514.clj:1).
Key must be integer
- 如何使
doseq
宏起作用? - 造成
Key must be integer
错误的small-and-spec
出了什么问题?
(defmacro and-spec [defs]
`(do
~@(map (fn [[name rest]]
`(s/def ~name (s/and ~@rest))) defs)))
doseq
用于副作用。它总是 returns nil
.