5

の通常のシーケンスから始めましょう

(require '[clojure.spec     :as spec]
         '[clojure.spec.gen :as gen])
(spec/def ::cat (spec/cat :sym symbol? :str string? :kws (spec/* keyword?)))

ベクトルに一致する

(spec/conform ::cat '[af "5"])
=> {:sym af, :str "5"}
(spec/conform ::cat '[af "5" :key])
=> {:sym af, :str "5", :kws [:key]}

リストも

(spec/conform ::cat '(af "5"))
=> {:sym af, :str "5"}
(spec/conform ::cat '(af "5" :key))
=> {:sym af, :str "5", :kws [:key]}

これを制限したい場合はspec/tuple、 ;を使用してみてください。しかし悲しいことに、これは固定長のベクトルにしかマッチしません。つまり、タプルの最後の部分に少なくとも空のリストが必要です:

(spec/def ::tuple (spec/tuple symbol? string? (spec/* keyword?)))
(spec/conform ::tuple '[af "5"])
=> :clojure.spec/invalid
(spec/exercise ::tuple)
=> ([[r "" ()] [r "" []]] [[kE "" (:M)] [kE "" [:M]]] ...)

::catwithに追加の条件を追加することもできますspec/and

(spec/def ::and-cat
  (spec/and vector? (spec/cat :sym symbol? :str string? :kws (spec/* keyword?))))

うまく一致する

(spec/conform ::and-cat '[af "5"])
=> {:sym af, :str "5"}
(spec/conform ::and-cat '[af "5" :key])
=> {:sym af, :str "5", :kws [:key]}
(spec/conform ::and-cat '(af "5" :key))
=> :clojure.spec/invalid

spec/catしかし残念なことに、 for ジェネレーターはもちろんvector?述語に準拠しないリストのみを生成するため、独自のデータの生成に失敗します。

(spec/exercise ::and-cat)
=> Couldn't satisfy such-that predicate after 100 tries.

要約すると、次のようなベクトルを受け入れて生成できる仕様をどのように作成し[hi "there"] [my "dear" :friend]ますか?

spec/cat質問を「リストの代わりにベクトルを生成する代替手段はありますか?」と言い換えることもできます。または「:kind 引数を に渡すことは可能spec/catですか?」または「元のジェネレーターの出力を取得してベクターにキャストするジェネレーターをスペックにアタッチできますか?」.

4

3 に答える 3