如何使用clojure.spec生成相互关联的参数?
我有一个方法可以从成对的字符串中删除公共前缀,并且一直在尝试为它创建一个生成器。生成随机字符串对是很简单的,但是如何强制使许多对具有公共前缀呢?简单地过滤成对生成的示例数量不足,因此我尝试创建一个自定义生成器来满足需求 这就是我现在拥有的;它可以工作,但我想生成更好的参数:如何使用clojure.spec生成相互关联的参数?,clojure,clojure.spec,Clojure,Clojure.spec,我有一个方法可以从成对的字符串中删除公共前缀,并且一直在尝试为它创建一个生成器。生成随机字符串对是很简单的,但是如何强制使许多对具有公共前缀呢?简单地过滤成对生成的示例数量不足,因此我尝试创建一个自定义生成器来满足需求 这就是我现在拥有的;它可以工作,但我想生成更好的参数: (ns liblevenshtein.distance (:require [clojure.spec.alpha :as spec] [clojure.spec.gen.alpha :as ge
(ns liblevenshtein.distance
(:require [clojure.spec.alpha :as spec]
[clojure.spec.gen.alpha :as gen]))
(spec/def ::word
(spec/and string? (complement nil?)))
(spec/def ::v-w (spec/cat :v ::word, :w ::word))
(spec/def ::non-empty-v-w
(spec/and ::v-w (fn [{:keys [v w]}]
(and (not-empty v)
(not-empty w)))))
(defn- drop-common-prefix [v w]
(loop [v v, a (.charAt v 0), s (.substring v 1),
w w, b (.charAt w 0), t (.substring w 1)]
(if (and (= a b)
(not-empty s)
(not-empty t))
(recur s (.charAt s 0) (.substring s 1)
t (.charAt t 0) (.substring t 1))
[v a s, w b t])))
(spec/fdef drop-common-prefix
:args ::non-empty-v-w
:ret (spec/tuple string? char? string?, string? char? string?)
:fn (fn [{{:keys [v w]} :args, [v' a s, w' b t] :ret}]
(and (= v' (str a s))
(.endsWith v v')
(= w' (str b t))
(.endsWith w w'))))
在试验发电机时,我得出了以下结论。它生成满足我要求的字符串对,但我不知道如何将它们拆分为函数的参数:
user=> (def prefix-pair-gen (gen/fmap (fn [[u v w]] [(str u v) (str u w)]) (spec/gen (spec/coll-of string? :type vector? :count 3))))
#'user/prefix-pair-gen
user=> (spec/def ::prefix-pair (spec/with-gen (spec/coll-of string? :type vector? :count 2) (fn [] prefix-pair-gen)))
:user/prefix-pair
user=> (gen/sample (spec/gen ::prefix-pair))
(["" ""]
["c" "cR"]
["lZ" "2F"]
["8a" "8a4"]
["n1D8CSq" "n1D8Gb1k"]
["X4PO" "X4Pu"]
["eAVM1" "eAVM1qg"]
["5e3DkZ6i" "5e3DkZv4Y"]
["3P7210" "3P7245cHM"]
["1c4D2j4UUK738" "1c4D2joFjd"])
我找到了解决办法,这是微不足道的。我应该多注意一下这些文件。
:args
说明:
:args函数参数的正则表达式规范,因为它们是
通过这种方式,单个规范可以处理函数
多重算术
因此,我可以直接提供生成的向量,如下所示:
(defn- drop-common-prefix [v w]
(loop [v v, a (.charAt v 0), s (.substring v 1),
w w, b (.charAt w 0), t (.substring w 1)]
(if (and (= a b)
(not-empty s)
(not-empty t))
(recur s (.charAt s 0) (.substring s 1)
t (.charAt t 0) (.substring t 1))
[v a s, w b t])))
(def prefix-pair-gen
(gen/fmap
(fn [[u v w]]
[(str u v) (str u w)])
(spec/gen
(spec/and (spec/coll-of string? :type vector? :count 3)
(fn [[u v w]]
(and (not-empty v)
(not-empty w)))))))
(spec/def ::prefix-pair
(spec/with-gen
(spec/coll-of string? :type vector? :count 2)
(constantly prefix-pair-gen)))
(spec/fdef drop-common-prefix
:args ::prefix-pair
:ret (spec/tuple string? char? string?, string? char? string?)
:fn (fn [{[v w] :args, [v' a s, w' b t] :ret}]
(and (= v' (str a s))
(.endsWith v v')
(= w' (str b t))
(.endsWith w w'))))
我可以通过以下方式验证其正确性:
user> (stest/summarize-results (stest/check `liblevenshtein.distance/drop-common-prefix))
{:sym liblevenshtein.distance/drop-common-prefix}
{:total 1, :check-passed 1}
你的问题是,给定一个对序列,如何使用序列中的每一对参数调用一个双参数函数?不是,但它是相关的。我需要为规范函数生成相关参数的元组:这可能超出clojure.spec的范围,在这种情况下,我将把生成器逻辑移到单元测试。