2016-06-02 2 views
11

私はclojure.specのガイド(http://clojure.org/guides/spec)に従っています。シーケンス仕様のためにaltorの違いを私は混乱しています。clojure.spec:シーケンス仕様のための `alt`と` vs `または`

私にとって、次の2つの例は同じように機能します。では、2つの違いは何ですか?

; 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]) 
+0

一つのことしようとする: 'スペック/それをexercise'するためにそれを渡し、その後、' or'を使用してスペックを書きますあなたのために10の例を生成/検証します。 'alt'に切り替えて同じことをします。私はスペックをデバッグするために 'spec/exercise'を常に使用しています。バグのある仕様から生成された出力に検証する必要があると考えるのは素晴らしいです。 –

答えて

9

s/alts/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 

altが反対を指定するのに対しorは、新しい正規表現コンテキストが開始されるサブシーケンスを指定します:ここでは一例である

(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 
5

http://clojure.org/guides/specから、我々は知っています

正規表現を組み合わせると、1つのシーケンスが記述されます。

つまり、ネストされたシーケンスを有効にするには、このようにする必要があります。

(s/def ::config (s/* 
       (s/cat :prop string? 
         :val (s/spec 
           (s/alt :s string? :b #(instance? Boolean %)))))) 

そして、あなたは(S /または)を行うならば、あなたのデータは、また、この(お知らせ周りかっこ)

(s/explain ::config ["-server" ["foo"] "-verbose" [true] "-user" [13]]) 

のように見えます。

(s/def ::config (s/* (s/cat :prop string? 
          :val (s/spec 
            (s/or :s string? :b #(instance? Boolean %)))))) 

あなたのデータは

(s/explain ::config ["-server" "foo" "-verbose" true "-user" 13]) 

ところで、非ネストされたシーケンスのための(周りに括弧がないお知らせ)古いものと同じでなければなりません。そこに(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] 
関連する問題