Применять Y-Combinator к рекурсивной функции с двумя аргументами в Clojure? - PullRequest
5 голосов
/ 14 августа 2010

Выполнение Y-Combinator для функции с одним аргументом, такой как факториал или Фибоначчи, в Clojure хорошо документировано: http://rosettacode.org/wiki/Y_combinator#Clojure

Мой вопрос - как вы делаете это для функции с двумя аргументами, такой как, например, этот геттер?

(Предполагается, что я хочу решить эту проблему рекурсивно, и этот неидиоматический код clojure намеренно существует по другой причине)

[версия без y-комбинатора]

(defn get_ [n lat]
    (cond
      (empty? lat) ()
        (= 0 (- n 1)) (first lat)
        true (get_ (- n 1) (rest lat))))

(get_ 3 '(a b c d e f g h i j))

Ответы [ 2 ]

4 голосов
/ 15 августа 2010

Количество аргументов ничего не меняет, поскольку args равно apply 'd. Вам просто нужно изменить структуру get_:

(defn get_ [f]
  (fn [n lat]
    (cond
      (empty? lat) ()
      (= 1 n) (first lat)
      :else (f (dec n) (next lat)))))

(defn Y [f]
  ((fn [x] (x x))
   (fn [x]
     (f (fn [& args]
          (apply (x x) args))))))
user=> ((Y getf) 3 '(a b c d e f g h i j))
c
2 голосов
/ 14 августа 2010

Это было бы довольно просто.

Скажем, у вас есть функция H:

(def H
  (fn [x] 
        (fn [x y]
              (stuff happens))))

Затем вы применяете тот же самый Y-Combinator:

((Y H) 4 5)

Где 4 и 5 - аргументы, которые вы хотите передать H.

Комбинатор по сути "имеет дело с" функцией верхнего уровня в H, а не с той, которая выполняет тяжелую работу (здесь с arity 2, здесь).

...