2016-03-03 107 views
1

我一直在用另一种语言重新实现一些Clojure函数,使用测试引用,我有点困惑于the testsclojure.core/comp测试Clojure的comp函数

(deftest test-comp 
    (let [c0 (comp)] 
    (are [x] (= (identity x) (c0 x)) 
     nil 
     42 
     [1 2 3] 
     #{} 
     :foo) 
    (are [x y] (= (identity x) (c0 y)) 
     (+ 1 2 3) 6 
     (keyword "foo") :foo))) 

comp本身只使用一次,没有参数。该行为似乎没有记录,但the source显示它只是返回identity函数。

(defn comp 
    ([] identity) 
    ([f] f) 
    ([f g] 
    (fn 
     ([] (f (g))) 
     ([x] (f (g x))) 
     ([x y] (f (g x y))) 
     ([x y z] (f (g x y z))) 
     ([x y z & args] (f (apply g x y z args))))) 
    ([f g & fs] 
    (reduce1 comp (list* f g fs)))) 

这是否意味着3/4这些宝石没有经过测试?还是有测试保存在其他地方?我通过GitHub搜索发现了这些测试,它们并不总是完全可靠。

为什么zero arity表单有测试,看起来是最不实用的变体?

回答

4
  1. 是的。它只在这里进行测试。实际上,在v1.3.0中添加零参数版本之前,没有对comp进行测试。请检查此commit及其parent
  2. 零参数comp是有用的,它有助于消除角落情况下的微不足道的分支代码。假设您想对给定的输入进行一系列转换。但是这些转换是动态生成的,并且可以降级到不应该进行转换的地步。

编辑: 要在我的观点2提供了一个例子:

(defn my-format 
    "Returns an HTML representation of the given text in a paragraph, 
    supports `:b' for bold and `:i' for italic font, and possibly more 
    in the future." 
    [text & more-args] 
    (let [wrap (fn [w t] (str "<" w ">" t "</" w ">"))] 
    (wrap "p" ((apply comp 
         (map #(partial wrap (name %)) more-args)) 
       text))) 
; => (my-format "hello world" :b :i) 
; "<p><b><i>hello world</i></b></p> 
; => (my-format "hello world") 
; "<p>hello world</p> 

的代码片段是微不足道的,但你的想法。如果comp不支持0-arity版本,代码看起来不会那么优雅。

+0

不太理解第二点。任何机会,你可以添加一个简单的例子? –

+0

@DanPrince更新了答案,HTH – Davyzhu