I am looking for ways to improve this little utility function:
(defun break-down (taste sequence)
"Break down a list SEQUENCE into consecutive lists of constant TASTE.
The TASTE argument is a function which is applied on sequence elements to
taste them. Taste values are
The answer is an alist whose terms have the form
(TASTE1 . SEQUENCE1)
such that:
1. The concatenation of the SEQUENCE1s yields SEQUENCE.
2. Each element of the list SEQUENCE1 has the given TASTE1.
3. Consecutive terms of the answer have distinct TASTE1.
"
…)
Examples:
CL-USER> (break-down #'stringp '(1 2 3 "a" "b" 5 "c" "d"))
((NIL 1 2 3) (T "a" "b") (NIL 5) (T "c" "d"))
CL-USER> (break-down
(lambda (n)
(cond ((< 0 n) :positive)
((> 0 n) :negative)
(t :zero)))
'(-1 3 34 -5 -6 0 1 2 0 34 -3 -6))
((:NEGATIVE -1) (:POSITIVE 3 34) (:NEGATIVE -5 -6) (:ZERO 0) (:POSITIVE 1 2)
(:ZERO 0) (:POSITIVE 34) (:NEGATIVE -3 -6))
(defun break-down (taste sequence)
"Break down a list SEQUENCE into consecutive lists of constant TASTE.
The TASTE argument is a function which is applied on sequence elements to
taste them. Taste values are
The answer is an alist whose terms have the form
(TASTE1 . SEQUENCE1)
such that:
1. The concatenation of the SEQUENCE1s yields SEQUENCE.
2. Each element of the list SEQUENCE1 has the given TASTE1.
3. Consecutive terms of the answer have distinct TASTE1.
"
(flet ((catamorphism (state next)
(destructuring-bind (current-taste current-subsequence accumulator) state
(let ((next-taste
(funcall taste next)))
(cond
((eq nil current-subsequence)
(list next-taste (list next) accumulator))
((eq next-taste current-taste)
(list current-taste (cons next current-subsequence) accumulator))
(t
(list next-taste
(list next)
(cons (cons current-taste (nreverse current-subsequence)) accumulator))))))))
(destructuring-bind (current-taste current-subsequence accumulator)
(reduce #'catamorphism sequence :initial-value (list nil nil nil))
(nreverse (cons (cons current-taste (nreverse current-subsequence)) accumulator)))))
I am especially interested in:
- Is there a good alternative to
destructuring-bind
in thecatamorphism
? - Is is more idiosyncratic to use
loop
instead ofreduce
? - Better identifiers and documentation :-)
- Is it possible to process arbitrary sequences?