说,我们有一个功能clothe
这就需要另外一个位置参数person
了多项可选的命名参数:hat
,:shirt
和:pants
。现实Clojure的规格为函数命名参数
(defn clothe [person & {:keys [hat shirt pants]}]
(str "Clothing " person " with " hat shirt pants "."))
(clothe 'me :hat "top hat")
=> "Clothing me with top hat."
我现在写规范此功能的方法是:
(require '[clojure.spec :as spec]
'[clojure.spec.gen :as gen])
(spec/def ::person symbol?)
(spec/def ::clothing
(spec/alt :hat (spec/cat :key #{:hat} :value string?)
:shirt (spec/cat :key #{:shirt} :value string?)
:pants (spec/cat :key #{:pants} :value string?)))
(spec/fdef clothe
:args (spec/cat :person ::person
:clothes (spec/* ::clothing))
:ret string?)
则是它允许参数列表就像
(clothe 'me :hat "top hat" :hat "nice hat")
=> "Clothing me with nice hat."
这即使允许通过的问题语言本身在任何时候都可能是一个错误。但是,也许比这更糟糕的是,它使生成的数据不切实际的功能如何,通常称为:
(gen/generate (spec/gen (spec/cat :person ::person
:clothes (spec/* ::clothing))))
=> (_+_6+h/!-6Gg9!43*e :hat "m6vQmoR72CXc6R3GP2hcdB5a0"
:hat "05G5884aBLc80s4AF5X9V84u4RW" :pants "3Q" :pants "a0v329r25f3k5oJ4UZJJQa5"
:hat "C5h2HW34LG732ifPQDieH" :pants "4aeBas8uWx1eQWYpLRezBIR" :hat "C229mzw"
:shirt "Hgw3EgUZKF7c7ya6q2fqW249GsB" :pants "byG23H2XyMTx0P7v5Ve9qBs"
:shirt "5wPMjn1F2X84lU7X3CtfalPknQ5" :pants "0M5TBgHQ4lR489J55atm11F3"
:shirt "FKn5vMjoIayO" :shirt "2N9xKcIbh66" :hat "K8xSFeydF" :hat "sQY4iUPF0Ef58198270DOf"
:hat "gHGEqi58A4pH2s74t0" :pants "" :hat "D6RKWJJoFLCAaHId8AF4" :pants "exab2w5o88b"
:hat "S7Ti2Cb1f7se7o86I1uE" :shirt "9g3K6q1" :hat "slKjK67608Y9w1sqV1Kxm"
:hat "cFbVMaq8bfP22P8cD678s" :hat "f57" :hat "2W83oa0WVWM10y1U49265k2bJx"
:hat "O6" :shirt "7BUJ824efBb81RL99zBrvH2HjziIT")
而且最糟糕的是,如果你碰巧有一个递归defenition与spec/*
没有限制的方式在代码上运行测试时生成的潜在递归事件的数量。
那么我的问题就变成了:是否有一种方法可以将命名参数指定为限制每个键的出现次数的函数?