2014-10-25 4 views
0

У меня есть функция, которая получает вектор и суммирует все элементы.Как передать функцию как параметры

(def rec 
    (fn [numbers acc] 
    (if (empty? numbers) 
     acc 
     (recur (rest numbers) (+ acc (first numbers)))))) 
(prn (rec [1 2 3] 0)) 

Но вместо того, чтобы вызвать функцию «+» Я хочу передать операцию в качестве параметра, то это значит, я хочу передать функцию в качестве параметра, а затем вызвать функцию.

Я пробовал:

(def rec 
    (fn [f numbers acc] 
    (if (empty? numbers) 
     acc 
     (recur (rest numbers) (f acc (first numbers)))))) 
(prn (rec + [4 2 1] 0)) 

Но это не работает, я знаю, что есть более эффективные способы обобщающие чисел в векторе, но я начинаю с функциональной, так что важно, чтобы сделать этот вид упражнение.

Заранее спасибо.

ответ

1

Вы должны повторятся с теми же аргументами, что и вектор параметров, в данном случае:

(recur f (rest numbers) (f acc (first numbers)))))) 

(кстати, это стандарт для использования defn для определения функций, (defn f[x] ...) является более кратким, чем (def f (fn [x] ...)))

+0

Я только что понял это. Огромное спасибо Диего. И спасибо за советы по определению функции. Является ли идентификация правильной? – renanreismartins

+0

@renanreismartins Из перспективы отступов/выравнивания/форматирования ваш код идеален. – amalloy

0

Более ideomatic Clojure будет использовать сократить здесь, я думаю,

(defn rec [f numbers acc] 
    (reduce f acc numbers)) 

(rec + [1 2 3] 0) 
# 6 
+0

Как вы можете видеть, функция 'rec' делает то же самое, что и' reduce', но с измененным порядком атрибутов – fl00r

0

Fa ctoring

В вашем

(def rec 
    (fn [numbers acc] 
    (if (empty? numbers) 
     acc 
     (recur (rest numbers) (+ acc (first numbers)))))) 

... Вы можете нажать аккумулятор acc под поверхностью rec:

(defn rec [numbers] 
    (loop [ns numbers, acc 0] 
    (if (empty? ns) 
     acc 
     (recur (rest ns) (+ acc (first ns)))))) 

Например,

(rec + [1 3]) 
; 4 

Если вы хотите пройти операция в качестве параметра, соглашение заключается в том, что вызов его с помощью аргументов дает его идентификатор: значение, которое возвращает другой аргумент, когда оно применяется к двум.

Таким образом

(+) ; => 0 
(*) ; => 1 

Таким образом, мы можем написать свой параметризованных rec в

(defn rec [op numbers] 
    (loop [ns numbers, acc (op)] 
    (if (empty? ns) 
     acc 
     (recur (rest ns) (op acc (first ns)))))) 

Это почти как reduce работает, хотя и не столь элегантно, ИМО.

Смежные вопросы