Я решил 45 задач с 4clojure.com и заметил повторяющуюся проблему в том, как я пытаюсь решить некоторые задачи с помощью рекурсии и аккумуляторов.
Я попытаюсь объяснить как можно лучше, что я делаю, чтобы в итоге получить нелепые решения, надеясь, что некоторые Clojurers «получат» то, чего не получаю я.
Например, в задаче 34 предлагается написать функцию (без использования диапазона), которая принимает два целых числа в качестве аргументов и создает диапазон (без использования диапазона). Проще говоря, вы делаете (... 1 7) и получаете (1 2 3 4 5 6).
Теперь этот вопрос не о решении этой конкретной проблемы.
Что, если я захочу решить эту проблему с помощью рекурсии и аккумулятора?
Мой мыслительный процесс выглядит следующим образом:
Мне нужно написать функцию с двумя аргументами, я начинаю с (fn [x y] )
Мне нужно будет рекурсировать, и мне нужно будет отслеживать список, я буду использовать аккумулятор, поэтому я пишу вторую функцию внутри первой, принимающую дополнительный аргумент:
(fn [x y]
((fn g [x y acc] ...) x y '())
(очевидно, я не могу правильно отформатировать этот код Clojure на SO!?)
Тут я уже не уверен, что делаю правильно: первая функция должна принимать ровно два целочисленных аргумента (не мой вызов) и я не уверен: если я хочу использовать аккумулятор, могу ли я использовать аккумулятор без создания вложенной функции?
Затем я хочу conj, но не могу:
(conj 0 1)
поэтому я делаю странные вещи, чтобы сначала убедиться, что у меня есть последовательность, и в итоге я получаю это:
(fn
[x y]
((fn g [x y acc] (if (= x y) y (conj (conj acc (g (inc x) y acc)) x)))
x
y
'()))
Но тогда это производит это:
(1 (2 (3 4)))
Вместо этого:
(1 2 3 4)
В итоге я делаю дополнительное сглаживание, и это работает, но совершенно некрасиво.
Я начинаю понимать некоторые вещи и даже начинаю, в некоторых случаях, "думать" в более кложурском стиле, но у меня проблема с написанием решения.
Например, здесь я решил:
- использовать аккумулятор
- для рекурсии, увеличивая x, пока не достигнет y
Но я заканчиваю с чудовищем выше.
Есть множество способов решить эту проблему, и, опять же, это не то, что мне нужно.
Что мне нужно, так это то, как после того, как я решил использовать cons/conj, использовать аккумулятор и рекурсию, я могу получить это (не написано мной):
#(loop [i %1
acc nil]
(if (<= %2 i)
(reverse acc)
(recur (inc i) (cons i acc))))
Вместо этого:
((fn
f
[x y]
(flatten
((fn
g
[x y acc]
(if (= x y) acc (conj (conj acc (g (inc x) y acc)) x)))
x
y
'())))
1
4)
Я понимаю, что это только начало, чтобы решить несколько проблем, но я немного разочарован уродливыми решениями, которые я склонен создавать...