功能组成失败

时间:2011-09-21 22:10:19

标签: clojure

我正在研究这个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))))))

根据我的判断,两者之间的最大区别在于第一个定义构成三个或更多个函数,而第二个定义构成两个或更多个函数

请指出我的定义不正确。

1 个答案:

答案 0 :(得分:8)

(list f1 f2 fs)看起来很可能 - 前两个是函数,最后一个是函数列表,所以你要创建一个包含多个对象类型的列表,然后统一处理它们。您可以使用list*来修复此问题。

但是作为一个更广泛的观点:圣洁的jeez,不要试图做“两个或更多”的功能,只做零或更多!没有特殊情况意味着更少的代码; clojure.core只有一堆展开的速度案例。如果你的骨架是(fn [& fs] (fn [& args] ...)),那么你的生活会更容易。