Idiomatic way in Emacs Lisp to visit each cons cell in a list?

Viewed 118

i would like to visit all the cons cells in a list and perform some action on them (including such things as setcar). is there an idiomatic way of doing this?

i can, i think, do something like this

(progn
  (setq a (list 1 2 3 4 5 6))
  (setq okay a)
  (while okay
    (if (eq (car okay) 3)
        (setcar okay 22))
    (setq okay (cdr okay))))

(where the if expression is my "application logic", say.)

but, if there's a terser way of doing this, i'd be interested in hearing about it.

2 Answers

If you want to mutate the cars of the list, then in recent emacsen the likely think you want is cl-mapl, which maps a function over successive tails of the list. This is essentially Common Lisp's mapl function: CL has

  • maplist which maps a function over tails and returns a new list of the values of the function, so (maplist (lambda (e) e) '(1 2 3)) is ((1 2 3) (2 3) (3));
  • mapl which is like maplist but returns the original list.

elisp (courtesy of some now-standard library) now has both cl-mapl and cl-maplist.

So:

> (let ((y (list 1 2 3 4 5 6 7)))
    (cl-mapl (lambda (tail)
               (rplaca tail 0))
             y)
    y)
(0 0 0 0 0 0 0)

or

> (let ((y (list 1 2 3 4 5 6 7)))
    (cl-mapl (lambda (tail)
               (rplaca tail (if (cdr tail) (cadr tail) 'fish)))
             y)
    y)
(2 3 4 5 6 7 fish)

(In neither of these cases do you need to make sure that y is returned: I just did it to make it clear that y is being destructively modified by this.)

(setq a (mapcar (lambda (x) (if (equal x 3) 22 x)) a))

That sets the value of variable a to the result of changing any members of a that are 3 to 22.

Choose the equality operator you want, equal, eql, or =, depending on whether you know that either all list members are numbers (use =) or you know that they are either numbers or you want to test object equality otherwise, (use eql), or you don't know what they might be (use equal).

You haven't indicated any need to do list-structure modification (setcar). It appears that all you care about is for a to be a list as I described.

Related