Я бы создал "приватную" вспомогательную функцию:
(defn- null-copy-vector [coll]
(vec (repeat (count coll) 0)))
и затем просто вызывал ее в каждой ветви функции:
(defn path
"Returns a lazy sequence of vectors representing a monotonic path
walked over coll in n-dimensional space, where n is the cardinality
of coll's alphabet."
([coll]
(let [alphabet (set coll)
alpha-map (zipmap alphabet (iterate inc 0)) ;; note 1
null-vector (null-copy-vector alphabet)]
(path coll null-vector alpha-map null-vector)))
([coll alpha-map]
(let [null-vector (null-copy-vector alpha-map)] ;; note 2
(path coll null-vector alpha-map null-vector)))
([coll origin alpha-map]
(path coll origin alpha-map (null-copy-vector origin)))
([coll origin alpha-map null-vector]
(let [unit-vector #(assoc null-vector (alpha-map %) 1)
sum-vectors #(vec (map + %1 %2))]
(reductions sum-vectors origin (map unit-vector coll)))))
Возможно, это не такудовлетворяющий вас, потому что null-copy-vector
не «внутри» общей функции здесь, но я думаю, что это довольно идиоматично.Для функции, которая не принимает несколько арностей, я мог бы использовать letfn , чтобы отделить «внутреннюю» функцию, но это не сработает здесь.
Разделение подобных вещей также позволяет вама) повторно использовать базовые функции строительных блоков в другом месте и б) позволяет тестировать небольшими блоками.Возможно, вы захотите пропустить defn- и просто использовать defn, чтобы упростить тестирование (хотя можно тестировать defn с немного большим количеством работы ).
Я также создал новую форму с четырьмя аргументами, которая принимает нулевой вектор в качестве последнего аргумента, позволяя вам передать его напрямую, если вы знаете его, чтобы избежать повторного создания его из уже нулевого вектора.Если вы хотите скрыть эту 4-аргументную форму, вы можете перетащить ее в отдельную функцию-помощник.
Не связанные заметки:
- Я изменил вашу первую ветку на более простую (imho) impl с использованием zipmap и бесконечной последовательности.
- Вместо (count (keys keys)) достаточно просто выполнить (map count) (счетчик находится внутри вашей вспомогательной функции).