是否可以在 Clojure 函数前提条件中使用 Prismatic schema.core/maybe?

Posted

技术标签:

【中文标题】是否可以在 Clojure 函数前提条件中使用 Prismatic schema.core/maybe?【英文标题】:Is it possible to use Prismatic schema.core/maybe in a Clojure function precondition? 【发布时间】:2014-11-19 05:12:56 【问题描述】:

我正在尝试在一个带有可选参数opts 的函数的前提条件中使用Prismatic schema.core/maybe,但是当我调用没有opts 的函数时,它似乎总是抛出一个AssertionError

(require '[schema.core :as schema])

(defn foo [& modules]
  :pre [(schema/validate (schema/maybe [(schema/enum :foo :bar)]) opts)]
  :yay)

(foo :foo)
;=> :yay

(foo :foo :bar)
;=> :yay

(foo)
;=> AssertionError Assert failed: (schema/validate (schema/maybe [(schema/enum :foo :bar)]) modules)  user/foo (form-init3808809389777994177.clj:1)

有趣的是,它按预期工作:

(schema/validate (schema/maybe [(schema/enum :foo :bar)]) nil)
;=> nil

我在defn 上使用过macroexpand,但那里没有任何异常。

我当然可以使用像

这样的先决条件来解决这个问题

【问题讨论】:

【参考方案1】:

函数前置条件必须评估为真才能通过断言,但schema/validate 如果验证通过则返回正在测试的表达式,如果失败则抛出异常。如果验证通过,您需要更改前提条件以始终返回 true:

(defn foo [& opts]
  :pre [(or (schema/validate (schema/maybe [(schema/enum :foo :bar)]) opts) true)]
  :yay)

(foo :foo) ;=> :yay
(foo :foo :bar) ;=> :yay
(foo) ;=> :yay
(foo :baz) ;=> ExceptionInfo Value does not match schema: [(not (#:foo :bar :baz))]

【讨论】:

我不敢相信我错过了!我希望 schema 有一个 valid? 函数来处理这种情况。我想我可以用(comp nil? schema.core/check) 自己动手。 虽然仔细想想,如果我这样做了,我会丢失 Schema 的漂亮错误消息,所以也许我最好还是坚持(or (nil? ...)) 方法。 s/checkvalid? 的否定,而且更有用——它返回描述性错误,如果验证通过则返回 nil。所以更好的前提条件可能是(not (s/check ...))

以上是关于是否可以在 Clojure 函数前提条件中使用 Prismatic schema.core/maybe?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Clojure 中对函数进行基准测试?

无论如何在clojure中构造一个lambda函数?

如何在 Clojure 中获取 Unix 时间戳?

测试列表是不是包含 Clojure 中的特定值

测试“进入”是不是成功的函数

clojure 函数,左值和返回值