22

Sorry, but elisp is not my best. I need to combine two lists of strings in this way:

("a" "b" "c") + ("d" "e" "f") -> ("a" "b" "c" "d" "e" "f")

Well, the order is not important, so I wrote this code:

(while lista
  (add-to-list 'listb (car lista)) 
  (setq lista (cdr lista)))

It works, but I'm wondering if there's a function that already does this.

Any clue? Thanks in advance.

Drew
  • 75,699
  • 9
  • 109
  • 225
Daniele
  • 637
  • 1
  • 5
  • 14
  • 5
    See node [Building Lists](http://www.gnu.org/software/emacs/manual/html_node/elisp/Building-Lists.html) of the Elisp manual. – Drew May 07 '17 at 22:18
  • 2
    `append` is the correct answer here, but another (destructive) way to do it would be `(setcdr (last a) b)`. – Sean Allred May 08 '17 at 05:23
  • 1
    Working on lists ? [dash.el](https://github.com/magnars/dash.el#-concat-rest-lists) ! `(-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)` – Ehvince May 09 '17 at 09:24
  • Never use `add-to-list` in Lisp code (it says this in the docstring). Instead, use `push`. – Resigned June 2023 Aug 20 '17 at 04:38

2 Answers2

34

You can also just use append.

(append '("a" "b" "c") '("d" "e" "f"))
John Kitchin
  • 11,555
  • 1
  • 19
  • 41
5

concatenate is an alias for ‘cl-concatenate’ in ‘cl.el’.

(concatenate TYPE SEQUENCE...)

Concatenate, into a sequence of type TYPE, the argument SEQUENCEs.

So for your example

(concatenate 'list '("a" "b" "c") '("d" "e" "f"))

Since it's defined in cl you may have to (require 'cl) first, otherwise you can use cl-concatenate which seems to be loaded by default.

Also, as pointed out by @phils cl-concatenate just calls append when TYPE is 'list, here's the source from cl-extra.el:

(defun cl-concatenate (type &rest sequences)
  "Concatenate, into a sequence of type TYPE, the argument SEQUENCEs.
\n(fn TYPE SEQUENCE...)"
  (pcase type
    (`vector (apply #'vconcat sequences))
    (`string (apply #'concat sequences))
    (`list (apply #'append (append sequences '(nil))))
    (_ (error "Not a sequence type name: %S" type))))

So if you're only using lists, it's simpler to directly use append, as pointed out by @John Kitchin.

Finally, @lawlist mentionned nconc:

nconc is a built-in function in ‘C source code’.

(nconc &rest LISTS)

Concatenate any number of lists by altering them. Only the last argument is not altered, and need not be a list.

What this means:

(nconc '("a" "b" "c") '("d" "e" "f"))
=> ("a" "b" "c" "d" "e" "f")

(setq l1 '("a" "b" "c")
      l2 '("d" "e" "f"))
(nconc l1 l2)
=> ("a" "b" "c" "d" "e" "f")
l1
=> ("a" "b" "c" "d" "e" "f")
l2
=> ("d" "e" "f")
JeanPierre
  • 7,323
  • 1
  • 18
  • 37
  • Thanks, but it looks like it returns an error if 2nd and 3rd argument are variables and not explicit lists. – Daniele May 07 '17 at 20:43
  • 1
    `(setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2)` works ok. – JeanPierre May 07 '17 at 21:09
  • @Daniele I suspect you were trying to *quote* the variables, which means they are not evaluated to their list values. (i.e. you want `varname` rather than `'varname`). – phils May 08 '17 at 01:11
  • For completeness, I might as well mention the non-CL way of concatenating any type of sequence in Emacs>=25: `seq-concatenate` (after `(require 'seq)`), though this in turn just wraps `cl-concatenate`. – Basil May 08 '17 at 13:53