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

是否可以在Clojure函数先决条件中使用Prismatic schema.core/maybe?,clojure,preconditions,plumatic-schema,Clojure,Preconditions,Plumatic Schema,我试图在一个函数的前提条件中使用一个可选参数opts,但是当我在没有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 :

我试图在一个函数的前提条件中使用一个可选参数
opts
,但是当我在没有
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
,但是那里没有什么不寻常的地方


当然,我可以使用一个先决条件来解决这个问题,比如

函数先决条件必须计算为truthy,断言才能通过,但是如果验证通过,
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))]

真不敢相信我错过了!对于这样的情况,我希望模式有一个
有效的?
函数。我想,我可以用
(comp-nil?schema.core/check)
(comp-nil?schema.core/check)。虽然我想起来了,如果我这样做,我会丢失schema的漂亮错误消息,所以也许我最好还是坚持
(或(nil?…)
方法。
s/check
有效的否定吗?
,更有用的是,它返回一个描述性错误,如果验证通过,则返回nil。因此,更好的先决条件可能是
(而不是(s/check…)