Subject: Re: Inserting into a list ?
From: rpw3@rpw3.org (Rob Warnock)
Date: Fri, 18 Apr 2008 21:08:05 -0500
Newsgroups: comp.lang.lisp
Message-ID: <CqOdnTH8BamYyZTVnZ2dnUVZ_tyknZ2d@speakeasy.net>
 <nicolas.edel@gmail.com> wrote:
+---------------
| pjb@informatimago.com (Pascal J. Bourguignon) wrote:
| > Basically, because there is no list in lisp.
| > See the lisp paradoxes in:http://www.informatimago.com/usenet.html
| 
| There is no list *but* you may use 'list with the typep function ?
| Hum ... I'll have follow the white^^link and better understand your
| meaning ;)
+---------------

TYPEP is a red herring here (or at least probably a source of
considerable confustion for you). The important thing Pascal is
trying to tell you is that there is no "list" *object* type in Lisp!!
The "type" LIST is *NOT* the type of any object -- "object" as in
"object identity" -- but is a union type of two *other* types,
CONS & NULL (whose sole member is the object NIL). If someone
passes you a "list" in a function call, all you can see inside
your function is that they passed you either NIL or a CONS. Since
NIL is an immutable literal constant [w.r.t. RPLACA/RPLACD], you
cannot mutate it, thus you cannot "insert" into it. [Said another
way, NIL is not a SETF-able "place".] Thus in this case you *CANNOT*
return the same LIST-type object that was passed to you with a
new element "inserted" into it. End of story. QED.


-Rob

p.s. Note that by using a considerable amount of imperative mutation,
you *can* return the "same" LIST-type object with a new element "inserted"
into it IF the LIST-type object is a CONS, even if you're inserting
into the front of the list. What you have to do is create a *new*
CONS cell, copy the contents of the existing CONS into it, then
RPLACA the new contents into the original CONS and also RPLACD the
original CONS with the newly-alocated one:

    > (defun push/inplace (obj place)
	(cond
	  ((consp place)
	   (let ((new-cons (cons (car place) (cdr place))))
	     (setf (car place) obj)
	     (setf (cdr place) new-cons)
	     place))
	  (t (error "PLACE arg must be a CONS, wasn't: ~s" place))))

    PUSH/INPLACE
    > 

Now compare this:

    > (let* ((x (list 1 2 3))
	     (y ((lambda (z)
		   (push 4 z))
		 x)))
	(list x y (eq x y)))

    ((1 2 3) (4 1 2 3) NIL)
    > 

with this:

    > (let* ((x (list 1 2 3))
	     (y ((lambda (z)
		   (push/inplace 4 z))
		 x)))
	(list x y (eq x y)))

    ((4 1 2 3) (4 1 2 3) T)
    > 

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607