13

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
    See node Building Lists of the Elisp manual. – Drew May 7 '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 8 '17 at 5:23
  • 1
    Working on lists ? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4) – Ehvince May 9 '17 at 9:24
  • Never use add-to-list in Lisp code (it says this in the docstring). Instead, use push. – Radon Rosborough Aug 20 '17 at 4:38
22

You can also just use append.

(append '("a" "b" "c") '("d" "e" "f"))
  • 2
    And, (nconc '("a" "b" "c") '("d" "e" "f")) – lawlist May 7 '17 at 20:08
  • 1
    Oh, yes, indeed append seems better here. – JeanPierre May 7 '17 at 20:10
  • 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. – John Kitchin May 7 '17 at 20:45
  • FYI cl-concatenate uses append when TYPE is list, so both answers are producing the same result. – phils May 8 '17 at 1:20
  • Yess, it surely does the job. Many thanks to everybody for your help. – Daniele May 8 '17 at 17:07
2

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")
  • Thanks, but it looks like it returns an error if 2nd and 3rd argument are variables and not explicit lists. – Daniele May 7 '17 at 20:43
  • 1
    (setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2) works ok. – JeanPierre May 7 '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 8 '17 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 '17 at 13:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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