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.

4
  • 5
    See node Building Lists of the Elisp manual.
    – Drew
    May 7, 2017 at 22:18
  • 2
    append is the correct answer here, but another (destructive) way to do it would be (setcdr (last a) b). May 8, 2017 at 5:23
  • 1
    Working on lists ? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
    – Ehvince
    May 9, 2017 at 9:24
  • Never use add-to-list in Lisp code (it says this in the docstring). Instead, use push. Aug 20, 2017 at 4:38

2 Answers 2

34

You can also just use append.

(append '("a" "b" "c") '("d" "e" "f"))
5
  • 2
    And, (nconc '("a" "b" "c") '("d" "e" "f"))
    – lawlist
    May 7, 2017 at 20:08
  • 1
    Oh, yes, indeed append seems better here.
    – JeanPierre
    May 7, 2017 at 20:10
  • 1
    nconc works but, if you store lists in variables, they will be modified by nconc. E.g. (let ((a '(1 2 3)) (b '(3 4 5))) (nconc a b) a) will modify the a variable. May 7, 2017 at 20:45
  • 1
    FYI cl-concatenate uses append when TYPE is list, so both answers are producing the same result.
    – phils
    May 8, 2017 at 1:20
  • Yess, it surely does the job. Many thanks to everybody for your help.
    – Daniele
    May 8, 2017 at 17:07
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")
4
  • Thanks, but it looks like it returns an error if 2nd and 3rd argument are variables and not explicit lists.
    – Daniele
    May 7, 2017 at 20:43
  • 1
    (setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2) works ok.
    – JeanPierre
    May 7, 2017 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 8, 2017 at 1: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 8, 2017 at 13:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.