Прежде всего, мы не говорим о методах: мы говорим о функциях. В clojure есть нечто, что вы могли бы вызвать метод, но это отличается от функции. Если вы прекратите использовать OO lingo, вы также потеряете стиль мышления OO.
То, что вы пытаетесь сделать, возможно. В основном вы хотите создать новую функцию с именем dupx
в функции dupseqx
. Сейчас вы создаете функцию, а затем выбрасываете ее (вы ничего не делаете с возвращаемым значением, и возвращается только последняя форма в функции). Поскольку функция похожа на любое другое значение, вы можете использовать тот же механизм, что и для любого другого значения: создать локальную «переменную». Какой механизм для этого? Это локальная привязка, и она работает следующим образом (имя в fn просто так, что вы можете вызывать его от себя; оно не должно совпадать с именем let
):
(let [dupx (fn dupx [v x]
(if (= x 1)
(list v)
(cons v (dupx v (dec x)))))]
(dupx 5 3))
Обратите внимание, что я исправил некоторые другие вещи.
Более короткая форма этого (исправление двойного имени уродства):
(letfn [(dupx [v x] (if (= x 1)
(list v)
(cons v (dupx v (dec x)))))]
(dupx 5 3))
Хорошо, во всем, что между "(let [...]" и соответствием ")", теперь у нас есть dupx
функция.
Итак, теперь остальная часть вашего кода работает:
(fn dupSeqX [aseq x]
(letfn [(dupx [v x] (if (= x 1) (list v) (cons v (dupx v (dec x)))))]
(reverse (reduce #(concat %1 (dupx %2 x)) '() aseq))))
Этот код можно сделать немного более идиоматическим:
- Правила кодирования: имя параметра
coll
вместо aseq
- Рекомендации по кодированию: DoNotUseCamalCase сделай как это
- Рекурсия, когда вам не нужно, это плохо для производительности и больших чисел.
- Вы заново изобретаете колесо. Это хорошо для изучения кодирования, но не очень хорошо, если вы хотите узнать язык и стандартную библиотеку.
Как я это написал?
Первый основной фн. coll
является стандартом для функции именования, которая ожидает последовательности.
(fn [coll times] )
Если вы читаете этот «каждый элемент последовательности», ваш мозг должен пройти MAP.
(fn [coll times]
(map (fn ....) coll))
"реплицирует каждый ..." - это, по сути, описание того, что вы должны вставить в функцию карты. Мы можем использовать repeat
(ваша функция дублирования, но с некоторыми дополнительными вкусностями, вроде этого, она ленива).
(fn [coll times]
(map (fn [val] (repeat times val)) coll))
Осталась одна проблема (из коана). Он хочет один seq назад, а не последовательность в последовательности для каждого элемента. Это означает, что мы должны согласовать результат вместе.
(fn [coll times]
(apply concat (map (fn [val] (repeat times val)) coll)))
Вы часто будете видеть шаблон (apply concat (map ....))
. Для этой цели есть стандартная функция в стандартной библиотеке mapcat
, и я сделаю внутреннюю функцию коротким синтаксисом.
(fn [coll times]
(mapcat #(repeat times %) coll))
Надеюсь, это поможет!