(defun split-list-from-end (predicate list start end count remove-empty-subseqs) (let ((length (length list))) (multiple-value-bind (result index) (let ((predicate predicate) (list (reverse list)) (start (if end (- length end) 0)) (end (- length start)) (count count) (remove-empty-subseqs remove-empty-subseqs)) (let ((count count) (done nil) (index start) (end (when end (- end start))) (list (nthcdr start list))) (flet ((should-collect-p (chunk) (unless (and remove-empty-subseqs (null chunk)) (when (numberp count) (decf count)) t)) (gather-chunk () (multiple-value-bind (chunk remaining examined ran-off-end) (collect-until predicate list end) (incf index examined) (when end (decf end examined)) (setf list remaining done ran-off-end) chunk))) (values (loop :with chunk :until (or done (eql 0 count)) :do (setf chunk (gather-chunk)) :when (should-collect-p chunk) :collect chunk) (+ index (if remove-empty-subseqs (if end ;; END is always non-NIL (loop :for value :in list :for i :below end :while (funcall predicate value) :summing 1) (loop :for value :in list ;; this LOOP is unreachable :while (funcall predicate value) :summing 1)) 0)))))) (loop :for cons on result :for car := (car cons) :do (setf (car cons) (nreverse car))) (values (nreverse result) (- length index)))))