2011-09-21 83 views
3

我正在研究koan的解決方案。我難以理解爲什麼我的解決方案不起作用,但使用comp的定義確實有效。當我看的comp的定義,我看到:函數組合失敗

(defn comp 
    "Takes a set of functions and returns a fn that is the composition 
    of those fns. The returned fn takes a variable number of args, 
    applies the rightmost of fns to the args, the next 
    fn (right-to-left) to the result, etc." 
    {:added "1.0"} 
    ([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 h] 
    (fn 
     ([] (f (g (h)))) 
     ([x] (f (g (h x)))) 
     ([x y] (f (g (h x y)))) 
     ([x y z] (f (g (h x y z)))) 
     ([x y z & args] (f (g (apply h x y z args)))))) 
    ([f1 f2 f3 & fs] 
    (let [fs (reverse (list* f1 f2 f3 fs))] 
     (fn [& args] 
     (loop [ret (apply (first fs) args) fs (next fs)] 
      (if fs 
      (recur ((first fs) ret) (next fs)) 
      ret)))))) 

而我的解決方案很相似:

(defn mycomp 
    ([f] f) 
    ([f1 f2] 
     (fn 
     ([] (f1 (f2))) 
     ([a] (f1 (f2 a))) 
     ([a & more] (f1 (apply f2 a more))) 
     ) 
    ) 
    ([f1 f2 & fs] 
     (let [fxns (reverse (list f1 f2 fs))] 
      (fn [& args] 
     (loop [ret (apply (first fxns) args) fxns (next fxns)] 
      (if fxns 
      (recur ((first fxns) ret) (next fxns)) 
      ret)))))) 

兩個,從我可以告訴之間最大的區別,是第一定義包括三個或更多功能,而第二個定義組成兩個或更多個功能

請指出我的定義有什麼不正確。

回答

8

(list f1 f2 fs)看起來可能是嫌犯 - 前兩個是函數,最後一個是函數列表,所以你創建一個包含多個對象類型的列表,然後統一處理它們。您可以使用list*來解決該問題。

但是,作爲一個更廣泛的觀點:不要試圖做「兩個或兩個以上」的功能,只做零或更多!沒有特殊情況意味着更少的代碼; clojure.core只有一堆展開速度的例子。如果你的骨骼是(fn [& fs] (fn [& args] ...)),你的生活就容易多了。

+0

感謝您指出'list *'的東西,我不明白'list'和'list *'之間有區別。另外,我使用零個或多個參數重新實現了我的解決方案,這使得代碼更易於理解。再次感謝! – Davidann