Skip to content

mapcar on dotted lists #54

Description

@q3cpma

While CL has a concept of improper (dotted or circular) lists, very few standard functions support them. Today, while tinkering with my NIH universal let, I found myself in need of a mapcar equivalent to subst to call on a destructuring lambda list which can be dotted.

Here's a simple and relatively efficient version (needs a basic queue structure since loop can't collect in finally and doesn't give access to the raw tail cons cell anyway):

(defun make-queue (&rest initial-contents)
  (let ((queue (cons nil (copy-list initial-contents))))
    (setf (car queue) (last queue))
    queue))

(declaim (inline push-queue))
(defun push-queue (obj queue)
  (let ((new-tail (list obj)))
    (setf (cdar queue) new-tail
          (car queue)  new-tail)))

(defun mapcar-dotted (fun list)
  (let ((queue (make-queue)))
    (do ((cell list (cdr cell)))
        ((atom cell) (progn
                       (when cell
                         (setf (cdar queue) (funcall fun cell)))
                       (cdr queue)))
      (push-queue (funcall fun (car cell)) queue))))

Basic test:

(format t "~@{~A~%~}"
        (mapcar-dotted #'identity nil)
        (mapcar-dotted #'identity '(1))
        (mapcar-dotted #'identity '(1 2 3))
        (mapcar-dotted #'identity '(1 2 . 3)))

;; NIL
;; (1)
;; (1 2 3)
;; (1 2 . 3)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions