Я новичок в Clojure и хочу определить функцию pt
, принимающую в качестве аргументов число n
и последовательность s
и возвращающую все разделы s
в n
частях, то есть ее факторизации в отношении n
-конкатенации. например, (pt 3 [0 1 2])
должно выдать:
(([] [] [0 1 2]) ([] [0] [1 2]) ([] [0 1] [2]) ([] [0 1 2] []) ([0] [] [1 2]) ([0] [1] [2]) ([0] [1 2] []) ([0 1] [] [2]) ([0 1] [2] []) ([0 1 2] [] []))
с неважным порядком.
В частности, я хочу, чтобы результат был ленивой последовательностью ленивых последовательностей векторов.
Моя первая попытка использования такой функции была следующей:
(defn pt [n s]
(lazy-seq
(if (zero? n)
(when (empty? s) [nil])
((fn split [a b]
(concat
(map (partial cons a) (pt (dec n) b))
(when-let [[bf & br] (seq b)] (split (conj a bf) br))))
[] s))))
После этого я написал несколько менее лаконичную версию, которая уменьшает временную сложность, избегая бесполезных сравнений для разделов из 1 части, приведенных ниже:
(defn pt [n s]
(lazy-seq
(if (zero? n)
(when (empty? s) [nil])
((fn pt>0 [n s]
(lazy-seq
(if (= 1 n)
[(cons (vec s) nil)]
((fn split [a b]
(concat
(map (partial cons a) (pt>0 (dec n) b))
(when-let [[bf & br] (seq b)] (split (conj a bf) br))))
[] s))))
n s))))
Проблема с этими решениями состоит в том, что, хотя они работают, они производят ленивую последовательность (не ленивых) минусов, и я подозреваю, что для достижения «внутренней лени» должен быть применен совершенно другой подход. Так что любые исправления, предложения, объяснения приветствуются!
EDIT : Прочитав ответ l0st3d, я подумал, что должен пояснить, что я хочу, чтобы раздел не был просто LazySeq, а был «действительно ленивым», в том смысле, что часть вычисляется и хранится в памяти только при запросе.
Например, обе функции, приведенные ниже, генерируют LazySeq, но только первая из них создает «действительно ленивую» последовательность.
(defn f [n]
(if (neg? n)
(lazy-seq nil)
(lazy-seq (cons n (f (dec n))))))
(defn f [n]
(if (neg? n)
(lazy-seq nil)
(#(lazy-seq (cons n %)) (f (dec n)))))
Таким образом, отображение (partial concat [a])
или #(lazy-seq (cons a %))
вместо (partial cons a)
не решает проблему.