From: Thomas Guettler
Subject: Adding Element to list
Date: 
Message-ID: <alsc0l$qcf$05$1@news.t-online.com>
Hi!

I am learning lisp.

How can I add an element to a list?

(setq li (list 1 2 3))
(setq li (append li (list 4)))

is too complicated.

Isn't there something like:

(setq li (list 1 2 3))
(magic-function li 4)
--> li == 1 2 3 4

  thomas

From: Raymond Wiker
Subject: Re: Adding Element to list
Date: 
Message-ID: <86wupq2omb.fsf@raw.grenland.fast.no>
Thomas Guettler <···········@thomas-guettler.de> writes:

> Hi!
> 
> I am learning lisp.
> 
> How can I add an element to a list?
> 
> (setq li (list 1 2 3))
> (setq li (append li (list 4)))
> 
> is too complicated.
> 
> Isn't there something like:
> 
> (setq li (list 1 2 3))
> (magic-function li 4)
> --> li == 1 2 3 4

(defun magic-function (list element)
  (append list (list element)))

        In Common Lisp this kind of thing is not only allowed, it is
expected.

        Note that this definition of magic-function is probably too
limited to be of any practical use.

        See "On Lisp" for a discussion of this particular example, as
well as a number of other small "software utilities".

-- 
Raymond Wiker                        Mail:  ·············@fast.no
Senior Software Engineer             Web:   http://www.fast.no/
Fast Search & Transfer ASA           Phone: +47 23 01 11 60
P.O. Box 1677 Vika                   Fax:   +47 35 54 87 99
NO-0120 Oslo, NORWAY                 Mob:   +47 48 01 11 60

Try FAST Search: http://alltheweb.com/
From: Thomas Stegen
Subject: Re: Adding Element to list
Date: 
Message-ID: <3D81C756.9030401@cis.strath.ac.uk>
Thomas Guettler wrote:
> Hi!
> 
> I am learning lisp.
> 
> How can I add an element to a list?
> 
> (setq li (list 1 2 3))
> (setq li (append li (list 4)))
> 
> is too complicated.
> 
> Isn't there something like:
> 
> (setq li (list 1 2 3))
> (magic-function li 4)
> --> li == 1 2 3 4

Try nconc

(nconc list '(element))



-- 
Thomas Stegen
From: Thomas Guettler
Subject: Re: Adding Element to list
Date: 
Message-ID: <alsfme$3r1$06$1@news.t-online.com>
Thomas Stegen schrieb:
> Thomas Guettler wrote:
> 
>> Hi!
>>
>> I am learning lisp.
>>
>> How can I add an element to a list?
>>
>> (setq li (list 1 2 3))
>> (setq li (append li (list 4)))
>>
>> is too complicated.
>>
>> Isn't there something like:
>>
>> (setq li (list 1 2 3))
>> (magic-function li 4)
>> --> li == 1 2 3 4
> 
> 
> Try nconc
> 
> (nconc list '(element))

Thank you!

BTW, I just found (push 4 li). It appends at the
beginning.

  thomas
From: Nils Goesche
Subject: Re: Adding Element to list
Date: 
Message-ID: <lkofb25cuo.fsf@pc022.bln.elmeg.de>
Thomas Guettler <···········@thomas-guettler.de> writes:

> Thomas Stegen schrieb:
> > Thomas Guettler wrote:
> >
> >> How can I add an element to a list?
> >>
> >> (setq li (list 1 2 3))
> >> (setq li (append li (list 4)))
> >>
> >> is too complicated.
> >>
> >> Isn't there something like:
> >>
> >> (setq li (list 1 2 3))
> >> (magic-function li 4)
> >> --> li == 1 2 3 4
> > Try nconc
> > (nconc list '(element))
> 
> BTW, I just found (push 4 li). It appends at the beginning.

Ain't that right.  (push 4 li) is equivalent to
(setq li (cons 4 li)).  If you want to put another element at the
front, you can do it with

(setq li (cons 5 (cons 4 li)))

or shorter with

(setq li (list* 5 4 li))

You should also try to understand the difference between APPEND and
NCONC and never use NCONC until you do.

(setq list (append list (list 4)))

and

(setq list (nconc list (list 4)))

may seem to do the same thing, but they don't:

CL-USER 3 > (defparameter *some-list* (list 1 2 3))
*SOME-LIST*

CL-USER 4 > (append *some-list* (list 4))
(1 2 3 4)

CL-USER 5 > *some-list*
(1 2 3)

CL-USER 6 > (nconc *some-list* (list 4))
(1 2 3 4)

CL-USER 7 > *some-list*
(1 2 3 4)

See?  NCONC modifies all its arguments but the last, and APPEND
doesn't.  This makes NCONC a bit dangerous if you are not aware of
this.  Also, while usually after doing (nconc list1 list2) list1 will
contain the concatenated list, there is one exception:

CL-USER 12 > (setq *some-list* nil)
NIL

CL-USER 13 > (nconc *some-list* (list 1 2 3))
(1 2 3)

CL-USER 14 > *some-list*
NIL

See?  This didn't work at all.  So, even when using NCONC, you should
/always/ do

(setq *some-list* (nconc *some-list* (list 1 2 3)))

that is, assign the return value of NCONC to the variable you want to
contain the concatenated list.  (But not when you use  PUSH or POP)

Regards,
-- 
Nils Goesche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Timothy Moore
Subject: Re: Adding Element to list
Date: 
Message-ID: <alug8o$3m8$0@216.39.145.192>
Thomas Guettler <···········@thomas-guettler.de> writes:

> Thomas Stegen schrieb:
> > Thomas Guettler wrote:
> >
> >> Hi!
> >>
> >> I am learning lisp.
> >>
> >> How can I add an element to a list?
> >>
> >> (setq li (list 1 2 3))
> >> (setq li (append li (list 4)))
> >>
> >> is too complicated.
> >>
> >> Isn't there something like:
> >>
> >> (setq li (list 1 2 3))
> >> (magic-function li 4)
> >> --> li == 1 2 3 4
> > Try nconc
> > (nconc list '(element))
> 
> Thank you!

Hold on.  This is fine as far as it goes, but if you then do the same
thing to the same list, you'll likely run into trouble.  That quoted
list is constant.  If you're going to fool around with nconc (and I
don't see what you find so distasteful about the use of append) better
try (nconc list (list 'element)).

If you want to learn how to write the magic-function (sic) you desire,
check out define-modify-macro in the HyperSpec.

Tim
From: Kaz Kylheku
Subject: Re: Adding Element to list
Date: 
Message-ID: <cf333042.0209141553.78b747a@posting.google.com>
Thomas Guettler <···········@thomas-guettler.de> wrote in message news:<···············@news.t-online.com>...
> Hi!
> 
> I am learning lisp.
> 
> How can I add an element to a list?
> 
> (setq li (list 1 2 3))
> (setq li (append li (list 4)))
> 
> is too complicated.

You are right; it is too complicated. The right approach, begins with
assimilating this rule of thumb: whenever possible, work at the front
of the list. It is often easier to manipulate a list at the front;
then if you need to reverse it, use the NREVERSE function.

So for instance if you need to collect some items in a list, use the
PUSH macro:

(defvar *list* (list 1 2 3))
(push 0 *list*)
*list* ==> (0 1 2 3)

If the order of the items doesn't matter, then it's acceptable to push
them to the front. This avoids copying the entire list; the  (push E
L) operation is roughly equivalent to (setf L (cons E L)). The second
operand of PUSH must be a place which is bound to a list value. A new
element is consed to the front of the list, and the value is replaced
with the new cons cell.

If you have to collect items in the order in which they appear, you
can still use PUSH, and then use NREVERSE to destructively reverse
your list. (Destructively meaning that the list is not copied, but
rather its cells are rearranged so that the last one is first, etc.).

> Isn't there something like:
> 
> (setq li (list 1 2 3))
> (magic-function li 4)
> --> li == 1 2 3 4

You can do this, but the problem is that it either requires the entire
list to be copied, or else it requires destructive manipulation of the
last cons cell. It also requires a linear search to find the tail of
the list.

If you want to build a list at the tail, and not do any copying, and
avoid the overhead of doing a NREVERSE, what you can do is keep a tail
pointer, and use it to destructively add one element at a time to the
list. This kind of coding pattern is best wrapped in a macro.

The standard LOOP macro contains an idiom for collecting elements into
a list; see whether that fits your problem before rolling your own.
From: Nils Goesche
Subject: Re: Adding Element to list
Date: 
Message-ID: <8765x85707.fsf@darkstar.cartan>
···@ashi.footprints.net (Kaz Kylheku) writes:

> If you want to build a list at the tail, and not do any
> copying, and avoid the overhead of doing a NREVERSE, what you
> can do is keep a tail pointer, and use it to destructively add
> one element at a time to the list. This kind of coding pattern
> is best wrapped in a macro.

Whether keeping a pointer to the tail is really faster than using
NREVERSE is surprisingly not a trivial question.  See chapter 3
of Richard C. Waters paper

 http://www.merl.com/papers/docs/TR93-17.pdf

Regards,
-- 
Nils Goesche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0
From: Tim Bradshaw
Subject: Re: Adding Element to list
Date: 
Message-ID: <ey3hegr5ylb.fsf@cley.com>
* Kaz Kylheku wrote:
> You can do this, but the problem is that it either requires the entire
> list to be copied, or else it requires destructive manipulation of the
> last cons cell. It also requires a linear search to find the tail of
> the list.

Well, heh, you can do this with a COLLECTING macro:

(defun make-collecting-list (&rest elements)
  (declare (dynamic-extent elements))
  (let (c)
    (values (collecting
              (setf c #'(lambda (e) (collect e)))
              (loop for x in elements do (collect x)))
            c)))

Then (make-collecting-list 1 2 3) returns two values: a list with
elements 1 2 3, and a function which takes one argument and will
collect that argument into the end of this list, and do it efficiently
since it has squirrelled away a tail pointer for the list.

--tim
From: Tim Bradshaw
Subject: Re: Adding Element to list
Date: 
Message-ID: <ey37khn5wxo.fsf@cley.com>
* I wrote:

> Then (make-collecting-list 1 2 3) returns two values: a list with
> elements 1 2 3, and a function which takes one argument and will
> collect that argument into the end of this list, and do it efficiently
> since it has squirrelled away a tail pointer for the list.

Of course, I should have said: this does modify the object
destructively, needless to say, it just avoids the linear search.
There are obviously other, less opaque ways of doing this as well.

--tim
From: Aleksandr Skobelev
Subject: Re: Adding Element to list
Date: 
Message-ID: <m3fzwbnsbu.fsf@list.ru>
Tim Bradshaw <···@cley.com> writes:

> Well, heh, you can do this with a COLLECTING macro:
> 
> (defun make-collecting-list (&rest elements)
>   (declare (dynamic-extent elements))
>   (let (c)
>     (values (collecting
>               (setf c #'(lambda (e) (collect e)))
>               (loop for x in elements do (collect x)))
>             c)))

Excuse me, but what is COLLECTING macro? It looks like there is no such
thing in HyperSpec.
From: Will Deakin
Subject: Re: Adding Element to list
Date: 
Message-ID: <am2hpl$2pd$1@helle.btinternet.com>
Aleksandr Skobelev wrote:
> Excuse me, but what is COLLECTING macro? It looks like there is no such
> thing in HyperSpec.
Try www.tfeb.org/lisp/hax.html#COLLECTING

:)w