Clojure/Spec:是否有内置方式将无参函数转为生成器?
Clojure/Spec 无参函数转生成器问题
场景描述
已有一个生成特定类型X实例的无参函数:
(defn generate-sample-of-x [] ... )
希望在Clojure/Spec中将其用作生成器,但未找到内置实现,于是自行编写了辅助函数:
(defn- generator-from-fn "Create a spec generator from a no-arg function" [f] (gen/fmap (fn [_] (f)) (gen/return 0)))
该函数可将任意无参函数转为生成器,示例用法:
(generator-from-fn generate-sample-of-x)
用户疑问
- 是否存在未发现的内置实现?
- 若没有,是否有更简洁的方式定义该辅助函数?
解答
1. 内置实现情况
Clojure Spec配套的clojure.test.check.generators库中没有专门的内置函数直接将无参函数转为生成器,但可以通过现有API组合实现。
2. 更简洁的实现方式
有几种更简洁的写法,推荐优先使用语义最匹配的方案:
- 方案一:使用
gen/invoke(推荐)gen/invoke的设计目的就是在生成器中调用函数,对于无参函数,直接传入函数本身即可。每次生成器生成值时,都会调用该函数获取新的实例,完全符合需求:
(defn- generator-from-fn [f] (gen/invoke f))
- 方案二:简化原有的
fmap写法
如果偏好原有的fmap思路,可以通过替换部分代码让结构更简洁:;; 用constantly替代匿名函数 (defn- generator-from-fn [f] (gen/fmap (constantly (f)) (gen/return 0))) ;; 用gen/void替代gen/return 0(gen/void是生成nil的轻量生成器) (defn- generator-from-fn [f] (gen/fmap (fn [_] (f)) gen/void))
内容的提问来源于stack exchange,提问作者Mick
相关产品推荐
相关产品推荐

