I am new to Clojure and I want to define a function pt
taking as arguments a number n
and a sequence s
and returning all the partitions of
The cons
call in your split
inline fn is the only place where eagerness is being introduced. You could replace that with something that lazily constructs a list, like concat
:
(defn pt [n s]
(lazy-seq
(if (zero? n)
(when (empty? s) [nil])
((fn split [a b]
(concat
(map (partial concat [a]) (pt (dec n) b))
(when-let [[bf & br] (seq b)] (split (conj a bf) br))))
[] s))))
(every? #(= clojure.lang.LazySeq (class %)) (pt 3 [0 1 2 3])) ;; => true
But, reading the code I feel like it's fairly unClojurey, and I think that's to do with the use of recursion. Often you'd use things like reductions
, partition-by
, split-at
and so to do this sort of thing. I feel like there should also be a way to make this a transducer and separate out the lazyness from the processing (so you can use sequence
to say you want it lazily), but I haven't got time to work that out right now. I'll try and come back with a more complete answer soon.