我正在关注clojure.spec的指南(http://clojure.org/guides/spec).我被之间的区别感到困惑alt,并or进行序列规范.
对我来说,以下两个例子同样有效.那两者之间的区别是什么?
; Use `alt`
(s/def ::config (s/* (s/cat :prop string?
:val (s/alt :s string? :b boolean?))))
(s/explain ::config ["-server" "foo" "-verbose" true "-user" 13])
; Use `or`
(s/def ::config (s/* (s/cat :prop string?
:val (s/or :s string? :b boolean?))))
(s/explain ::config ["-server" "foo" "-verbose" true "-user" 13])
Run Code Online (Sandbox Code Playgroud)
Leo*_*hin 12
s/alt用于连接嵌套的正则表达式规范,其中using s/or指定嵌套序列.在您的示例中,它没有区别,因为您没有使用嵌套的正则表达式规范.这是一个例子:
(s/def ::number-regex (s/* number?))
(s/def ::or-example (s/cat :nums (s/or :numbers ::number-regex)))
(s/valid? ::or-example [1 2 3])
;;-> false
(s/valid? ::or-example [[1 2 3]])
;;-> true
Run Code Online (Sandbox Code Playgroud)
如您所见,or指定一个嵌套序列,在该序列中启动新的正则表达式上下文,而alt指定相反的:
(s/def ::alt-example (s/cat :nums (s/alt :numbers ::number-regex)))
(s/valid? ::alt-example [1 2 3])
;;-> true
(s/valid? ::alt-example [[1 2 3]])
;;-> false
Run Code Online (Sandbox Code Playgroud)
小智 8
来自http://clojure.org/guides/spec,我们知道
当结合使用正则表达式时,它们描述单个序列.
这意味着如果你想要有效嵌套序列,你应该这样做.
(s/def ::config (s/*
(s/cat :prop string?
:val (s/spec
(s/alt :s string? :b #(instance? Boolean %))))))
Run Code Online (Sandbox Code Playgroud)
然后你的数据看起来像这样(注意括号左右)
(s/explain ::config ["-server" ["foo"] "-verbose" [true] "-user" [13]])
Run Code Online (Sandbox Code Playgroud)
另外,如果你这样做(s /或).
(s/def ::config (s/* (s/cat :prop string?
:val (s/spec
(s/or :s string? :b #(instance? Boolean %))))))
Run Code Online (Sandbox Code Playgroud)
您的数据应与旧数据相同(请注意,周围没有括号)
(s/explain ::config ["-server" "foo" "-verbose" true "-user" 13])
Run Code Online (Sandbox Code Playgroud)
BTW,对于非嵌套序列.(s/alt)和(s /或)之间仍然有一点点差异:
;;; for (s/or)
(s/def ::name-or-id (s/or :name string?
:id int?))
(s/conform ::name-or-id 42) ;;=> [:id 42]
;;; for (s/alt)
(s/def ::name-or-id (s/alt :name string?
:id int?))
(s/conform ::name-or-id [42]) ;;=> [:id 42]
Run Code Online (Sandbox Code Playgroud)