2016-03-03 106 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