Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to append multiple elements to a list in Emacs lisp

Tags:

list

emacs

elisp

In Emacs lisp there is add-to-list to add a single element to a list (if it doesn't exist already).

Instead of one, I want to add multiple elements. Also, I do not want to filter duplicate elements but add them to the list nonetheless.

Currently, I have implemented the following function:

(defun append-to-list (list-var elements)
  "Append ELEMENTS to the end of LIST-VAR.

The return value is the new value of LIST-VAR."
  (set list-var (append (symbol-value list-var) elements)))

The function does what I want but I was wondering if something like this (or better) already exists in Emacs lisp. I don't want to reinvent the wheel.

Update 1: Stefan points out below that this code does not work with lexical scoping. Is there a way to make it work?

Update 2: Previously I thought that duplicate filtering would be fine but it's not. I do need the duplicates.

like image 315
Viktor Rosenfeld Avatar asked Jun 22 '14 22:06

Viktor Rosenfeld


4 Answers

This would be almost equivalent1 but faster, as it does not make a copy of the original list before appending the new elements.

(defun append-to-list (list-var elements)
  "Append ELEMENTS to the end of LIST-VAR.

The return value is the new value of LIST-VAR."
  (unless (consp elements)
    (error "ELEMENTS must be a list"))
  (let ((list (symbol-value list-var)))
    (if list
        (setcdr (last list) elements)
      (set list-var elements)))
  (symbol-value list-var))

1append does not copy the final element, but uses it directly as the tail of the new list, so that part is identical. However if there are additional references to the original list object (or some part thereof), then there will be a functional difference between copying that list (via append), and just extending it (with setcdr). Which of those two outcomes you actually want is up to you, of course.

like image 188
phils Avatar answered Nov 03 '22 05:11

phils


I have the following in my init file that allows for adding multiple elements. I don't know how efficient it is to loop through the items to add but it prevents duplicate elements.

(defun jlp/add-to-list-multiple (list to-add)
  "Adds multiple items to LIST.
Allows for adding a sequence of items to the same list, rather
than having to call `add-to-list' multiple times."
  (interactive)
  (dolist (item to-add)
    (add-to-list list item)))
like image 29
Jonathan Leech-Pepin Avatar answered Nov 03 '22 04:11

Jonathan Leech-Pepin


If you don't care about ordering:

(setf var (cl-list* elt1 elt2 elt3 var))

The last argument to list* becomes the tail of the resulting list.

like image 3
gsg Avatar answered Nov 03 '22 03:11

gsg


You can also use dash.el if you want to filter duplicate elements.

(setq list1 (-union list1 list2))
like image 2
Josh Cho Avatar answered Nov 03 '22 03:11

Josh Cho