Сбой композиции функции - PullRequest
       0

Сбой композиции функции

3 голосов
/ 22 сентября 2011

Я работаю над решением этого коана . Я озадачен тем, почему мое решение не работает, но использование определения 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 Ответ

8 голосов
/ 22 сентября 2011

(list f1 f2 fs) выглядит вероятным подозрением - первые две являются функциями, а последняя является списком функций, поэтому вы создаете список, содержащий несколько типов объектов, а затем обрабатываете их равномерно.Вы можете исправить это, используя list*.

Но в более широком смысле: святой господи, не пытайтесь выполнять «две или более» функции, просто делайте ноль или больше!Никаких особых случаев означает гораздо меньше кода;У clojure.core есть только несколько развернутых кейсов для скорости.Если ваш скелет (fn [& fs] (fn [& args] ...)), ваша жизнь намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...