HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Generic sequence splitter in Common Lisp

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
genericlispsequencecommonsplitter

Problem

I wrote a function 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.