From: tenshi
Subject: LISP newbee question
Date: 
Message-ID: <k6klm0h90srcg5ocjbp6ba9h7p3nnd4o9r@4ax.com>
I'm trying to learn LISP from various tutorials online. So far I'm
finding the syntax a bit confusing and the below keeps bugging me.
To my understanding APPEND should combine two lists into one. Can
someone please take a look at the below example and explain wy the dot
occur and how I can avoid this. I'm using Allegro CL Trial Version.

> (setf a '(a b c d e f) )
> (setf b '(1 2 3 4 5 6) )
> (append (rest a) (first b) )
(b c d e f . 1)
>

From: Zach Beane
Subject: Re: LISP newbee question
Date: 
Message-ID: <m3hdp1xel0.fsf@unnamed.xach.com>
tenshi <··@mm.org> writes:

> I'm trying to learn LISP from various tutorials online. So far I'm
> finding the syntax a bit confusing and the below keeps bugging me.
> To my understanding APPEND should combine two lists into one. 

That's right.

> Can
> someone please take a look at the below example and explain wy the dot
> occur and how I can avoid this. I'm using Allegro CL Trial Version.
>
>> (setf a '(a b c d e f) )
>> (setf b '(1 2 3 4 5 6) )
>> (append (rest a) (first b) )
> (b c d e f . 1)
>>

The result of (first b) is not a list, it's the number 1.

You could make a list out of it by doing:

   (list (first b))

So, try something like:

   (append (rest a) (list (first b)))

Zach
From: martin
Subject: Re: LISP newbee question
Date: 
Message-ID: <pan.2004.10.11.18.55.30.714293@spam.chello.at>
On Mon, 11 Oct 2004 18:46:32 +0000, tenshi wrote:

> I'm trying to learn LISP from various tutorials online. So far I'm
> finding the syntax a bit confusing and the below keeps bugging me.
> To my understanding APPEND should combine two lists into one. Can
> someone please take a look at the below example and explain wy the dot
> occur and how I can avoid this. I'm using Allegro CL Trial Version.
> 
>> (setf a '(a b c d e f) )
>> (setf b '(1 2 3 4 5 6) )
>> (append (rest a) (first b) )
> (b c d e f . 1)

The last argument to APPEND should be a list to acchieve the desired
result. what happens here is that the cdr of the last element of a copy 
of the list of (rest a) is set to 1 which means that it looks like this 
in terms of CONSES 
(cons 'b (cons 'c (cons 'd (cons 'e (cons 'f 1)))))

see http://www.lisp.org/HyperSpec/Body/fun_append.html

regards 

martin
From: Pascal Bourguignon
Subject: Re: LISP newbee question
Date: 
Message-ID: <873c0lt6pi.fsf@thalassa.informatimago.com>
martin <············@spam.chello.at> writes:

> On Mon, 11 Oct 2004 18:46:32 +0000, tenshi wrote:
> 
> > I'm trying to learn LISP from various tutorials online. So far I'm
> > finding the syntax a bit confusing and the below keeps bugging me.
> > To my understanding APPEND should combine two lists into one. Can
> > someone please take a look at the below example and explain wy the dot
> > occur and how I can avoid this. I'm using Allegro CL Trial Version.
> > 
> >> (setf a '(a b c d e f) )
> >> (setf b '(1 2 3 4 5 6) )
> >> (append (rest a) (first b) )
> > (b c d e f . 1)
> 
> The last argument to APPEND should be a list to acchieve the desired
> result.

ALL arguments to APPEND should be lists!

> what happens here is that the cdr of the last element of a copy 
> of the list of (rest a) is set to 1 which means that it looks like this 
> in terms of CONSES 
> (cons 'b (cons 'c (cons 'd (cons 'e (cons 'f 1)))))
instead of what you wanted:
  (cons 'b (cons 'c (cons 'd (cons 'e (cons 'f (cons 1 nil))))))
 
> see http://www.lisp.org/HyperSpec/Body/fun_append.html

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Voting Democrat or Republican is like choosing a cabin in the Titanic.
From: Barry Wilkes
Subject: Re: LISP newbee question
Date: 
Message-ID: <lledrrsb.fsf@acm.org>
Pascal Bourguignon <····@mouse-potato.com> writes:
>
> ALL arguments to APPEND should be lists!
>
No, the last argument to append can be any object.

Barry.
From: Pascal Bourguignon
Subject: Re: LISP newbee question
Date: 
Message-ID: <87y8idrq3p.fsf@thalassa.informatimago.com>
Barry Wilkes <·······@acm.org> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
> >
> > ALL arguments to APPEND should be lists!
> >
> No, the last argument to append can be any object.

This is abuse.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Voting Democrat or Republican is like choosing a cabin in the Titanic.
From: Steven M. Haflich
Subject: Re: LISP newbee question
Date: 
Message-ID: <kOCad.11724$nj.7274@newssvr13.news.prodigy.com>
Pascal Bourguignon wrote:

> Barry Wilkes <·······@acm.org> writes:
> 
>>Pascal Bourguignon <····@mouse-potato.com> writes:
>>
>>>ALL arguments to APPEND should be lists!
>>>
>>
>>No, the last argument to append can be any object.
> 
> 
> This is abuse.

It is not abuse.  Barry quotes directly for the CL ANS.
Non-lists as the last argument to APPEND is well defined
and reliable behavior.

This raises the obvious question, of course, why we have
a function like IDENTITY in the language when APPEND would
serve just as well.  No wonder CL is so damn big...
From: Kenny Tilton
Subject: Re: LISP newbee question
Date: 
Message-ID: <0zDad.19213$4C.4067098@twister.nyc.rr.com>
Steven M. Haflich wrote:
> Pascal Bourguignon wrote:
> 
>> Barry Wilkes <·······@acm.org> writes:
>>
>>> Pascal Bourguignon <····@mouse-potato.com> writes:
>>>
>>>> ALL arguments to APPEND should be lists!
>>>>
>>>
>>> No, the last argument to append can be any object.
>>
>>
>>
>> This is abuse.
> 
> 
> It is not abuse.  Barry quotes directly for the CL ANS.

legal-schmegal. all code entered in obfuscation contests is legal.

using:

    (append <list> <atom>)

...to achieve:

    (rplacd (last <list>) <atom>)

... obfuscates because one generally thinks of append as 
non-destructively concatenating lists. Witness the CLHS syntax for 
append is:

    append &rest lists => result

Going against the grain invites even strong Lispnik readers to miss what 
is going on.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Steven M. Haflich
Subject: Re: LISP newbee question
Date: 
Message-ID: <rcEad.11779$nj.9692@newssvr13.news.prodigy.com>
Kenny Tilton wrote:

> legal-schmegal. all code entered in obfuscation contests is legal.
> 
> using:
> 
>    (append <list> <atom>)
> 
> ...to achieve:
> 
>    (rplacd (last <list>) <atom>)

Um, your rplacd code looks like the equivalent of (NCONC <list> <atom>)
which is similar to append in that the ANS explicitly allows the last
argument to be any object.

I consider this ability of nconc and append to be useful capabilities.
They are provided precisely because the obvious implementations can
provide this functionality at zero cost.  It would _add_ cost to check
for and prohibit the capability.

The rplacd code is _almost_ equivalent and arguably clearer in intent
for the destructive case, but is only appicable for the 2-arg case, and
is incompletely general -- it fails mobily if the first arg is nil.
It it is clearer more general to use nconc.

The append equivalent is slightly more verbose to code than the rplacd
above.  All the more reason to use append.

For the situation where the atomicity of the last argumnet is not evident
from the code, that's why God created comments.  And I wonder if you feel
the same about a non-list last argument to list*.
From: Paul F. Dietz
Subject: Re: LISP newbee question
Date: 
Message-ID: <AtmdnXqT5caliPbcRVn-ug@dls.net>
Steven M. Haflich wrote:

> Um, your rplacd code looks like the equivalent of (NCONC <list> <atom>)
> which is similar to append in that the ANS explicitly allows the last
> argument to be any object.

However, it's not clear this is always allowed, since the return value
is described to be a list.  So, this form

   (nconc nil nil 'a)

would violate the type constraint on the return value, and (as I read
the standard) its evaluation would have undefined consequences.

	Paul
From: Steven M. Haflich
Subject: Re: LISP newbee question
Date: 
Message-ID: <A2Iad.11915$nj.2705@newssvr13.news.prodigy.com>
Paul F. Dietz wrote:

> Steven M. Haflich wrote:
> 
>> Um, your rplacd code looks like the equivalent of (NCONC <list> <atom>)
>> which is similar to append in that the ANS explicitly allows the last
>> argument to be any object.
> 
> However, it's not clear this is always allowed, since the return value
> is described to be a list.  So, this form
> 
>   (nconc nil nil 'a)
> 
> would violate the type constraint on the return value, and (as I read
> the standard) its evaluation would have undefined consequences.

I think you overread the standard.  The specification that the return type
is a list appears bogus, since the intention is explicit and clear.  If
one liked, one could defer to 1.5.1.4.1 "Resolution of Apparent Conflicts
in Exceptional Situations" and the Description that follows right after
the specification of the return type:

    Returns a list that is the concatenation of lists. If no lists are
    supplied, (nconc) returns nil. nconc is defined using the following
    recursive relationship:

     (nconc)  ()
     (nconc nil . lists) ==(nconc . lists)
     (nconc list)  list
     (nconc list-1 list-2) ==(progn (rplacd (last list-1) list-2) list-1)
     (nconc list-1 list-2 . lists) ==(nconc (nconc list-1 list-2) . lists)

This is a formal part of the ANS, and is arguably "more specific" than
the casual statement of the return type.  In any case, I have no doubt
that this was what was intended.  Do youi know of any implementation
that doesn't work this way?

It is curious that the text of append is explicit about the case
of a non-nil atom for the last argument, but not nconc.
From: Justin Dubs
Subject: Re: LISP newbee question
Date: 
Message-ID: <2e262238.0410120631.7e2e2e0c@posting.google.com>
"Paul F. Dietz" <·····@dls.net> wrote in message news:<······················@dls.net>...
> Steven M. Haflich wrote:
> 
> > Um, your rplacd code looks like the equivalent of (NCONC <list> <atom>)
> > which is similar to append in that the ANS explicitly allows the last
> > argument to be any object.
> 
> However, it's not clear this is always allowed, since the return value
> is described to be a list.  So, this form
> 
>    (nconc nil nil 'a)
> 
> would violate the type constraint on the return value, and (as I read
> the standard) its evaluation would have undefined consequences.

The problem is that your definition of "list" is not the standard's
definition of "list."  A chain of cons cells ending in nil is a
"proper list."  A chain of cons cells ending in nil or any terminating
atom is a "list."  Append returns a list.

The return value of append is described as:
"result -- an object. This will be a list unless the last list was not
a list and all preceding lists were null." [1]

A "list" is defined as:
"a chain of conses [...] and the cdr of each cons is either the next
link in the chain or a terminating atom" [2]

A "proper list" is defined as:
"A list terminated by the empty list" [3]

While I don't like usage of append with a non-list for the final
argument, it certainly does seem to be well-defined.

Justin Dubs

[1] http://www.lisp.org/HyperSpec/Body/fun_append.html
[2] http://www.lisp.org/HyperSpec/Body/glo_l.html#list
[3] http://www.lisp.org/HyperSpec/Body/glo_p.html#proper_list
From: Paul F. Dietz
Subject: Re: LISP newbee question
Date: 
Message-ID: <ssCdnUFwAs2wD_HcRVn-tw@dls.net>
Justin Dubs wrote:
> "Paul F. Dietz" <·····@dls.net> wrote in message news:<······················@dls.net>...
> 
>>Steven M. Haflich wrote:
>>
>>
>>>Um, your rplacd code looks like the equivalent of (NCONC <list> <atom>)
>>>which is similar to append in that the ANS explicitly allows the last
>>>argument to be any object.
>>
>>However, it's not clear this is always allowed, since the return value
>>is described to be a list.  So, this form
>>
>>   (nconc nil nil 'a)
>>
>>would violate the type constraint on the return value, and (as I read
>>the standard) its evaluation would have undefined consequences.
> 
> 
> The problem is that your definition of "list" is not the standard's
> definition of "list."  A chain of cons cells ending in nil is a
> "proper list."  A chain of cons cells ending in nil or any terminating
> atom is a "list."  Append returns a list.

Um, we're talking about NCONC, not APPEND.

And see 14.1.2:

    A non-nil atom by itself is not considered to be a list of any kind
    ---not even a dotted list.


	Paul
From: Justin Dubs
Subject: Re: LISP newbee question
Date: 
Message-ID: <2e262238.0410130412.3283d3e4@posting.google.com>
"Paul F. Dietz" <·····@dls.net> wrote in message news:<······················@dls.net>...
> Justin Dubs wrote:
> > "Paul F. Dietz" <·····@dls.net> wrote in message news:<······················@dls.net>...
> > 
> >>Steven M. Haflich wrote:
> >>
> >>
> >>>Um, your rplacd code looks like the equivalent of (NCONC <list> <atom>)
> >>>which is similar to append in that the ANS explicitly allows the last
> >>>argument to be any object.
> >>
> >>However, it's not clear this is always allowed, since the return value
> >>is described to be a list.  So, this form
> >>
> >>   (nconc nil nil 'a)
> >>
> >>would violate the type constraint on the return value, and (as I read
> >>the standard) its evaluation would have undefined consequences.
> > 
> > 
> > The problem is that your definition of "list" is not the standard's
> > definition of "list."  A chain of cons cells ending in nil is a
> > "proper list."  A chain of cons cells ending in nil or any terminating
> > atom is a "list."  Append returns a list.
> 
> Um, we're talking about NCONC, not APPEND.

Ahh... yes.  I /knew/ that seemed too easy... :-)

Justin Dubs
From: Frank Buss
Subject: Re: LISP newbee question
Date: 
Message-ID: <ckf39u$84g$1@newsreader2.netcologne.de>
Kenny Tilton <·······@nyc.rr.com> wrote:

> using:
> 
>     (append <list> <atom>)
> 
> ...to achieve:
> 
>     (rplacd (last <list>) <atom>)
> 
> ... obfuscates because one generally thinks of append as 
> non-destructively concatenating lists.

you can't replace append with rplacd, because the doc says "append 
returns a new list that is the concatenation of the copies" and at least 
with LispWorks it works like expected:

CL-USER 1 > (setf x '(1 2 3))
(1 2 3)

CL-USER 2 > (append x 4)
(1 2 3 . 4)

CL-USER 3 > x
(1 2 3)

CL-USER 4 > (rplacd (last x) 4)
(3 . 4)

CL-USER 5 > x
(1 2 3 . 4)

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: William Bland
Subject: Re: LISP newbee question
Date: 
Message-ID: <pan.2004.10.11.23.40.01.888018@abstractnonsense.com>
On Mon, 11 Oct 2004 22:12:12 +0000, Kenny Tilton wrote:
> 
> using:
> 
>     (append <list> <atom>)
> 
> ...to achieve:
> 
>     (rplacd (last <list>) <atom>)
> 
> ... obfuscates because one generally thinks of append as 
> non-destructively concatenating lists. Witness the CLHS syntax for 
> append is:
> 
>     append &rest lists => result
> 
> Going against the grain invites even strong Lispnik readers to miss what 
> is going on.
> 
> kenny

I wouldn't describe myself as a "strong Lispnik" - still a bit of a CL
newbie - but I find this pretty obvious when one is used to
box-and-pointer diagrams.

Just my two cents.

Cheers,
	Bill.
-- 
"If you give someone Fortran, he has Fortran. If you give someone Lisp,
he has any language he pleases." -- Guy Steele
From: Thomas A. Russ
Subject: Re: LISP newbee question
Date: 
Message-ID: <ymillebajv0.fsf@sevak.isi.edu>
tenshi <··@mm.org> writes:

> 
> I'm trying to learn LISP from various tutorials online. So far I'm
> finding the syntax a bit confusing and the below keeps bugging me.
> To my understanding APPEND should combine two lists into one. Can
> someone please take a look at the below example and explain wy the dot
> occur and how I can avoid this. I'm using Allegro CL Trial Version.
> 
> > (setf a '(a b c d e f) )
> > (setf b '(1 2 3 4 5 6) )
> > (append (rest a) (first b) )
> (b c d e f . 1)

Others have explained what is happening.  I'll point out one of the nice
things about the interactive nature of Lisp that you can use to try to
figure out some of what is happening on your own.

When you run into trouble with a particular nested expression, it can
often help to try the individual parts of it separately.  That can help
you get a better idea of what is going on:

  (rest a)   =>   (B C D E F)
  (first b)  =>   1

At this point it should be clear that while the first argument is a
list, the second is a single atom, namely the number "1".  To get the
result you desire, there are a couple of methods:

  (list (first b))  =>  (1)
  (butlast a 5)     =>  (1)

The first of these is generally preferred.


-- 
Thomas A. Russ,  USC/Information Sciences Institute