2

Is there built in function or macro to append list to a mutable list. Something like PUSH, but slightly different.

Here is the PUSH using exapmle:

(setq v '(3))
(push '(1 2) v) ;v now ((1 2) 3)

And I need fallowing behavior:

(setq v '(3))
(mappend '(1 2) v) ;v should be (1 2 3)
Shmygol
  • 913
  • 7
  • 16
  • 2
    the title talks about 'mutable variables', the question about 'mutable list'? What is it? What's wrong with just using APPEND? – Rainer Joswig Feb 12 '12 at 10:12
  • 3
    '(3) and '(1 2) should not be considered mutable. See http://stackoverflow.com/a/3896580/78720 for more information. – sigjuice Feb 12 '12 at 10:48

1 Answers1

0

I think you are looking for nconc?

[Function] nconc &rest lists

nconc takes lists as arguments. It returns a list that is the arguments concatenated together. The arguments are changed rather than copied. (Compare this with append, which copies arguments rather than destroying them.) For example:

(setq x '(a b c)) (setq y '(d e f)) (nconc x y) => (a b c d e f) x => (a b c d e f)

You could use nconc to define a pushlist macro, to have an interface analogous to push:

(defmacro pushlist (lst place)
  `(setf ,place (nconc ,lst ,place)))

And test it:

CL-USER> 
(defparameter *v* (list 3))
*V*
(pushlist (list 1 2) *v*)
CL-USER> 
(1 2 3)
CL-USER>
*v*
(1 2 3)
CL-USER> 

Also note that I'm using (list 3), instead of '(3), after reading sigjuice's comment.

Clayton Stanley
  • 7,513
  • 9
  • 32
  • 46
  • Note that your `pushlist` macro as defined can evaluate expressions in `place` twice; using e.g. `define-modify-macro` avoids this problem. – Hugh Feb 13 '12 at 00:53
  • True. I think this is only a performance hit though, assuming that one would expect place to eval to the same thing on repeated calls. Also if place is not a cons (which for me is pretty-much all use cases), then there is no need for the define-modify-macro. So I went with simplicity over efficiency for the post. Although I will read up on define-modify-macro after your comment; there's more for me to learn there. – Clayton Stanley Feb 13 '12 at 01:22
  • On Lisp has an example of why that's not a good assumption to make. – Hugh Feb 13 '12 at 02:10
  • I'm pretty sure this isn't a "once-only" scenario – Clayton Stanley Feb 13 '12 at 03:45
  • 1
    `(let ((counter 0) (list-of-lists (list (list 'a 'b) (list 'c 'd) (list 'e 'f)))) (pushlist (list 'g 'h) (nth (incf counter) list-of-lists)) list-of-lists)` – Hugh Feb 13 '12 at 04:27
  • Actually, on reviewing the question, I think he wants to append stuff to the original list, so something like `(setf (cdr (last original-list)) new-suffix)` might be more what he wants. – Hugh Feb 13 '12 at 04:34
  • Nice example. The incf counter in a place might actually be used in practical code, I've just never used that pattern. My places are pretty much never conses. – Clayton Stanley Feb 13 '12 at 04:38
  • nconc is exactly what I need. Thanks a lot and sorry for not clear question. ) – Shmygol Feb 13 '12 at 18:26