(This is a repost of an old blog post of mine from Teknik.)
I had a function that returned multiple values.
I wanted to iterate over it while collecting all of the values, so I avoid losing any data.
And I found out that, welp,
MAPCAR only works on primary return values.
And so, with some help from
#lisp on Freenode and
Bike doing an actual majority of the coding work,
MULTIPLE-VALUE-MAPCAR was born.
(defun multiple-value-mapcar (function &rest lists) (assert (not (null lists))) (let* ((values (loop for l = lists then (mapcar #'cdr l) until (some #'endp l) collecting (multiple-value-list (apply function (mapcar #'car l))))) (max-values (loop for vl in values maximizing (length vl))) (lists (make-list max-values))) (loop for vl in values do (loop for i from 0 below max-values do (push (nth i vl) (nth i lists)))) (values-list (mapcar #'nreverse lists)))) (multiple-value-mapcar #'values '(1 2 3 4) '(a b c d e f) '(:q :w :e :r :t)) ;;=> (1 2 3 4) ;;=> (A B C D) ;;=> (:Q :W :E :R) (let ((hash (make-hash-table))) (setf (gethash 'fuck hash) t (gethash 'shit hash) nil) (multiple-value-mapcar (rcurry #'gethash hash) '(fuck shit stack))) ;;=> (T NIL NIL) ;;=> (T T NIL)