From: vanekl
Subject: NIL is not of type CONS
Date: 
Message-ID: <f74ad422-03f0-4b67-a3d7-7df97c422e1d@x69g2000hsx.googlegroups.com>
Is this supposed to throw an error when setq is called?
In SBCL 1.0.12.34 it does, in Clisp 2.41 it doesn't.
Function runs w/o error when the "declare" is commented out.
[Test function is deliberately stripped down to bare minimum to
reproduce error.]

(defun test (tt)
  (declare  (type cons tt))
  (setq tt nil))

(test '(a 1))


And this is the error message that SBCL/Swank/Slime is showing:

The value NIL is not of type CONS.
   [Condition of type TYPE-ERROR]

From: Geoffrey Summerhayes
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <144effe6-c784-42ce-8e89-7c667fdfc0b6@a35g2000prf.googlegroups.com>
On Dec 17, 3:03 pm, vanekl <·····@acd.net> wrote:
> Is this supposed to throw an error when setq is called?
> In SBCL 1.0.12.34 it does, in Clisp 2.41 it doesn't.
> Function runs w/o error when the "declare" is commented out.
> [Test function is deliberately stripped down to bare minimum to
> reproduce error.]
>
> (defun test (tt)
>   (declare  (type cons tt))
>   (setq tt nil))
>
> (test '(a 1))
>
> And this is the error message that SBCL/Swank/Slime is showing:
>
> The value NIL is not of type CONS.
>    [Condition of type TYPE-ERROR]

From the HS 3.3 Declarations:

The consequences are undefined if a program violates a declaration or
a proclamation.

---
Geoff
From: Rainer Joswig
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <joswig-6B568B.21221417122007@news-europe.giganews.com>
In article 
<····································@x69g2000hsx.googlegroups.com>,
 vanekl <·····@acd.net> wrote:

> Is this supposed to throw an error when setq is called?
> In SBCL 1.0.12.34 it does, in Clisp 2.41 it doesn't.
> Function runs w/o error when the "declare" is commented out.
> [Test function is deliberately stripped down to bare minimum to
> reproduce error.]
> 
> (defun test (tt)
>   (declare  (type cons tt))
>   (setq tt nil))
> 
> (test '(a 1))

? (typep nil 'cons)
NIL

NIL is not a cons. But you declared TT to have type CONS.

CLISP does not check these declarations. Few Common Lisp implementations
do. Most of the time these kind of type declarations are either ignored
or only used of optimization purposes. Basically you tell
the Lisp compiler that your code will always call TEST with
an object of type CONS.

CMUCL (and its fork SBCL) have extended this and the compiler
does some kind of type checking based on the declarations
in the code and what the compiler can infer. So, SBCL
warns you that the code violates the declaration.

> 
> 
> And this is the error message that SBCL/Swank/Slime is showing:
> 
> The value NIL is not of type CONS.
>    [Condition of type TYPE-ERROR]

-- 
http://lispm.dyndns.org/
From: vanekl
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <a22587dd-7bc9-4c54-bb64-c656752d5c53@q3g2000hsg.googlegroups.com>
On Dec 17, 8:22 pm, Rainer Joswig <······@lisp.de> wrote:
> In article
> <····································@x69g2000hsx.googlegroups.com>,
>
>  vanekl <·····@acd.net> wrote:
> > Is this supposed to throw an error when setq is called?
> > In SBCL 1.0.12.34 it does, in Clisp 2.41 it doesn't.
> > Function runs w/o error when the "declare" is commented out.
> > [Test function is deliberately stripped down to bare minimum to
> > reproduce error.]
>
> > (defun test (tt)
> >   (declare  (type cons tt))
> >   (setq tt nil))
>
> > (test '(a 1))
>
> ? (typep nil 'cons)
> NIL
>
> NIL is not a cons. But you declared TT to have type CONS.
>
> CLISP does not check these declarations. Few Common Lisp implementations
> do. Most of the time these kind of type declarations are either ignored
> or only used of optimization purposes. Basically you tell
> the Lisp compiler that your code will always call TEST with
> an object of type CONS.
>
> CMUCL (and its fork SBCL) have extended this and the compiler
> does some kind of type checking based on the declarations
> in the code and what the compiler can infer. So, SBCL
> warns you that the code violates the declaration.

This was not a warning, but an error was thrown at run-time, not
compile-time.

>
>
> > And this is the error message that SBCL/Swank/Slime is showing:
>
> > The value NIL is not of type CONS.
> >    [Condition of type TYPE-ERROR]
>
> --http://lispm.dyndns.org/

Thanks, everybody, for responding so quickly.

I understand the technical arguments made, but I was running some
legacy code I found on the web so I assumed the code was stable and
would run. Guess it wasn't designed to run on SBCL or CMUCL.

Personally, if I was king of the world, I would have allowed NIL to be
a subtype of CONS, but maybe write a warning message out instead of
throwing an error. Carrying this out to its logical conclusion, I
think I would allow NIL to be a subtype of all other types. Of course
this is just my opinion. Something to think about.
From: Geoffrey Summerhayes
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5a300568-59c1-4a78-b2d1-531887312ec7@s19g2000prg.googlegroups.com>
On Dec 17, 3:37 pm, vanekl <·····@acd.net> wrote:
>
> I understand the technical arguments made, but I was running some
> legacy code I found on the web so I assumed the code was stable and
> would run. Guess it wasn't designed to run on SBCL or CMUCL.
>
> Personally, if I was king of the world, I would have allowed NIL to be
> a subtype of CONS, but maybe write a warning message out instead of
> throwing an error. Carrying this out to its logical conclusion, I
> think I would allow NIL to be a subtype of all other types. Of course
> this is just my opinion. Something to think about.
>

That carries a price. Declaring a type can allow the
compiler to cut out a lot of type-checking code and
just produce code that works on that type. Adding NIL
to everything means forcing an additional check as well.

As for the particular case of CONS, the type LIST is
either a cons cell or nil, and shouldn't cause an error
in this case.

---
Geoff
From: vanekl
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <8a51fdf7-dd82-41d0-ad13-2c393c8454e6@i72g2000hsd.googlegroups.com>
On Dec 17, 8:58 pm, Geoffrey Summerhayes <·······@gmail.com> wrote:
> On Dec 17, 3:37 pm, vanekl <·····@acd.net> wrote:
>
>
>
> > I understand the technical arguments made, but I was running some
> > legacy code I found on the web so I assumed the code was stable and
> > would run. Guess it wasn't designed to run on SBCL or CMUCL.
>
> > Personally, if I was king of the world, I would have allowed NIL to be
> > a subtype of CONS, but maybe write a warning message out instead of
> > throwing an error. Carrying this out to its logical conclusion, I
> > think I would allow NIL to be a subtype of all other types. Of course
> > this is just my opinion. Something to think about.
>
> That carries a price. Declaring a type can allow the
> compiler to cut out a lot of type-checking code and
> just produce code that works on that type. Adding NIL
> to everything means forcing an additional check as well.
>
> As for the particular case of CONS, the type LIST is
> either a cons cell or nil, and shouldn't cause an error
> in this case.
>
> ---
> Geoff

You're right, of course. Checking for special cases (NIL) carries a
price.
Pascal's and your suggestions of using 'list instead of 'cons
essentially tables the discussion for now, but a little voice in my
head is still bothering me that the degenerate case (NIL) should be
considered valid or perhaps just warrant a warning in the case when
the type declaration is just a compiler hint (such as shown in this
demo). (typep nil 'cons) should still return NIL, but, in my highly
opinionated reasoning, shouldn't throw an error in this situation. I
understand this adds complexity, but I think the domain I'm talking
about is well-defined, the Lisp language is not redefined in any way,
and the compiler is more developer-friendly. But, as I said, now that
I have a work-around, I'm don't see any reason to press the point.
From: Alan Crowe
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <86abo9gdy7.fsf@cawtech.freeserve.co.uk>
vanekl <·····@acd.net> writes:
> You're right, of course. Checking for special cases (NIL) carries a
> price.
> Pascal's and your suggestions of using 'list instead of 'cons
> essentially tables the discussion for now, but a little voice in my
> head is still bothering me that the degenerate case (NIL) should be
> considered valid or perhaps just warrant a warning in the case when
> the type declaration is just a compiler hint (such as shown in this
> demo). (typep nil 'cons) should still return NIL, but, in my highly
> opinionated reasoning, shouldn't throw an error in this situation. I
> understand this adds complexity, but I think the domain I'm talking
> about is well-defined, the Lisp language is not redefined in any way,
> and the compiler is more developer-friendly. But, as I said, now that
> I have a work-around, I'm don't see any reason to press the point.

I think that CL has this sorted just right.

Look at System Class LIST.
It says
 
     The types cons and null form an exhaustive partition of
     the type list.

So you can write a function to find the length of a list
like this

         (defun size (thing)
           (typecase thing
             (null 0)
             (cons (+ 1 (size (cdr thing))))))

But notice the gotcha, the type whose only example is nil is
(eql nil) or (member nil) or most simply null

The type with no examples at all, (member) is called nil

(member) = nil
(member nil) = null
(or null cons) = list

(or nil cons) < list
(or nil cons) = cons

(subtypep 'nil 'cons) => t ;vacuous the empty set is a subset
                           ;of every set
 
(subtypep 'null 'cons) => nil ;useful, the empty list is not
                              ;a cons

(subtypep 'nil 'list) => t ;vacuous and misleading

(subtypep 'null 'list) => t ;the one you were thinking off
                            ;an empty list is a list 

Once you get the types nil and null straight this works
logically and usefully.

Alan Crowe
Edinburgh
Scotland
From: vanekl
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <7e96f7f6-9d52-4e3f-9061-480a2150c0d3@c4g2000hsg.googlegroups.com>
On Dec 17, 10:21 pm, Alan Crowe <····@cawtech.freeserve.co.uk> wrote:
> vanekl <·····@acd.net> writes:
> > You're right, of course. Checking for special cases (NIL) carries a
> > price.
> > Pascal's and your suggestions of using 'list instead of 'cons
> > essentially tables the discussion for now, but a little voice in my
> > head is still bothering me that the degenerate case (NIL) should be
> > considered valid or perhaps just warrant a warning in the case when
> > the type declaration is just a compiler hint (such as shown in this
> > demo). (typep nil 'cons) should still return NIL, but, in my highly
> > opinionated reasoning, shouldn't throw an error in this situation. I
> > understand this adds complexity, but I think the domain I'm talking
> > about is well-defined, the Lisp language is not redefined in any way,
> > and the compiler is more developer-friendly. But, as I said, now that
> > I have a work-around, I'm don't see any reason to press the point.
>
> I think that CL has this sorted just right.
>
> Look at System Class LIST.
> It says
>
>      The types cons and null form an exhaustive partition of
>      the type list.
>
> So you can write a function to find the length of a list
> like this
>
>          (defun size (thing)
>            (typecase thing
>              (null 0)
>              (cons (+ 1 (size (cdr thing))))))
>
> But notice the gotcha, the type whose only example is nil is
> (eql nil) or (member nil) or most simply null
>
> The type with no examples at all, (member) is called nil
>
> (member) = nil
> (member nil) = null
> (or null cons) = list
>
> (or nil cons) < list
> (or nil cons) = cons
>
> (subtypep 'nil 'cons) => t ;vacuous the empty set is a subset
>                            ;of every set
>
> (subtypep 'null 'cons) => nil ;useful, the empty list is not
>                               ;a cons
>
> (subtypep 'nil 'list) => t ;vacuous and misleading
>
> (subtypep 'null 'list) => t ;the one you were thinking off
>                             ;an empty list is a list
>
> Once you get the types nil and null straight this works
> logically and usefully.
>
> Alan Crowe
> Edinburgh
> Scotland

This is very informative.
You're right, I had the wrong idea about NIL and NULL, but this didn't
factor into the root cause of my misunderstanding.

I erroneously thought one could always assign subtypes. For example,
assigning subtypes works just fine in the following test (where an
integer is assigned to a number, which is composed of REAL and COMPLEX
types):

(defun assign_subtype_test (arg1)
  (declare (type number arg1))
  (setq arg1 42))

(assign_subset_test 1.23)

(subtypep 'integer 'number )
(subtypep 'nil 'cons)

However, assigning subtypes apparently is not always possible.
From: Paul Khuong
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <d0a70be7-6758-4fb9-897d-caa90119c9be@d27g2000prf.googlegroups.com>
On Dec 17, 6:34 pm, vanekl <·····@acd.net> wrote:
> On Dec 17, 10:21 pm, Alan Crowe <····@cawtech.freeserve.co.uk> wrote:
[...]
> > But notice the gotcha, the type whose only example is nil is
> > (eql nil) or (member nil) or most simply null
>
> > The type with no examples at all, (member) is called nil
> > (member) = nil
> > (member nil) = null
> > (or null cons) = list
> > (or nil cons) < list
> > (or nil cons) = cons
> > (subtypep 'nil 'cons) => t ;vacuous the empty set is a subset
> >                            ;of every set
> > (subtypep 'null 'cons) => nil ;useful, the empty list is not
> >                               ;a cons
[...]
> This is very informative.
> You're right, I had the wrong idea about NIL and NULL, but this didn't
> factor into the root cause of my misunderstanding.
>
> I erroneously thought one could always assign subtypes. For example,
> assigning subtypes works just fine in the following test (where an
> integer is assigned to a number, which is composed of REAL and COMPLEX
> types):
[..]
> (subtypep 'integer 'number )
> (subtypep 'nil 'cons)
>
> However, assigning subtypes apparently is not always possible.

Did you not read what you quoted? nil is the bottom type, inhabited by
no value and subtypep of every type. *null* is the type that contains
only the value nil, and, indeed, (subtypep 'null 'cons) => NIL, T (on
my implementation; it could also be NIL, NIL). Obviously, if x:Type
and (subtypep 'Type 'Type2), x is also of type Type2. What else would
subtyping mean otherwise? 'Assigning subtypes' is meaningless. Every
value is a member of an infinite chain of types, for example (member
x) < (member x y) < (member x y z) < (member x y z ...) ... You're
nearly always `assigning subtypes'. Again, NIL is not a CONS.

Paul Khuong
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5so8f8F1ai2noU1@mid.individual.net>
vanekl wrote:

> Pascal's and your suggestions of using 'list instead of 'cons
> essentially tables the discussion for now, but a little voice in my
> head is still bothering me that the degenerate case (NIL) should be
> considered valid or perhaps just warrant a warning in the case when
> the type declaration is just a compiler hint (such as shown in this
> demo). (typep nil 'cons) should still return NIL, but, in my highly
> opinionated reasoning, shouldn't throw an error in this situation. I
> understand this adds complexity, but I think the domain I'm talking
> about is well-defined, the Lisp language is not redefined in any way,
> and the compiler is more developer-friendly. But, as I said, now that
> I have a work-around, I'm don't see any reason to press the point.

But 'nil is not a cons cell. Some cons-cell-specific operations simply 
don't work on 'nil. Try, for example, (setf (car nil) 5).

You seem to be thinking that cons cells and lists are conceptually the 
same, but they are not. A cons cell is just a pair of values, nothing 
more, nothing less. That lists are implemented using cons cells in Lisp 
is just a convention. You can use cons cells for all kinds of other 
things as well.

Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: vanekl
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <d9a69a39-1fa3-402b-84aa-e790029f559b@e6g2000prf.googlegroups.com>
On Dec 17, 9:36 pm, Pascal Costanza <····@p-cos.net> wrote:
> vanekl wrote:
> > Pascal's and your suggestions of using 'list instead of 'cons
> > essentially tables the discussion for now, but a little voice in my
> > head is still bothering me that the degenerate case (NIL) should be
> > considered valid or perhaps just warrant a warning in the case when
> > the type declaration is just a compiler hint (such as shown in this
> > demo). (typep nil 'cons) should still return NIL, but, in my highly
> > opinionated reasoning, shouldn't throw an error in this situation. I
> > understand this adds complexity, but I think the domain I'm talking
> > about is well-defined, the Lisp language is not redefined in any way,
> > and the compiler is more developer-friendly. But, as I said, now that
> > I have a work-around, I'm don't see any reason to press the point.
>
> But 'nil is not a cons cell. Some cons-cell-specific operations simply
> don't work on 'nil. Try, for example, (setf (car nil) 5).
>
> You seem to be thinking that cons cells and lists are conceptually the
> same, but they are not. A cons cell is just a pair of values, nothing
> more, nothing less. That lists are implemented using cons cells in Lisp
> is just a convention. You can use cons cells for all kinds of other
> things as well.
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

I was thinking that NIL was a degenerate case of a CONS cell, sort of
like the mathematical powerset always contains the empty set, or all
pointers may be NULL. I think I have been reading too much into this.
I stand corrected.
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <b3203592-efcd-458d-9391-a7eb53130924@e23g2000prf.googlegroups.com>
On Dec 17, 12:37 pm, vanekl <·····@acd.net> wrote:
> I understand the technical arguments made, but I was running some
> legacy code I found on the web so I assumed the code was stable and
> would run. Guess it wasn't designed to run on SBCL or CMUCL.
>
> Personally, if I was king of the world, I would have allowed NIL to be
> a subtype of CONS

This is already true:

  (subtypep 'nil 'cons) -> T

In fact, the type NIL is a subtype of every other type, even itself!

Type NIL is the empty type; that is to say, the set of domain values
of type NIL is empty: there are no instances.

However, the type of the object NIL is not NIL, but the type NULL.

I suspect what you want is for the type NULL to be a subtype of CONS
in your wacky kindgdom. It would be quite silly.

A NULL (i.e. the object NIL) isn't a kind of CONS, because it doesn't
have all the properties of a CONS. It doesn't have two mutable fields
called CAR and CDR. You cannot substitute an instance of NULL (i.e.
the object NIL) where an instance of a CONS is required.

In OOP circles, where the collective memory doesn't go back farther
than around 1993, this obvious substitutability idea is known as:

http://en.wikipedia.org/wiki/Liskov_substitution_principle

Lisp does have a LIST type, of which both NULL and CONS are subtypes.
If you declare something to be of type LIST, or check it explicitly
using LISTP, you're in fact checking for CONS and NULL simultaneously.
From: vanekl
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fa8eb115-6671-48f8-98aa-0bd0a4b31443@i72g2000hsd.googlegroups.com>
On Dec 18, 1:51 am, Kaz Kylheku <········@gmail.com> wrote:
> On Dec 17, 12:37 pm, vanekl <·····@acd.net> wrote:
>
> > I understand the technical arguments made, but I was running some
> > legacy code I found on the web so I assumed the code was stable and
> > would run. Guess it wasn't designed to run on SBCL or CMUCL.
>
> > Personally, if I was king of the world, I would have allowed NIL to be
> > a subtype of CONS
>
> This is already true:
>
>   (subtypep 'nil 'cons) -> T
>
> In fact, the type NIL is a subtype of every other type, even itself!
>
> Type NIL is the empty type; that is to say, the set of domain values
> of type NIL is empty: there are no instances.
>
> However, the type of the object NIL is not NIL, but the type NULL.
>
> I suspect what you want is for the type NULL to be a subtype of CONS
> in your wacky kindgdom. It would be quite silly.
>
> A NULL (i.e. the object NIL) isn't a kind of CONS, because it doesn't
> have all the properties of a CONS. It doesn't have two mutable fields
> called CAR and CDR. You cannot substitute an instance of NULL (i.e.
> the object NIL) where an instance of a CONS is required.
>
> In OOP circles, where the collective memory doesn't go back farther
> than around 1993, this obvious substitutability idea is known as:
>
> http://en.wikipedia.org/wiki/Liskov_substitution_principle
>
> Lisp does have a LIST type, of which both NULL and CONS are subtypes.
> If you declare something to be of type LIST, or check it explicitly
> using LISTP, you're in fact checking for CONS and NULL simultaneously.

Thank you, this makes sense.
My ass is hurting, though. Anybody else want to step up and take a
wack while we're at it?
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5so5fhF1a3agoU2@mid.individual.net>
vanekl wrote:

>>> And this is the error message that SBCL/Swank/Slime is showing:
>>> The value NIL is not of type CONS.
>>>    [Condition of type TYPE-ERROR]
>> --http://lispm.dyndns.org/
> 
> Thanks, everybody, for responding so quickly.
> 
> I understand the technical arguments made, but I was running some
> legacy code I found on the web so I assumed the code was stable and
> would run. Guess it wasn't designed to run on SBCL or CMUCL.

You probably want the type 'list, not 'cons. 'list is either a cons or NIL.

> Personally, if I was king of the world, I would have allowed NIL to be
> a subtype of CONS, but maybe write a warning message out instead of
> throwing an error. Carrying this out to its logical conclusion, I
> think I would allow NIL to be a subtype of all other types. Of course
> this is just my opinion. Something to think about.

This would make it hard to exclude NIL when you want to exclude it, 
which is also a very useful case.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: vanekl
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <b37b026d-22b4-4076-9fbe-19edbb69ccd0@i72g2000hsd.googlegroups.com>
On Dec 17, 8:45 pm, Pascal Costanza <····@p-cos.net> wrote:
> vanekl wrote:
> >>> And this is the error message that SBCL/Swank/Slime is showing:
> >>> The value NIL is not of type CONS.
> >>>    [Condition of type TYPE-ERROR]
> >> --http://lispm.dyndns.org/
>
> > Thanks, everybody, for responding so quickly.
>
> > I understand the technical arguments made, but I was running some
> > legacy code I found on the web so I assumed the code was stable and
> > would run. Guess it wasn't designed to run on SBCL or CMUCL.
>
> You probably want the type 'list, not 'cons. 'list is either a cons or NIL.
>
> > Personally, if I was king of the world, I would have allowed NIL to be
> > a subtype of CONS, but maybe write a warning message out instead of
> > throwing an error. Carrying this out to its logical conclusion, I
> > think I would allow NIL to be a subtype of all other types. Of course
> > this is just my opinion. Something to think about.
>
> This would make it hard to exclude NIL when you want to exclude it,
> which is also a very useful case.
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

YES! Changing it to list (instead of cons) worked!
Thank you!
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <c7ef5097-7e0e-434c-a8f7-a6897b2e9839@b40g2000prf.googlegroups.com>
vanekl ha escrito:

> The value NIL is not of type CONS.
>    [Condition of type TYPE-ERROR]

Just one more inconsistence of Common Lisp.
The more you discover about these inconsistencies, the more you
discover how much CL sucks.

If the empty list is NIL, then NIL should be of type CONS. For me,
this should be the logical behavior.
From: Geoff Wozniak
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <589973cd-5a35-49ea-a674-078e2ef1ffdf@b1g2000pra.googlegroups.com>
On Dec 18, 8:12 am, Javier <·······@gmail.com> wrote:
> vanekl ha escrito:
>
> > The value NIL is not of type CONS.
> >    [Condition of type TYPE-ERROR]
>
> Just one more inconsistence of Common Lisp.
> The more you discover about these inconsistencies, the more you
> discover how much CL sucks.
>

If this is true, then perhaps I can not consider CLisp and not feel
bad.

> If the empty list is NIL, then NIL should be of type CONS. For me,
> this should be the logical behavior.

Consider the definition of a list from a potentially "non-sucky"
language:

  type 'a list = Nil | Cons 'a * 'a list

You can say effectively the same thing in CL (without the qualifier):

  (deftype list () `(or (eql nil) cons)))

which, as Alan pointed out, is the same as

  (deftype list () `(or null cons)))

This shows that, by definition, a cons is not a list; it is something
else entirely.  The fact that it is used to make lists may be the
confusing point.  This is understandable since introductions to Lisp
often have you calling cons and seeing a list.  A cons is one of the
"atomic" types in that it is a fundamental building block.  Null and
cons partition the set of list values.
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <c0661ce5-8bb8-40fa-8314-1fed5405df23@r29g2000hsg.googlegroups.com>
On 18 dic, 15:55, Geoff Wozniak <·············@gmail.com> wrote:
> On Dec 18, 8:12 am, Javier <·······@gmail.com> wrote:
>
> > vanekl ha escrito:
>
> > > The value NIL is not of type CONS.
> > >    [Condition of type TYPE-ERROR]
>
> > Just one more inconsistence of Common Lisp.
> > The more you discover about these inconsistencies, the more you
> > discover how much CL sucks.
>
> If this is true, then perhaps I can not consider CLisp and not feel
> bad.
>
> > If the empty list is NIL, then NIL should be of type CONS. For me,
> > this should be the logical behavior.
>
> Consider the definition of a list from a potentially "non-sucky"
> language:
>
>   type 'a list = Nil | Cons 'a * 'a list
>
> You can say effectively the same thing in CL (without the qualifier):
>
>   (deftype list () `(or (eql nil) cons)))
>
> which, as Alan pointed out, is the same as
>
>   (deftype list () `(or null cons)))
>
> This shows that, by definition, a cons is not a list; it is something
> else entirely.  The fact that it is used to make lists may be the
> confusing point.  This is understandable since introductions to Lisp
> often have you calling cons and seeing a list.  A cons is one of the
> "atomic" types in that it is a fundamental building block.  Null and
> cons partition the set of list values.

I understand what you can do with deftype, and how Lisp is constructed
around the list type. I even used deftype somewhere in the past to
make my own types (it is useful for creating your own object system,
for example). This is not my point. My point is that NIL means too
much things in practical use which, from my point of view, should not
be there.
I think that CL should have used a similar aproach  than scheme and
call the empty list simply '(). In lisp, '() means NIL. Somewhere, I
would like to have NIL and '() to mean different things.
For example, to distinguish from an uninitialized value from an empty
list.
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sqnjqF18u9dqU1@mid.individual.net>
Javier wrote:

> I think that CL should have used a similar aproach  than scheme and
> call the empty list simply '(). In lisp, '() means NIL. Somewhere, I
> would like to have NIL and '() to mean different things.
> For example, to distinguish from an uninitialized value from an empty
> list.

Common Lisp actually has a concept of uninitialized (unbound) variables, 
both for global variables and for slots in CLOS objects. You get an 
exception that you can react on or, in the case of CLOS, you can define 
a method that intercepts unboundness conditions. There is also a clear 
way to test for unboundness, and to make such variables unbound.

Scheme is very ugly in that regard - check out the stupid non-portable 
(if #f #f) idiom, or the mess in one of the original R6RS drafts with 
the 'undefined value'.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <62ba4105-3c54-4e79-92c0-51be9799f9d3@s19g2000prg.googlegroups.com>
On 18 dic, 21:07, Pascal Costanza <····@p-cos.net> wrote:
> Javier wrote:
> > I think that CL should have used a similar aproach  than scheme and
> > call the empty list simply '(). In lisp, '() means NIL. Somewhere, I
> > would like to have NIL and '() to mean different things.
> > For example, to distinguish from an uninitialized value from an empty
> > list.
>
> Common Lisp actually has a concept of uninitialized (unbound) variables,
> both for global variables and for slots in CLOS objects. You get an
> exception that you can react on or, in the case of CLOS, you can define
> a method that intercepts unboundness conditions. There is also a clear
> way to test for unboundness, and to make such variables unbound.
>
> Scheme is very ugly in that regard - check out the stupid non-portable
> (if #f #f) idiom, or the mess in one of the original R6RS drafts with
> the 'undefined value'.
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

All of this seems to be a problem from my own to not being able to
express what I mean.
Let me say it with other words, focused on what you have just told:
I'm not talking about unbound variables. I'm talking about real NULL
values, or not real NULL values. Must be an empty list false? and why?
For example, in Java, if you got an instance of an empty collection,
it is clear that the object is present, it is "true", but empty. In
Scheme, the same thing happens. But in CL, an empty list is false, or
NIL. This is confusing, because if I want to use a variable which can
allocate a list, I am not able to distinguish it from any other type
of variable, which might be NIL, too.
For example, using some methods (which you like so much):

(defmethod my-method ((a list))
  (format t "some list operations"))

(defmethod my-method (a)
  (format t "am i going to be executed if a is a boolean whose value
is NIL?"))

This is related to a boring thing in CL, which is that there is not a
real working boolean type.
There might be ways of avoiding this "bug" in the CL specification,
but some users which are not used to this CL idiosyncrasy, will get
confused. This happened to me in the past, and learned the lesson.
This issue, and other ones, is what made me think that CL sucks. It is
just my opinion.
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sqstqF1av13tU1@mid.individual.net>
Javier wrote:
> On 18 dic, 21:07, Pascal Costanza <····@p-cos.net> wrote:
>> Javier wrote:
>>> I think that CL should have used a similar aproach  than scheme and
>>> call the empty list simply '(). In lisp, '() means NIL. Somewhere, I
>>> would like to have NIL and '() to mean different things.
>>> For example, to distinguish from an uninitialized value from an empty
>>> list.
>> Common Lisp actually has a concept of uninitialized (unbound) variables,
>> both for global variables and for slots in CLOS objects. You get an
>> exception that you can react on or, in the case of CLOS, you can define
>> a method that intercepts unboundness conditions. There is also a clear
>> way to test for unboundness, and to make such variables unbound.
>>
>> Scheme is very ugly in that regard - check out the stupid non-portable
>> (if #f #f) idiom, or the mess in one of the original R6RS drafts with
>> the 'undefined value'.
>>
>> Pascal
>>
>> --
>> My website:http://p-cos.net
>> Common Lisp Document Repository:http://cdr.eurolisp.org
>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
> 
> All of this seems to be a problem from my own to not being able to
> express what I mean.
> Let me say it with other words, focused on what you have just told:
> I'm not talking about unbound variables. I'm talking about real NULL
> values, or not real NULL values. Must be an empty list false? and why?
> For example, in Java, if you got an instance of an empty collection,
> it is clear that the object is present, it is "true", but empty. In
> Scheme, the same thing happens. But in CL, an empty list is false, or
> NIL. This is confusing, because if I want to use a variable which can
> allocate a list, I am not able to distinguish it from any other type
> of variable, which might be NIL, too.
> For example, using some methods (which you like so much):
> 
> (defmethod my-method ((a list))
>   (format t "some list operations"))
> 
> (defmethod my-method (a)
>   (format t "am i going to be executed if a is a boolean whose value
> is NIL?"))
> 
> This is related to a boring thing in CL, which is that there is not a
> real working boolean type.
> There might be ways of avoiding this "bug" in the CL specification,
> but some users which are not used to this CL idiosyncrasy, will get
> confused. This happened to me in the past, and learned the lesson.
> This issue, and other ones, is what made me think that CL sucks. It is
> just my opinion.

Yes, the conflation of the empty list and the false boolean value can 
sometimes be problematic. That's why in CL you sometimes resort to 
multiple values, where the first value might be 'NIL, and the second 
value tells whether it was actually really 'NIL, or "just not there."

It's also the case that (type-of 'nil) may not help you much, because 
you cannot distinguish between lists and booleans here.

But saying that CL sucks in this regard is also too simplistic. I am not 
aware of any language that is successful at introducing nullity without 
introducing paradoxes at the same time. The problem with nothingness is 
in general that it is a hard concept to get right. (Consider the problem 
of nothingness in philosophy, or of the number zero or the empty set in 
mathematics, etc.)

For example, the value null in Java is a _big_ problem in that language 
because it breaks its static type system in a serious way: You can 
assign null to any reference, but you cannot send it _any_ message, so 
you immediately violate the type guarantees of that variable. This leads 
to ugly designs like the Null pattern (look it up, it really exist!), or 
to suggestions to extend the type system with mandatory types that can 
never be null (but lead to other problems).

Not even in Scheme it works as well as it appears to. Or do you really 
think it makes a lot of sense that function returns, say, either a 
number of #f?

There are no really good solutions here, only pragmatic ones, which suck 
more or less to varying degrees. Common Lisp's design leads to more 
compact code in a lot of cases, and that is a nice, pragmatic property.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5ss54vF1aqeiuU1@mid.individual.net>
Pascal Costanza wrote:

> I am not 
> aware of any language that is successful at introducing nullity without 
> introducing paradoxes at the same time. The problem with nothingness is 
> in general that it is a hard concept to get right. (Consider the problem 
> of nothingness in philosophy, or of the number zero or the empty set in 
> mathematics, etc.)

As a sidenote, an interesting case is Objective-C, in which you can send 
messages to null, which are simply ignored (they don't throw exceptions 
in those situations). Friends of mine who program in Objective-C a lot 
say that that's what you actually want most of the time, so that seems 
to be another pragmatic solution to reduce code size.

Good that we can have that in Common Lisp as well: You can always define 
methods on null:

(defmethod foo ((object null)) (values))

 > (foo nil)
  ;;; er, nothing of course ;-)


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Tobias C. Rittweiler
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <87zlw73tws.fsf@freebits.de>
Pascal Costanza <··@p-cos.net> writes:

> Yes, the conflation of the empty list and the false boolean value can
> sometimes be problematic. That's why in CL you sometimes resort to
> multiple values, where the first value might be 'NIL, and the second
> value tells whether it was actually really 'NIL, or "just not there."

There is another way which can sometimes result in more conciseness.
It's not often mentioned, but in Common Lisp, there is (of course!) a
difference between (values) and (values nil), and you can differentiate
between those two.

So instead of returning (values nil nil) where the second value
represents an existence flag, you simply write (values). Then you can
use the following macro to coerce a default value around a computation:

  (defmacro default-value (value form)
    `(destructuring-bind (&optional (result ,value))
         (multiple-value-list ,form)
       result))

This gives:

  (default-value 'foo 42)       ==> 42
  (default-value 'foo nil)      ==> NIL
  (default-value 'foo (values)) ==> FOO

  -T.
From: jurgen_defurne
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <15f3c16f-239b-4134-9a40-d39b84f5a2e6@l32g2000hse.googlegroups.com>
On Dec 18, 9:56 pm, Javier <·······@gmail.com> wrote:
> On 18 dic, 21:07, Pascal Costanza <····@p-cos.net> wrote:
>
>
>
> > Javier wrote:
> > > I think that CL should have used a similar aproach  than scheme and
> > > call the empty list simply '(). In lisp, '() means NIL. Somewhere, I
> > > would like to have NIL and '() to mean different things.
> > > For example, to distinguish from an uninitialized value from an empty
> > > list.
>
> > Common Lisp actually has a concept of uninitialized (unbound) variables,
> > both for global variables and for slots in CLOS objects. You get an
> > exception that you can react on or, in the case of CLOS, you can define
> > a method that intercepts unboundness conditions. There is also a clear
> > way to test for unboundness, and to make such variables unbound.
>
> > Scheme is very ugly in that regard - check out the stupid non-portable
> > (if #f #f) idiom, or the mess in one of the original R6RS drafts with
> > the 'undefined value'.
>
> > Pascal
>
> > --
> > My website:http://p-cos.net
> > Common Lisp Document Repository:http://cdr.eurolisp.org
> > Closer to MOP & ContextL:http://common-lisp.net/project/closer/
>
> All of this seems to be a problem from my own to not being able to
> express what I mean.
> Let me say it with other words, focused on what you have just told:
> I'm not talking about unbound variables. I'm talking about real NULL
> values, or not real NULL values. Must be an empty list false? and why?
> For example, in Java, if you got an instance of an empty collection,
> it is clear that the object is present, it is "true", but empty. In
> Scheme, the same thing happens. But in CL, an empty list is false, or
> NIL. This is confusing, because if I want to use a variable which can
> allocate a list, I am not able to distinguish it from any other type
> of variable, which might be NIL, too.
> For example, using some methods (which you like so much):
>
> (defmethod my-method ((a list))
>   (format t "some list operations"))
>
> (defmethod my-method (a)
>   (format t "am i going to be executed if a is a boolean whose value
> is NIL?"))
>
> This is related to a boring thing in CL, which is that there is not a
> real working boolean type.
> There might be ways of avoiding this "bug" in the CL specification,
> but some users which are not used to this CL idiosyncrasy, will get
> confused. This happened to me in the past, and learned the lesson.
> This issue, and other ones, is what made me think that CL sucks. It is
> just my opinion.

FWIW, in Perl an empty list is also false.

Jurgen
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <1f273287-b5d4-4fd7-97e9-ad470ea4e6e3@n20g2000hsh.googlegroups.com>
On 18 dic, 15:55, Geoff Wozniak <·············@gmail.com> wrote:

>   type 'a list = Nil | Cons 'a * 'a list


If you are refering to Ocaml, I might be wrong, but what you are
calling Nil here is not NIL in Lisp terms. Nil is not a value from
which you can assign to a variable of any other type.
From: Russell McManus
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <87zlw8caew.fsf@thelonious.cl-user.org>
Javier <·······@gmail.com> writes:

> Just one more inconsistence of Common Lisp.  The more you discover
> about these inconsistencies, the more you discover how much CL
> sucks.

Compared to what?

-russ
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <42507cf2-a810-4aa0-afae-ecfe2a53b192@j20g2000hsi.googlegroups.com>
On 18 dic, 16:03, Russell McManus <···············@yahoo.com> wrote:
> Javier <·······@gmail.com> writes:
> > Just one more inconsistence of Common Lisp.  The more you discover
> > about these inconsistencies, the more you discover how much CL
> > sucks.
>
> Compared to what?


In Scheme, the empty list is '(), not NIL. For example.
In Scheme, a boolean value is either #f or #t, not T or NIL, because
NIL can be so much things in CL... (for example, an empty list, a
false value, an empty array, a non-initialized value...).

Something similar occurs in C, which NULL means 0 for a lot of things.
But at least in C, NULL is consistent because you know that,
computationally, it always means 0. But you don't know what NIL is in
Lisp, really.
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <f1e8476d-de10-4f11-8378-dfa5046ea682@p1g2000hsb.googlegroups.com>
On Dec 18, 8:16 am, Javier <·······@gmail.com> wrote:
> On 18 dic, 16:03, Russell McManus <···············@yahoo.com> wrote:
>
> > Javier <·······@gmail.com> writes:
> > > Just one more inconsistence of Common Lisp.  The more you discover
> > > about these inconsistencies, the more you discover how much CL
> > > sucks.
>
> > Compared to what?
>
> In Scheme, the empty list is '(), not NIL.

Listen, trolling fool. Many people around here know Scheme very well.
You aren't telling anyone anything they don't know already. So kindly
save the Scheme lecturing for your local village, okay?

If you want to program in Scheme, go program in Scheme. Many
programmers use both CL and Scheme. We know where to find
comp.lang.scheme if we want to read about Scheme.

The Scheme representation of lists and booleans introduces numerous
inconveniences into programming. You have to write more code to test
for more cases.

> For example.
> In Scheme, a boolean value is either #f or #t, not T or NIL, because
> NIL can be so much things in CL.

That's right. In CL there is even a NULL class so that you can give
NIL even more meanings. That is to say, you can specialize methods
parameters to the NULL class so that you can then use NIL in places
where objects of other types are expected.

Effectively, for any given type, you can pretend there is a supertype
which includes that type, as well as the NULL type. For example, given
a WIDGET class, you can pretend that there is a WIDGET* class which is
partitioned into WIDGET and NULL. You write methods that specialize
for WIDGET and ones which specialize for NULL. Then you can use the
NIL object in all the same generic functions as WIDGET. Suddenly NIL
is not just the empty list but a special kind of widget.

Java and C++ programmers have come know this under the name ``Null
Object Design Pattern''. The NODP allows you to reduce the complexity
of code by not having to check for annoying cases such as null
references. In Lisp we don't have to check for NIL because, similarly,
methods and functions can be overloaded to handle it gracefully. So
for instance (FIRST NIL) doesn't produce an error. By contrast, in
Scheme, you have to check whether a list is non-empty before you can
access it in this way. This is annoying.

In C program design, you might use sentinel nodes to eliminate case
tests in data structures. If a doubly-linked list is implemented as a
circular list with a special sentinel node, you can write an insertion
without any special cases:

  newnode->next = successor;
  newnode->prev = predecessor;
  successor->prev = newnode;
  predecessor->next = newnode;

In cases where you are inserting at the head or tail, the roles of
predecessor or succeessor are taken up by the sentinel node. This
``null object'' simplifies code and speeds it up. If you use a null
pointer for head and tail, you have cases to deal with. Insertion in
the middle of the lists, is different from insertion at the head and
tail.

Eliminating cases is good because cases have run-time overhead, and
they complicate testing, since every case must receive coverage.

.. (for example, an empty list, a
> false value, an empty array, a non-initialized value...).
>
> Something similar occurs in C, which NULL means 0 for a lot of things.

That is false; yet another thing you have no clue about. In C, a null
pointer constant has one of two forms:

- an integral constant expression of value zero; or
- such an expression cast to (void *).

Only the first form is a numeric zero. The NULL macro expands to one
of these two, the choice being up to the implementor. Therefore this
is not a portable construct:

  int x = NULL;

If your C implementation defines the NULL macro as ((void *) 0), then
the above is a compile-time error.

> But at least in C, NULL is consistent because you know that,
> computationally, it always means 0.

Who is this ``you'' you are referring to? Probably some set of
clueless people of which you are a member.

> But you don't know what NIL is in Lisp, really.

The same ``you'' obviously.  I know what NIL is in Lisp, really.
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <b0b7cc46-b46b-485f-826c-df63c965599b@l1g2000hsa.googlegroups.com>
On 18 dic, 21:44, Kaz Kylheku <········@gmail.com> wrote:

> That is false; yet another thing you have no clue about. In C, a null
> pointer constant has one of two forms:

Listen, trolling fool. Many people around here know C very well.
You aren't telling anyone anything they don't know already. So kindly
save the C lecturing for your local village, okay?
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <f1d9e100-8e7b-496c-ba54-9bb97f174e9c@s12g2000prg.googlegroups.com>
On Dec 18, 1:27 pm, Javier <·······@gmail.com> wrote:
> On 18 dic, 21:44, Kaz Kylheku <········@gmail.com> wrote:
>
> > That is false; yet another thing you have no clue about. In C, a null
> > pointer constant has one of two forms:
>
> Listen, trolling fool.

If I am the troll, shouldn't I be in comp.lang.scheme preaching about
the virtues of Common Lisp?

> Many people around here know C very well.

But, alas, not you.

> You aren't telling anyone anything they don't know already.

Right. If it weren't for my reply, you'd still be clueless about what
NULL really means. This is the thanks I get.

> So kindly save the C lecturing for your local village, okay?

However, the biggest fool from that village could yet be your mentor
in computer science.
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <21bc817f-97c8-4293-9e9c-6291b5aee8f6@w56g2000hsf.googlegroups.com>
On 18 dic, 23:18, Kaz Kylheku <········@gmail.com> wrote:

> Right. If it weren't for my reply, you'd still be clueless about what
> NULL really means. This is the thanks I get.

Thank you very much for the lesson you have given to me about what
really NULL means.
I am now proud to have learned that NULL means Kaz Kylheku.
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fk8s3r$era$4@news.net.uni-c.dk>
Den Tue, 18 Dec 2007 08:16:22 -0800 skrev Javier:

>> > Just one more inconsistence of Common Lisp.  The more you discover
>> > about these inconsistencies, the more you discover how much CL sucks.
>>
>> Compared to what?
> 
> In Scheme, the empty list is '(), not NIL. For example. In Scheme, a
> boolean value is either #f or #t, not T or NIL, because NIL can be so
> much things in CL... (for example, an empty list, a false value, an
> empty array, a non-initialized value...).

CL-USER> (typep nil 'array)
NIL
CL-USER> *unbound*
; Evaluation aborted.

> Something similar occurs in C, which NULL means 0 for a lot of things.
> But at least in C, NULL is consistent because you know that,
> computationally, it always means 0. But you don't know what NIL is in
> Lisp, really.

Just cut your bullshit already.

Maciej
From: Martti Halminen
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <4767fdf3$0$27846$4f793bc4@news.tdc.fi>
Javier wrote:

> Something similar occurs in C, which NULL means 0 for a lot of things.
> But at least in C, NULL is consistent because you know that,
> computationally, it always means 0. 

Actually, you don't know that. While it may be true in most 
implementations, it is not required. In the Symbolics C compiler, null 
was something like (0 . nil).

-- 
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sqn5aF1af5d5U1@mid.individual.net>
Javier wrote:
> On 18 dic, 16:03, Russell McManus <···············@yahoo.com> wrote:
>> Javier <·······@gmail.com> writes:
>>> Just one more inconsistence of Common Lisp.  The more you discover
>>> about these inconsistencies, the more you discover how much CL
>>> sucks.
>> Compared to what?
> 
> 
> In Scheme, the empty list is '(), not NIL. For example.
> In Scheme, a boolean value is either #f or #t, not T or NIL, because
> NIL can be so much things in CL... (for example, an empty list, a
> false value, an empty array, a non-initialized value...).

Are you really sure that you know what you're talking about? It doesn't 
seem so...

This is Scheme:

#;> (pair? (cons 1 2))
#t
#;> (pair? '())
#f

Exactly the same in Common Lisp:

[1]> (typep (cons 1 2) 'cons)
T
[2]> (typep '() 'cons)
NIL

What was it again that is cleaner in Scheme in this regard?!?


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <7cd41c90-46b7-4438-9d57-064680083848@p69g2000hsa.googlegroups.com>
On 18 dic, 20:59, Pascal Costanza <····@p-cos.net> wrote:
> Javier wrote:
> > On 18 dic, 16:03, Russell McManus <···············@yahoo.com> wrote:
> >> Javier <·······@gmail.com> writes:
> >>> Just one more inconsistence of Common Lisp.  The more you discover
> >>> about these inconsistencies, the more you discover how much CL
> >>> sucks.
> >> Compared to what?
>
> > In Scheme, the empty list is '(), not NIL. For example.
> > In Scheme, a boolean value is either #f or #t, not T or NIL, because
> > NIL can be so much things in CL... (for example, an empty list, a
> > false value, an empty array, a non-initialized value...).
>
> Are you really sure that you know what you're talking about? It doesn't
> seem so...
>
> This is Scheme:
>
> #;> (pair? (cons 1 2))
> #t
> #;> (pair? '())
> #f
>
> Exactly the same in Common Lisp:
>
> [1]> (typep (cons 1 2) 'cons)
> T
> [2]> (typep '() 'cons)
> NIL
>
> What was it again that is cleaner in Scheme in this regard?!?

That Scheme return #f, which is not the same as '(). In Lisp, NIL and
'() are the same.
For example, in Scheme:

(if '() (display "correct") (display "incorrect"))
=> correct

In CL:

(if '() (format t "correct") (format t "incorrect"))
=> incorrect

What are the reasons to treat '() as the same of a false value? This
is the point. I hope I have expressed it correctly. (I hope this
answer to Kent M Pitman, too).
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sqorqF1aqseuU1@mid.individual.net>
Javier wrote:
> On 18 dic, 20:59, Pascal Costanza <····@p-cos.net> wrote:
>> Javier wrote:
>>> On 18 dic, 16:03, Russell McManus <···············@yahoo.com> wrote:
>>>> Javier <·······@gmail.com> writes:
>>>>> Just one more inconsistence of Common Lisp.  The more you discover
>>>>> about these inconsistencies, the more you discover how much CL
>>>>> sucks.
>>>> Compared to what?
>>> In Scheme, the empty list is '(), not NIL. For example.
>>> In Scheme, a boolean value is either #f or #t, not T or NIL, because
>>> NIL can be so much things in CL... (for example, an empty list, a
>>> false value, an empty array, a non-initialized value...).
>> Are you really sure that you know what you're talking about? It doesn't
>> seem so...
>>
>> This is Scheme:
>>
>> #;> (pair? (cons 1 2))
>> #t
>> #;> (pair? '())
>> #f
>>
>> Exactly the same in Common Lisp:
>>
>> [1]> (typep (cons 1 2) 'cons)
>> T
>> [2]> (typep '() 'cons)
>> NIL
>>
>> What was it again that is cleaner in Scheme in this regard?!?
> 
> That Scheme return #f, which is not the same as '(). In Lisp, NIL and
> '() are the same.

But that's an issue unrelated to your original statement. In Scheme, 
neither '() nor #f are of type pair (cons) either, and that's what you 
seemed to have problems with.

> For example, in Scheme:
> 
> (if '() (display "correct") (display "incorrect"))
> => correct
> 
> In CL:
> 
> (if '() (format t "correct") (format t "incorrect"))
> => incorrect
> 
> What are the reasons to treat '() as the same of a false value? This
> is the point. I hope I have expressed it correctly. (I hope this
> answer to Kent M Pitman, too).

That's an old question. See 
http://www.lisp.org/humor/large-programs.html for an equally old good 
answer. (It refers to the language T instead of Scheme, but T had a big 
influence on newer versions of Scheme, and that link is as valid for 
Scheme as it was for T.)


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sqp0mF1aqseuU2@mid.individual.net>
Pascal Costanza wrote:

>> What are the reasons to treat '() as the same of a false value? This
>> is the point. I hope I have expressed it correctly. (I hope this
>> answer to Kent M Pitman, too).
> 
> That's an old question. See 
> http://www.lisp.org/humor/large-programs.html for an equally old good 
> answer. (It refers to the language T instead of Scheme, but T had a big 
> influence on newer versions of Scheme, and that link is as valid for 
> Scheme as it was for T.)

Short answer: Treating the empty list as the boolean false value usually 
makes your programs much more compact. The main reason for this is that 
the empty list is almost always the base case case for recursive 
algorithms anyway, where you have to stop your recursion (and that 
matters even if you don't use a recursive programming style yourself).


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: ··············@gmail.com
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <28fa2804-a952-4afd-b631-a539dd07ea6b@w40g2000hsb.googlegroups.com>
> > That's an old question. See
> >http://www.lisp.org/humor/large-programs.htmlfor an equally old good
> > answer. (It refers to the language T instead of Scheme, but T had a big
> > influence on newer versions of Scheme, and that link is as valid for
> > Scheme as it was for T.)
>
> Short answer: Treating the empty list as the boolean false value usually
> makes your programs much more compact. The main reason for this is that
> the empty list is almost always the base case case for recursive
> algorithms anyway, where you have to stop your recursion (and that
> matters even if you don't use a recursive programming style yourself).

this is all true. but...

it must be noted that while this chosen semantics of CL is practical
in many situations when dealing with lists, it's somewhat arbitrary
and can make it easier to write code with accidental unexpected
behavior and whose intent is not as clear as it could be. booleans,
lists and the nothing-value are different things in my head.

what i mean is that the list type and cons-cells in CL are positively
discriminated, creating some turbulence in the force... :)

and from my CL coding experience i can say that i did not use lists/
cons cells more then the rest of the language.

oh, damn, i think i'm speaking blasphemy! i must quickly get my kevlar
vest before the bullets get here... :)

- attila

ps: this is just a subjective opinion about things that inherently
involve subjectivity.
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <u63yvjsep.fsf@nhplace.com>
Javier <·······@gmail.com> wrote:

> What are the reasons to treat '() as the same of a false value? This
> is the point. I hope I have expressed it correctly. (I hope this
> answer to Kent M Pitman, too).

The primary reason to treat this separately is to permit punning.  A
language that permits no punning is much more complicated because you
have to have special little operators for all kinds of things that
really do the same thing, but with what C calls casting.  We used to
joke about Barbara Liskov's language CLU that it was so pushy about
separated strong typing that you had to have a separate operator to
add octal numbers instead of decimal numbers.  All languages, at some
point or another, decide they will tolerate some things having
relations or dual uses.  If you make () and #f different, then you
have to have both (member? x y) and (member x y), or you have to write
(not (null (member x y))) when you want to coerce the latter to the
former.  If you're someone who just thinks "it's good for people to do
this extra work", they probably have a job for you in the government
somewhere making forms for people to fill out.  But one thing I like
about Lisp, and it goes hand in hand with dynamic typing, is the
general meta-principle of not having to write an excess amount of text
to get the effect you want.  And I write things like
  (do ((x something (cdr x)))
      ((not x))
    ...)
[in those cases where I use DO at all, which isn't a lot these days]
not because I don't know that x is a list and I should be writing NULL,
but rather because I happen to like thinking of a shrinking list as 
receding into nothingness.  And for nothing, I use NOT, not NULL.
I also happen not to like doing 
  (if (not (null x)) y z)
and generally I just write
  (if x y z)
meaning "if x is something then y else z".  Your preference in this
might differ, and that's ok; I don't assert mine is the only possible
preference.  But I assert that mine is as valid as yours, and therefore
that while I understand you don't like this, I don't deny that you have
a valid point; I merely believe that I also have a valid point.  And
so the language isn't incoherent for what it does, it's just not the
same language as you might have designed.

The choice of what to regard as true or false is not something that
logic can dictate.  It is an arbitrary choice, and one that leads to
issues almost no matter what you do.

NIL is actually three things:  a symbol, the empty list, and false.

I personally find it a minor nuisance that it's a symbol; I'd rather
not have the symbol space have a hole in it that way.  It would work
for me if the empty list and false were the same, but neither was the
symbol NIL.  But it wouldn't be compatible, and it's so easy to
overcome that it's hardly worth mentioning.  Just shadowing NIL gets
you out of most of the problem.

Personally, I've never had a problem with, and have always been a
little annoyed with, the decision of Scheme to separate #f and ().
It's a fine experiment to have tried, and their community seems happy
with it, but I'm glad it wasn't our CL community that tried it.  The
CL community is more "pluralistic" than the Scheme community, and I
think it would not have been successful for us.

Btw, I think what makes NIL as a symbol wrong is not the invading of the
symbol space, it's the choice of the string "NIL" as the base case.
It looks ok visually in simple examples but it's really pretty dumb.
I wouldn't have been bothered if || (the symbol that had no characters)
were a false value, nor probably even if it were _the_ false value.
It's a bit ugly to look at, but it could have had some other syntax, #f
or #n some such, to mark it better.

But I would not have thrust my preference on someone else by
suggesting the language should change incompatibly to suit my personal
whims or interests in experimentation.  If I were going to experiment,
I'd get my own language where people could voluntarily join up if they
liked what I was doing.  My problem with changing standards in general
is not that I'm anti-change, I'm anti-forced-change.  The world is too
big and complicated and unsynchronized to work that way these days.
From: Arthur Smyles
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <7b78c221-2307-4756-9635-0dd9e254f14d@i3g2000hsf.googlegroups.com>
> I also happen not to like doing
>   (if (not (null x)) y z)

Neither do I which is why I write it as:

(if (pair? x) y z)

> Personally, I've never had a problem with, and have always been a
> little annoyed with, the decision of Scheme to separate #f and ().

why?
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <f291a321-fddd-4a04-819e-17243b8dd757@a35g2000prf.googlegroups.com>
On 19 dic, 04:05, Kent M Pitman <······@nhplace.com> wrote:
> If you make () and #f different, then you
> have to have both (member? x y) and (member x y), or you have to write
> (not (null (member x y))) when you want to coerce the latter to the
> former.  If you're someone who just thinks "it's good for people to do
> this extra work", they probably have a job for you in the government
> somewhere making forms for people to fill out.  But one thing I like
> about Lisp, and it goes hand in hand with dynamic typing, is the
> general meta-principle of not having to write an excess amount of text
> to get the effect you want.  And I write things like
>   (do ((x something (cdr x)))
>       ((not x))
>     ...)
> [in those cases where I use DO at all, which isn't a lot these days]
> not because I don't know that x is a list and I should be writing NULL,
> but rather because I happen to like thinking of a shrinking list as
> receding into nothingness.  And for nothing, I use NOT, not NULL.
> I also happen not to like doing
>   (if (not (null x)) y z)
> and generally I just write
>   (if x y z)
> meaning "if x is something then y else z".  Your preference in this
> might differ, and that's ok; I don't assert mine is the only possible
> preference.  But I assert that mine is as valid as yours, and therefore
> that while I understand you don't like this, I don't deny that you have
> a valid point; I merely believe that I also have a valid point.  And
> so the language isn't incoherent for what it does, it's just not the
> same language as you might have designed.
>
> The choice of what to regard as true or false is not something that
> logic can dictate.  It is an arbitrary choice, and one that leads to
> issues almost no matter what you do.
>
> NIL is actually three things:  a symbol, the empty list, and false.
>
> I personally find it a minor nuisance that it's a symbol; I'd rather
> not have the symbol space have a hole in it that way.  It would work
> for me if the empty list and false were the same, but neither was the
> symbol NIL.  But it wouldn't be compatible, and it's so easy to
> overcome that it's hardly worth mentioning.  Just shadowing NIL gets
> you out of most of the problem.
>
> Personally, I've never had a problem with, and have always been a
> little annoyed with, the decision of Scheme to separate #f and ().
> It's a fine experiment to have tried, and their community seems happy
> with it, but I'm glad it wasn't our CL community that tried it.  The
> CL community is more "pluralistic" than the Scheme community, and I
> think it would not have been successful for us.
>
> Btw, I think what makes NIL as a symbol wrong is not the invading of the
> symbol space, it's the choice of the string "NIL" as the base case.
> It looks ok visually in simple examples but it's really pretty dumb.
> I wouldn't have been bothered if || (the symbol that had no characters)
> were a false value, nor probably even if it were _the_ false value.
> It's a bit ugly to look at, but it could have had some other syntax, #f
> or #n some such, to mark it better.
>
> But I would not have thrust my preference on someone else by
> suggesting the language should change incompatibly to suit my personal
> whims or interests in experimentation.  If I were going to experiment,
> I'd get my own language where people could voluntarily join up if they
> liked what I was doing.  My problem with changing standards in general
> is not that I'm anti-change, I'm anti-forced-change.  The world is too
> big and complicated and unsynchronized to work that way these days.

Your point of view is of course valid (and I am no one to judge it),
but this is rather extrange. I ear a lot of time that a language
should encourage good programming practices, to be clear, and, at the
same time, practical. I thought that CL was such a language when I
started up to learn it some years ago. But found some "paricularities"
I still dislike, some of them are, for example:
- funcall and apply, when the direct syntax of scheme seems to be
easier and more practical (yes, I know the implications of having
separete symbol tables for functions and variables, but still think
that the scheme aproach is better).
- dinamic scope (with defvar, etc), which is an easy way to introduce
bugs.
- the nil behavior
- the arbitrarity in the order and the way that some standard funtion
takes their parameter
- the way the variables types are declares, etc
- asdf

But Scheme lacks some of the features I like from CL, like CLOS, AMOP,
deftype, setf functions, a huge standard library, etc...
From: Barry Margolin
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <barmar-821FE3.20191819122007@comcast.dca.giganews.com>
In article 
<····································@a35g2000prf.googlegroups.com>,
 Javier <·······@gmail.com> wrote:

> But found some "paricularities"
> I still dislike, some of them are, for example:
> - funcall and apply, when the direct syntax of scheme seems to be
> easier and more practical (yes, I know the implications of having
> separete symbol tables for functions and variables, but still think
> that the scheme aproach is better).

Scheme has apply, just not funcall.  You need apply to tell it to spread 
the arguments.

> - dinamic scope (with defvar, etc), which is an easy way to introduce
> bugs.
> - the nil behavior
> - the arbitrarity in the order and the way that some standard funtion
> takes their parameter
> - the way the variables types are declares, etc

Most of these can probably be attributed to historic baggage.  Common 
Lisp did not start from scratch, it was designed to be an incremental 
evolution of the popular Lisp dialects of the time, Maclisp and Zetalisp 
in particular.

As long as it's used carefully, dynamic scope is a very powerful 
technique.  Consider the *PRINT-xxx* variables -- isn't it easier to 
just bind them around a section of code than to arrange for every 
function to take extra parameters that they will pass on, eventually to 
be used when calling printing functions?  But perhaps if we were doing 
this over we might use use a macro like WITH-PRINT-OPTIONS.  This would 
assign to global variables, and use UNWIND-PROTECT to revert them, so 
that there would be a clear distinction between the syntax used to 
control printing and ordinary variable binding.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <803416bd-f474-438b-b44f-85b9d54a42ce@n20g2000hsh.googlegroups.com>
On 20 dic, 02:19, Barry Margolin <······@alum.mit.edu> wrote:
> In article
> <····································@a35g2000prf.googlegroups.com>,
>
>  Javier <·······@gmail.com> wrote:
> > But found some "paricularities"
> > I still dislike, some of them are, for example:
> > - funcall and apply, when the direct syntax of scheme seems to be
> > easier and more practical (yes, I know the implications of having
> > separete symbol tables for functions and variables, but still think
> > that the scheme aproach is better).
>
> Scheme has apply, just not funcall.  You need apply to tell it to spread
> the arguments.
>
> > - dinamic scope (with defvar, etc), which is an easy way to introduce
> > bugs.
> > - the nil behavior
> > - the arbitrarity in the order and the way that some standard funtion
> > takes their parameter
> > - the way the variables types are declares, etc
>
> Most of these can probably be attributed to historic baggage.  Common
> Lisp did not start from scratch, it was designed to be an incremental
> evolution of the popular Lisp dialects of the time, Maclisp and Zetalisp
> in particular.
>
> As long as it's used carefully, dynamic scope is a very powerful
> technique.  Consider the *PRINT-xxx* variables -- isn't it easier to
> just bind them around a section of code than to arrange for every
> function to take extra parameters that they will pass on, eventually to
> be used when calling printing functions?  But perhaps if we were doing
> this over we might use use a macro like WITH-PRINT-OPTIONS.  This would
> assign to global variables, and use UNWIND-PROTECT to revert them, so
> that there would be a clear distinction between the syntax used to
> control printing and ordinary variable binding.

I never used such variables except *PRINT-CIRCLE*, so I have some
questions:

1.- Couldn't we use lexical scope for such variables?
2.- Are not optional parameters a posible solution for the problem you
stated?
3.- Even if you mind writing that optional parameters, I think there
would be ways of avoiding such parameters, writing some macros. For
example:

(with-print-circle
  (print some-circle-list))

which may expand:

(print some-circle-list :print-circle t)

This would complicate the implementation of printing function, but
would avoid the inherents problems of dynamic scope, I think.
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <usl1xnz5r.fsf@nhplace.com>
Javier <·······@gmail.com> writes:

> I never used such variables except *PRINT-CIRCLE*, so I have some
> questions:
> 
> 1.- Couldn't we use lexical scope for such variables?

I assume by lexical you don't mean 

  (let ((print-circle t))
    (foo))

since I suspect you realize that the whole point of lexical variables is
not to allow them to cross a function call boundary.  I'm going to guess
that by lexical you mean "explicit argument passing" as in

 (defun foo (print-circle-preference) 
   ... (your-print x :print-circle print-circle-preference) ...)

There are several reasons this isn't done, but the main one is that if
you have a heavily recursive program, you don't have to pass it at
every function call.  This saves a great many "stack pushes" during
function calls to functions that don't need to carry the data flow and
are only carrying it because some caller farther in will need it.  It
is more efficient because it optimizes infrequently used things.

A huge number of programs do printing and if they all had to carry
this information, it would be quite tricky.  By omitting the arguments,
all of those intermediate callers that are not doing the printing don't
have to know there is dataflow on this point.  That makes writing, 
modifying, and calling those programs easier.

Part of the problem, too, is that there are many of these option
variables and you'd have to pass them all.  If you passed them as a
structure, like a drawing pen is done, that might work.  But it makes
hard to bind a single element locally, you have to cons a whole extra
block of values to pass whenever you change modes.

And, incidentally, the existing mechanism also means that
interactively for testing you can just set options according to your
preference for debugging; and yet you can wrap your program later for
production use with something that assures the settings are set to
something useful and reliable for production use.

> 2.- Are not optional parameters a posible solution for the problem you
> stated?

I think I've covered this above.  Let me know if not.

> 3.- Even if you mind writing that optional parameters, I think there
> would be ways of avoiding such parameters, writing some macros. For
> example:
> 
> (with-print-circle
>   (print some-circle-list))
>
> which may expand:
> 
> (print some-circle-list :print-circle t)
> 
> This would complicate the implementation of printing function, but
> would avoid the inherents problems of dynamic scope, I think.

(defmacro with-print-circle (&body forms)
  `(let ((*print-circle* t))
     ,@forms))

Or maybe I'm not seeing what problem you're trying to solve.
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fkdiqm$sn5$1@news.net.uni-c.dk>
Den Wed, 19 Dec 2007 20:04:26 -0800 skrev Javier:

>> > - dinamic scope (with defvar, etc), which is an easy way to introduce
>> > bugs.

[snip]

>> As long as it's used carefully, dynamic scope is a very powerful
>> technique.  Consider the *PRINT-xxx* variables -- isn't it easier to
>> just bind them around a section of code than to arrange for every
>> function to take extra parameters that they will pass on, eventually to
>> be used when calling printing functions?  But perhaps if we were doing
>> this over we might use use a macro like WITH-PRINT-OPTIONS.  This would
>> assign to global variables, and use UNWIND-PROTECT to revert them, so
>> that there would be a clear distinction between the syntax used to
>> control printing and ordinary variable binding.
> 
> I never used such variables except *PRINT-CIRCLE*, so I have some
> questions:
> 
> 1.- Couldn't we use lexical scope for such variables? 

You don't really understand lexical scoping, do you?

> 2.- Are not optional parameters a posible solution for the problem you 
> stated?
> 3.- Even if you mind writing that optional parameters, I think there
> would be ways of avoiding such parameters, writing some macros. For
> example:
> 
> (with-print-circle
>   (print some-circle-list))
>
> which may expand:
> 
> (print some-circle-list :print-circle t)

And that would buy you what exactly? More typing and you still need to 
pass the parameters down the call stack, which is the point here.

> This would complicate the implementation of printing function, but would
> avoid the inherents problems of dynamic scope, I think.

"Inherent problems"? There are no inherent problems with special 
variables, as long as you apply them properly. Having only lexical 
variables is no better than having only specials, it leads to ugly warts 
and hacks because neither covers 100% of legitimate scenarios you might 
find yourself in. I find more inherent problems in your thinking that for 
every possible problem there's exactly one perfect solution and 
everything else is necessarily a flaw.

Cheers,
Maciej
From: Rob Warnock
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <QuCdneTH3PhiQvTanZ2dnUVZ_q3inZ2d@speakeasy.net>
Barry Margolin  <······@alum.mit.edu> wrote:
+---------------
| Scheme has apply, just not funcall.
| You need apply to tell it to spread the arguments.
+---------------

Which is why, way back when I was still going back & forth
between Scheme & CL, I had this in my Scheme toolbox:

    (define (funcall func . rest)
      (apply func rest))

;-}  ;-}


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <uwsranj2t.fsf@nhplace.com>
Javier <·······@gmail.com> writes:

> I still dislike, some of them are, for example:

I've edited out some of the ones that I had no comment on.  But I had
comments/questions about a few...

> - dinamic scope (with defvar, etc), which is an easy way to introduce
> bugs.

If you always use *...* around your special (dynamic) variables, it's 
very hard to make a mistake, and many compilers will warn you when you
do something wrong.

> - the arbitrarity in the order and the way that some standard funtion
> takes their parameter

I'm curious what you mean by this--you mean like GETHASH?

> - the way the variables types are declares, etc

I'm not sure what you mean about that.  Maybe this is something I know
about but don't recognize from your description.  Can you elaborate?

> - asdf

That's not part of the language, so I'm not sure why it's here.
Do you mean the absence of it?

> But Scheme lacks some of the features I like from CL, like CLOS, AMOP,
> deftype, setf functions, a huge standard library, etc...

That may change at some point, but I agree that for now it holds
Scheme back.
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <dce13498-dfa6-4b5a-87a5-71c77098efb2@d27g2000prf.googlegroups.com>
On 20 dic, 04:25, Kent M Pitman <······@nhplace.com> wrote:
> Javier <·······@gmail.com> writes:

> > - dinamic scope (with defvar, etc), which is an easy way to introduce
> > bugs.
>
> If you always use *...* around your special (dynamic) variables, it's
> very hard to make a mistake, and many compilers will warn you when you
> do something wrong.

Well, not only the need of using **, but also the implications that
this thing have. I hope I can express this:
For example, as said before in this thread, I would prefer to use
optional parameters for functions which actually depends on global
variables (like printing funcions using *PRINT-...*) than using the
complicate UNWIND-PROTECT, etc. This a concept which is dificult to
understand at first, and not so easy to remember when you are not a
full time CL developer.
This is one of these things which, in my opinion, are too much
abstract, and, at the same time, not much more practical than
conventional solutions.
CL has other tools which are simpler and can be more apropiate. For
example, optional parameters are nice. In a function like print, one
would simple use an optional parameter like :print-circle to indicate
that we want to print lists which are circular. Or even a global
variable which truly indicate the default port to which print
something, and an optional parameter like :print-to to indicate an
alternative port.


> > - the arbitrarity in the order and the way that some standard funtion
> > takes their parameter
>
> I'm curious what you mean by this--you mean like GETHASH?

Yes, for example. And how make-instance behaves: (make-instance 'my-
class) instead of (make-instance my-clas) or even (make-my-class).

>
> > - the way the variables types are declares, etc
>
> I'm not sure what you mean about that.  Maybe this is something I know
> about but don't recognize from your description.  Can you elaborate?

Yes, sorry for my english.
For example, instead of:
(defun my-fun (a b)
  (declare (fixnum a) (fixnum b))
  ...)

something like:
(defun my-fun (a:fixnum b:fixnum)
  ...)

If you have got a big program in which you have to declare a lot of
variables and arguments, the declare statement is very unplesant.

>
> > - asdf
>
> That's not part of the language, so I'm not sure why it's here.
> Do you mean the absence of it?

The difficulty to use it. It is not part of the language, but it is
the standard package manager.
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <ulk7phfya.fsf@nhplace.com>
Javier <·······@gmail.com> writes:

> For example, as said before in this thread, I would prefer to use
> optional parameters for functions which actually depends on global
> variables (like printing funcions using *PRINT-...*) than using the
> complicate UNWIND-PROTECT, etc.

Maybe I'm misunderstanding you, but you aren't generally supposed to
use UNWIND-PROTECT for managing the print control variables, nor any
special variable.  You can and should use LET to create dynamic bindings.
In fact, UNWIND-PROTECT will not do what you want under multitasking.

 (let ((*print-base* 8) (*print-radix* nil))
   (print 32)
   (let ((*print-radix* t))
     (print 32)))

  40
  #o40
  => 32

There is a protocol for the WRITE function that takes keyworded
arguments so you don't have to bind those variables if you don't want
to.

 (write 32 :base 8 :radix t)
 #o40
 => 32

> This a concept which is dificult to understand at first, and not so
> easy to remember when you are not a full time CL developer.

I don't think UNWIND-PROTECT should be hard to understand for the things
it's intended for.  But this is not one of them.

> This is one of these things which, in my opinion, are too much
> abstract, and, at the same time, not much more practical than
> conventional solutions.
> CL has other tools which are simpler and can be more apropiate. For
> example, optional parameters are nice. In a function like print, one
> would simple use an optional parameter like :print-circle to indicate
> that we want to print lists which are circular.

Look at the arguments to WRITE.  Perhaps it's what you want.

> Or even a global
> variable which truly indicate the default port to which print
> something,

*standard-output*

> and an optional parameter like :print-to to indicate an
> alternative port.

That's exactly. what the stream argument to the I/O functions does.

> > > - the arbitrarity in the order and the way that some standard funtion
> > > takes their parameter
> >
> > I'm curious what you mean by this--you mean like GETHASH?
> 
> Yes, for example.

As someone noted, it's a point of view thing whether gethash associates
a key with a table or a table with a key.  That is, in the case of
 (get 'x 'y)
X has a property named Y.  You can think of GETHASH as generating a kind
of property so that
 (defvar *y-property* (make-hash-table))
 (gethash 'x *y-property*)
feels like GET.

> And how make-instance behaves: (make-instance 'my-
> class) instead of (make-instance my-clas) or even (make-my-class).

If you prefer, you can do 
 (let ((my-class (find-class 'my-class)))
   (make-instance my-class))
The API that uses the symbols is just a convenience (which most people like).

> > > - the way the variables types are declares, etc
> >
> > I'm not sure what you mean about that.  Maybe this is something I know
> > about but don't recognize from your description.  Can you elaborate?
> 
> Yes, sorry for my english.

It's not a problem--you're doing just great with English.  No need to
apologize.

A veces, he pasado muchas horas en seleccionar precisamente las
palabras correctas para cualquier texto que escribo en espa�ol (y aun
m�s tiempo en portugu�s, que hablo bastante peor que el espa�ol).  Por
eso, me debes creer que entiendo intimamente la dificultad y creo que
todos aqu� te agradecemos tu esfuerzo en poner todo en ingl�s.  No me
causar�a ning�n problema leer lo que quieres decir espa�ol, pero como
el newsgroup est� acostumbrado hablar en ingl�s, supongo que no hay
mucho remedio.  Me puede escribir directamente por email en espa�ol si
llegue al punto en que usar el ingl�s es demasiado doloroso. :)

> For example, instead of:
> (defun my-fun (a b)
>   (declare (fixnum a) (fixnum b))
>   ...)
> 
> something like:
> (defun my-fun (a:fixnum b:fixnum)
>   ...)
> 
> If you have got a big program in which you have to declare a lot of
> variables and arguments, the declare statement is very unplesant.

Well, first, the part about pairing them as in (fixnum a) (fixnum b) 
can be reduced to just (declare (fixnum a b)) if you want.  And at that
point, it really isn't that far from

  int a, b;

which many languages make you do.  

Or maybe what you're not happy about is just the visual separation
between the binding and the declaration.

In that case, what a lot of people do if they want to associate a type
directly is either to just use DEFMETHOD (and then they get
enforcement of the type as well), as in:

 (defmethod my-fun ((a fixnum) (b fixnum)) ...)

or else you could write macro.  A very simplistic form (that didn't allow
&OPTIONAL, &REST, etc. would look like this:

 (defmacro defun-typed (name bindings &body forms)
   (let ((vars  (mapcar #'car bindings))
         (types (mapcar #'cadr bindings)))
     `(defun ,name ,vars
        (declare ,@(mapcar #'(lambda (var type) `(type ,type ,var))
                           vars
                           types))
        ,@forms)))

 (macroexpand-1 '(defun-typed foo ((x integer) (y float)) (+ x y)))

 => (DEFUN FOO (X Y) (DECLARE (TYPE INTEGER X) (TYPE FLOAT Y)) (+ X Y))

> > > - asdf
> >
> > That's not part of the language, so I'm not sure why it's here.
> > Do you mean the absence of it?
> 
> The difficulty to use it. It is not part of the language, but it is
> the standard package manager.

It's one of them.

(I have my own I should publish, I suppose.  I like it, but no one else
knows about it, so no one uses it... Mine is more like what Java does
in certain ways.  But there are others that are published--so look around
if you don't like asdf.)
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <34bdd772-7335-45c0-9eba-03e26678d3af@e23g2000prf.googlegroups.com>
On 20 dic, 10:29, Kent M Pitman <······@nhplace.com> wrote:
> Javier <·······@gmail.com> writes:
> > For example, as said before in this thread, I would prefer to use
> > optional parameters for functions which actually depends on global
> > variables (like printing funcions using *PRINT-...*) than using the
> > complicate UNWIND-PROTECT, etc.
>
> Maybe I'm misunderstanding you, but you aren't generally supposed to
> use UNWIND-PROTECT for managing the print control variables, nor any
> special variable.  You can and should use LET to create dynamic bindings.
> In fact, UNWIND-PROTECT will not do what you want under multitasking.
>
>  (let ((*print-base* 8) (*print-radix* nil))
>    (print 32)
>    (let ((*print-radix* t))
>      (print 32)))
>
>   40
>   #o40
>   => 32
>
> There is a protocol for the WRITE function that takes keyworded
> arguments so you don't have to bind those variables if you don't want
> to.
>
>  (write 32 :base 8 :radix t)
>  #o40
>  => 32
>
> > This a concept which is dificult to understand at first, and not so
> > easy to remember when you are not a full time CL developer.
>
> I don't think UNWIND-PROTECT should be hard to understand for the things
> it's intended for.  But this is not one of them.
>
> > This is one of these things which, in my opinion, are too much
> > abstract, and, at the same time, not much more practical than
> > conventional solutions.
> > CL has other tools which are simpler and can be more apropiate. For
> > example, optional parameters are nice. In a function like print, one
> > would simple use an optional parameter like :print-circle to indicate
> > that we want to print lists which are circular.
>
> Look at the arguments to WRITE.  Perhaps it's what you want.
>
> > Or even a global
> > variable which truly indicate the default port to which print
> > something,
>
> *standard-output*
>
> > and an optional parameter like :print-to to indicate an
> > alternative port.
>
> That's exactly. what the stream argument to the I/O functions does.
>
> > > > - the arbitrarity in the order and the way that some standard funtion
> > > > takes their parameter
>
> > > I'm curious what you mean by this--you mean like GETHASH?
>
> > Yes, for example.
>
> As someone noted, it's a point of view thing whether gethash associates
> a key with a table or a table with a key.  That is, in the case of
>  (get 'x 'y)
> X has a property named Y.  You can think of GETHASH as generating a kind
> of property so that
>  (defvar *y-property* (make-hash-table))
>  (gethash 'x *y-property*)
> feels like GET.
>
> > And how make-instance behaves: (make-instance 'my-
> > class) instead of (make-instance my-clas) or even (make-my-class).
>
> If you prefer, you can do
>  (let ((my-class (find-class 'my-class)))
>    (make-instance my-class))
> The API that uses the symbols is just a convenience (which most people like).
>
> > > > - the way the variables types are declares, etc
>
> > > I'm not sure what you mean about that.  Maybe this is something I know
> > > about but don't recognize from your description.  Can you elaborate?
>
> > Yes, sorry for my english.
>
> It's not a problem--you're doing just great with English.  No need to
> apologize.
>
> A veces, he pasado muchas horas en seleccionar precisamente las
> palabras correctas para cualquier texto que escribo en español (y aun
> más tiempo en portugués, que hablo bastante peor que el español).  Por
> eso, me debes creer que entiendo intimamente la dificultad y creo que
> todos aquí te agradecemos tu esfuerzo en poner todo en inglés.  No me
> causaría ningún problema leer lo que quieres decir español, pero como
> el newsgroup está acostumbrado hablar en inglés, supongo que no hay
> mucho remedio.  Me puede escribir directamente por email en español si
> llegue al punto en que usar el inglés es demasiado doloroso. :)
>
> > For example, instead of:
> > (defun my-fun (a b)
> >   (declare (fixnum a) (fixnum b))
> >   ...)
>
> > something like:
> > (defun my-fun (a:fixnum b:fixnum)
> >   ...)
>
> > If you have got a big program in which you have to declare a lot of
> > variables and arguments, the declare statement is very unplesant.
>
> Well, first, the part about pairing them as in (fixnum a) (fixnum b)
> can be reduced to just (declare (fixnum a b)) if you want.  And at that
> point, it really isn't that far from
>
>   int a, b;
>
> which many languages make you do.
>
> Or maybe what you're not happy about is just the visual separation
> between the binding and the declaration.
>
> In that case, what a lot of people do if they want to associate a type
> directly is either to just use DEFMETHOD (and then they get
> enforcement of the type as well), as in:
>
>  (defmethod my-fun ((a fixnum) (b fixnum)) ...)
>
> or else you could write macro.  A very simplistic form (that didn't allow
> &OPTIONAL, &REST, etc. would look like this:
>
>  (defmacro defun-typed (name bindings &body forms)
>    (let ((vars  (mapcar #'car bindings))
>          (types (mapcar #'cadr bindings)))
>      `(defun ,name ,vars
>         (declare ,@(mapcar #'(lambda (var type) `(type ,type ,var))
>                            vars
>                            types))
>         ,@forms)))
>
>  (macroexpand-1 '(defun-typed foo ((x integer) (y float)) (+ x y)))
>
>  => (DEFUN FOO (X Y) (DECLARE (TYPE INTEGER X) (TYPE FLOAT Y)) (+ X Y))
>
> > > > - asdf
>
> > > That's not part of the language, so I'm not sure why it's here.
> > > Do you mean the absence of it?
>
> > The difficulty to use it. It is not part of the language, but it is
> > the standard package manager.
>
> It's one of them.
>
> (I have my own I should publish, I suppose.  I like it, but no one else
> knows about it, so no one uses it... Mine is more like what Java does
> in certain ways.  But there are others that are published--so look around
> if you don't like asdf.)

It is evident that you have a solution for every problem I may have
about CL. Well, CL is big, it is not a surprise. What is a surprise is
to find someone here which explains everything not doing personal
disqualification.
I have no comment for what you have said, just because I understand
that you are right, and I know very little, about CL.

Con respecto a mi inglés, te agradezco el apoyo y las palabras que me
has dedicado en mi lengua materna, el español. Te envío un correo por
si te apeteciera charlar.
From: Geoff Wozniak
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fkdncv$s9q$1@aioe.org>
On 2007-12-20 00:03:25 -0500, Javier <·······@gmail.com> said:

> Yes, for example. And how make-instance behaves: (make-instance 'my-
> class) instead of (make-instance my-clas) or even (make-my-class).

If you want to have something akin to MAKE-MY-CLASS (like what 
DEFSTRUCT does), it's easy to define a function to do it.

(defun make-my-class (&rest initargs)
  (apply #'make-instance 'my-class initargs))

And, as I'm sure you'll notice is a common theme in the advice you're 
receiving, you can make a macro to define this function when you define 
the class.  Something like,

(defmacro my-defclass (name superclasses slots &optional options)
  (let ((initargs (gensym "INITARGS-")))
    `(progn
       (defclass ,name ,superclasses ,slots ,@(when options (list options)))
       (defun ,(intern (format nil "MAKE-~S" name)) (&rest ,initargs)
           (apply #'make-instance ',name ,initargs)))))


You might have to be a bit more careful interning the symbol.
From: Nicolas Neuss
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <87odcl3f0k.fsf@ma-patru.mathematik.uni-karlsruhe.de>
Javier <·······@gmail.com> writes:

> ...

May I ask how many lines of Scheme code you programmed yourself?  And how
many lines of CL code?  I have the impression that many of your objections
are only due to lack in experience in both languages.  I had some of your
feelings when I started programming in Scheme, and got angry about Scheme
maybe 50.000 Scheme lines later.  I switched to Common Lisp at this point,
living happily since then (having programmed maybe 100.000 lines of CL
code now).

Nicolas
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <20e836dd-6c61-4f94-840e-f02fd74e32dd@x69g2000hsx.googlegroups.com>
On 20 dic, 10:13, Nicolas Neuss <········@math.uni-karlsruhe.de>
wrote:
> Javier <·······@gmail.com> writes:
> > ...
>
> May I ask how many lines of Scheme code you programmed yourself?  And how
> many lines of CL code?  I have the impression that many of your objections
> are only due to lack in experience in both languages.  I had some of your
> feelings when I started programming in Scheme, and got angry about Scheme
> maybe 50.000 Scheme lines later.  I switched to Common Lisp at this point,
> living happily since then (having programmed maybe 100.000 lines of CL
> code now).

I agree with this. My fault is not having a big project for using CL.
I worked on such projects in other languages in the past.
I've been using CL directly, although I learned CL and Scheme at the
same time.
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fkdjfc$sn6$1@news.net.uni-c.dk>
Den Wed, 19 Dec 2007 21:03:25 -0800 skrev Javier:

>> > - the arbitrarity in the order and the way that some standard funtion
>> > takes their parameter
>>
>> I'm curious what you mean by this--you mean like GETHASH?
> 
> Yes, for example. And how make-instance behaves: (make-instance 'my-
> class) instead of (make-instance my-clas) or even (make-my-class).

You are aware of the difference between a symbol and its value as a 
variable, right? How exactly do you see it working differently?

Maciej
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fkdjfc$sn5$2@news.net.uni-c.dk>
Den Wed, 19 Dec 2007 21:03:25 -0800 skrev Javier:

>> > - the arbitrarity in the order and the way that some standard funtion
>> > takes their parameter
>>
>> I'm curious what you mean by this--you mean like GETHASH?
> 
> Yes, for example. And how make-instance behaves: (make-instance 'my-
> class) instead of (make-instance my-clas) or even (make-my-class).

You are aware of the difference between a symbol and its value as a 
variable, right? How exactly do you see it working differently?

Maciej
From: lin8080
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <476AD03A.CF8F89AC@freenet.de>
Some comments:

copy from init.lisp:variables
   *macroexpand-hook* *gensym-counter* *package* *modules*
*random-state*
   + ++ +++ - * ** *** / // /// *standard-input*
   *standard-output* *error-output* *query-io* *debug-io* *terminal-io*
   *trace-output* *read-base* *read-suppress* *read-eval* *readtable*
   *print-readably* *print-escape* *print-pretty* *print-circle*
*print-base*
   *print-radix* *print-case* *print-gensym* *print-level*
*print-length*
   *print-lines* *print-miser-width* *print-pprint-dispatch*
*print-array*
   *print-right-margin* *read-default-float-format*
*default-pathname-defaults*
   *load-verbose* *load-print* *load-pathname* *load-truename*
   *compile-verbose* *compile-print* *compile-file-pathname*
   *compile-file-truename* *features*

Are that all? No. Who can keep that in mind? No one. Does the number
rise? yes.

For example. Take a linux-system, login as root and change values in the
kernel-settings. You will see options you never expect that they are
there.
Now what about a lisp-system? Place all *vars* in a seperate config
file? Make simple guiable click-orgies? Press the whole stuff in 24+
lines without a scroll bar? What if you have a linux-kernel-like
config-overview?
And what if you use this linux-kernel-output as an overview for your
selfmade classes, packages and whatever fits in?
What will you call an easy-to-use working platform?



> > If you always use *...* around your special (dynamic) variables, it's
> > very hard to make a mistake, and many compilers will warn you when you
> > do something wrong.

> Well, not only the need of using **, but also the implications that
> this thing have. 

....
-----------------------------------------------
> For example, instead of:
> (defun my-fun (a b)
>   (declare (fixnum a) (fixnum b))
>   ...)
> something like:
> (defun my-fun (a:fixnum b:fixnum)
>   ...)

... but which one is more lispy?
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sum62F1b7c1rU1@mid.individual.net>
Javier wrote:

> I ear a lot of time that a language
> should encourage good programming practices, to be clear, and, at the
> same time, practical. I thought that CL was such a language when I
> started up to learn it some years ago.

CL doesn't encode any specific opinion about what would or would not be 
a good programming style. It just offers useful language constructs. 
You're on your own here.

This is a good opportunity to cite one of my favorite quotes:

"No amount of language design can _force_ a programmer to write clear 
programs. [...] The emphasis should not be on eliminating "bad" language 
constructs, but on discovering or inventing helpful ones." - Guy Steele 
and Gerald Sussman


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <872df99d-f4b1-4600-98cf-5a41fac8a2e8@q77g2000hsh.googlegroups.com>
On 20 dic, 09:07, Pascal Costanza <····@p-cos.net> wrote:
> Javier wrote:
> > I ear a lot of time that a language
> > should encourage good programming practices, to be clear, and, at the
> > same time, practical. I thought that CL was such a language when I
> > started up to learn it some years ago.
>
> CL doesn't encode any specific opinion about what would or would not be
> a good programming style. It just offers useful language constructs.
> You're on your own here.

I agree with this.
But see what had happened with Perl and what is happening with C++
(they where created with the intention of offering useful language
construct)... and why Java and C# has succeed even being less
powerful.
But I don't want to be polemic on this, really.
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5svsu9F1ak5e5U1@mid.individual.net>
Javier wrote:
> On 20 dic, 09:07, Pascal Costanza <····@p-cos.net> wrote:
>> Javier wrote:
>>> I ear a lot of time that a language
>>> should encourage good programming practices, to be clear, and, at the
>>> same time, practical. I thought that CL was such a language when I
>>> started up to learn it some years ago.
>> CL doesn't encode any specific opinion about what would or would not be
>> a good programming style. It just offers useful language constructs.
>> You're on your own here.
> 
> I agree with this.
> But see what had happened with Perl and what is happening with C++
> (they where created with the intention of offering useful language
> construct)... and why Java and C# has succeed even being less
> powerful.
> But I don't want to be polemic on this, really.

No need to be polemic.

Languages like Common Lisp and C++ are targeted at expert users, 
languages like Java and C# at 'average' programmers. It's good that 
there are different languages for different target groups.

Personally, I have doubts that targeting 'average' programmers is a good 
idea, but that's a different discussion. And if you look at Java and C# 
nowadays, they have actually become quite complicated as well, and are 
not easy to master by 'average' programmers anymore - without the 
rewards that the complexities in languages like Common Lisp and C++ give 
you from the start.

Yes, simpler languages are typically much more attractive in the 
beginning. However, they rarely stay simple in the long run. So maybe 
it's better to address the complex issues from the start, and not 
pretend they can be replaced by simpler solutions.

I can't judge Perl, because I don't know it well enough.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: tim Josling
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <13mlh5u328b3i08@corp.supernews.com>
On Thu, 20 Dec 2007 20:08:57 +0100, Pascal Costanza wrote:

> Javier wrote:
> ...
> Personally, I have doubts that targeting 'average' programmers is a good 
> idea, but that's a different discussion. And if you look at Java and C# 
> nowadays, they have actually become quite complicated as well, and are 
> not easy to master by 'average' programmers anymore - without the 
> rewards that the complexities in languages like Common Lisp and C++ give 
> you from the start.
> ... 
> Pascal
>

"Java in a Nutshell" for Java 1.5 - there will be more in Java 1.6 and 1.7
is coming out soon - is over 1,000 pages. And this does not include the
many frameworks and tools that you need to use. The early promise of a
low-cognitive-load language is now a lost cause.

Ruby on contrast seems to deliver on this promise, and it is a very
powerful language as well.

Tim Josling
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fkeir9$47p$2@news.net.uni-c.dk>
Den Thu, 20 Dec 2007 19:38:38 +0000 skrev tim Josling:

>> Personally, I have doubts that targeting 'average' programmers is a
>> good idea, but that's a different discussion. And if you look at Java
>> and C# nowadays, they have actually become quite complicated as well,
>> and are not easy to master by 'average' programmers anymore - without
>> the rewards that the complexities in languages like Common Lisp and C++
>> give you from the start.
>>
> "Java in a Nutshell" for Java 1.5 - there will be more in Java 1.6 and
> 1.7 is coming out soon - is over 1,000 pages. And this does not include
> the many frameworks and tools that you need to use. The early promise of
> a low-cognitive-load language is now a lost cause.

Oh yeah, I remember having a Java DB project assigned (fortunately, the 
only Java project I've ever had to do at my Uni), and trying to find the 
right libraries was a nightmare. Before you're allowed to know what XYZ 
does, you need to learn about ABC and JKL, and at one point you 
inevitably arrive to PQR which again refers you to XYZ. That was 
incredibly frustrating.

> Ruby on contrast seems to deliver on this promise, and it is a very
> powerful language as well.

I have only used Ruby in the context of Rails, but it didn't leave a good 
impression. It yields itself too easily to magic (partly because it lacks 
real macros, partly because magic is so cool and so easy), and then fails 
to have enough tools to let you control magic, which is not very fun.

Cheers,
Maciej
From: tim Josling
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <13mm6fgnk7ice35@corp.supernews.com>
On Thu, 20 Dec 2007 20:20:57 +0000, Maciej Katafiasz wrote:

> I have only used Ruby in the context of Rails, but it didn't leave a good 
> impression. It yields itself too easily to magic (partly because it lacks 
> real macros, partly because magic is so cool and so easy), and then fails 
> to have enough tools to let you control magic, which is not very fun.
> 
> Cheers,
> Maciej

Obviously it lacks macros and parentheses with all that means. My comments
were meant to be in the context of a possible Java replacement.

It is also somewhat immature in the tools and performance areas.

Regards,
Tim Josling
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fkeibf$47p$1@news.net.uni-c.dk>
Den Thu, 20 Dec 2007 20:08:57 +0100 skrev Pascal Costanza:

>>> CL doesn't encode any specific opinion about what would or would not
>>> be a good programming style. It just offers useful language
>>> constructs. You're on your own here.
>> 
>> I agree with this.
>> But see what had happened with Perl and what is happening with C++
>> (they where created with the intention of offering useful language
>> construct)... and why Java and C# has succeed even being less powerful.
>> But I don't want to be polemic on this, really.
> 
> No need to be polemic.
> 
> Languages like Common Lisp and C++ are targeted at expert users,
> languages like Java and C# at 'average' programmers. It's good that
> there are different languages for different target groups.
> 
> Personally, I have doubts that targeting 'average' programmers is a good
> idea, but that's a different discussion. And if you look at Java and C#
> nowadays, they have actually become quite complicated as well, and are
> not easy to master by 'average' programmers anymore - without the
> rewards that the complexities in languages like Common Lisp and C++ give
> you from the start.

I agree fully about not targeting "average" ones, but it's arguable 
whether C++ actually gives you anything in return. It is my firmest 
belief that it doesn't. Certainly nothing on the level you get from CL.

> Yes, simpler languages are typically much more attractive in the
> beginning. However, they rarely stay simple in the long run. So maybe
> it's better to address the complex issues from the start, and not
> pretend they can be replaced by simpler solutions.

Personally I'd classify C++'s complexity management in the same group as 
Java, ie. "oops, all of sudden it got complex". An interesting case is 
Python, which comes from a very different angle, but with similar goals 
of simplicity, and also hits several cases where lack of prior design for 
edge cases can bite badly (a good example being Python's closures, or 
rather the huge list of warts that make them painful to actually use).

Another one is Ruby, which steals a lot from Lisp, but not quite 
everything, and in some cases you end up missing exactly those bits. 
Also, a sometimes very annoying complexity vector is how Ruby allows you 
to poke a lot of internals, but there's really no design to it, no 
documented protocol, not even on the level of what Python does, and then 
when you end up actually needing some pokage, it's very easy to run into 
areas that never happened to be useful to any of the developers, so 
you're left in the cold. In CL the proper way might be frustratingly hard 
to find, but most of the time, it exists.

Cheers,
Maciej
From: Marco Antoniotti
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <b8eac3e0-083a-4eb3-b5dd-378c18f39c37@i3g2000hsf.googlegroups.com>
On Dec 20, 9:12 pm, Maciej Katafiasz <········@gmail.com> wrote:
> Den Thu, 20 Dec 2007 20:08:57 +0100 skrev Pascal Costanza:
>
>
>
> >>> CL doesn't encode any specific opinion about what would or would not
> >>> be a good programming style. It just offers useful language
> >>> constructs. You're on your own here.
>
> >> I agree with this.
> >> But see what had happened with Perl and what is happening with C++
> >> (they where created with the intention of offering useful language
> >> construct)... and why Java and C# has succeed even being less powerful.
> >> But I don't want to be polemic on this, really.
>
> > No need to be polemic.
>
> > Languages like Common Lisp and C++ are targeted at expert users,
> > languages like Java and C# at 'average' programmers. It's good that
> > there are different languages for different target groups.
>
> > Personally, I have doubts that targeting 'average' programmers is a good
> > idea, but that's a different discussion. And if you look at Java and C#
> > nowadays, they have actually become quite complicated as well, and are
> > not easy to master by 'average' programmers anymore - without the
> > rewards that the complexities in languages like Common Lisp and C++ give
> > you from the start.
>
> I agree fully about not targeting "average" ones, but it's arguable
> whether C++ actually gives you anything in return. It is my firmest
> belief that it doesn't. Certainly nothing on the level you get from CL.
>
> > Yes, simpler languages are typically much more attractive in the
> > beginning. However, they rarely stay simple in the long run. So maybe
> > it's better to address the complex issues from the start, and not
> > pretend they can be replaced by simpler solutions.
>
> Personally I'd classify C++'s complexity management in the same group as
> Java, ie. "oops, all of sudden it got complex".

C++ is "more complex" than Java (hence of many other languages) for
sure.  Just think 'const' plus references plus memory management.
OTOH, it seems to me that its design is a marvel of devilish care to
detail.

Cheers

Marco
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fkf15l$8bv$1@news.net.uni-c.dk>
Den Thu, 20 Dec 2007 15:09:09 -0800 skrev Marco Antoniotti:

>> > Personally, I have doubts that targeting 'average' programmers is a
>> > good idea, but that's a different discussion. And if you look at Java
>> > and C# nowadays, they have actually become quite complicated as well,
>> > and are not easy to master by 'average' programmers anymore - without
>> > the rewards that the complexities in languages like Common Lisp and
>> > C++ give you from the start.
>>
>> I agree fully about not targeting "average" ones, but it's arguable
>> whether C++ actually gives you anything in return. It is my firmest
>> belief that it doesn't. Certainly nothing on the level you get from CL.
>>
>> > Yes, simpler languages are typically much more attractive in the
>> > beginning. However, they rarely stay simple in the long run. So maybe
>> > it's better to address the complex issues from the start, and not
>> > pretend they can be replaced by simpler solutions.
>>
>> Personally I'd classify C++'s complexity management in the same group
>> as Java, ie. "oops, all of sudden it got complex".
> 
> C++ is "more complex" than Java (hence of many other languages) for
> sure.  Just think 'const' plus references plus memory management. OTOH,
> it seems to me that its design is a marvel of devilish care to detail.

It is more complex, but it doesn't mean it managed its complexity 
properly. It started as "C with classes", and C is a remarkably simple 
and small language (not to be confused with ease of use). Then C++ just 
grew all sorts of extensions, additions, with all kinds of weird fringe 
cases that certainly weren't designed. One of the nice examples is the 
namespace lookup rules, which were hastily changed very close to the 
final draft, as they suddenly found out there were fatal issues with it. 
Not that the new rules (which have their own name, "Koenig lookup") are 
without their own fatal flaws, there was a nice thread on c.l.c++.m once 
with more details than you could wish for, here:

http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/d9eb5db7019673e0/

'const' is another bitch and a perfect example of why C++ is not a 
language to be used.

Cheers,
Maciej
From: John Thingstad
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <op.t3nvpyimut4oq5@pandora.alfanett.no>
P� Fri, 21 Dec 2007 01:25:25 +0100, skrev Maciej Katafiasz  
<········@gmail.com>:

>
> 'const' is another bitch and a perfect example of why C++ is not a
> language to be used.
>

I found it was best to just avoid supplying const parameters to class  
functions.
Logic dictates const should mean would be that the function dosn't change  
the variable.
But in fact all references also have to also be const which in practice is  
almost never what you want.
Const variables, const functions etc. seem to work OK.

beyond that.. inlining class members wrapped in the class was a really bad  
idea as was seperating header from body. Still I used it sucessfully for  
10 years and it is entirly possible to write large programs in it.

All languages I have encountered have things that annoy me. The trick is  
get past it and just produce code.

--------------
John Thingstad
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <92350b6c-f097-4668-821f-2126eb9aad28@i29g2000prf.googlegroups.com>
On Dec 20, 3:09 pm, Marco Antoniotti <·······@gmail.com> wrote:
> On Dec 20, 9:12 pm, Maciej Katafiasz <········@gmail.com> wrote:
>
>
>
> > Den Thu, 20 Dec 2007 20:08:57 +0100 skrev Pascal Costanza:
>
> > >>> CL doesn't encode any specific opinion about what would or would not
> > >>> be a good programming style. It just offers useful language
> > >>> constructs. You're on your own here.
>
> > >> I agree with this.
> > >> But see what had happened with Perl and what is happening with C++
> > >> (they where created with the intention of offering useful language
> > >> construct)... and why Java and C# has succeed even being less powerful.
> > >> But I don't want to be polemic on this, really.
>
> > > No need to be polemic.
>
> > > Languages like Common Lisp and C++ are targeted at expert users,
> > > languages like Java and C# at 'average' programmers. It's good that
> > > there are different languages for different target groups.
>
> > > Personally, I have doubts that targeting 'average' programmers is a good
> > > idea, but that's a different discussion. And if you look at Java and C#
> > > nowadays, they have actually become quite complicated as well, and are
> > > not easy to master by 'average' programmers anymore - without the
> > > rewards that the complexities in languages like Common Lisp and C++ give
> > > you from the start.
>
> > I agree fully about not targeting "average" ones, but it's arguable
> > whether C++ actually gives you anything in return. It is my firmest
> > belief that it doesn't. Certainly nothing on the level you get from CL.
>
> > > Yes, simpler languages are typically much more attractive in the
> > > beginning. However, they rarely stay simple in the long run. So maybe
> > > it's better to address the complex issues from the start, and not
> > > pretend they can be replaced by simpler solutions.
>
> > Personally I'd classify C++'s complexity management in the same group as
> > Java, ie. "oops, all of sudden it got complex".
>
> C++ is "more complex" than Java (hence of many other languages) for
> sure.  Just think 'const' plus references plus memory management.
> OTOH, it seems to me that its design is a marvel of devilish care to
> detail.

Devilish care to detail?  Dude, all this "modern" C++ style comes out
of using the template system as a compile-time meta-language ... which
is a complete accident.  They paid such attention to detail that they
didn't even realize that they'd designed a complete turing-equivalent
language in their damn template system!
From: Joost Diepenmaat
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <8763ytp1j5.fsf@zeekat.nl>
Pascal Costanza <··@p-cos.net> writes:

> Yes, simpler languages are typically much more attractive in the
> beginning. However, they rarely stay simple in the long run. So maybe
> it's better to address the complex issues from the start, and not
> pretend they can be replaced by simpler solutions.
>
> I can't judge Perl, because I don't know it well enough.

AFAIK perl was never intended to be simple, just easy to get into if you 
knew some shell scripting and a bit of C-like syntax.

Perl offers a lot of power fairly decently up until you get to the
subjects where the language was extended a lot in perl 5 (especially objects
and threads). Perl's OO system is very flexible but the moment you step
up and over the basics (simple hash tables for properties, no
complicated mix-ins/multiple inheritance etc) things get very messy very
quickly. And threads are just plain unusable except in very constrained 
circumstances (for instance, it's nearly impossible to move anything but
basic types between threads).

Some other points are the places where the idiomatic constructs are easy
to grasp even for new coders, but hide so much detail that you have to
learn a lot before you know what's *really* going on, and if you don't,
adapting those idioms slightly can get you into big trouble. (return-
context, type-coercion and prototypes come to mind).

Larry Wall's reasoning has always been that perl should make the simple
things easy and the hard things possible, and IMO he succeeded for the
most part, but /some/ of the hard things are much harder and uglier
than they might have been. 

Of course, it's never been a particulary simple, pretty or consistent 
language to begin with, but it doesn't /actively/ try to prevent you 
from doing things the language wasn't designed to do; but some of the 
solutions will turn out uglier than others. 

Ps: as someone who's used to perl I think current behaviour of NIL as
both false and the empty list perfectly simple, straightforward and 
intuitive :-) 

Joost.
From: Holger Schauer
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <yxzd4t01dw8.fsf@gmx.de>
On 5223 September 1993, Pascal Costanza wrote:
> Languages like Common Lisp and C++ are targeted at expert users,
> languages like Java and C# at 'average' programmers. It's good that
> there are different languages for different target groups.

I'm not sure about there being targets for language designs. I
certainly wouldn't see myself as an expert programmer, but I've used
CL considerably and (a long time ago) messed also somewhat with
C++. Guess what: it's possible to use both languages. I've neither
used Java nor C#, but I'm pretty certain it's possible to use them,
too. But perhaps I'm missing your point, I just can't see what makes
CL a language that's not within (intellectual) reach of Joe
Average. 

> Yes, simpler languages are typically much more attractive in the
> beginning. However, they rarely stay simple in the long run. So maybe
> it's better to address the complex issues from the start, and not
> pretend they can be replaced by simpler solutions.
> I can't judge Perl, because I don't know it well enough.

I use Perl in my day job and some things seem to me to fall into the
category you're describing. For instance, I always need to lookup how
to move hashtables around (which, in my opinion, should be simple
enough, but in Perl you're forced to use references which don't fall
into Perls "simple" category). Joe Average is probably simply going to
use global variables and that's kind of a solution, sure, but it's
going to come at a price.

Now, I don't know what audience Perl is targeting, but it's certainly
easy to pick up (at least if you're having a Unix background).
However, I wouldn't call Perl "simple" or "easy" at all when you get
into more complex issues. Quite by contrast, I find that in CL there
are not many areas that are particularly hard, so perhaps easy/hard
and target audience expert/average might be just different axis to
judge languages. But if so, I'm still interested why CL qualifies as a
language targetting experts.

Holger

-- 
---          http://hillview.bugwriter.net/            ---
Fachbegriffe der Informatik - Einfach erkl�rt
38: Windows 95
       Das Fortran 77 der Benutzungsoberfl�chen
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <ufxxwrqf5.fsf@nhplace.com>
Holger Schauer <··············@gmx.de> writes:

> On 5223 September 1993, Pascal Costanza wrote:
> > Languages like Common Lisp and C++ are targeted at expert users,
> > languages like Java and C# at 'average' programmers. It's good that
> > there are different languages for different target groups.
> 
> I'm not sure about there being targets for language designs.

How could there not be targets other than by people simply ignoring
the fact that such selection does occur?  That's like saying it's
possible to seek a mate without having a target type of person you're
seeking... you can say it.  But when you start to meet the people you
don't want to be with, and to seek others, how can you claim there is
no target type?  In that case, you have no basis for saying why the
status quo was not fine, nor any basis for saying why you need a
process which requires selection.  

Languages either seek to increase their growth (which is to say they
target new groups of people they want to attract) or they don't care
if they grow (which is to say they target the people who already like
what they are, and are not focused on other groups).  But how can you
be in the state where you have no care at all about who you are and
what effect you'll have?  Might as well just flip coins as design such
a system, since it won't matter who uses it or why.

> I certainly wouldn't see myself as an expert programmer, but I've
> used CL considerably and (a long time ago) messed also somewhat with
> C++. Guess what: it's possible to use both languages. I've neither
> used Java nor C#, but I'm pretty certain it's possible to use them,
> too. But perhaps I'm missing your point, I just can't see what makes
> CL a language that's not within (intellectual) reach of Joe Average.

I don't think that was Pascal's point.  I think he more meant that
some languages spend effort adding features that will attract or repel
a particular audience.

As an example, I talked to at least one manager on the Harlequin Dylan
project who told me outright that he was actively making choices to
court the C++ market, and that it didn't matter to him at all (he even
said openly he thought it was a good thing) if it lost him the Lisp
market (which he perceived would scare off the C++ folks).

As another example, I was told COBOL was designed to be programmed by
one group but to allow a manager to look over the shoulder of the
programmer and get a sense for what the programmer was done.

Some languages are highly abstract/mathematical/etc.  That doesn't
make them impossible to use by Joe Average--impossibility is a hard
charge to make.  But I doubt you'll lose money betting that Joe
Average will have less interest in a very mathy/functional language
than a heavily imperative one full of side-effects and special-purpose
bells and whistles.  Whatever your take on languages at the functional
programming end of the world, and whether they are good, the one
indisputable datapoint is that they have not taken over the world.
Languages like PERL, C, Autocad, SED, etc. surely have enormously 
larger installed bases.

You might want to look at
  http://www.nhplace.com/kent/PS/Lambda.html
or, if you're busy, just this section of it:
  http://www.nhplace.com/kent/PS/Lambda.html#thought_experiment
for some other thoughts of mine on the matter of languages as
political party. The paper overall is a bit dated in some ways, but 
I think still makes some useful points.

> > Yes, simpler languages are typically much more attractive in the
> > beginning. However, they rarely stay simple in the long run. So maybe
> > it's better to address the complex issues from the start, and not
> > pretend they can be replaced by simpler solutions.
> > I can't judge Perl, because I don't know it well enough.
> 
> I use Perl in my day job and some things seem to me to fall into the
> category you're describing. For instance, I always need to lookup how
> to move hashtables around (which, in my opinion, should be simple
> enough, but in Perl you're forced to use references which don't fall
> into Perls "simple" category). Joe Average is probably simply going to
> use global variables and that's kind of a solution, sure, but it's
> going to come at a price.
> 
> Now, I don't know what audience Perl is targeting, but it's certainly
> easy to pick up (at least if you're having a Unix background).

It's not targeting the same community as the Scheme crowd is, you can be
sure of that.

> However, I wouldn't call Perl "simple" or "easy" at all when you get
> into more complex issues. Quite by contrast, I find that in CL there
> are not many areas that are particularly hard, so perhaps easy/hard
> and target audience expert/average might be just different axis to
> judge languages.

I agree that these are not necessarily aligned axes.

> But if so, I'm still interested why CL qualifies as a
> language targetting experts.

I'd say if you're hearing this as "disallows people who are not experts"
you are not going to get an answer because this is not the intended sense.

But the thing I'd say in response to what I perceive Pascal to be
saying, and the reason I'd say similar things, is that Lisp provides
more flexibility and fewer imposed constraints than some other
languages.  There are any of a number of features that this might
implicate, from dynamic typing to the multi-paradigm nature of
programming, that are open to abuse by people lacking self-discipline.
But they are also the power of the language.  

Of course, there's good reason to think that all programming requires
more expertise than is commonly acknowledged, so there are some
unexamined premises in this discussion that may make it hard to push
too deeply into it.  We're speaking in generalities here, and most
generalities tend to fall when they are inspected in a more specific,
less general way.
From: Don Geddis
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <87bq8jti86.fsf@geddis.org>
Holger Schauer <··············@gmx.de> wrote on Fri, 21 Dec 2007:
> On 5223 September 1993, Pascal Costanza wrote:
>> Languages like Common Lisp and C++ are targeted at expert users,
>> languages like Java and C# at 'average' programmers.
>
> I just can't see what makes CL a language that's not within (intellectual)
> reach of Joe Average.

Targeting one group isn't the same as prohibiting another.

As to how you target an experience group in language design, it's pretty
easy.  Imagine some feature that is only useful in complex, difficult
situations, but also has the potential to be abused and cause difficult-
to-debug errors if you don't understand it well enough.

A language targeted at "average" programmers will eliminate the proposed
feature, under the justification that some inexperienced programmers might
use it incorrectly, and become confused.  While, at the same time, few such
"average" programmers will ever be in a situation where they can take
advantage of its power.

A language targeted at "expert" programmers, while not being inaccessible to
average programmer, may be filled with such language features: things that
provide a great deal of power, but at the same time may cause confusion or
errors for those new to programming.

In Common Lisp, you might put features like this into such a category:
macros, compiler macros, AMOP, multiple inheritance in CLOS, etc.

The designers of Java knew all about these possible language features, and
deliberately chose to exclude them from Java, not because they thought it
made the language "better" in some objective or technical sense, not because
the features are not useful in some situations, but instead because they were
concerned that "average" or new programmers might become confused by the
features, and/or misuse them and thereby write bad code.

        -- Don
_______________________________________________________________________________
Don Geddis                  http://don.geddis.org/               ···@geddis.org
I wish I could help, but I don't want to.  -- Phoebe (on "Friends")
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5t47faF1aka0dU1@mid.individual.net>
Holger Schauer wrote:
> On 5223 September 1993, Pascal Costanza wrote:
>> Languages like Common Lisp and C++ are targeted at expert users,
>> languages like Java and C# at 'average' programmers. It's good that
>> there are different languages for different target groups.
> 
> I'm not sure about there being targets for language designs. I
> certainly wouldn't see myself as an expert programmer, but I've used
> CL considerably and (a long time ago) messed also somewhat with
> C++. Guess what: it's possible to use both languages. I've neither
> used Java nor C#, but I'm pretty certain it's possible to use them,
> too. But perhaps I'm missing your point, I just can't see what makes
> CL a language that's not within (intellectual) reach of Joe
> Average. 

OK, it didn't get clear from my posting, but I don't believe in the 
notion of 'average' programmers. Yet, many languages are designed with 
the hypothetical 'average' programmer in mind.

As two data points, Java has originally been described with the 
following design goal, among others: "Primary characteristics of the 
Java programming language include a simple language that can be 
programmed without extensive programmer training while being attuned to 
current software practices."

See http://java.sun.com/docs/white/langenv/Intro.doc2.html#349


Common Lisp had the following design goals, among others: "Common Lisp 
culls what experience has shown to be the most useful and understandable 
constructs from not only MacLisp but also Interlisp, other Lisp 
dialects, and other programming languages." and "Common Lisp is a 
descendant of MacLisp, which has traditionally placed emphasis on 
providing system-building tools. Such tools may in turn be used to build 
the user-level packages such as Interlisp provides; these packages are 
not, however, part of the Common Lisp core specification. It is expected 
such packages will be built on top of the Common Lisp core."

See http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node6.html


C# is a direct descendant of Java, so is probably pretty close in its 
design goals. I know from my own experience that it's hard and tedious 
to get things done in Java, and don't expect C# to be that much different.

For the C++ design goals, I have found this link: 
http://www.dmk.com/c++/stroustrup_1986_10.html - what is described there 
matches my impression of C++, which is that you get a number of somewhat 
high-level features, but with the constraint that the constructs are 
always as close to the metal as possible, and that you have to add more 
work to get really high-level. I don't agree with this design goal, I 
think it's the wrong direction for programming language, but it's clear 
that such a goal is targeted more at expert programmers than at 
'average' programmers, in the sense that you really have to be aware 
what the implications of that design goal are.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5suqltF1bj1boU1@mid.individual.net>
Javier wrote:

> But Scheme lacks some of the features I like from CL, like CLOS, AMOP,
> deftype, setf functions, a huge standard library, etc...

Scheme as defined in one of the RnRS reports yes. But each single Scheme 
implementation is typically much more complete than that. You may want 
to take a closer look at single Scheme implementations, maybe you like 
more what you see there...

Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <20c8efa8-4d1f-4ec6-af28-98fed9c38335@d4g2000prg.googlegroups.com>
On Dec 19, 5:03 pm, Javier <·······@gmail.com> wrote:
> Your point of view is of course valid (and I am no one to judge it),

Yours, however, is fucking idiotic.
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <f984132c-7f92-4930-b1e5-0e85653676de@t1g2000pra.googlegroups.com>
On 20 dic, 21:36, Kaz Kylheku <········@gmail.com> wrote:
> On Dec 19, 5:03 pm, Javier <·······@gmail.com> wrote:
>
> > Your point of view is of course valid (and I am no one to judge it),
>
> Yours, however, is fucking idiotic.

You couldn't support not having the last word? Could you?
You must win at any price. I know how people like you are.
Please, forget me.
From: Damien Kick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <13mjrop9p7tqbd2@corp.supernews.com>
Javier wrote:

> Something similar occurs in C, which NULL means 0 for a lot of things.
> But at least in C, NULL is consistent because you know that,
> computationally, it always means 0.

<pause> It's hard to know which of the many FAQs about null pointers 
<http://c-faq.com/null/> is best used here but I chose this one because 
it references _Through the Looking-Glass_.

<blockquote>
Q: This is strange. NULL is guaranteed to be 0, but the null pointer is not?

A: When the term ``null'' or ``NULL'' is casually used, one of several 
things may be meant:

1. The conceptual null pointer, the abstract language concept defined in 
question 5.1. It is implemented with...
2. The internal (or run-time) representation of a null pointer, which 
may or may not be all-bits-0 and which may be different for different 
pointer types. The actual values should be of concern only to compiler 
writers. Authors of C programs never see them, since they use...
3. The null pointer constant, which is a constant integer 0 [footnote] 
(see question 5.2). It is often hidden behind...
4. The NULL macro, which is #defined to be 0 (see question 5.4). 
Finally, as red herrings, we have...
5. The ASCII null character (NUL), which does have all bits zero, but 
has no necessary relation to the null pointer except in name; and...
6. The ``null string,'' which is another name for the empty string (""). 
Using the term ``null string'' can be confusing in C, because an empty 
string involves a null ('\0') character, but not a null pointer, which 
brings us full circle...

In other words, to paraphrase the White Knight's description of his song 
in Through the Looking-Glass, the name of the null pointer is ``0'', but 
the name of the null pointer is called ``NULL'' (and we're not sure what 
the null pointer is).

This document uses the phrase ``null pointer'' (in lower case) for sense 
1, the token ``0'' or the phrase ``null pointer constant'' for sense 3, 
and the capitalized word ``NULL'' for sense 4.[footnote]
</blockquote>
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <78f82e18-2015-41f6-859a-97c4cb152003@r60g2000hsc.googlegroups.com>
On Dec 18, 5:12 am, Javier <·······@gmail.com> wrote:
> vanekl ha escrito:
>
> > The value NIL is not of type CONS.
> >    [Condition of type TYPE-ERROR]
>
> Just one more inconsistence of Common Lisp.
> The more you discover about these inconsistencies, the more you
> discover how much CL sucks.
>
> If the empty list is NIL, then NIL should be of type CONS. For me,
> this should be the logical behavior.

Well, that just means you are pitifully stupid. And that you have poor
reading comprehension, since there has already been a whole thread
about why this isn't a good idea.

Here is a repetition of what has already been said in the thread:

NIL can't be of type CONS because a CONS has a whole bunch of
properties which are not true of NIL.

This means that NIL cannot be substituted in place of a CONS.  It is
simply not a kind of CONS.

For instance (setf (car x) 42) is expected to work if X is a CONS.
However, it blows up if X is NIL, because NIL doesn't have the CAR
slot where the 42 can go.

Since NIL is not a kind of CONS, there is no point in modeling a
subtype relationship between them.
From: Leandro Rios
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <4767dac2$0$1340$834e42db@reader.greatnowhere.com>
Javier escribi�:
> vanekl ha escrito:
> 
>> The value NIL is not of type CONS.
>>    [Condition of type TYPE-ERROR]
> 
> Just one more inconsistence of Common Lisp.
> The more you discover about these inconsistencies, the more you
> discover how much CL sucks.
> 
> If the empty list is NIL, then NIL should be of type CONS. For me,
> this should be the logical behavior.

Did you read the entire thread? If not, please do. If you did, well... 
do it again.

Leandro
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <utzmgszy6.fsf@nhplace.com>
Javier <·······@gmail.com> writes:

> vanekl ha escrito:
> 
> > The value NIL is not of type CONS.
> >    [Condition of type TYPE-ERROR]
> 
> Just one more inconsistence of Common Lisp.
> The more you discover about these inconsistencies, the more you
> discover how much CL sucks.
>
> If the empty list is NIL, then NIL should be of type CONS. For me,
> this should be the logical behavior.

Actually, the design of lists, built recursively from conses, is based
directly on logic.  The CONS datatype exists in most Lisp dialects,
not just Common Lisp; in a few it is called PAIR.  But as the name
PAIR makes clear, NIL (not being a pair) would be an inappropriate
member of the set of all pairs.

You're probably wanting the LIST datatype, which is a union of the
singleton type NULL (which contains only the member element NIL) and
the type CONS (which contains all pairs).

Even lists can have elements you personally probably won't like, from
what you've said here, since it can contain pairs the right [cdr] half
of which do not bottom out at NIL, sometimes called dotted lists.

The concept you want is "proper list", and lisp allows but does not
require you to use those.  I think this is true of most dynamically 
typed dialects of Lisp, to include Scheme, if you count that a Lisp 
dialect (which on some days I do and on some I don't).

If you don't like Common Lisp, that's absolutely fine.  No thing is
universally liked by everyone, and we certainly can't make you like
something.  But please make sure that the premises from which you're
drawing your conclusions are valid before you get too upset about
things.  I think in this case you're just not understanding what the
definition of a Lisp list is.  It's not logically inconsistent in any
way.  There are some things in Lisp that aren't all that logical; but
this really isn't one of them.  There are some things about CL that 
are not general to Lisp, but this isn't one of them either.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <rNOSPAMon-732741.14341618122007@news.gha.chartermi.net>
In article <·············@nhplace.com>,
 Kent M Pitman <······@nhplace.com> wrote:

> Javier <·······@gmail.com> writes:
> 
> > vanekl ha escrito:
> > 
> > > The value NIL is not of type CONS.
> > >    [Condition of type TYPE-ERROR]
> > 
> > Just one more inconsistence of Common Lisp.
> > The more you discover about these inconsistencies, the more you
> > discover how much CL sucks.
> >
> > If the empty list is NIL, then NIL should be of type CONS. For me,
> > this should be the logical behavior.
> 
> Actually, the design of lists, built recursively from conses, is based
> directly on logic.  The CONS datatype exists in most Lisp dialects,
> not just Common Lisp; in a few it is called PAIR.  But as the name
> PAIR makes clear, NIL (not being a pair) would be an inappropriate
> member of the set of all pairs.

Not necessarily.  NIL does behave like an immutable pair whose CAR and 
CDR are NIL.  i.e. NIL behaves as if its definition were something along 
the lines of:

#1=(#1# . #1#)

except that the CAR and CDR of the resulting CONS cell are immutable.

That there is not an immutable CONS cell type in CL is IMHO a bug.  
Likewise for the fact that there is no proper-cons-cell type, whose CDR 
can only be NIL or another proper cons cell.

rg
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <uzlw7icty.fsf@nhplace.com>
Ron Garret <·········@flownet.com> writes:

> > Actually, the design of lists, built recursively from conses, is based
> > directly on logic.  The CONS datatype exists in most Lisp dialects,
> > not just Common Lisp; in a few it is called PAIR.  But as the name
> > PAIR makes clear, NIL (not being a pair) would be an inappropriate
> > member of the set of all pairs.
> 
> Not necessarily.  NIL does behave like an immutable pair whose CAR and 
> CDR are NIL.  i.e. NIL behaves as if its definition were something along 
> the lines of:
> 
> #1=(#1# . #1#)
> 
> except that the CAR and CDR of the resulting CONS cell are immutable.

Well, and except that ATOM and CONSP are often the predicates of
choice for stopping recursion, so that would have to change, too.

What you say is true in theory, and I think of it from time to time,
but I'm convinced that while it's a perfectly reasonable
implementation strategy, it's a terrible theory of how to specify the
language.  The main reason is that the CONS/ATOM line is really something
that is not just arbitrary but important.

I'm less clear on the car/cdr of NIL thing.  I think there are some
advantages of that, but many disadvantages.  Enshrining it by making
the change you're suggesting seems like creeping a bit too far in the
wrong direction.

> That there is not an immutable CONS cell type in CL is IMHO a bug.  

Maclisp had this. Hey, cool. I don't have to explain this now in detail.
I can finally just allude to it... Phew.
http://www.maclisp.info/pitmanual/system.html#24.31.4

> Likewise for the fact that there is no proper-cons-cell type, whose CDR 
> can only be NIL or another proper cons cell.

I somewhat agree, though in practice there are very few things you could
do differently based on this.

Speedwise, list operations are optimized pretty well by Lisp.  So I don't
guess it's about that.

You could also be making a general plea for static typing for the sake
of early error detection.  Some people like that, and such languages do
exist.  I'm not arguing against them; I'm just saying they're not Lisp.
At least not like any Lisp I know.

Can you say more clearly how this type would manifest in Lisp without
it turning all staticky? :)
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <rNOSPAMon-B212EE.20391318122007@news.gha.chartermi.net>
In article <·············@nhplace.com>,
 Kent M Pitman <······@nhplace.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > > Actually, the design of lists, built recursively from conses, is based
> > > directly on logic.  The CONS datatype exists in most Lisp dialects,
> > > not just Common Lisp; in a few it is called PAIR.  But as the name
> > > PAIR makes clear, NIL (not being a pair) would be an inappropriate
> > > member of the set of all pairs.
> > 
> > Not necessarily.  NIL does behave like an immutable pair whose CAR and 
> > CDR are NIL.  i.e. NIL behaves as if its definition were something along 
> > the lines of:
> > 
> > #1=(#1# . #1#)
> > 
> > except that the CAR and CDR of the resulting CONS cell are immutable.
> 
> Well, and except that ATOM and CONSP are often the predicates of
> choice for stopping recursion, so that would have to change, too.

I'll wager that NULL is used more often than ATOM to stop recursion in 
actual code.

> What you say is true in theory, and I think of it from time to time,
> but I'm convinced that while it's a perfectly reasonable
> implementation strategy, it's a terrible theory of how to specify the
> language.  The main reason is that the CONS/ATOM line is really something
> that is not just arbitrary but important.

I disagree.  There is no particular reason that NIL should be the 
end-list marker.  Any unique object can serve that purpose.  It is in 
fact completely arbitrary except insofar as you want to pun the CAR/CDR 
of the end-list marker (whatever it may be), which leads me to...

> I'm less clear on the car/cdr of NIL thing.  I think there are some
> advantages of that, but many disadvantages.  Enshrining it by making
> the change you're suggesting seems like creeping a bit too far in the
> wrong direction.

Um, the car/cdr of NIL thing is not a change.  That's the way CL is 
currently defined, and while the merits of this approach are debatable, 
I do recall you being one of its defenders in the past.  (And IMO 
defending (consp nil) returning false on logical grounds is less tenable 
in light of the fact that the CAR and CDR of NIL are both defined.)

> > That there is not an immutable CONS cell type in CL is IMHO a bug.  
> 
> Maclisp had this. Hey, cool. I don't have to explain this now in detail.
> I can finally just allude to it... Phew.
> http://www.maclisp.info/pitmanual/system.html#24.31.4

:-)

> > Likewise for the fact that there is no proper-cons-cell type, whose CDR 
> > can only be NIL or another proper cons cell.
> 
> I somewhat agree, though in practice there are very few things you could
> do differently based on this.
>
> Speedwise, list operations are optimized pretty well by Lisp.  So I don't
> guess it's about that.

Actually, that's exactly what it's about.  Any function that expects a 
proper list (mapcar, length, etc.) has to traverse the entire length of 
the list before it knows whether or not it should blow up.  Worse, it 
has to do this EVERY SINGLE TIME because there's no way to guarantee 
that some other thread doesn't sneak in and replace that trailing NIL 
with something else.  Either immutable cons cels or proper cons cells 
would solve this problem.  But it is in fact a problem.

> You could also be making a general plea for static typing for the sake
> of early error detection.  Some people like that, and such languages do
> exist.  I'm not arguing against them; I'm just saying they're not Lisp.
> At least not like any Lisp I know.
> 
> Can you say more clearly how this type would manifest in Lisp without
> it turning all staticky? :)

Adding a proper-cons type to Lisp wouldn't make it any more statically 
typed than it currently is.  Lisp already has a number of built-in 
container types that are constrained to hold only certain kinds of 
objects, notably bit vectors and character vectors (a.k.a. strings).  So 
this is in no way unprecedented.

rg
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <uabo6n0id.fsf@nhplace.com>
Ron Garret <·········@flownet.com> writes:

> I'll wager that NULL is used more often than ATOM to stop recursion in 
> actual code.

Well, I didn't mean literally as a function call count. I do agree
with you on this.  But I think there is enough code that wants to make
such a distinction that it's not fair to say that such code is just
buggy and could be brought into line by changing a function name with
no loss of functionality.

Especially if you count (if x ...) as a shorthand for (if (not (null
x)) ...)  in the case of x being a list, then I agree with you that
NULL is probably used a majority of the time.

> > I'm less clear on the car/cdr of NIL thing.  I think there are some
> > advantages of that, but many disadvantages.  Enshrining it by making
> > the change you're suggesting seems like creeping a bit too far in the
> > wrong direction.
> 
> Um, the car/cdr of NIL thing is not a change.

The fact of its behavior is long-standing certainly. (I think it comes
in to MACLISP by way of INTERLISP, btw.)

> That's the way CL is currently defined, 

Not as accessors.  But as a description of the datatype it would be.
It's one thing to describe this a working by
  (metaphorical-defmethod car ((x null)) nil) 
  (metaphorical-defmethod cdr ((x null)) nil)
and it's quite another to describe it by
  (metaphorical-defclass null (...) ((car :initform nil) (cdr :initform nil)))

> and while the merits of this approach are debatable, 
> I do recall you being one of its defenders in the past.

I think it's been seen to be useful to do the metaphorical-defmethod
thing.  I think it would completely confuse people conceptually to
merge it with pair descriptively.  But I could be wrong--it's just a
personal impression. I'm not even sure right/wrong is meaningful in
such discussions.  These arguments get settled by people making their
own dialects and hanging out a shingle asking people to try them, not
by people saying they want to perturb existing space where people are
happy.  Success stories sway me more than sales of untried things.

> (And IMO 
> defending (consp nil) returning false on logical grounds is less tenable 
> in light of the fact that the CAR and CDR of NIL are both defined.)

You can take that position. I don't. I think you're saying in this
sentence that it's not reasonable to ask people, early on, to
understand the metaphorical-defmethod explanation above.  At times
like this, I like the suggestion someone made about calling Lisp not
object-oriented but generic-function-centric.  (I actually like the
term object-oriented for other reasons, but acknowledge it's been
perverted to mean that the definition is all done around objects, when
I think it's a data abstraction violation to be saying that... But in
the hypothetical world where it was reasonable for someone to hijack
object-oriented to mean what it seems to mean to people these days,
the name generic-function-centric captures in some ways how the two
paradigms differ.  Whereas what you're saying is we need to revise our
datastuctures so we can still use the term object-oriented to explain
the behavior when it shouldn't be necessary to do that.  Not all function
behavior needs to be explained in terms of class definitions, after all.
That's a BIG deal.  In other languages, if you didn't get your definitions
in when the class was defined, that's the end of the story... CL is not
like that.)

> > > That there is not an immutable CONS cell type in CL is IMHO a bug.  
> > 
> > Maclisp had this. Hey, cool. I don't have to explain this now in detail.
> > I can finally just allude to it... Phew.
> > http://www.maclisp.info/pitmanual/system.html#24.31.4
> 
> :-)
> 
> > > Likewise for the fact that there is no proper-cons-cell type, whose CDR 
> > > can only be NIL or another proper cons cell.
> > 
> > I somewhat agree, though in practice there are very few things you could
> > do differently based on this.
> >
> > Speedwise, list operations are optimized pretty well by Lisp.  So I don't
> > guess it's about that.
> 
> Actually, that's exactly what it's about.

You're probably at this point thinking I'm tring to argue you down, but I'm
really listening and I'll ponder what you have to say here.  Please do not
take my comments below as detracting from your point but rather as helping you
hone your argument a bit.

> Any function that expects a 
> proper list (mapcar, length, etc.) has to traverse the entire length of 
> the list before it knows whether or not it should blow up.  Worse, it 
> has to do this EVERY SINGLE TIME because there's no way to guarantee 
> that some other thread doesn't sneak in and replace that trailing NIL 
> with something else.  Either immutable cons cels or proper cons cells 
> would solve this problem.  But it is in fact a problem.

I don't think this is your strongest argument.  I suspect something in the
teachability area would be a stronger one.

I'm frankly not swayed that it needs to come up a lot that you have to do
this kind of check.  Even in static languages, frankly, there are still things
you can do wrong later on in the list.  They are fewer, but not gone.  And in
a dynamic language, there are many things that could go wrong.  So absent
a declaration that ALL of the data in the list was of the right form, not just
the final piece, you still have to do linear time checking.  So it looks 
superficially like you're saying you can turn O(n) into O(1) here, and that
might be a big deal, but you can't rewrite:

 (defun foo (frob-list)
   (check-the-frob-list frob-list)
   ...)

into 
 
 (defmethod foo ((frob-list rg\'s-proper-list))
   ;no longer needed
   ;(check-the-frob-list frob-list)
   ...)

in the general case since there is more to check in a frob list than listness.
So you're really only getting O(1).  Or that's what it looks like to me.

There is some argument to be made that the cognitive overhead of
training people to use lists on a simpler kind of list than the full
dotted pair list might be good.  It would risk that regular cons would
be socially marginalized and fall away, and that might have some ill
effects later on.  I'm not sure about that.  But it's an easier argument
to see that teachers might like a list type that didn't get bolixed up
with dotted pairs while people were still learning to cons proper lists.

There's a whole question of whether you want not just a proper-list type
but a proper-list function, a proper-cons, a proper-append, etc. or whether
you want to rely on declaration processing.  You might think this was obvious
by type dispatch but it does not follow from your suggestion that cons
can decide to make a proper list just because it receives a proper list.
That means you could never make a mutable CONS that pointed to a non-mutable
one, and I'm pretty sure you wouldn't want THAT.  Ditto for PROPER-APPEND.
Curiously, I'm willing to believe that PUSH _could_ make that distinction
since it has a kind of weird dual-use thing going that allows you to know.

> > You could also be making a general plea for static typing for the sake
> > of early error detection.  Some people like that, and such languages do
> > exist.  I'm not arguing against them; I'm just saying they're not Lisp.
> > At least not like any Lisp I know.
> > 
> > Can you say more clearly how this type would manifest in Lisp without
> > it turning all staticky? :)
> 
> Adding a proper-cons type to Lisp wouldn't make it any more statically 
> typed than it currently is.  Lisp already has a number of built-in 
> container types that are constrained to hold only certain kinds of 
> objects, notably bit vectors and character vectors (a.k.a. strings).  So 
> this is in no way unprecedented.

I do see what you're saying here.  My issues are mostly those from above.

Thanks for answering, though.  It helps to see in more detail what you're
suggesting.  I don't know if I've ever heard this specific suggestion, btw.
It's hard for me to believe it hasn't been discussed though.  I'm hardly the
central clearinghouse of all things Lisp.  I'm just more chatty than many 
of the others who have done serious design.  (I'm really pleased to see
Dan Weinreb joining the fray lately, though.)
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <3aa797ef-bfbf-424a-99d8-527ee4a83fd6@r60g2000hsc.googlegroups.com>
On Dec 19, 7:54 am, Kent M Pitman <······@nhplace.com> wrote:

> It's one thing to describe this a working by
>   (metaphorical-defmethod car ((x null)) nil)
>   (metaphorical-defmethod cdr ((x null)) nil)
> and it's quite another to describe it by
>   (metaphorical-defclass null (...) ((car :initform nil) (cdr :initform nil)))

Really?  Why?  The only difference I see is mutability.


> > (And IMO
> > defending (consp nil) returning false on logical grounds is less tenable
> > in light of the fact that the CAR and CDR of NIL are both defined.)
>
> You can take that position. I don't. I think you're saying in this
> sentence that it's not reasonable to ask people, early on, to
> understand the metaphorical-defmethod explanation above.

No.  What I'm saying is that it's disingenuous to advocate the
metaphorical-defmethod model while at the same time saying that NIL is
not a cons *because* cons cells are based on logic.  The metaphorical-
defmethod model is tenable, but it's a hack, but it is NOT a NECESSARY
hack.  The immutable-cons-cell model of NIL is tenable also.  My only
point here is that it is unfair to say, as some have done, that people
who think NIL should be of type PAIR are idiots.

> Whereas what you're saying is we need to revise our datastuctures

Not at all.  (There seems to be a common misunderstanding schema at
work here.)  All I'm saying is that advocating such a revision is a
tenable position.


> You're probably at this point thinking I'm tring to argue you down, but I'm
> really listening and I'll ponder what you have to say here.  Please do not
> take my comments below as detracting from your point but rather as helping you
> hone your argument a bit.

I appreciate that, but your honing would be more effective if you
understood what I was actually arguing for :-)


> > Any function that expects a
> > proper list (mapcar, length, etc.) has to traverse the entire length of
> > the list before it knows whether or not it should blow up.  Worse, it
> > has to do this EVERY SINGLE TIME because there's no way to guarantee
> > that some other thread doesn't sneak in and replace that trailing NIL
> > with something else.  Either immutable cons cels or proper cons cells
> > would solve this problem.  But it is in fact a problem.
>
> I don't think this is your strongest argument.  I suspect something in the
> teachability area would be a stronger one.

Perhaps.  In my own experience I have often encountered bugs resulting
from an improper list being passed to mapcar or some such thing.  I
suspect I'm not alone.

> So it looks
> superficially like you're saying you can turn O(n) into O(1) here

For one case that I believe is very common, yes.

> but you can't rewrite:
>
>  (defun foo (frob-list)
>    (check-the-frob-list frob-list)
>    ...)
>
> into
>
>  (defmethod foo ((frob-list rg\'s-proper-list))
>    ;no longer needed
>    ;(check-the-frob-list frob-list)
>    ...)
>
> in the general case

Of course.


> There is some argument to be made that the cognitive overhead of
> training people to use lists on a simpler kind of list than the full
> dotted pair list might be good.  It would risk that regular cons would
> be socially marginalized and fall away

Personally I would call that an ancillary benefit, not a risk.


> There's a whole question of whether you want not just a proper-list type
> but a proper-list function

In what way would proper-list differ from list?

> a proper-cons, a proper-append, etc. or whether
> you want to rely on declaration processing.  You might think this was obvious
> by type dispatch but it does not follow from your suggestion that cons
> can decide to make a proper list just because it receives a proper list.
> That means you could never make a mutable CONS that pointed to a non-mutable
> one, and I'm pretty sure you wouldn't want THAT.

Why not?  (Actually, if I had my druthers, CONS would mean immutable-
cons, and you'd need to do extra typing to get a mutable cons cell.
IMO cons cells are cool mainly when they are used in a functional
style.  Where you find yourself tempted to mutate a cons cell,
especially when you want to turn a proper-cons into an improper-cons I
think that's generally an indication that you're doing something
wrong, and you really ought to be using a structure.  IMHO.)

> > > You could also be making a general plea for static typing for the sake
> > > of early error detection.  Some people like that, and such languages do
> > > exist.  I'm not arguing against them; I'm just saying they're not Lisp.
> > > At least not like any Lisp I know.
>
> > > Can you say more clearly how this type would manifest in Lisp without
> > > it turning all staticky? :)
>
> > Adding a proper-cons type to Lisp wouldn't make it any more statically
> > typed than it currently is.  Lisp already has a number of built-in
> > container types that are constrained to hold only certain kinds of
> > objects, notably bit vectors and character vectors (a.k.a. strings).  So
> > this is in no way unprecedented.
>
> I do see what you're saying here.

Woohoo!  :-)

rg
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <ufxxxhfok.fsf@nhplace.com>
Ron Garret <···@flownet.com> writes:

> > There's a whole question of whether you want not just a proper-list type
> > but a proper-list function
> 
> In what way would proper-list differ from list?

In whether it returned something that could be rplacd'd with a list or
that required that it could only be rplacd'd with a proper list.

If you say it can't be rplacd'd, you're abusing the term proper list,
or redefining the language in a fundamental way, since lists can
already be proper without being immutable.

http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#list
http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_p.htm#proper_list

- - - - -

Note, too, that Zetalisp kind of treaded a narrow line there by making
list return a cdr-coded list, which was a bet against rplacd'ing, but not
a bet that was so strong as to disallow rplacd'ing, it just penalized it.
(And it didn't allow you to presume by looking at the head that the tail
ended in NIL, as a result.)
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5e13aa4c-da88-4bb1-bee4-533b2e73a0d3@1g2000hsl.googlegroups.com>
On Dec 18, 8:39 pm, Ron Garret <·········@flownet.com> wrote:
> (And IMO defending (consp nil) returning false on logical grounds is less tenable
> in light of the fact that the CAR and CDR of NIL are both defined.)

That (CAR NIL) is defined doesn't assert that NIL is a cons.

In the object system, we can specialize any method we want to take
arguments of the NULL class.

If I have an EMPLOYEE class and a SALARY accessor, I can make an
additional method so that (SALARY NIL) works just as well as (SALARY
E) where E is an employee.

The existence of the NULL method of the SALARY generic function
doesn't cause NIL to be considered an instance of class EMPLOYEE.

Applicability of functions isn't a the determiner of type in Common
Lisp.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <73f6da4f-df58-4e49-84e1-57bba09ef959@e6g2000prf.googlegroups.com>
On Dec 19, 11:30 am, Kaz Kylheku <········@gmail.com> wrote:
> On Dec 18, 8:39 pm,RonGarret<·········@flownet.com> wrote:
>
> > (And IMO defending (consp nil) returning false on logical grounds is less tenable
> > in light of the fact that the CAR and CDR of NIL are both defined.)
>
> That (CAR NIL) is defined doesn't assert that NIL is a cons.
>
> In the object system, we can specialize any method we want to take
> arguments of the NULL class.
>
> If I have an EMPLOYEE class and a SALARY accessor, I can make an
> additional method so that (SALARY NIL) works just as well as (SALARY
> E) where E is an employee.
>
> The existence of the NULL method of the SALARY generic function
> doesn't cause NIL to be considered an instance of class EMPLOYEE.
>
> Applicability of functions isn't a the determiner of type in Common
> Lisp.

Except that CAR is not a generic function.

rg
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <u1w9hj2vn.fsf@nhplace.com>
Ron Garret <···@flownet.com> writes:

> On Dec 19, 11:30 am, Kaz Kylheku <········@gmail.com> wrote:
> > Applicability of functions isn't a the determiner of type in Common
> > Lisp.
> Except that CAR is not a generic function.

That's a separate question. Explaining that something is or might be
implemented that way doesn't require that it is.  The functions that
read the parts out of SIMPLE-CONDITIONS are probably implemented by
generic functions, but not guaranteed to be, for example.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <ff9edf9f-c556-4064-922a-c9da14f385f5@r60g2000hsc.googlegroups.com>
On Dec 19, 10:29 pm, Kent M Pitman <······@nhplace.com> wrote:
> Ron Garret <····@flownet.com> writes:
> > On Dec 19, 11:30 am, Kaz Kylheku <········@gmail.com> wrote:
> > > Applicability of functions isn't a the determiner of type in Common
> > > Lisp.
> > Except that CAR is not a generic function.
>
> That's a separate question. Explaining that something is or might be
> implemented that way doesn't require that it is.  The functions that
> read the parts out of SIMPLE-CONDITIONS are probably implemented by
> generic functions, but not guaranteed to be, for example.

OK, but then it should be fair to treat CONSP in the same way and
assert that (metaphorical-defmethod consp ((x null)) ...) should
return T.  If you say that (car nil) is nil because CAR is a
metaphorical generic function  then you have abandoned logic and
principle and you are saying essentially (car nil) and (consp nil) are
nil simply because that's the way it is.  There's nothing necessarily
wrong with that, but it's intellectually dishonest to try to defend
both (car nil) and (consp nil) on the basis of some lofty principle
when the fact of the matter is it's just a hack.

rg
From: Rob Warnock
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <HJadnXkVkvV7J_TanZ2dnUVZ_trinZ2d@speakeasy.net>
Kaz Kylheku  <········@gmail.com> wrote:
+---------------
| Ron Garret <·········@flownet.com> wrote:
| > (And IMO defending (consp nil) returning false on logical grounds is
| > less tenable of the fact that the CAR and CDR of NIL are both defined.)
| 
| That (CAR NIL) is defined doesn't assert that NIL is a cons.
+---------------

Indeed. Just as the fact that (CAR 'NIL) is defined doesn't assert
that (CAR 'ANY-OTHER-SYMBOL) is defined. NIL is... *spehhhshull*!
[Said in the voice of Dana Carvey's "Church Lady" character on
"Saturday Night Live".]

+---------------
| In the object system, we can specialize any method we want to take
| arguments of the NULL class.
+---------------

That too.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <u1w9ioxxz.fsf@nhplace.com>
····@rpw3.org (Rob Warnock) writes:

> Kaz Kylheku  <········@gmail.com> wrote:
> +---------------
> | Ron Garret <·········@flownet.com> wrote:
> | > (And IMO defending (consp nil) returning false on logical grounds is
> | > less tenable of the fact that the CAR and CDR of NIL are both defined.)
> | 
> | That (CAR NIL) is defined doesn't assert that NIL is a cons.
> +---------------
> 
> Indeed. Just as the fact that (CAR 'NIL) is defined doesn't assert
> that (CAR 'ANY-OTHER-SYMBOL) is defined. NIL is... *spehhhshull*!
> [Said in the voice of Dana Carvey's "Church Lady" character on
> "Saturday Night Live".]

Since I've got the MACLISP manual finally online, this probably is my
cue to point you what MACLISP used to do.  It had a control variable
that affected whether you were allowed to car/cdr into symbols in
order to get extra junk that you normally were not supposed to see.

http://www.maclisp.info/pitmanual/list.html#8.17.1

That kind of thing would not fly in a modern Lisp, where the implementations
differ on what's inside.  But in MACLISP many people knew the data layouts
and would use car/cdr/cxr to get to the various parts of a symbol.
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <2d7360cd-c98b-4662-b2d2-10d5d3f13c1e@e25g2000prg.googlegroups.com>
On Dec 18, 8:39 pm, Ron Garret <·········@flownet.com> wrote:
> In article <·············@nhplace.com>,
>  Kent M Pitman <······@nhplace.com> wrote:
>
> > > Likewise for the fact that there is no proper-cons-cell type, whose CDR
> > > can only be NIL or another proper cons cell.
>
> > I somewhat agree, though in practice there are very few things you could
> > do differently based on this.
>
> > Speedwise, list operations are optimized pretty well by Lisp.  So I don't
> > guess it's about that.
>
> Actually, that's exactly what it's about.  Any function that expects a
> proper list (mapcar, length, etc.) has to traverse the entire length of
> the list before it knows whether or not it should blow up.  Worse, it
> has to do this EVERY SINGLE TIME because there's no way to guarantee
> that some other thread doesn't sneak in and replace that trailing NIL
> with something else.  Either immutable cons cels or proper cons cells
> would solve this problem.  But it is in fact a problem.

Mapcar and friends *don't* have to signal an error when given an
improper list, (and I don't see how length is going to avoid
traversing the whole length of the list anyhow :).  But even if mapcar
*were* required to signal an error, another fix would be to just
weaken that requirement to something like what it is now.  "proper"
cons cells wouldn't solve the problem anyhow, since you still need to
deal with circular lists.

In the Cadence dialect of Lisp (SKILL), cons cells can only have nil
or another cons cell as a cdr, and based on my experience, you don't
gain anything by it.  You arrange your cons-cell-based data structures
a little differently, and everything else is about the same.  What I
*would* like to see is the ability to express recursive types, like

  (deftype list-o-things (thing) `(or null (cons ,thing (list-o-
things ,thing))))

or having specialized cons cells like

  (deftype icons () '(cons integer (or null icons)))

  (make-cons 10 x :car-type 'integer :cdr-type '(or null icons))
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <9679a6ed-8419-42b4-a976-b31ef770cf5a@p1g2000hsb.googlegroups.com>
On Dec 20, 11:11 am, "Thomas F. Burdick" <········@gmail.com> wrote:

> Mapcar and friends *don't* have to signal an error when given an
> improper list

Maybe not, but I've never encountered a CL implementation that didn't.

rg
From: Rob Warnock
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <1KKdnceRBri32vbanZ2dnUVZ_hmtnZ2d@speakeasy.net>
Ron Garret  <···@flownet.com> wrote:
+---------------
| "Thomas F. Burdick" <········@gmail.com> wrote:
| > Mapcar and friends *don't* have to signal an error when given an
| > improper list
| 
| Maybe not, but I've never encountered a CL implementation that didn't.
+---------------

Let me introduce you to one:

    $ cmucl
    ...[chatter]...
    cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))

    (111 122 133)
    cmucl> 

And another:

    $ clisp -q
    [1]> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
    (111 122 133)
    [2]> 

And another:

    $ telnet prompt.franz.com
    ...[chatter]...
    This development copy of Allegro CL is licensed to:
       QA
    ...[chatter]...
    CL-USER(1): (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
    (111 122 133)
    CL-USER(2): 

Now you've encountered three!!  ;-}


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <a313bc0a-3f1a-4755-8d6c-1bb01023388a@e25g2000prg.googlegroups.com>
On Dec 20, 8:55 pm, ····@rpw3.org (Rob Warnock) wrote:
> Ron Garret  <····@flownet.com> wrote:
> +---------------
> | "Thomas F. Burdick" <········@gmail.com> wrote:
> | > Mapcar and friends *don't* have to signal an error when given an
> | > improper list
> |
> | Maybe not, but I've never encountered a CL implementation that didn't.
> +---------------
>
> Let me introduce you to one:
>
>     $ cmucl
>     ...[chatter]...
>     cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))

Well, that's not what I meant, and I suspect you know it.  So let me
be more precise: I don't know of any CL implementation where mapcar
does not signal an error if the shortest list passed to it is an
improper list.

Furthermore, I would say that if you are relying on the behavior you
highlight (i.e. passing an improper list and relying on the fact that
the iteration will end before reaching the end of the improper list)
that is almost certainly an indication that you are doing something
very badly wrong, and that you would be well served by having the
implementation complain at you in one way or another.

rg
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <70939bcd-2509-48c0-a9ac-f0feba3a4e0d@a35g2000prf.googlegroups.com>
On Dec 21, 7:40 am, Ron Garret <····@flownet.com> wrote:
> On Dec 20, 8:55 pm, ····@rpw3.org (Rob Warnock) wrote:
>
> > Ron Garret  <····@flownet.com> wrote:
> > +---------------
> > | "Thomas F. Burdick" <········@gmail.com> wrote:
> > | > Mapcar and friends *don't* have to signal an error when given an
> > | > improper list
> > |
> > | Maybe not, but I've never encountered a CL implementation that didn't.
> > +---------------
>
> > Let me introduce you to one:
>
> >     $ cmucl
> >     ...[chatter]...
> >     cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>

> Well, that's not what I meant, and I suspect you know it.  So let me
> be more precise: I don't know of any CL implementation where mapcar
> does not signal an error if the shortest list passed to it is an
> improper list.

But that was exactly your point!  You said that the need for "proper"
conses had to do with not requiring mapcar and length and friends to
traverse the whole length of the list just to signal an error for an
improper list.  Every implementation I've used (MCL, SBCL, CMUCL, ACL,
CLISP) all  signal an error if and only if control gets to a point
where they expected a cons but got an atom.  This seems to me exactly
why there's such weak language in the spec about improper lists here.

> Furthermore, I would say that if you are relying on the behavior you
> highlight (i.e. passing an improper list and relying on the fact that
> the iteration will end before reaching the end of the improper list)
> that is almost certainly an indication that you are doing something
> very badly wrong, and that you would be well served by having the
> implementation complain at you in one way or another.

I don't.  I like the idiom of having repeating data in a circular list
and depending on the input data to halt iteration; it leads to very
clean, clear code IMO:

  (loop for x in (quote #1=(1 2 3 4 5 6 7 8 9 10 . #1#))
        for y in some-list
        collect (cons y x))

It's certainly nicer than putting the wrap-around logic in the loop.
With LOOP, I could always put that logic in an iterator function and
have a "with iter = (make-iter) for x = (funcall iter)" clause, but no
such luck here:

  (mapcar #'cons some-list (quote #1=(1 2 3 4 5 6 7 8 9 10 . #1#))
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <1e7eac25-c043-49c0-b435-cacf291ae5ca@a35g2000prf.googlegroups.com>
On Dec 21, 9:52 am, "Thomas F. Burdick" <········@gmail.com> wrote:

> > >     $ cmucl
> > >     ...[chatter]...
> > >     cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>
> > Well, that's not what I meant, and I suspect you know it.  So let me
> > be more precise: I don't know of any CL implementation where mapcar
> > does not signal an error if the shortest list passed to it is an
> > improper list.
>
> But that was exactly your point!

With all due respect, I believe I am more of an authority on what
point I was trying to make than you are.

> You said that the need for "proper"
> conses had to do with not requiring mapcar and length and friends to
> traverse the whole length of the list just to signal an error for an
> improper list.

That's right.

> Every implementation I've used (MCL, SBCL, CMUCL, ACL,
> CLISP) all  signal an error if and only if control gets to a point
> where they expected a cons but got an atom.  This seems to me exactly
> why there's such weak language in the spec about improper lists here.

That's right too.  And IMO that behavior is broken.

> > Furthermore, I would say that if you are relying on the behavior you
> > highlight (i.e. passing an improper list and relying on the fact that
> > the iteration will end before reaching the end of the improper list)
> > that is almost certainly an indication that you are doing something
> > very badly wrong, and that you would be well served by having the
> > implementation complain at you in one way or another.
>
> I don't.  I like the idiom of having repeating data in a circular list

But a circular list is a proper list, so I don't see how this is
relevant.

rg
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <4c79bc70-5e4a-4e5d-a729-eadcd0cd5fb7@b40g2000prf.googlegroups.com>
On Dec 21, 5:11 pm, Ron Garret <····@flownet.com> wrote:

> But a circular list is a proper list

Correction: a circular list can be built out of proper conses.  (Gotta
really watch myself around you guys.)

rg
From: pdp
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <878x3nzab8.fsf@atthis.clsnet.nl>
Some entity, AKA Ron Garret <···@flownet.com>,
wrote this mindboggling stuff:
(selectively-snipped-or-not-p)


> Correction: a circular list can be built out of proper conses.  (Gotta
> really watch myself around you guys.)

yeps, but can yoy repl to tha bugger to send it on its proper course
is the question....;-)

Cor

-- 
Alle schraifvauden zijn opsettelick, teneynde ieder lafaart de cans te 
           gevuh over spelingk te mekkuh instede de inhaut
   (defvar My-Computer '((OS . "GNU/Emacs")  (IPL . "GNU/Linux")))
                        SPAM DELENDA EST
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <012616e3-4f18-41ea-8e27-35e97eda1436@l6g2000prm.googlegroups.com>
On Dec 21, 5:11 pm, Ron Garret <····@flownet.com> wrote:
> On Dec 21, 9:52 am, "Thomas F. Burdick" <········@gmail.com> wrote:
>
> > > >     $ cmucl
> > > >     ...[chatter]...
> > > >     cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>
> > > Well, that's not what I meant, and I suspect you know it.  So let me
> > > be more precise: I don't know of any CL implementation where mapcar
> > > does not signal an error if the shortest list passed to it is an
> > > improper list.
>
> > But that was exactly your point!
>
> With all due respect, I believe I am more of an authority on what
> point I was trying to make than you are.

I really couldn't care less what you in your heart of hearts wanted to
express.  What you said was:

> Actually, that's exactly what it's about.  Any function that expects a
> proper list (mapcar, length, etc.) has to traverse the entire length of
> the list before it knows whether or not it should blow up.  Worse, it
> has to do this EVERY SINGLE TIME because there's no way to guarantee
> that some other thread doesn't sneak in and replace that trailing NIL
> with something else.  Either immutable cons cels or proper cons cells
> would solve this problem.  But it is in fact a problem.

So I was addressing your point about detecting proper-list-ness and
the inherent ineficciency of doing so with CL-style conses.  I don't
know where in this big circle of begging the question you lost your
point, but that's something for you and your psychoanalyst to
discuss.  For comp.lang.lisp, please pick one line of thinking and
stick to it.  KTHXBYE

> > I don't.  I like the idiom of having repeating data in a circular list
>
> But a circular list is a proper list, so I don't see how this is
> relevant.

> Correction: a circular list can be built out of proper conses.  (Gotta
> really watch myself around you guys.)

You say that like you're going to get "caught" but this is right at
the heart of the matter.  "Proper" conses don't per se make proper
lists.  So we get back to the point I already mentioned: based on
experience, I don't see any gain from having conses that require their
CDRs to be of type (or null cons).  You still have improper lists, you
don't have any efficiency gain, you don't have any improvements wrt
correctness of your data structures.  No big down sides, but no real
gain, either.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5a93c961-b67c-44b6-839a-99bf4a6505bb@i12g2000prf.googlegroups.com>
On Dec 21, 10:59 pm, "Thomas F. Burdick" <········@gmail.com> wrote:
> On Dec 21, 5:11 pm, Ron Garret <····@flownet.com> wrote:
>
> > On Dec 21, 9:52 am, "Thomas F. Burdick" <········@gmail.com> wrote:
>
> > > > >     $ cmucl
> > > > >     ...[chatter]...
> > > > >     cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>
> > > > Well, that's not what I meant, and I suspect you know it.  So let me
> > > > be more precise: I don't know of any CL implementation where mapcar
> > > > does not signal an error if the shortest list passed to it is an
> > > > improper list.
>
> > > But that was exactly your point!
>
> > With all due respect, I believe I am more of an authority on what
> > point I was trying to make than you are.
>
> I really couldn't care less what you in your heart of hearts wanted to
> express.  What you said was:
>
> > Actually, that's exactly what it's about.  Any function that expects a
> > proper list (mapcar, length, etc.) has to traverse the entire length of
> > the list before it knows whether or not it should blow up.  Worse, it
> > has to do this EVERY SINGLE TIME because there's no way to guarantee
> > that some other thread doesn't sneak in and replace that trailing NIL
> > with something else.  Either immutable cons cels or proper cons cells
> > would solve this problem.  But it is in fact a problem.
>
> So I was addressing your point about detecting proper-list-ness and
> the inherent ineficciency of doing so with CL-style conses.  I don't
> know where in this big circle of begging the question you lost your
> point, but that's something for you and your psychoanalyst to
> discuss.  For comp.lang.lisp, please pick one line of thinking and
> stick to it.  KTHXBYE

This is a simple misunderstanding.  I said "proper list" where I
should have said "non-dotted list".  My bad.

> > > I don't.  I like the idiom of having repeating data in a circular list
>
> > But a circular list is a proper list, so I don't see how this is
> > relevant.
> > Correction: a circular list can be built out of proper conses.  (Gotta
> > really watch myself around you guys.)
>
> You say that like you're going to get "caught" but this is right at
> the heart of the matter.  "Proper" conses don't per se make proper
> lists.

Right.  I should have said non-dotted cons.  My bad.

>  So we get back to the point I already mentioned: based on
> experience, I don't see any gain from having conses that require their
> CDRs to be of type (or null cons).  You still have improper lists

But you no longer have dotted lists, which are what cause mapcar to
bomb.

> you
> don't have any efficiency gain, you don't have any improvements wrt
> correctness of your data structures.

Not so.  Mapcar will never bomb on a non-dotted cons the way it can
with a regular cons.

> No big down sides, but no real gain, either.

IMO immunity from a common class of error is a real gain.

rg
From: Nicolas Neuss
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <87y7bkpi8s.fsf@ma-patru.mathematik.uni-karlsruhe.de>
Ron Garret <···@flownet.com> writes:

> Not so.  Mapcar will never bomb on a non-dotted cons the way it can
> with a regular cons.
>
>> No big down sides, but no real gain, either.
>
> IMO immunity from a common class of error is a real gain.

I would be very much interested how common this type of error really is.  I
must admit that I have run into it only very rarely.  It probably depends
heavily on the programming style used.  Maybe there is also a simple rule
how you can avoid it.

Yours,
Nicolas
From: Edi Weitz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <uk5n8xroz.fsf@agharta.de>
On Thu, 20 Dec 2007 22:55:06 -0600, ····@rpw3.org (Rob Warnock) wrote:

> Ron Garret  <···@flownet.com> wrote:
> +---------------
> | "Thomas F. Burdick" <········@gmail.com> wrote:
> | > Mapcar and friends *don't* have to signal an error when given an
> | > improper list
> | 
> | Maybe not, but I've never encountered a CL implementation that didn't.
> +---------------
>
> Let me introduce you to one:
>
>     $ cmucl
>     ...[chatter]...
>     cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>
>     (111 122 133)
>     cmucl> 
>
> And another:
>
>     $ clisp -q
>     [1]> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>     (111 122 133)
>     [2]> 
>
> And another:
>
>     $ telnet prompt.franz.com
>     ...[chatter]...
>     This development copy of Allegro CL is licensed to:
>        QA
>     ...[chatter]...
>     CL-USER(1): (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>     (111 122 133)
>     CL-USER(2): 
>
> Now you've encountered three!!  ;-}

Hehe.  Not that facts matter in a Usenet discussion, but LispWorks,
OpenMCL, and SBCL don't signal an error for me either when asked to
evaluate this form.

Maybe Ron can simply give us a list of the CL implementation he /has/
encountered so far, then we know what we're talking about... :)

Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Duane Rettig
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <o0k5n7exf4.fsf@gemini.franz.com>
Edi Weitz <········@agharta.de> writes:

> On Thu, 20 Dec 2007 22:55:06 -0600, ····@rpw3.org (Rob Warnock) wrote:
>
>> Ron Garret  <···@flownet.com> wrote:
>> +---------------
>> | "Thomas F. Burdick" <········@gmail.com> wrote:
>> | > Mapcar and friends *don't* have to signal an error when given an
>> | > improper list
>> | 
>> | Maybe not, but I've never encountered a CL implementation that didn't.
>> +---------------

 [...]

>> Now you've encountered three!!  ;-}
>
> Hehe.  Not that facts matter in a Usenet discussion, but LispWorks,
> OpenMCL, and SBCL don't signal an error for me either when asked to
> evaluate this form.
>
> Maybe Ron can simply give us a list of the CL implementation he /has/
> encountered so far, then we know what we're talking about... :)

Ron was obviously baiting us; obviously if you left off the first list
you'd have seen quite a few more implementations that gave an error
upon encountering the improper list.

The key phrase here is "upon encountering".  The error terminology is
clear: "should be prepared to signal an error" explicitly states
(1.4.2) that the implementation does not go out of its way to discover
an erroneous situation if the normal action of the operator can be
performed with "lazy" checking.  So I would be surprised and concerned
about any implementation that _did_ go out of its way to check - it
could probably be argued that that implementation was in fact not
following the standard.  Best case, that implementation would be
extremely slow.

One could almost design an implementation where there was indeed a
"proper-cons" type, whose cdr was only allowed to be either another
proper-cons or nil.  This would allow mapcar and others to only test
for nil at the end.  But it wouldn't fix the issue of lazy testing;
the fact that only proper lists could be constructed with
proper-conses doesn't preclude proper lists being constructed with
regular conses.  It's because although "proper-cons" could be a type,
"proper list" is not a type - it is a description of state.  Hence,
mapcar is doomed to always do lazy error checking (unless an
implementation decides to go beyond the spec and run through the list
to ensure that it is proper; such an implementation would also need to
check for circularity as well...

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <09ee5580-9c4b-4582-b97d-04b676a69084@s8g2000prg.googlegroups.com>
On Dec 21, 10:05 am, Duane Rettig <·····@franz.com> wrote:

> Ron was obviously baiting us;

No, that was not my intent.

> obviously if you left off the first list
> you'd have seen quite a few more implementations that gave an error
> upon encountering the improper list.

Yes, that is the point I was trying to make.

> The key phrase here is "upon encountering".  The error terminology is
> clear: "should be prepared to signal an error" explicitly states
> (1.4.2) that the implementation does not go out of its way to discover
> an erroneous situation if the normal action of the operator can be
> performed with "lazy" checking.  So I would be surprised and concerned
> about any implementation that _did_ go out of its way to check - it
> could probably be argued that that implementation was in fact not
> following the standard.  Best case, that implementation would be
> extremely slow.

I am discussing what is desirable in the abstract, not what is
consistent with the standard.  Remember, the context of the discussion
is the question of whether NIL not being a CONS can be justified on
principle or it it's just a hack.

> One could almost design an implementation where there was indeed a
> "proper-cons" type, whose cdr was only allowed to be either another
> proper-cons or nil.

Almost?  Why almost?

> "proper list" is not a type - it is a description of state.

Yes, IMHO that is a Bad Thing (tm).

> Hence, mapcar is doomed to always do lazy error checking (unless an
> implementation decides to go beyond the spec and run through the list
> to ensure that it is proper; such an implementation would also need to
> check for circularity as well...

Or one could write a proper-mapcar which only accepted proper conses.
Such a function would be immune to the following sort of error:

[1]> (mapcar '1+ '(1 . 2))

*** - MAPCAR: A proper list must not end with 2
The following restarts are available:
ABORT          :R1      ABORT

which in my experience is very common and often hard to debug.

rg
From: Duane Rettig
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <o0ve6rqi4e.fsf@gemini.franz.com>
Ron Garret <···@flownet.com> writes:

> On Dec 21, 10:05�am, Duane Rettig <·····@franz.com> wrote:
>
>> Ron was obviously baiting us;
>
> No, that was not my intent.

Poor choice of words.  Probably better was "toying with".

>> obviously if you left off the first list
>> you'd have seen quite a few more implementations that gave an error
>> upon encountering the improper list.
>
> Yes, that is the point I was trying to make.
>
>> The key phrase here is "upon encountering". �The error terminology is
>> clear: "should be prepared to signal an error" explicitly states
>> (1.4.2) that the implementation does not go out of its way to discover
>> an erroneous situation if the normal action of the operator can be
>> performed with "lazy" checking. �So I would be surprised and concerned
>> about any implementation that _did_ go out of its way to check - it
>> could probably be argued that that implementation was in fact not
>> following the standard. �Best case, that implementation would be
>> extremely slow.
>
> I am discussing what is desirable in the abstract, not what is
> consistent with the standard.  Remember, the context of the discussion
> is the question of whether NIL not being a CONS can be justified on
> principle or it it's just a hack.
>
>> One could almost design an implementation where there was indeed a
>> "proper-cons" type, whose cdr was only allowed to be either another
>> proper-cons or nil.
>
> Almost?  Why almost?

Explained below.  Think of me in implementation mode.  Obviously
I _could_ do it, but why would I want to?

>> "proper list" is not a type - it is a description of state.
>
> Yes, IMHO that is a Bad Thing (tm).

Precisely why almost.

>> Hence, mapcar is doomed to always do lazy error checking (unless an
>> implementation decides to go beyond the spec and run through the list
>> to ensure that it is proper; such an implementation would also need to
>> check for circularity as well...
>
> Or one could write a proper-mapcar which only accepted proper conses.
> Such a function would be immune to the following sort of error:

Another almost-solution, since as you note elsewhere a proper-cons
could still create improper lists.

> [1]> (mapcar '1+ '(1 . 2))
>
> *** - MAPCAR: A proper list must not end with 2
> The following restarts are available:
> ABORT          :R1      ABORT
>
> which in my experience is very common and often hard to debug.

Yes; often one has to depend on the backtrace for situations like
that, to aid in getting the context of the failure.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <3eb8dadd-0092-49b1-97b1-abd361564eb9@s12g2000prg.googlegroups.com>
On Dec 21, 11:54 pm, Duane Rettig <·····@franz.com> wrote:
> Ron Garret <····@flownet.com> writes:
> > On Dec 21, 10:05 am, Duane Rettig <·····@franz.com> wrote:
>
> >> Ron was obviously baiting us;
>
> > No, that was not my intent.
>
> Poor choice of words.  Probably better was "toying with".

No, I wasn't even doing that.  I was just being sloppy in saying what
I meant to say.

> >> One could almost design an implementation where there was indeed a
> >> "proper-cons" type, whose cdr was only allowed to be either another
> >> proper-cons or nil.
>
> > Almost?  Why almost?
>
> Explained below.  Think of me in implementation mode.  Obviously
> I _could_ do it, but why would I want to?

Because the resulting implementation would allow one to write code
that was immune from a certain class of fairly common error (or at
least detect the onset of that error earlier than would otherwise be
possible).  Some of your customers might consider that value-added.

> >> "proper list" is not a type - it is a description of state.
>
> > Yes, IMHO that is a Bad Thing (tm).
>
> Precisely why almost.

Sorry, that doesn't make sense to me.

> >> Hence, mapcar is doomed to always do lazy error checking (unless an
> >> implementation decides to go beyond the spec and run through the list
> >> to ensure that it is proper; such an implementation would also need to
> >> check for circularity as well...
>
> > Or one could write a proper-mapcar which only accepted proper conses.
> > Such a function would be immune to the following sort of error:
>
> Another almost-solution, since as you note elsewhere a proper-cons
> could still create improper lists.

Yes, but improper lists break down into two sub-categories: circular
lists, and lists with non-pair-non-nil terminating CDRs.  The
sloppiness I was referring to above was using the term "improper list"
to refer exclusively to refer to improper lists of the second kind,
since they are the ones that tend to cause problems (and are, IMO, a
reliable indicator of poor software design).  A proper cons cannot be
used to create improper lists of the second kind.

(N.B. The mere fact that I need to coin a term like improper-list-of-
the-second-kind to even talk about this problem with precision is an
indication that something is deeply wrong with the current state of
affairs.)

> > [1]> (mapcar '1+ '(1 . 2))
>
> > *** - MAPCAR: A proper list must not end with 2
> > The following restarts are available:
> > ABORT          :R1      ABORT
>
> > which in my experience is very common and often hard to debug.
>
> Yes; often one has to depend on the backtrace for situations like
> that, to aid in getting the context of the failure.

Indeed.  IMO the world would be a better place if one could reliably
prevent such errors from happening to begin with.

rg
From: Duane Rettig
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <o0sl1upow0.fsf@gemini.franz.com>
Ron Garret <···@flownet.com> writes:

>> >> One could almost design an implementation where there was indeed a
>> >> "proper-cons" type, whose cdr was only allowed to be either another
>> >> proper-cons or nil.
>>
>> > Almost? �Why almost?
>>
>> Explained below. �Think of me in implementation mode. �Obviously
>> I _could_ do it, but why would I want to?
>
> Because the resulting implementation would allow one to write code
> that was immune from a certain class of fairly common error (or at
> least detect the onset of that error earlier than would otherwise be
> possible).  Some of your customers might consider that value-added.

The problem is that adding a proper-cons type doesn't shift all
possible proper-lists into the proper-cons implementation.  One could
build a proper list out of regular cons cells, and so something like
mapcar could not just check for the existence of proper-cons and error
if not, because it may still need to traverse a proper-list made up of
regular cons cells.

>> >> "proper list" is not a type - it is a description of state.
>>
>> > Yes, IMHO that is a Bad Thing (tm).
>>
>> Precisely why almost.
>
> Sorry, that doesn't make sense to me.

I'm not sure if it was the context or the grammar that didn't make
sense.  I should have quoted the "why almost", to refer back to your

       Almost? �Why almost?

above.  As to why I made the statement, it is precisely because the
term "proper list" is a description and not a type (i.e. in a system
with a proper-cons type, one could still have a proper-list
constructed of regular cons cells) that the existence of proper-cons
cells doesn't really buy that much.  See below.

>> >> Hence, mapcar is doomed to always do lazy error checking (unless an
>> >> implementation decides to go beyond the spec and run through the list
>> >> to ensure that it is proper; such an implementation would also need to
>> >> check for circularity as well...
>>
>> > Or one could write a proper-mapcar which only accepted proper conses.
>> > Such a function would be immune to the following sort of error:
>>
>> Another almost-solution, since as you note elsewhere a proper-cons
>> could still create improper lists.
>
> Yes, but improper lists break down into two sub-categories: circular
> lists, and lists with non-pair-non-nil terminating CDRs.  The
> sloppiness I was referring to above was using the term "improper list"
> to refer exclusively to refer to improper lists of the second kind,
> since they are the ones that tend to cause problems (and are, IMO, a
> reliable indicator of poor software design).  A proper cons cannot be
> used to create improper lists of the second kind.

It could even be possible to restrict rplacd / (setf cdr) to check for
the existence of a proper-cons, and if so, to ensure that the value to
set is then also a proper-cons _and_ to walk the cdrs of that value to
ensure that no cons cell matches the one being modified.  This would
ensure that proper-cons cells could only construct proper-lists.

But none of this would not ensure that proper-lists could only be
constructed out of proper-cons cells.

At Franz, we file rfes (requests for enhancement) even for things that
are not likely to occur.  I have filed such an rfe for proper-cons.
In it, I described the basic premise, the likely implementation, the
costs, and the benefits.  Under costs was the obvious slowdown that
rplacd / (setf cdr) would see (though the most egregious time cost
would occur when both the modified cons and the value are
proper-conses).  Under benefits, there really wasn't much to say; the
ideal benefit would have been that functions could detect
improper-lists, but for what we've discussed here, that's still not
possible.

Perhaps you can think of other benefits of this extension?

Other possibilities include restricting what can be done with regular
cons cells, but that seems like a path that is fraught with
nonconformances, incompatibilities with current usages, and general
mayhem.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <77114be0-4019-4676-b1d1-86cac8f3a9b8@s8g2000prg.googlegroups.com>
On Dec 22, 10:26 am, Duane Rettig <·····@franz.com> wrote:
> Ron Garret <····@flownet.com> writes:
> >> >> One could almost design an implementation where there was indeed a
> >> >> "proper-cons" type, whose cdr was only allowed to be either another
> >> >> proper-cons or nil.
>
> >> > Almost?  Why almost?
>
> >> Explained below.  Think of me in implementation mode.  Obviously
> >> I _could_ do it, but why would I want to?
>
> > Because the resulting implementation would allow one to write code
> > that was immune from a certain class of fairly common error (or at
> > least detect the onset of that error earlier than would otherwise be
> > possible).  Some of your customers might consider that value-added.
>
> The problem is that adding a proper-cons type doesn't shift all
> possible proper-lists into the proper-cons implementation.  One could
> build a proper list out of regular cons cells, and so something like
> mapcar could not just check for the existence of proper-cons and error
> if not, because it may still need to traverse a proper-list made up of
> regular cons cells.

That's true.  The burden is on the user to actually use proper-cons,
er, properly in order to reap the benefits.

> >> >> "proper list" is not a type - it is a description of state.
>
> >> > Yes, IMHO that is a Bad Thing (tm).
>
> >> Precisely why almost.
>
> > Sorry, that doesn't make sense to me.
>
> I'm not sure if it was the context or the grammar that didn't make
> sense.

I assemble the above exchange as saying: 1) there is an obstacle to
implementing proper-cons (that being the meaning that one could
"almost" produce such an implementation) and 2) that obstacle is
somehow connected to my opinion that proper-listness ought to be type
rather than state.

> one could still have a proper-list
> constructed of regular cons cells) that the existence of proper-cons
> cells doesn't really buy that much.

Well, I can build a proper list out of all manner of things, not just
cons cells.  I can for example do this:

(defstruct cons car cdr)

and build a (data structure isomorphic to) a proper list out of that.
I can do the same thing with a bunch of instances of (simple-vector
2).  For that matter, I can build a proper-cons at the user level in
the same way.

The point is that a proper list (actually I should say a non-dotted
list) is a useful enough abstraction that IMO it would be beneficial
to give it first-class status in the type system, and not just have it
be a pun on some other data structure.

> >> >> Hence, mapcar is doomed to always do lazy error checking (unless an
> >> >> implementation decides to go beyond the spec and run through the list
> >> >> to ensure that it is proper; such an implementation would also need to
> >> >> check for circularity as well...
>
> >> > Or one could write a proper-mapcar which only accepted proper conses.
> >> > Such a function would be immune to the following sort of error:
>
> >> Another almost-solution, since as you note elsewhere a proper-cons
> >> could still create improper lists.
>
> > Yes, but improper lists break down into two sub-categories: circular
> > lists, and lists with non-pair-non-nil terminating CDRs.  The
> > sloppiness I was referring to above was using the term "improper list"
> > to refer exclusively to refer to improper lists of the second kind,
> > since they are the ones that tend to cause problems (and are, IMO, a
> > reliable indicator of poor software design).  A proper cons cannot be
> > used to create improper lists of the second kind.
>
> It could even be possible to restrict rplacd / (setf cdr) to check for
> the existence of a proper-cons, and if so, to ensure that the value to
> set is then also a proper-cons _and_ to walk the cdrs of that value to
> ensure that no cons cell matches the one being modified.  This would
> ensure that proper-cons cells could only construct proper-lists.

What I'm actually advocating is not proper-cons but non-dotted-cons.
Circular lists are OK.

> But none of this would not ensure that proper-lists could only be
> constructed out of proper-cons cells.

That's right.  If someone wishes not to avail themselves of the safety
that non-dotted-cons would provide there is no way to force them to do
it.  This is not unlike the debates that take place over adding safe
pointers or array bound checking to C.

> At Franz, we file rfes (requests for enhancement) even for things that
> are not likely to occur.  I have filed such an rfe for proper-cons.

Well, I brought up proper-cons (which should properly be called non-
dotted-cons) along with immutable-cons more as a thought experiment
than a serious proposal.  The overarching point here is that NIL not
being a CONS is not justifiable on first principles in light of the
fact that the CAR and CDR of NIL are well defined.

rg
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <580f5ceb-3f5b-47c6-9cc3-0f62cd94946f@d4g2000prg.googlegroups.com>
On Dec 22, 2:17 pm, Ron Garret <····@flownet.com> wrote:

> Well, I brought up proper-cons

Heh, I just realized that I didn't bring up proper-cons, Duane did :-)

The reason I thought I had brought it up is because proper-cons (which
should properly be called non-dotted-cons) is an idea that I have
batted around in the past, and I'm on the road right now so I have to
use the b0rken Google Groups UI to participate in this discussion.
Among other annoying features, it doesn't let you go back and read the
context of a discussion without losing the response you are in the
process of composing.

I just wanted to clarify the extent of my advocacy for proper-cons. I
do think it would be beneficial, but it's very far from the top of my
list of potential enhancements.

rg
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <uk5n6m4cn.fsf@nhplace.com>
Ron Garret <···@flownet.com> writes:

> I just wanted to clarify the extent of my advocacy for proper-cons. I
> do think it would be beneficial, but it's very far from the top of my
> list of potential enhancements.

Ah, so it's you that's not taking your idea seriously, not us.  Some
of the pushback you probably perceive is that people were taking your
suggestion seriously and trying to see if they could live with the
idea.  I think they ran into some legitimate concerns, which you may
see as rejection of your ideas, rather than as embracing a dialog
about your ideas.

It would be surprising if these ideas were not already thoroughly
explored in Abelson's "Boxer", btw.  I wish someone here knew how the
corresponding issues worked there.  Maybe someone has time to research
online papers/manuals and find out if anything says what they offered
in that language in the way of primitives (perhaps to be reported back
here).  One reason I post so much about history here is that it can
usefully inform things without making one have to relive history... in
this case, this is history I don't know about, and only know of, but
it seems it would be similarly worthwhile.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5a020dd6-75e3-43e8-9f70-ec24ee8dd3e9@s8g2000prg.googlegroups.com>
On Dec 22, 8:18 pm, Kent M Pitman <······@nhplace.com> wrote:
> Ron Garret <····@flownet.com> writes:
> > I just wanted to clarify the extent of my advocacy for proper-cons. I
> > do think it would be beneficial, but it's very far from the top of my
> > list of potential enhancements.
>
> Ah, so it's you that's not taking your idea seriously, not us.

Proper-cons wasn't my idea (at least not in this discussion), it was
Duane's.  Immutable cons was my idea, and I do think that would be a
useful addition (but still not at the top of my list).

> Some
> of the pushback you probably perceive is that people were taking your
> suggestion seriously and trying to see if they could live with the
> idea.  I think they ran into some legitimate concerns, which you may
> see as rejection of your ideas, rather than as embracing a dialog
> about your ideas.

No, I didn't see it that way.  I thought this was on the whole a
pretty civilized discussion, particularly by the standards of
C.L.L.  ;-)

rg
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <uodcim4jq.fsf@nhplace.com>
Ron Garret <···@flownet.com> writes:

> What I'm actually advocating is not proper-cons but non-dotted-cons.
> Circular lists are OK.

(mapcar #'(lambda (x) x) '#1=(3 . #1#))

is the reason that circular lists are disallowed in CL's mapcar; so
that it won't just loop forever.  That is, it's considered that people
should not write infinite loops this way.  The present wording is, as
is frequently noted, annoyingly over-restrictive because it disallows
the fairly useful construction:

(mapcar #'+ '(1 2 3 4) '#1=(3 . #1#))

which won't loop forever.

Hence, what several people have noted is that it is simply not true that
MAPCAR could just look at the type and know it didn't have to check unless
(a) It jumped to a special routine that did the same things as the loop
    over conses (which still have to be supported) but bypassed the dotted
    check, AND
(b) It still checked for infinite loops.

Unless you want to change the contract of MAPCAR, of course.

> The overarching point here is that NIL not being a CONS is not
> justifiable on first principles in light of the fact that the CAR
> and CDR of NIL are well defined.

Languages ought not be designed or justified on the basis of deriving
the meaning of something from the set of operations on it.  That would
be like saying if a language allowed WRITE-CHAR on an integer to
output the character's code, one would no longer have any moral
justification for saying that characters are different than codes.  I
don't think that's so.  It think this neglects some large areas that
influence language design called things "abstraction", "coding style",
etc.  One simply does not, by virtue of having provided a couple of
convenience functions, relinquish the right to draw a line of
demarcation around abstraction.  Nor do I acknowledge any implication
that abstraction and coding style are second-class principles (that
is, I don't know what "first principles" connotes here with adequate
specificity to know what debate tools are at my disposal, but I
certainly won't allow myself to be reduced in my defense of how a
language is specified to not appealing to such things, illogical and
irrational as those things sometimes are).

Incidentally, I don't mean to say some of your points in here are
unreasonable observations.  I think you got some interesting
discussion out of this.  I think it detracts from that discussion to
try to push it overly far.  I think some of the concerns raised have
been rational as well, and if you want people to treat your
observations with due respect, I think it's good to treat some of the
resulting criticisms with equal respect, to include not saying people
can't justify their desire to exclude that implementation.  I think
you can probably justify your desire to have that definition, but you
cannot UNIQUELY justify your desire such that you can exclude people's
desire to have it otherwise.  In pushing for what seems to me
exclusivity or logical undeniability of your position, I see you
losing the otherwise reasonable foothold you've established.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <cbde0d53-ade5-442b-b7e7-109d7e8452d8@d4g2000prg.googlegroups.com>
On Dec 22, 8:13 pm, Kent M Pitman <······@nhplace.com> wrote:
> Ron Garret <····@flownet.com> writes:
> > What I'm actually advocating is not proper-cons but non-dotted-cons.
> > Circular lists are OK.
>
> (mapcar #'(lambda (x) x) '#1=(3 . #1#))
>
> is the reason that circular lists are disallowed in CL's mapcar; so
> that it won't just loop forever.  That is, it's considered that people
> should not write infinite loops this way.

Why not?

> The present wording is, as
> is frequently noted, annoyingly over-restrictive because it disallows
> the fairly useful construction:
>
> (mapcar #'+ '(1 2 3 4) '#1=(3 . #1#))
>
> which won't loop forever.

Indeed.

> Hence, what several people have noted is that it is simply not true that
> MAPCAR could just look at the type and know it didn't have to check unless
> (a) It jumped to a special routine that did the same things as the loop
>     over conses (which still have to be supported) but bypassed the dotted
>     check, AND
> (b) It still checked for infinite loops.
>
> Unless you want to change the contract of MAPCAR, of course.

That would be my preference.

> > The overarching point here is that NIL not being a CONS is not
> > justifiable on first principles in light of the fact that the CAR
> > and CDR of NIL are well defined.
>
> Languages ought not be designed or justified on the basis of deriving
> the meaning of something from the set of operations on it.

Why not?  That's pretty much what Python does.  (Maybe I just answered
my own question ;-)

> That would
> be like saying if a language allowed WRITE-CHAR on an integer to
> output the character's code, one would no longer have any moral
> justification for saying that characters are different than codes.

No, because the set of operations on characters and integers are still
different.  In C, for example, characters and integers have the same
operations, and indeed one could say (and people often do) that they
are the same data type.  It is not a coincidence that there is no char-
code in the C standard library.

> I don't think that's so.  It think this neglects some large areas that
> influence language design called things "abstraction", "coding style",
> etc.  One simply does not, by virtue of having provided a couple of
> convenience functions, relinquish the right to draw a line of
> demarcation around abstraction.

You do when the abstraction is indistinguishable from some other
abstraction.  Consider:

? (defconstant rnil '#1=(#1# . #1#))
RNIL
? (defmethod print-object ((n (eql rnil)) stream) (format stream
"rnil"))
#<STANDARD-METHOD PRINT-OBJECT ((EQL rnil) T)>
? rnil
rnil
? (car rnil)
rnil
? (cdr rnil)
rnil
? (consp rnil)
T

RNIL is almost indistinguishable from NIL.  We can make completely
indistinguishable by:

(hypothetical-defmethod null ((n (eql rnil))) t)
(hypothetical-defmethod atom ((n (eql rnil))) t)
(hypothetical-defmethod symbolp ((n (eql rnil))) t)
(hypothetical-defmethod consp ((n (eql rnil))) nil)

But notice that to make RNIL be a serviceable replacement for NIL only
the first (and maybe the second depending on your coding style) of
these is needed.  In light of this, I think it is untenable to argue
that NIL's non-consness is anything other than completely arbitrary.

> Nor do I acknowledge any implication
> that abstraction and coding style are second-class principles (that
> is, I don't know what "first principles" connotes here with adequate
> specificity to know what debate tools are at my disposal, but I
> certainly won't allow myself to be reduced in my defense of how a
> language is specified to not appealing to such things, illogical and
> irrational as those things sometimes are).

I have not been following the entire discussion so it's possible that
I missed something, but the only argument I've seen for NIL's non-
consness is an abstract one to the effect of "it's that way because
Lisp derives from logic, and the rules of logic compel it."  It's
possible that there is some other argument based on more pragmatic
considerations, and that would certainly be legitimate.  But the only
such argument I can imagine is something along the lines of: it lets
you test for the end of lists using ATOM.  But there's no reason why
NIL could not answer true to both ATOM and CONSP.  Considering CONSP
(or ATOM) to be a hypothetical generic function that special-cases NIL
is no more (and no less) arbitrary than treating CAR and CDR that way.

> Incidentally, I don't mean to say some of your points in here are
> unreasonable observations.

I didn't think you were.

> I think some of the concerns raised have been rational as well

Why, thank you.  :-)

> I think
> you can probably justify your desire to have that definition, but you
> cannot UNIQUELY justify your desire such that you can exclude people's
> desire to have it otherwise.  In pushing for what seems to me
> exclusivity or logical undeniability of your position, I see you
> losing the otherwise reasonable foothold you've established.

Well, my position is that the consness of NIL is arbitrary.  I have
argued for that position by presenting a self-consistent definition of
NIL that is CONSP, and which is no more complex than the extant
definition.  I think that constitutes a sound argument.

Now, I also happen to think that NIL should be CONSP, but I do not
(and never have) claimed that that position is anything other than
completely arbitrary.  Indeed, it would be the height of hypocrisy for
me to do that after arguing that any position on that issue is
arbitrary.

rg
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <59cbb2ef-ce95-490b-8d77-f78d52eb1e6a@b40g2000prf.googlegroups.com>
On Dec 22, 10:26 am, Duane Rettig <·····@franz.com> wrote:

> At Franz, we file rfes (requests for enhancement) even for things that
> are not likely to occur.  I have filed such an rfe for proper-cons.

Having now given this a bit more thought, I think that immutable-cons
would actually be more useful than proper-cons (or even non-dotted-
cons :-)  Immutable conses would probably be subject to all sorts of
optimizations, and would probably make the GC happy too.  And if
desired, the non-dottedness of immutable conses can be computed in
constant time when they are constructed, so immutable-cons subsumes
non-dotted-cons, at least for the purposes to which I wanted to put
it.

So to the extent that my opinion matters, I would suggest changing
this RFE accordingly.

rg
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <87eb1392-5485-47af-8280-67410ec721ea@s12g2000prg.googlegroups.com>
On Dec 22, 6:05 pm, Ron Garret <····@flownet.com> wrote:
> On Dec 22, 10:26 am, Duane Rettig <·····@franz.com> wrote:
>
> > At Franz, we file rfes (requests for enhancement) even for things that
> > are not likely to occur.  I have filed such an rfe for proper-cons.
>
> Having now given this a bit more thought, I think that immutable-cons
> would actually be more useful than proper-cons (or even non-dotted-
> cons :-)  Immutable conses would probably be subject to all sorts of
> optimizations, and would probably make the GC happy too.  And if
> desired, the non-dottedness of immutable conses can be computed in
> constant time when they are constructed, so immutable-cons subsumes
> non-dotted-cons, at least for the purposes to which I wanted to put
> it.

I agree with Ron here, immutable cons would be a useful type to
have :-).  Especially if

  (compile
   (defun oops (key amount)
     (let ((plist '(a 1 b 10 c 100)))
       (incf (getf key plist) amount))))

  (oops 'c 11)

gave an error "modifying an immutable list" or something.
From: Kent M Pitman
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <u8x3kwun0.fsf@nhplace.com>
"Thomas F. Burdick" <········@gmail.com> writes:

> On Dec 22, 6:05 pm, Ron Garret <····@flownet.com> wrote:
> > On Dec 22, 10:26 am, Duane Rettig <·····@franz.com> wrote:
> >
> > > At Franz, we file rfes (requests for enhancement) even for things that
> > > are not likely to occur.  I have filed such an rfe for proper-cons.
> >
> > Having now given this a bit more thought, I think that immutable-cons
> > would actually be more useful than proper-cons (or even non-dotted-
> > cons :-)  Immutable conses would probably be subject to all sorts of
> > optimizations, and would probably make the GC happy too.  And if
> > desired, the non-dottedness of immutable conses can be computed in
> > constant time when they are constructed, so immutable-cons subsumes
> > non-dotted-cons, at least for the purposes to which I wanted to put
> > it.
> 
> I agree with Ron here, immutable cons would be a useful type to
> have :-).  Especially if
> 
>   (compile
>    (defun oops (key amount)
>      (let ((plist '(a 1 b 10 c 100)))
>        (incf (getf key plist) amount))))
> 
>   (oops 'c 11)
> 
> gave an error "modifying an immutable list" or something.

Is what you really want an immutable list in particular, or the ability
to notate a literal datum as intended to be allocated in (or copied to)
read-only memory?  [The latter is what MACLISP did.]
  http://www.maclisp.info/pitmanual/system.html#24.31.4

I think it would be upward-compatible for a Common Lisp implementation
to simply enforce that anything that was seen by QUOTE would be
allocated in read-only space, at least in file-compiled code... I'd
have to look in more detail at the spec to make sure that for
compiled-in-memory code it was ok to do this, since it's been a while.

But really, if you intend to rely on the identity or modifiability of
a literal datum, LOAD-TIME-VALUE is the way to go.  So I don't see a
reason for QUOTE to bear that load.

(I think the wording in the spec was still tangled at the time we went
to press. I'm pretty sure it was on my to-do list to fix it and that I
just didn't get to it in time.  There was a seemingly endless list of
such things that I was mapping over... so to speak.)
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <606f4469-726e-4628-b8b0-a03336f72cd1@b40g2000prf.googlegroups.com>
On Dec 22, 8:33 am, Ron Garret <····@flownet.com> wrote:

> (N.B. The mere fact that I need to coin a term like improper-list-of-
> the-second-kind to even talk about this problem with precision is an
> indication that something is deeply wrong with the current state of
> affairs.)

You could very well have used "dotted list".

> > > [1]> (mapcar '1+ '(1 . 2))
>
> > > *** - MAPCAR: A proper list must not end with 2
> > > The following restarts are available:
> > > ABORT          :R1      ABORT
>
> > > which in my experience is very common and often hard to debug.
>
> > Yes; often one has to depend on the backtrace for situations like
> > that, to aid in getting the context of the failure.
>
> Indeed.  IMO the world would be a better place if one could reliably
> prevent such errors from happening to begin with.

In the narrowest possible sense, proper-conses prevent this error from
happening.  They're not a shortcut around understanding what conses
do, though.  The situation you get is that instead of producing

  (1 2 . 3)

the same person will instead produce

  (1 (2 (3)))
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <1722bca7-65d9-421a-8ebf-7c072ce4b080@e23g2000prf.googlegroups.com>
On Dec 22, 10:40 am, "Thomas F. Burdick" <········@gmail.com> wrote:
> On Dec 22, 8:33 am, Ron Garret <····@flownet.com> wrote:
>
> > (N.B. The mere fact that I need to coin a term like improper-list-of-
> > the-second-kind to even talk about this problem with precision is an
> > indication that something is deeply wrong with the current state of
> > affairs.)
>
> You could very well have used "dotted list".

Ah.  So I could.  (And so I will :-)  And I also hereby withdraw my
comment about something being deeply wrong.

> > > > [1]> (mapcar '1+ '(1 . 2))
>
> > > > *** - MAPCAR: A proper list must not end with 2
> > > > The following restarts are available:
> > > > ABORT          :R1      ABORT
>
> > > > which in my experience is very common and often hard to debug.
>
> > > Yes; often one has to depend on the backtrace for situations like
> > > that, to aid in getting the context of the failure.
>
> > Indeed.  IMO the world would be a better place if one could reliably
> > prevent such errors from happening to begin with.
>
> In the narrowest possible sense, proper-conses prevent this error from
> happening.  They're not a shortcut around understanding what conses
> do, though.  The situation you get is that instead of producing
>
>   (1 2 . 3)
>
> the same person will instead produce
>
>   (1 (2 (3)))

I don't understand that.  proper-cons and cons do the same thing,
except for some additional type-checking.  So I don't see why
introducing proper-cons would cause someone to produce a completely
different data structure.  If you really want (1 2 . 3) (which I still
maintain ought to be a very rare circumstance) then you wouldn't use
proper-cons.

rg
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <f11f5e65-0f30-40cb-98d5-b7a1f60a16a7@t1g2000pra.googlegroups.com>
On Dec 22, 1:28 pm, Ron Garret <····@flownet.com> wrote:

> On Dec 22, 10:40 am, "Thomas F. Burdick" <········@gmail.com> wrote:
>
> > > > > [1]> (mapcar '1+ '(1 . 2))
>
> > > > > *** - MAPCAR: A proper list must not end with 2
> > > > > The following restarts are available:
> > > > > ABORT          :R1      ABORT
>
> > > > > which in my experience is very common and often hard to debug.
>
> > > > Yes; often one has to depend on the backtrace for situations like
> > > > that, to aid in getting the context of the failure.
>
> > > Indeed.  IMO the world would be a better place if one could reliably
> > > prevent such errors from happening to begin with.
>
> > In the narrowest possible sense, proper-conses prevent this error from
> > happening.  They're not a shortcut around understanding what conses
> > do, though.  The situation you get is that instead of producing
>
> >   (1 2 . 3)
>
> > the same person will instead produce
>
> >   (1 (2 (3)))
>
> I don't understand that.  proper-cons and cons do the same thing,
> except for some additional type-checking.  So I don't see why
> introducing proper-cons would cause someone to produce a completely
> different data structure.  If you really want (1 2 . 3) (which I still
> maintain ought to be a very rare circumstance) then you wouldn't use
> proper-cons.

Well, I was referring to the situation where someone consed up (1 2 .
3) on accident, by starting their accumulation by consing onto the
last element, rather than the list of the last element.  My experience
with newbies in CL, Scheme, and elisp is that that's a pretty common
mistake until cons cells "click" for them.  In SKILL, you get the same
difficulty getting cons cells straight, but they tend to produce
things more like (1 (2 (3))) because there are no dotted pairs in the
language (even though consp is spelled dtpr ["dotted pair"] like it
was in Franz Lisp).

As for the legitimate circumstance for having something like (1 2 .
3), it would be if you're building a tree out of cons cells, so it's
not really a list anyhow.  In SKILL you'd always use (1 2 3) there,
but if 1 2 and 3 are sub-nodes rather than numbers, it really doesn't
make much of a difference either way.  You should be using defstruct
or defclass in either language :-)

For your concern about dotted lists, I wonder where you think they
would have come from, that having a non-dotted-cons (ndcons?) would
have helped.

It's a bit neither here nor there, but I think that not having proper
cons cells (turning the terminology so far on its head) discourages
you from using alists and encourages plists, since ((a . 1) (b . 2))
uses the same number of cons cells as (a 1 b 2), but ((a 1) (b 2))
uses more.  I don't have an absolute preference for plists or alists,
but to filter plists you need to use mapcan, which undoes all the
newbie friendliness you might expect to come from non-dotted conses.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <06795f86-93d9-46a6-bf24-f00b2f9577ad@a35g2000prf.googlegroups.com>
On Dec 23, 11:38 am, "Thomas F. Burdick" <········@gmail.com> wrote:

> For your concern about dotted lists, I wonder where you think they
> would have come from, that having a non-dotted-cons (ndcons?) would
> have helped.

I have no idea where they came from (that's part of the problem!)  I
just know that I have often encountered situations in complex systems
where mapcar bombed because it got fed a dotted list from somewhere.

> It's a bit neither here nor there, but I think that not having proper
> cons cells (turning the terminology so far on its head) discourages
> you from using alists and encourages plists, since ((a . 1) (b . 2))
> uses the same number of cons cells as (a 1 b 2), but ((a 1) (b 2))
> uses more.  I don't have an absolute preference for plists or alists,
> but to filter plists you need to use mapcan, which undoes all the
> newbie friendliness you might expect to come from non-dotted conses.

This is getting off-topic, but IMO plist vs alist is not something
newbies ought to be concerned about at all.  Newbies should be
presented with an abstract associative mapping type with underlying
implementations that can be swapped in and out (e.g.
http://www.flowet.com/ron/lisp/dictionary.lisp)  Actually implementing
an underlying implementation (or even choosing one for that matter)
ought to be considered an intermediate exercise, not a beginning one.
IMHO.

rg
From: vanekl
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <b314d437-e3f6-4acb-95c6-1f548885d3f4@l32g2000hse.googlegroups.com>
http://www.flownet.com/ron/lisp/dictionary.lisp
From: Ken Tilton
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <476bfb0f$0$31139$607ed4bc@cv.net>
Edi Weitz wrote:
> On Thu, 20 Dec 2007 22:55:06 -0600, ····@rpw3.org (Rob Warnock) wrote:
> 
> 
>>Ron Garret  <···@flownet.com> wrote:
>>+---------------
>>| "Thomas F. Burdick" <········@gmail.com> wrote:
>>| > Mapcar and friends *don't* have to signal an error when given an
>>| > improper list
>>| 
>>| Maybe not, but I've never encountered a CL implementation that didn't.
>>+---------------
>>
>>Let me introduce you to one:
>>
>>    $ cmucl
>>    ...[chatter]...
>>    cmucl> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>>
>>    (111 122 133)
>>    cmucl> 
>>
>>And another:
>>
>>    $ clisp -q
>>    [1]> (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>>    (111 122 133)
>>    [2]> 
>>
>>And another:
>>
>>    $ telnet prompt.franz.com
>>    ...[chatter]...
>>    This development copy of Allegro CL is licensed to:
>>       QA
>>    ...[chatter]...
>>    CL-USER(1): (mapcar #'+ '(1 2 3) '#1=(100 . #1#) '(10 20 30 40 . 50))
>>    (111 122 133)
>>    CL-USER(2): 
>>
>>Now you've encountered three!!  ;-}
> 
> 
> Hehe.  Not that facts matter in a Usenet discussion, but LispWorks,
> OpenMCL, and SBCL don't signal an error for me either when asked to
> evaluate this form.
> 
> Maybe Ron can simply give us a list of the CL implementation he /has/
> encountered so far, then we know what we're talking about... :)

Speaking of encountering, why are youse guys using a test case in which 
mapcar will not encounter the impropriety?

ACL:

(mapcar #'+ '(1 2 3 4 5 6) '#1=(100 . #1#) '(10 20 30 40 . 50))

-> Error: Attempt to take the car of 50 which is not listp.

kt
From: Edi Weitz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <ur6hfuaxh.fsf@agharta.de>
On Fri, 21 Dec 2007 12:42:38 -0500, Ken Tilton <···········@optonline.net> wrote:

> Speaking of encountering, why are youse guys using a test case in
> which mapcar will not encounter the impropriety?

See Thomas' reply.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Pascal J. Bourguignon
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <7cmys4ymf9.fsf@simias.anevia.com>
Edi Weitz <········@agharta.de> writes:

> On Thu, 20 Dec 2007 22:55:06 -0600, ····@rpw3.org (Rob Warnock) wrote:
>
>> Ron Garret  <···@flownet.com> wrote:
>> +---------------
>> | "Thomas F. Burdick" <········@gmail.com> wrote:
>> | > Mapcar and friends *don't* have to signal an error when given an
>> | > improper list
>> | 
>> | Maybe not, but I've never encountered a CL implementation that didn't.
>> +---------------
>>
>> Let me introduce you to one:
>> [...]
>> Now you've encountered three!!  ;-}
>
> Hehe.  Not that facts matter in a Usenet discussion, but LispWorks,
> OpenMCL, and SBCL don't signal an error for me either when asked to
> evaluate this form.
>
> Maybe Ron can simply give us a list of the CL implementation he /has/
> encountered so far, then we know what we're talking about... :)


On the other hand, I'd bet most of them signal an error in this case:

C/USER[32]> (mapcar (function +) '(1 2 . 3) '(30 20 . 10))

*** - MAPCAR: A proper list must not end with 3
The following restarts are available:
ABORT          :R1      ABORT
C/Break 1 USER[33]> 


-- 
__Pascal Bourguignon__
·························@anevia.com
http://www.anevia.com
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <d38211ad-d5ff-4c37-86e0-f6d4c2849bf8@v4g2000hsf.googlegroups.com>
On Dec 18, 2:34 pm, Ron Garret <·········@flownet.com> wrote:
> In article <·············@nhplace.com>,
>  Kent M Pitman <······@nhplace.com> wrote:
> > Actually, the design of lists, built recursively from conses, is based
> > directly on logic.  The CONS datatype exists in most Lisp dialects,
> > not just Common Lisp; in a few it is called PAIR.  But as the name
> > PAIR makes clear, NIL (not being a pair) would be an inappropriate
> > member of the set of all pairs.
>
> Not necessarily.  NIL does behave like an immutable pair whose CAR and
> CDR are NIL.  i.e. NIL behaves as if its definition were something along
> the lines of:
>
> #1=(#1# . #1#)
>
> except that the CAR and CDR of the resulting CONS cell are immutable.

Yes, there is always that pesky ``except'', isn't there!

If we conveniently ignore any differences between them, any two
things, no
matter how unlike, can be regarded to be alike.

An object with immutable slots is simply not a subtype of an object
with mutable slots. It can't do everything that the mutable object can
do and is therefore not substitutable for it.

A CONS can be subject to RPLACA and RPLACD, which blow up on NIL.

They would also blow up on immutable conses, if Lisp had them, which
is why such conses couldn't (or shouldn't) be subtyped from regular
conses. It's not clear that the subtyping could go the other way
either.

The problem is that changing slots from mutable to immutable OR vice
versa is a forward-and-backward-incompatible change which wrecks all
chances of a subtyping relationship. The immutability of a slot is a
special capability which a mutable slot lacks, and likewise the
mutability of a slot is a special capability which an immutable slot
lacks.

A type with mutable slots could be derived from a type with readable
slots whose mutability is unknown: a base type whose slots are not
required to support assignment, but whose values cannot be relied upon
to be stable, either. The immutable subtype strengthens the type with
predicates of stability. The mutable subtype strengthens the type with
predicates regarding the correct execution of a storage operation, and
the postcondition regarding the most recently stored value being the
one that is retrieved.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <rNOSPAMon-BF1BA9.00442719122007@news.gha.chartermi.net>
In article 
<····································@v4g2000hsf.googlegroups.com>,
 Kaz Kylheku <········@gmail.com> wrote:

> On Dec 18, 2:34 pm, Ron Garret <·········@flownet.com> wrote:
> > In article <·············@nhplace.com>,
> >  Kent M Pitman <······@nhplace.com> wrote:
> > > Actually, the design of lists, built recursively from conses, is based
> > > directly on logic.  The CONS datatype exists in most Lisp dialects,
> > > not just Common Lisp; in a few it is called PAIR.  But as the name
> > > PAIR makes clear, NIL (not being a pair) would be an inappropriate
> > > member of the set of all pairs.
> >
> > Not necessarily.  NIL does behave like an immutable pair whose CAR and
> > CDR are NIL.  i.e. NIL behaves as if its definition were something along
> > the lines of:
> >
> > #1=(#1# . #1#)
> >
> > except that the CAR and CDR of the resulting CONS cell are immutable.
> 
> Yes, there is always that pesky ``except'', isn't there!
> 
> If we conveniently ignore any differences between them, any two
> things, no matter how unlike, can be regarded to be alike.

That's true.  So what?

> An object with immutable slots is simply not a subtype of an object
> with mutable slots. It can't do everything that the mutable object can
> do and is therefore not substitutable for it.

Then how do you account for this:

[1]> (subtypep 'string 'vector)
T ;
T
[2]> (setf (elt (vector #\a #\b #\c) 0) 0)
0
[3]> (setf (elt "foo" 0) 0)

*** - SYSTEM::STORE: 0 does not fit into "foo", bad type
The following restarts are available:
ABORT          :R1      ABORT


(Here's a hint: look up the Liskov Substitution Principle, and in 
particular why no OO language actually adheres to it.)

> A CONS can be subject to RPLACA and RPLACD, which blow up on NIL.

Yes, but that is an implementation detail, and a controversial one in 
the context of a discussion that begins (as this one did) with the 
statement, "the design of lists, built recursively from conses, is based 
directly on logic."

BTW, I never said that immutable pairs should be a subtype of pairs (or 
vice-versa).  They could be disjoint, but then it would make sense to 
define e.g. CONSP to return T if its argument were either a pair or an 
immutable pair.

rg
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <e582fa88-65c0-472b-be73-8f666205b980@p69g2000hsa.googlegroups.com>
On Dec 19, 12:44 am, Ron Garret <·········@flownet.com> wrote:
> > An object with immutable slots is simply not a subtype of an object
> > with mutable slots. It can't do everything that the mutable object can
> > do and is therefore not substitutable for it.
>
> Then how do you account for this:
>
> [1]> (subtypep 'string 'vector)
> T ;
> T
> [2]> (setf (elt (vector #\a #\b #\c) 0) 0)
> 0
> [3]> (setf (elt "foo" 0) 0)


[1]> (type-of (vector #\a #\b #\c))
(SIMPLE-VECTOR 3)
[2]> (type-of "foo")
(SIMPLE-BASE-STRING 3)
[1]> (subtypep (type-of "foo") (type-of (vector #\a #\b #\c)))
NIL ;
T

A string isn't a subtype of the kind of generic simple vector that is
made by the VECTOR function.

In this Lisp system, I don't actually have any way of creating
something whose type is VECTOR.

Since such a beast doesn't actually exist, it doesn't have assignable
slots.

A method which accepts VECTOR arguments, and stores data in their
slots is making unwarranted assumptions about their subtyping.
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <51914d1a-62b1-4d8b-8c08-a6d080794203@b40g2000prf.googlegroups.com>
On Dec 19, 11:14 am, Kaz Kylheku <········@gmail.com> wrote:
> On Dec 19, 12:44 am,RonGarret<·········@flownet.com> wrote:
>
> > > An object with immutable slots is simply not a subtype of an object
> > > with mutable slots. It can't do everything that the mutable object can
> > > do and is therefore not substitutable for it.
>
> > Then how do you account for this:
>
> > [1]> (subtypep 'string 'vector)
> > T ;
> > T
> > [2]> (setf (elt (vector #\a #\b #\c) 0) 0)
> > 0
> > [3]> (setf (elt "foo" 0) 0)
>
> [1]> (type-of (vector #\a #\b #\c))
> (SIMPLE-VECTOR 3)
> [2]> (type-of "foo")
> (SIMPLE-BASE-STRING 3)
> [1]> (subtypep (type-of "foo") (type-of (vector #\a #\b #\c)))
> NIL ;
> T
>
> A string isn't a subtype of the kind of generic simple vector that is
> made by the VECTOR function.

I never said that it was.  I just said it was a sub-type of vector.

> In this Lisp system, I don't actually have any way of creating
> something whose type is VECTOR.

[1]> (typep #(1 2 3) 'vector)
T

> A method which accepts VECTOR arguments, and stores data in their
> slots is making unwarranted assumptions about their subtyping.

That may well be, but the point is that the vector type does exist
(even if it is an abstract type).  On your view, if vector does not
have assignable slots, none of its sub-types can have assignable slots
either.  And yet they do.

rg
From: tim Josling
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <13mjp0kdnli0rb5@corp.supernews.com>
On Wed, 19 Dec 2007 00:44:27 -0800, Ron Garret wrote:

> In article 
> <····································@v4g2000hsf.googlegroups.com>,
>  Kaz Kylheku <········@gmail.com> wrote:
> 
>> On Dec 18, 2:34 pm, Ron Garret <·········@flownet.com> wrote:
>> ...
> 
>> An object with immutable slots is simply not a subtype of an object
>> with mutable slots. It can't do everything that the mutable object can
>> do and is therefore not substitutable for it.
> 
> Then how do you account for this:
> 
> [1]> (subtypep 'string 'vector)
> T ;
> T
> [2]> (setf (elt (vector #\a #\b #\c) 0) 0)
> 0
> [3]> (setf (elt "foo" 0) 0)
> ...
> rg

You left out the type that's all, I think:

In gcl:

?(setf aa (make-array '(3) :element-type 'character))

"   "

?(type-of aa)

STRING

?(setf (aref aa 0) nil)

Error: Expected a CHARACTER 

?(setf (aref aa 0) #\b))

#\b

?aa

"b  "

?(setf (aref "aaa" 0) #\b)

#\b

Presumably it amended the literal and then discarded it.

Tim Josling
From: Ron Garret
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <117feaf0-8586-4990-bbbe-5618b2309845@e25g2000prg.googlegroups.com>
On Dec 19, 7:40 pm, tim Josling <·············@westnet.com.au> wrote:
> On Wed, 19 Dec 2007 00:44:27 -0800, Ron Garret wrote:
> > In article
> > <····································@v4g2000hsf.googlegroups.com>,
> >  Kaz Kylheku <········@gmail.com> wrote:
>
> >> On Dec 18, 2:34 pm, Ron Garret <·········@flownet.com> wrote:
> >> ...
>
> >> An object with immutable slots is simply not a subtype of an object
> >> with mutable slots. It can't do everything that the mutable object can
> >> do and is therefore not substitutable for it.
>
> > Then how do you account for this:
>
> > [1]> (subtypep 'string 'vector)
> > T ;
> > T
> > [2]> (setf (elt (vector #\a #\b #\c) 0) 0)
> > 0
> > [3]> (setf (elt "foo" 0) 0)
> > ...
> > rg
>
> You left out the type that's all, I think:
>
> In gcl:
>
> ?(setf aa (make-array '(3) :element-type 'character))
>
> "   "
>
> ?(type-of aa)
>
> STRING
>
> ?(setf (aref aa 0) nil)
>
> Error: Expected a CHARACTER
>
> ?(setf (aref aa 0) #\b))
>
> #\b
>
> ?aa
>
> "b  "
>
> ?(setf (aref "aaa" 0) #\b)
>
> #\b
>
> Presumably it amended the literal and then discarded it.
>
> Tim Josling

You're missing the point, which is that Lisp does not obey the Liskov
Substitution Principle.  The particular counterexample is that strings
are sub-types of vector, but you can do things with vectors that you
can't do with strings.

That is perhaps a poor example because (vector #\a #\b #\c) is not
just a vector but a (simple-vector 3).  So here's a better example:

[14]> (subtypep '(simple-vector 0) '(simple-vector *))
T ;

But on Kaz's theory of subtypes this is not possible because a (simple-
vector 0) is not a valid argument to elt, whereas a (simple-vector *)
(usually) is.

rg
From: Thomas F. Burdick
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <54088d68-9b6d-45c4-b576-63ce089c30f5@e10g2000prf.googlegroups.com>
On Dec 18, 10:32 pm, Kaz Kylheku <········@gmail.com> wrote:



> On Dec 18, 2:34 pm, Ron Garret <·········@flownet.com> wrote:
>
> > In article <·············@nhplace.com>,
> >  Kent M Pitman <······@nhplace.com> wrote:
> > > Actually, the design of lists, built recursively from conses, is based
> > > directly on logic.  The CONS datatype exists in most Lisp dialects,
> > > not just Common Lisp; in a few it is called PAIR.  But as the name
> > > PAIR makes clear, NIL (not being a pair) would be an inappropriate
> > > member of the set of all pairs.
>
> > Not necessarily.  NIL does behave like an immutable pair whose CAR and
> > CDR are NIL.  i.e. NIL behaves as if its definition were something along
> > the lines of:
>
> > #1=(#1# . #1#)
>
> > except that the CAR and CDR of the resulting CONS cell are immutable.
>
> Yes, there is always that pesky ``except'', isn't there!

*yawn*

[snip]

> A CONS can be subject to RPLACA and RPLACD, which blow up on NIL.
>
> They would also blow up on immutable conses, if Lisp had them, which
> is why such conses couldn't (or shouldn't) be subtyped from regular
> conses.

Right, Lisp doesn't have immutable conses, because rplaca would blow
up on them, just like it's not allowed to on these:

  (defun please (engage)
    (let ((brain '(before mouth)))
      (rplaca brain engage)))

Oh wait, it would be legal for rplaca to throw an error there,
wouldn't it?
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sq4l0F19sraqU1@mid.individual.net>
Javier wrote:
> vanekl ha escrito:
> 
>> The value NIL is not of type CONS.
>>    [Condition of type TYPE-ERROR]
> 
> Just one more inconsistence of Common Lisp.
> The more you discover about these inconsistencies, the more you
> discover how much CL sucks.
> 
> If the empty list is NIL, then NIL should be of type CONS. For me,
> this should be the logical behavior.

A CONS is not a list. A CONS is a CONS.

It's just a convention to implement lists with conses and nil (and 
mentioning these ingredients is not even the complete picture).

If you want the list type, use the type LIST.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: John Thingstad
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <op.t3jdetv7ut4oq5@pandora.alfanett.no>
P� Tue, 18 Dec 2007 14:12:20 +0100, skrev Javier <·······@gmail.com>:

> vanekl ha escrito:
>
>> The value NIL is not of type CONS.
>>    [Condition of type TYPE-ERROR]
>
> Just one more inconsistence of Common Lisp.
> The more you discover about these inconsistencies, the more you
> discover how much CL sucks.
>
> If the empty list is NIL, then NIL should be of type CONS. For me,
> this should be the logical behavior.

Have you listened.. There is a type LIST which does include the type NIL.
CONS is a tuple of places or atoms. It is not a list. No more than a node  
is a tree.

use listp rather than consp

--------------
John Thingstad
From: Tim Bradshaw
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <a597a0c9-9f26-45f1-a1d3-c41752411fda@b1g2000pra.googlegroups.com>
On Dec 18, 3:02 pm, "John Thingstad" <·······@online.no> wrote:

>
> Have you listened.. There is a type LIST which does include the type NIL.

No, or not unless your language is very imprecise. I haven't read all
the articles here, but I suspect the OP (and you) are getting confused
about types and instances.

There is a type LIST.  NIL is an instance of that type.
There is a type CONS. NIL is *not* an insance of that type.
There is a type NULL. NIL is an (is in fact the only) instance of that
type.
There is a type NIL: NIL is *not* an instance of that type, and in
fact that type has no instances.

There are then relations between these types in terms of supertypes
and subtypes.
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5618deda-320f-45d7-bbba-0e965471927c@f3g2000hsg.googlegroups.com>
On 18 dic, 17:20, Tim Bradshaw <··········@tfeb.org> wrote:
> There is a type LIST.  NIL is an instance of that type.
> There is a type CONS. NIL is *not* an insance of that type.
> There is a type NULL. NIL is an (is in fact the only) instance of that
> type.
> There is a type NIL: NIL is *not* an instance of that type, and in
> fact that type has no instances.

This is because I say CL sucks. Too much arbitrary in its design.
I suppose they had some reasons for doing it this way, but seems to be
too much obscure for a lot of programmers, and little useful at the
end.
From: Tim Bradshaw
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <1da26b3c-7e6f-4fd8-93c1-78fb79edb9c2@w40g2000hsb.googlegroups.com>
On Dec 18, 4:51 pm, Javier <·······@gmail.com> wrote:

> This is because I say CL sucks. Too much arbitrary in its design.
> I suppose they had some reasons for doing it this way, but seems to be
> too much obscure for a lot of programmers, and little useful at the
> end.

You should go and read some stuff about type systems in logic (these
are sometimes known as "sorts") before making even more of a fool of
yourself.  There is a fairly substantial literature as it's a very
important part of modern (in a loose sense) mathematics.  In all
approaches I've seen (there are many more, of course) you fairly
rapidly find yourself needing two types: the type of which everything
is a member (in CL this is the type T) and the type which has no
members (in CL this is the type NIL).
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fk8u5g$era$6@news.net.uni-c.dk>
Den Tue, 18 Dec 2007 08:51:26 -0800 skrev Javier:

>> There is a type LIST.  NIL is an instance of that type. There is a type
>> CONS. NIL is *not* an insance of that type. There is a type NULL. NIL
>> is an (is in fact the only) instance of that type.
>> There is a type NIL: NIL is *not* an instance of that type, and in fact
>> that type has no instances.
> 
> This is because I say CL sucks. Too much arbitrary in its design. I
> suppose they had some reasons for doing it this way, but seems to be too
> much obscure for a lot of programmers, and little useful at the end.

The only thing that might potentially happen because of you saying that 
CL sucks is that you will be (correctly) regarded as a troll. 
Fortunately, your words have no bearing on the CL standard or 
implementations.

Maciej
From: Espen Vestre
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <m1sl20aqkn.fsf@gazonk.netfonds.no>
Javier <·······@gmail.com> writes:

> I suppose they had some reasons for doing it this way, but seems to be
> too much obscure for a lot of programmers, and little useful at the
> end.

Are you sure you're speaking for "most" programmers now? Some parts of
CL carry a bit of cruft from its heritage, but I don't think that what
you commented on is an example of that.
-- 
  (espen)
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <0451c27b-6706-44d3-9a05-8a4da249c494@d27g2000prf.googlegroups.com>
On 18 dic, 17:57, Espen Vestre <·····@vestre.net> wrote:
> Javier <·······@gmail.com> writes:
> > I suppose they had some reasons for doing it this way, but seems to be
> > too much obscure for a lot of programmers, and little useful at the
> > end.
>
> Are you sure you're speaking for "most" programmers now? Some parts of
> CL carry a bit of cruft from its heritage, but I don't think that what
> you commented on is an example of that.

And what might be an example of that?

My opinion is that NIL may behave confusing in some cases. The case
that the empty list and NIL are the same, is one of them. The case
that NIL is a subtype of everything, too. One might understand that T
is a subtype of everything, but can't understand why the NIL type is.
Even more, can't understand why NIL type is needed at all, if there is
no instance of it, not even the value NIL (which is not of type
NIL!!!). I repeat: there might be some obscure reasons, and I think a
lot of CL programmers do not understand why (this thread is an
example). Non-CL programmers will be, of course, much more confused.
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <e33e6a10-684f-4bf4-a93a-a143c4fc9905@a35g2000prf.googlegroups.com>
On Dec 18, 9:42 am, Javier <·······@gmail.com> wrote:
> On 18 dic, 17:57, Espen Vestre <·····@vestre.net> wrote:
>
> > Javier <·······@gmail.com> writes:
> > > I suppose they had some reasons for doing it this way, but seems to be
> > > too much obscure for a lot of programmers, and little useful at the
> > > end.
>
> > Are you sure you're speaking for "most" programmers now? Some parts of
> > CL carry a bit of cruft from its heritage, but I don't think that what
> > you commented on is an example of that.
>
> And what might be an example of that?
>
> My opinion is that NIL may behave confusing in some cases.
> that the empty list and NIL are the same, is one of them. The case
> that NIL is a subtype of everything, too. One might understand that T
> is a subtype of everything, but can't understand why the NIL type is.
> Even more, can't understand why NIL type is needed at all, if there is
> no instance of it, not even the value NIL (which is not of type
> NIL!!!).

You need a type which is the subtype of everything in order to
properly close the bottom end of the type spindle.

If you are implementing algorithms which do various things with types,
like sorting a type lattice or whatever, it may be very useful to have
a value which is the subtype of everything.

The second question is, what two symbols to use for naming types at
these two opposite ends of the spindle? The subtype of everything and
the supertype of everything? Using NIL and T is neat. If not NIL and
T, then you need some other symbols. It's a lot easier to remember one
convention everywhere: that when two special symbols are needed, NIL
and T are used.

A lot of questions regarding NIL and T uses are pointless. It's just
convention.

Here is one: how come in the FORMAT function, T is a nickname for
*STANDARD-OUTPUT*, and NIL means that the output should be captured in
a string? How is NIL related to string streams? It isn't. It's just
that FORMAT has a stream parameter there, right? And you have the
possibility to pass a T and NIL. As well as other junk: a vector, a
string, a symbol, or anything.  A meaning was assigned to the non-
stream values T and NIL.

NIL and T have the useful property that they evaluate to themselves.
They can't be used as variable names and can't be quoted. Of course,
symbols from the keyword package could be used in place of NIL and T,
since they also have this property. But that would mean inventing new
symbols in every situation and remembering them all.

It's easier to remember that when there are up to two special cases,
or values, or types, or whatever in some situation, they are denoted
NIL and T, rather than two unique keywords invented just for that
situation.
From: Tim Bradshaw
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <e4be7f4c-5fc7-4c02-a947-1366bc806a09@f3g2000hsg.googlegroups.com>
On Dec 19, 1:45 am, Kaz Kylheku <········@gmail.com> wrote:

>
> The second question is, what two symbols to use for naming types at
> these two opposite ends of the spindle? The subtype of everything and
> the supertype of everything? Using NIL and T is neat. If not NIL and
> T, then you need some other symbols. It's a lot easier to remember one
> convention everywhere: that when two special symbols are needed, NIL
> and T are used.

One thing that occurred to me is that, if one was implementing a type
system, and you were writing you methods for the top and bottom types,
then you'd find they look like this:

(defmethod subtypep (x (type (eql top)))
  t)
(defmethod subtypep (x (type (eql bottom)))
  nil)

--tim
From: Espen Vestre
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <m1odcnc0ye.fsf@gazonk.netfonds.no>
Javier <·······@gmail.com> writes:

> One might understand that T is a subtype of everything

But it isn't...
-- 
  (espen)
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <c8d6f34d-603a-4c82-8c8e-85ba4cc2d4b6@c4g2000hsg.googlegroups.com>
On 18 dic, 19:27, Espen Vestre <·····@vestre.net> wrote:
> Javier <·······@gmail.com> writes:
> > One might understand that T is a subtype of everything
>
> But it isn't...

Which is not so obvious why...
From: Kaz Kylheku
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <b32c8a2f-5d40-4959-9ccc-aaf4a83505eb@t1g2000pra.googlegroups.com>
On Dec 18, 12:24 pm, Javier <·······@gmail.com> wrote:
> On 18 dic, 19:27, Espen Vestre <·····@vestre.net> wrote:
>
> > Javier <·······@gmail.com> writes:
> > > One might understand that T is a subtype of everything
>
> > But it isn't...
>
> Which is not so obvious why...

Because there is also a type which is the supertype of everything
(including itself).

And T was used for the name of this type already.
From: Espen Vestre
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <m1d4t3bv9e.fsf@gazonk.netfonds.no>
Javier <·······@gmail.com> writes:

>> > One might understand that T is a subtype of everything
>>
>> But it isn't...
>
> Which is not so obvious why...

Well, it is a supertype of everything, so... I recommend that you to
take some math courses. You don't have to know everything about type
theory to get a better feeling of this stuff, a little knowledge of
lattices is a good start.
-- 
  (espen)
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sqnn2F18u9dqU2@mid.individual.net>
Javier wrote:
> On 18 dic, 17:20, Tim Bradshaw <··········@tfeb.org> wrote:
>> There is a type LIST.  NIL is an instance of that type.
>> There is a type CONS. NIL is *not* an insance of that type.
>> There is a type NULL. NIL is an (is in fact the only) instance of that
>> type.
>> There is a type NIL: NIL is *not* an instance of that type, and in
>> fact that type has no instances.
> 
> This is because I say CL sucks. Too much arbitrary in its design.
> I suppose they had some reasons for doing it this way, but seems to be
> too much obscure for a lot of programmers, and little useful at the
> end.

We're looking forward to your alternative superior design (which should, 
of course, support the use cases that Common Lisp supports as well).

;)

Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Javier
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <2fa15c83-7049-4193-b52f-a9d1771f9f89@d4g2000prg.googlegroups.com>
On 18 dic, 21:09, Pascal Costanza <····@p-cos.net> wrote:
> Javier wrote:
> > On 18 dic, 17:20, Tim Bradshaw <··········@tfeb.org> wrote:
> >> There is a type LIST.  NIL is an instance of that type.
> >> There is a type CONS. NIL is *not* an insance of that type.
> >> There is a type NULL. NIL is an (is in fact the only) instance of that
> >> type.
> >> There is a type NIL: NIL is *not* an instance of that type, and in
> >> fact that type has no instances.
>
> > This is because I say CL sucks. Too much arbitrary in its design.
> > I suppose they had some reasons for doing it this way, but seems to be
> > too much obscure for a lot of programmers, and little useful at the
> > end.
>
> We're looking forward to your alternative superior design (which should,
> of course, support the use cases that Common Lisp supports as well).
>
> ;)
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

World is not about superior or inferior designs or whatever. That is
just a point of view.
CL is convenient because it is a standard, and it is huge. But in this
respect, I consider Scheme to be better designed in the basis. Scheme,
with the libraries and possibilities of CL, would be my dreamed
language.
From: Pascal Costanza
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <5sqt07F1aav4vU1@mid.individual.net>
Javier wrote:

> World is not about superior or inferior designs or whatever. That is
> just a point of view.
> CL is convenient because it is a standard, and it is huge. But in this
> respect, I consider Scheme to be better designed in the basis. Scheme,
> with the libraries and possibilities of CL, would be my dreamed
> language.

You may like Dylan (probably the version with s-expressions more than 
the one with a more mainstream syntax, but it may even not matter to 
you, depending on your preferences).


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal J. Bourguignon
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <7czlw4yw12.fsf@simias.anevia.com>
Javier <·······@gmail.com> writes:

> On 18 dic, 17:20, Tim Bradshaw <··········@tfeb.org> wrote:
>> There is a type LIST.  NIL is an instance of that type.
>> There is a type CONS. NIL is *not* an insance of that type.
>> There is a type NULL. NIL is an (is in fact the only) instance of that
>> type.
>> There is a type NIL: NIL is *not* an instance of that type, and in
>> fact that type has no instances.
>
> This is because I say CL sucks. Too much arbitrary in its design.
> I suppose they had some reasons for doing it this way, but seems to be
> too much obscure for a lot of programmers, and little useful at the
> end.

I'd rather say you say CL sucks because you don't understand the
theorical basis for this.  It's no more arbitrary that anything else
in mathematics.

NIL = {}
NULL = { NIL } = { {} }
CONS = { c | c = { { 0, { a } }, { 1, { b } } } }
LIST = NULL union CONS

The basic idea being that you only need to suppose there exists
something named {},  and that you can build "sets" of things.  Of
course, when all you have is {}, which is called NIL, the only thing
you can build is {{}}, which is called NULL.  But then you have two
things, and you can build more things: {NIL,NULL} and {NULL} and then
you have four things, and the sky's the limit. (You can build
relations, functions, lambda calculus, the universe!)


So now, since you say too much is arbitrary, please tell us what you
want to remove to reduce arbitrariness:

     - there exists something.
or:
     - there is a way to build sets of somethings.
?


(for more details, see http://en.wikipedia.org/wiki/Axiomatic_set_theory)

-- 
__Pascal Bourguignon__
·························@anevia.com
http://www.anevia.com
From: Maciej Katafiasz
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <fk8sio$era$5@news.net.uni-c.dk>
Den Tue, 18 Dec 2007 08:20:59 -0800 skrev Tim Bradshaw:

>> Have you listened.. There is a type LIST which does include the type
>> NIL.
> 
> No, or not unless your language is very imprecise. I haven't read all
> the articles here, but I suspect the OP (and you) are getting confused
> about types and instances.

Unlike many things John has said recently, this is both very clear and 
completely correct. NIL is a subtype of every type, as is explicitly 
stated in http://www.lispworks.com/documentation/HyperSpec/Body/t_nil.htm

Cheers,
Maciej
From: Tim Bradshaw
Subject: Re: NIL is not of type CONS
Date: 
Message-ID: <21fbd68a-de08-4a50-b697-001437203ff8@s19g2000prg.googlegroups.com>
On Dec 18, 4:30 pm, Maciej Katafiasz <········@gmail.com> wrote:

>
> Unlike many things John has said recently, this is both very clear and
> completely correct. NIL is a subtype of every type, as is explicitly
> stated inhttp://www.lispworks.com/documentation/HyperSpec/Body/t_nil.htm
>

I understand this.  I'm really disagreeing witht he term "include" -
types don't include other types, they are supertypes or subtypes of
other types (or neither).  Types could be thought of as including
instances (because at least one way of thinking of types, I think, is
as sets of instances). At least that's who I think of it.