微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将剂量指令与宏配合使用以生成规格

如何解决将剂量指令与宏配合使用以生成规格

我发现自己写了很多这样的规范:

(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/ands/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
  1. 如何使doseq宏正常工作?
  2. 造成small-and-spec错误Key must be integer怎么了?

解决方法

(defmacro and-spec [defs]
    `(do
        ~@(map (fn [[name rest]]
              `(s/def ~name (s/and ~@rest))) defs)))

doseq用于副作用。它总是返回nil

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。