patternMinor
Generic sequence splitter in Common Lisp
Viewed 0 times
genericlispsequencecommonsplitter
Problem
I wrote a function
Any comments, improvements, critiques welcome.
split-seq-by-n which accepts a sequence and a number and splits the sequence into subsequences of length n (the last subsequence getting the remaining elements). It works on all subclasses of 'sequence, among others 'string, 'cons, 'vector etc.;; Splits sequence into subsequences of length n
(defun split-seq-by-n (seq n)
(labels ((seq-split (seq n &optional acc orig-n)
(cond ((zerop (length seq)) (nreverse acc))
((zerop n) (seq-split seq
orig-n
(cons (subseq seq 0 0) acc)
orig-n))
(t (seq-split (subseq seq 1)
(1- n)
(cons (concatenate (class-of seq)
(if acc (car acc) (subseq seq 0 0))
(list (elt seq 0)))
(cdr acc))
orig-n)))))
(seq-split seq n nil n)))Any comments, improvements, critiques welcome.
Solution
It looks okay for a recursion exercise, but it's naive code. Not usable in 'production'.
- it conses like mad. It creates a lot of intermediate garbage. Splitting a string involves making lots of smaller strings.
- for lists it is not efficient, too
- CONCATENATE in loops or recursive functions is a code smell
- the recursive implementation with the subroutine is good style in a functional language, but makes it hard to debug in the real world. For example, how do you TRACE the internal function?
- Common Lisp does not guarantee tail call optimization (TCO). Individual implementations do support it. Still, for general portable code it might be preferable to code loop.
Context
StackExchange Code Review Q#40954, answer score: 4
Revisions (0)
No revisions yet.