-
chevron_right
MULTIPLE-VALUE-MAPCAR
Michał "phoe" Herda · Sunday, 23 December, 2018 - 12:01
(This is a repost of an old blog post of mine from Teknik.)
#common-lisp
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)