Вы просите рекурсивной функции, и даже если в большинстве случаев установить и список функций предпочтительнее выше создавая собственную рекурсивную функцию, это не всегда возможно. Эта проблема также очень легко записывается рекурсивно по идиоматическому функциональному способу с использованием аккумулятора
Идея заключается в том, что вы начинаете с пустого аккумулятора и строите свой результат шаг за шагом. Аккумулятор (acc в этом фрагменте кода) проведет ответ в конце.
(defn add-pairs [v1]
(loop [the-list v1 acc []]
(if (next the-list) ;; checks wether there's more than 1 left in the-list
(recur (rest the-list)
(conj acc (+ (first the-list) (second the-list))))
acc)))
Что здесь происходит? Вы передаете вектор [1 2 3 4]
в v1
. Затем цикл начинается и в нем две переменные инициализируются:
the-list <- [1 2 3 4]
acc []
достаточно просто сумма двух первых элементов (+ (first the-list) (second the-list)
добавляются к аккумулятору. Затем с recur
цикл вызывается снова, передавая остальную часть списка (rest the-list)
и аккумулятор, теперь содержащий 3 (являющийся суммой двух первых элементов). Новые vaues являются:
the-list <- [2 3 4]
acc [3]
следующие шаги:
the-list <- [3 4]
acc [3 5]
the-list <- [4]
acc [3 5 7]
Тогда, если условие больше не выполняется и условие еще возвращается (обычно является аккумулятор, теперь держа раствор).
Общая идея
Вы начинаете с пустого аккумулятора и ваш входной набор. Каждый шаг, накопитель накапливается. В большинстве случаев набор входных данных становится все меньше. Затем выполняется некоторое if-условие, и аккумулятор возвращается.
Также очень классика в этой конкретной проблеме состоит в том, что входной набор теряет свой первый элемент на каждом шаге. (отдых) Здесь очень практично (cdr в большинстве других lisps).
общий вид
Петля форма/повторятся в Clojure очень хорошо, но во многих других языках, этот синтаксис отсутствует. Очень классическое решение состоит в том, чтобы иметь две функции: одну рекурсивную, которая выполняет цикл, и одно с тем же именем, но другую arity, которая выполняет инициализацию аккумулятора. Simpler в коде, чем это объяснить, так вот она в какой-то составил Java-подобный синтаксис:
function add-pairs(v1 acc) {
if (cond)
//do stuff to v1 and acc
add-pairs(v1 acc)
else
return acc }
function add-pairs(v1) {
return add-pairs(v1,[])
}
var result = add-pairs([42 666 1447])
В моем опыте, вы могли бы сделать лучше, чтобы написать свой собственный (неизменно рекурсивной, если мы включаем 'повторялись 's) версий стандартных функций библиотеки, чем писать ab-initio-решения для задач, которые стандартные функции решают в одной строке. Вам предлагаются два таких решения. – Thumbnail