18

Possible Duplicate:
what is the ‘cons’ to add an item to the end of the list?

After watching many tutorials on lisp and searching high and low on google for answers, I still cannot figure out how to add to the end of a list in LISP.

I want my function to add 'a at the end of the list '(b c d) but I only know how to add it in front. Can someone help me use cons correctly to add 'a at the end of the list? Here is my code. Thanks in advance.

(defun AddRt (a list)
  (cond
    ((null list)
      0)
    (t
      (princ (cons a (cons (car list) (cdr list))))
    )))


(AddRt 'a '(b c d))
Community
  • 1
  • 1
Bert
  • 814
  • 1
  • 7
  • 9

3 Answers3

20

Either push to last, or use nconc:

> (defparameter a (list 1 2 3))
A
> (push 4 (cdr (last a)))
(4)
> a
(1 2 3 4)
> (nconc a (list 5))
(1 2 3 4 5)
> a
(1 2 3 4 5)

note that these are destructive operators, i.e., they modify the object which is the value of a, not just the binding of a.

This is why, BTW, you should never use nconc on quoted lists, like (nconc '(1 2 3) '(4 5 6)).

PS. Note that adding to the end of a list requires its full traversal and is thus an O(length(list)) operation. This may be a bad idea if your lists are long, so people often use the push/nreverse idiom, e.g.,

(let (range)
  (dotimes (i 10 (nreverse range))
    (push i range)))
==> (0 1 2 3 4 5 6 7 8 9)
sds
  • 58,617
  • 29
  • 161
  • 278
7

You may use a recursive function. Also, you should avoid using princ inside.

The following function, endcons, does exactly the same thing as cons, except the value is added at the end.

(defun endcons (a v)
   (if (null v) (cons a nil) (cons (car v) (endcons a (cdr v)))))

(endcons 'a '(b c d))

Of course, you could also use append:

(append '(b c d) '(a))

See also this related question: what is the 'cons' to add an item to the end of the list?

Community
  • 1
  • 1
  • If I don't use princ, how should I go about outputting (endcons 'a '(b c d)) to the screen? Thank you for your help. – Bert Nov 13 '12 at 20:24
  • You may use princ afterwards, for example `(princ (endcons 'a '(b c d)))`. It's always a bad idea to define a function that does some work and the output at the same time: what will happen if you want to use it many times and don't want to be annoyed by thousands of lines of garbage ? Always separate « real work » and IO. –  Nov 14 '12 at 12:41
4

One way is to reverse the list. Add the element to beginning of the reversed list. And then finally reverse the whole list.

Scheme code:

(define (add-to-tail l x)
   (reverse (cons x (reverse l)))

But if this is an operation you need often, then I'd suggest you find a data structure other than (single linked) lists.

soegaard
  • 30,661
  • 4
  • 57
  • 106
  • 1
    I believe this is not a good approach: you are doing 2 reverse iterations, which might take long time on a great list number. – Francisco Maria Calisto Oct 28 '15 at 17:35
  • 1
    This is a good point. For a long list, it might be better to mutate the final pair. The OP didn't specify the language. In a language with immutable (single linked) lists, the reverse-twice method is the only choice. For languages with mutable lists the reverse-twice method might be a good idea for short lists (there is no way around benchmarking this). If the list to be reversed is used as part of several data structures it might not be possible to mutate it. Finally for a long mutable list, which is used only once, it is better to use `reverse!`. – soegaard Oct 28 '15 at 17:43
  • Great comment! Can you please give me some examples of immutable and mutable languages? – Francisco Maria Calisto Oct 28 '15 at 17:50
  • Racket has both types of single-linked lists, but the default is immutable. – soegaard Oct 28 '15 at 17:51