From: Rainer Joswig
Subject: (type-of 1) ?
Date: 
Message-ID: <joswig-1707980848220001@194.163.195.67>
fixnum?
bit?

From: Paul Dietz
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <35AF2AB9.EF4FF12E@interaccess.com>
Rainer Joswig wrote:
> 
> fixnum?
> bit?

According to the hyperspec, (TYPE-OF x)
must be a recognizable subtype of any built-in
type containing x.  Since 1 is in the type BIT,
which is a built-in type, (TYPE-OF 1) must be
a recognizable subtype of BIT.  This rules
out FIXNUM.

	Paul
From: Rainer Joswig
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <joswig-1707981341190001@pbg3.lavielle.com>
In article <·················@interaccess.com>, Paul Dietz
<·····@interaccess.com> wrote:

> Rainer Joswig wrote:
> > 
> > fixnum?
> > bit?
> 
> According to the hyperspec, (TYPE-OF x)
> must be a recognizable subtype of any built-in
> type containing x.  Since 1 is in the type BIT,
> which is a built-in type, (TYPE-OF 1) must be
> a recognizable subtype of BIT.  This rules
> out FIXNUM.
> 
>         Paul

Sounds like most vendors would need to change their code.
From: Tim Bradshaw
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <ey3ww9c4e3h.fsf@todday.aiai.ed.ac.uk>
* Rainer Joswig wrote:

> Sounds like most vendors would need to change their code.

It does seem that this is implied though.  I wonder if this is a bug
in the spec, as it really is a weird special case.  OTOH I can't see
what the fix would be.

--tim
From: Barry Margolin
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <CsMr1.54$P34.737251@cam-news-reader1.bbnplanet.com>
In article <·················@interaccess.com>,
Paul Dietz  <·····@interaccess.com> wrote:
>Rainer Joswig wrote:
>> 
>> fixnum?
>> bit?
>
>According to the hyperspec, (TYPE-OF x)
>must be a recognizable subtype of any built-in
>type containing x.  Since 1 is in the type BIT,
>which is a built-in type, (TYPE-OF 1) must be
>a recognizable subtype of BIT.  This rules
>out FIXNUM.

It looks like what's specified in the ANSI standard doesn't match what
X3J13 specified in the cleanup issue TYPE-OF-UNCONSTRAINED.  That the
ADD-CONSTRAINTS proposal that was passed included a list of built-in types
for which the above must be true, and BIT wasn't in that list.  The ANSI
spec, on the other hand, has replaced that list with a reference to the
glossary term "built-in type".

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Howard R. Stearns
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <35B3A45C.E5CFB2DC@elwood.com>
Barry Margolin wrote:
> 
> In article <·················@interaccess.com>,
> Paul Dietz  <·····@interaccess.com> wrote:
> >Rainer Joswig wrote:
> >>
> >> fixnum?
> >> bit?
> >
> >According to the hyperspec, (TYPE-OF x)
> >must be a recognizable subtype of any built-in
> >type containing x.  Since 1 is in the type BIT,
> >which is a built-in type, (TYPE-OF 1) must be
> >a recognizable subtype of BIT.  This rules
> >out FIXNUM.
> 
> It looks like what's specified in the ANSI standard doesn't match what
> X3J13 specified in the cleanup issue TYPE-OF-UNCONSTRAINED.  That the
> ADD-CONSTRAINTS proposal that was passed included a list of built-in types
> for which the above must be true, and BIT wasn't in that list.  The ANSI
> spec, on the other hand, has replaced that list with a reference to the
> glossary term "built-in type".
> 
> --
> Barry Margolin, ······@bbnplanet.com
> GTE Internetworking, Powered by BBN, Cambridge, MA

Indeed, I believe there was a mistake, and the result is even more
messed up than noted so far.  Here's a listing of problems as I see it:

Issue: TYPE-OF OVERCONSTRAINED:

The specification of TYPE-OF says that:

   For any object that is an element of some built-in type: 
     a. the type returned is a recognizable subtype of that built-in
        type.  

The glossary defines built-in type as "one of the types in Figure
4-2."

Figure 4-2 lists (among others):
  bit fixnum bignum unsigned-byte ratio 
  standard-char base-char extended-char
  short-float single-float double-float long-float
  keyword
  base-string 
  simple-array simple-base-string simple-string simple-bit-vector
simple-vector
  compiled-function

It seems overconstrained to require that TYPE-OF return recognizable
subtypes of the above.  

There are some indications that this is not what was intended:

1. There is an example for TYPE-OF that shows:

 (type-of (expt 2 40))
  =>  BIGNUM
  OR=>  INTEGER
  OR=>  (INTEGER 1099511627776 1099511627776)
  OR=>  SYSTEM::TWO-WORD-BIGNUM
  OR=>  FIXNUM

Now, examples are not part of the spec, and the last possibility shows
that implemenations in which FIXNUM is type equivalent to BIGNUM are
being considered, but without comments, how might users interpret
this?

2. Since BIT is listed, a strict interpretation means that (type-of 1)
and (type-of 0) must return BIT, not FIXNUM.  This does not follow
standard practice.

3. The only way an implementation can actually do this and still
return portable type specifiers is for (TYPE-OF X), where X is some
integer, is to always return (INTEGER X X).  That is the only way that
the returned value of, say (type-of 5) can be both a recognizable
subtype of FIXNUM and a recognizable subtype of UNSIGNED-BYTE.  

4. The specification for TYPE-OF explicitly says that:

   For each of the types short-float, single-float, double-float, or
   long-float of which the object is an element, the typespec is a
   recognizable subtype of that type.  

This despite the fact that each of these is also listed in Figure 4-2,
so the sentence should not be necessary.  In addition, the types
fixnum, bignum, etc. are conspicuously absent from the sentence.

5. The original proposal which caused the restriction to be added,
listed a SUBSET of the built-in types to which it applied, and did not
mention FIXNUM, BIGNUM, etc.  In fact, the proposal specifically noted
that FIXNUM, and BIGNUM were deliberately left out because their
division was implementation dependent, and that KEYWORD and
STANDARD-CHAR were left out.  This listing was later merged with
another table, and it is possible that this merging was not intend to
strengthen the requirement for TYPE-OF as much as it ended up doing.

6. In CLtL2, Steele described this restriction on TYPEP much like the
original, unmerged, proposal, leaving out fixnum, bignum, etc.
	
If we keep the strict interpretation as written, here is the only
possible implementation I can think of which keeps the letter and
spirit of the the specification:

(defun TYPE-OF (object)
  (typecase object
    (integer `(integer ,object ,object))
    (standard-char 'standard-char)
    (base-char 'base-char)
    (extended-char 'extended-char)
    (single-float 'single-float)
    (double-float 'double-float)
    (short-float 'short-float)
    (long-float 'long-float)
    (keyword 'keyword)
    (simple-base-string 'simple-base-string)
    (simple-string 'simple-string)
    (simple-bit-vector 'simple-bit-vector)
    (simple-vector 'simple-vector)
    (simple-array 'simple-array)
    (base-string 'base-string)
    (compiled-function 'compiled-function)
    (t (let ((class (class-of object)))
	 (or (proper-name class) class)))))

where:
(defun proper-name (class &optional environment)
  (let ((name (class-name class)))
    (when (and name (symbolp name)
	       (eq class (find-class name nil environment)))
      name)))

This raises another issue: Is it meaningful to refer to a name as
being "a proper name in an environment", or only in the null
environment.  If environment matters, as for FIND-CLASS, then TYPE-OF
should take an optional environment argument in order to comply with
the restraint that:

   For objects of metaclass structure-class or standard-class, and for
   conditions, type-of returns the proper name of the class returned
   by class-of if it has a proper name, and otherwise returns the class
   itself.
From: Paul Dietz
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <35B3F760.15C25D66@interaccess.com>
This discussion indicates to me that TYPE-OF is
a good candidate for elimination from Common Lisp.

Perhaps someone could convice me otherwise: show
me where it would be useful (vs. CLASS-OF or
(CLASS-NAME (CLASS-OF ...))).

	Paul
From: Sunil Mishra
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <efyd8azi7xe.fsf@cleon.cc.gatech.edu>
Sam Steingold <···@goems.com> writes:

> >>>> In message <·················@interaccess.com>
> >>>> Sent on Mon, 20 Jul 1998 21:05:20 -0500
> >>>> Honorable Paul Dietz <·····@interaccess.com> writes
> >>>> on the subject of "Re: (type-of 1) ?":
>  >> This discussion indicates to me that TYPE-OF is
>  >> a good candidate for elimination from Common Lisp.
>  >> 
>  >> Perhaps someone could convice me otherwise: show
>  >> me where it would be useful (vs. CLASS-OF or
>  >> (CLASS-NAME (CLASS-OF ...))).
> 
> CLISP:
> (class-name (class-of 1))
>         ==> integer
> 
> ACL & CMUCL
> (class-name (class-of 1))
>         ==> fixnum
> 
> what's correct?

Both are correct, I'd say, though I should probably check the ANSI
documents before making such a declaration. This fully highlights the need
for something like typep that can check for subtypes, though it says
nothing for type-of. But here's a place where type-of makes more sense than
class-of on harlequin lispworks 3.2.2...

CL-USER 21 > (make-array 10 :element-type 'fixnum)
#(268605474 277701279 277702231 278664234 277702345 277702333 277702321
277702359 277702387 27770240\
7)

CL-USER 22 > (type-of *)
(SIMPLE-ARRAY (SIGNED-BYTE 32) (10))

CL-USER 23 > (class-of 1)
#<BUILT-IN-CLASS INTEGER 10264F38>

CL-USER 24 > (class-of ***)
#<BUILT-IN-CLASS VECTOR 102648D8>

It doesn't look like you could get all that information by examining the
built-in-class.

Sunil
From: Paul Dietz
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <35B54241.6E419A14@interaccess.com>
>  But here's a place where type-of makes more sense than
> class-of on harlequin lispworks 3.2.2...
>
> CL-USER 21 > (make-array 10 :element-type 'fixnum)
> #(268605474 277701279 277702231 278664234 277702345 277702333 277702321
> 277702359 277702387 277702407)
>
> CL-USER 22 > (type-of *)
> (SIMPLE-ARRAY (SIGNED-BYTE 32) (10))
>
> CL-USER 23 > (class-of 1)
> #<BUILT-IN-CLASS INTEGER 10264F38>
>
> CL-USER 24 > (class-of ***)
> #<BUILT-IN-CLASS VECTOR 102648D8>


The problem is that this is nonportable.

I am finding the "it's up to the implementation" parts of
the CL standard to be less and less satisfactory the more
I look at them.  The portion of TYPE-OF that is portable
between implementations is so weak that it is, as far as
I can tell, nearly useless.  So why make the *name* TYPE-OF be
common between implementations?

	Paul
From: Sunil Mishra
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <efy90lmzjua.fsf@cleon.cc.gatech.edu>
Paul Dietz <·····@interaccess.com> writes:

> The problem is that this is nonportable.
> 
> I am finding the "it's up to the implementation" parts of
> the CL standard to be less and less satisfactory the more
> I look at them.  The portion of TYPE-OF that is portable
> between implementations is so weak that it is, as far as
> I can tell, nearly useless.  So why make the *name* TYPE-OF be
> common between implementations?
> 
> 	Paul

I think there are many things in the standard that have exactly this
property. The stack debugger, the declarations, the step and trace
utilities... They all have implementation dependent properties.

In all the time I have been programming, I have never had to use type-of. I
can see it's utility in debugging, for gathering information about data,
but not much else. Well, perhaps with one exception, where I might wish to
create a data object of exactly the same type as another. In these
respects, I do believe that type-of has a place in the standard.

This vagueness in the return value of type-of seems necessary though. It
would be far too much work to figure out a generally efficient type system
for anyone that would allow for the standardization of type-of. Leaving the
vendors with this flexibility, IMHO, is important.

Sunil
From: Kent M Pitman
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <sfwk956z0i9.fsf@world.std.com>
Paul Dietz <·····@interaccess.com> writes:

> So why make the *name* TYPE-OF be common between implementations?

Mainly because it would break a lot of programs.  TYPE-OF is much older
than these other things.  Common Lisp is a commercial implementation,
not an academic one.  Breaking things costs real money to real people,
many of whom don't have huge resources to be fixing gratuitously
broken things and are struggling to justify scarce budgets as it is.

The right thing to do is probably to deprecate it so that in the future
it can be removed after a lot of notice.  But a sudden removal would serve
your sense of aesthetics, make the language only a tiny bit smaller, and
cost a lot.

In my experience, TYPE-OF is mostly used in custom print and describe
code.  It mostly doesn't matter what it prints in such cases; it's more
often used to help the user visually tell the difference between a
number and a list without SEEING the list (which might be long).  Whether
it says it's a BIT or a FIXNUM rarely matters in distinguishing it from
a LIST or an ARRAY.

I also wouldn't be surprised if some vendor wanted to have the option of
"omitting the class system stuff".  We were forced to make some concessions
in the error sytem representation (omitting multiple inheritance from pre-defined
classes) by some vendor who wanted to do this.  TYPE-OF nicely doesn't
require the class system to be prsent.  CLASS-OF, etc. does.  So what
"saves space" may be a matter of your personal perspective.  Do you mean
"cognitive space" or "space in a dumped image"?  The two are not always
mapped one to one.

Also, I've been in meetings with people hell-bent on removing all but the
most minimal stuff from the language and I can tell you it's scary.
At ISO we had fights where we removed TAGBODY because it was "bad style"
and we didn't have tail recursion because "it takes a lot of pages to
explainand we like short standards" and we didn't have LOOP because no
one could agree on whether RETURN should be in it.  For several iterations
of the ISLISP draft there was no way to loop other than to recurse and
then only for a short while until you run out of stack.  Eventually that
got fixed, thank goodness.

The same group tasked someone to go figure out what the minimal set of
trig functions was (never mind that even though theoretically one
could be computed from another, both round-off error and efficiency
make it a bad idea for people to be dividing sines by cosines and vice
versa just to get back tangent and friends. 

Then that same group decided we didn't need all six of <, >, =<, /=,
>=, and <=.  So there we had a big fight over which two or three to
include.  And for a while the draft reflected that.  That was later
fixed in ISLISP, too, fortunately.

It's a disease, IMO--removing things to make things simpler.  It doesn't end
up making things simpler.  It makes the language smaller and programs longer.  
Have you ever asked yourself why English with 120,000 words most of which
have 2-5 meanings and some of which have 40-50 meanings is the preferred
language worldwide?  Not compared to something like French or Spanish.
That's probably just an accident.  But compared to Esperanto or Loglan,
which were designed to be small and easy to learn but are not widely used.
You'd think if they were so much easier, they'd be catching on all over.
Can you imagine how long and utterly dull your favorite novel would be
in Esperanto?  Do you suppose that Lisp will be any more exciting if reduced
to a minimal subset?  You can already make a conforming subset implementation
if you like--nothing is stopping any vendor from doing that and you'd think
if it was such a popular idea the vendors would be tripping over each other
to get to the market opportunity before the others.  Think of how much smaller
the image would be. Probably easily 100 bytes.  Think of how much faster to
market you'd be.  Probably 20 minutes.  Think of how much less time it would
take the average user to learn the language.  Probably 15 seconds.  And
think of how every time someone wanted to map the function they'd have
to write #'(lambda (x) (class-name (class-of x))) instead of #'type-of.
Oops.  Sorry. That doesn't reduce the amount of time.  Well, forget that
datapoint.  Mostly we saved, right?  The implementor saves almost nothing
and users lose every time they want to write something simple.

While we're at it, might as well remove PRINT.  One can always say
 (prin1 x) (terpri) (write-char #\Space)
Well, of course, if you have to map it, you have to write a lambda
around the whole thing.

And then there's subtraction.   It can be implemented (at least for
integers) with just addition and a bit of storage and some time to 
iterate.  Ever play with church numerals? :-)   

Might as well remove :around, :after, :before, etc. since call-next-method
is enough.  (Forget the fact that :after is declarative and call-next-method
is imperative.  That kind of petty distinction just clutters things.)

Might as well remove first and rest since car and cdr are enough.
Or vice versa.  Darn.  I hate it when there's a fight.  (If only we still
had hunks, we could just remove conses altogether... :-)

Might as well remove one of NULL and NOT since both comput the same value.
Never mind that they have different intentional meanings.  No one seems
to use the intentional stuff right anyway.

BIT by BIT (or is it FIXNUM by FIXNUM), I can just feel the language getting
better as we remove more and more from it...
From: David H Wild
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <4869ce4757dhwild@argonet.co.uk>
In article <···············@world.std.com>,
 Kent M Pitman <······@world.std.com> wrote:
> But compared to Esperanto or Loglan, which were designed to be small and
> easy to learn but are not widely used. You'd think if they were so much
> easier, they'd be catching on all over. Can you imagine how long and
> utterly dull your favorite novel would be in Esperanto?

Kent,

Have you ever used Esperanto? You can have as many words as you like, it's
only the grammar which is restricted. Even in English, if I say "I are" you
would immediately change it in your own mind to "I am", so the distinction
isn't significant.

Esperanto actually allows you to create your own words, as much as you
like, as long as their *form* corresponds to the rules.�"Mi amas vin" means
"I love you", while "mi ametas vin" would mean that I love you a bit, and
"mi amegas vin" would be the equivalent of "I adore you".

"Ametas" and "amegas" wouldn't normally appear in a dictionary, any more than
an "ish" ending attached to another English word - such as "greenish" or
"largeish".

In fact, Esperanto has a lot in common with Lisp. They are both extendable
languages - if you don't find the bit you need you can add it, as long as you
stick to the rules for word formation. It is rather similar to the problem
posed in another thread; "How do I make a function which will take any number
of parameters?", and the answer is to put the parameters in a list, and then
make that list the one definite parameter for the function. It isn't written
into the rules of LISP - but it follows from them.

-- 
 __  __  __  __      __ ___   _____________________________________________
|__||__)/ __/  \|\ ||_   |   / Acorn Risc_PC
|  ||  \\__/\__/| \||__  |  /...Internet access for all Acorn RISC machines
___________________________/ ······@argonet.co.uk
From: Robert Maas
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <76hoks$7gk$1@remarQ.com>
> While we're at it, might as well remove PRINT.  One can always say
>  (prin1 x) (terpri) (write-char #\Space)

Is that what PRINT is supposed to do? I can never remember that.
Whenever I want that or something similar I do it with FORMAT:
 (format t "~S~% " x)
That gives me the flexibility of slightly changing the format just by
slightly changing the format-string, for example:
 (format t "~A~%" x)
I even have trouble remembering what PRINC PRIN1 and PRIN2 do, so I
'hand-code' exactly what I want in FORMAT even when one of those standard
functions could do the job.
From: Raymond Toy
Subject: Re: (type-of 1) ?
Date: 
Message-ID: <4nemv9x3cf.fsf@rtp.ericsson.se>
>>>>> "Sam" == Sam Steingold <···@goems.com> writes:

    Sam> (no, I do not buy the knee-jerk reply that CLISP is wrong.
    Sam> E.g., neither CMUCL nor ACL implement multiple value shiftf
    Sam> as per SETF-MULTIPLE-STORE-VARIABLES:ALLOW; CLISP does -
    Sam> effective yesterday :-).

Curiously, I think CMUCL originally did support multiple-value shiftf.
However, someone reported a bug in shiftf and Bruno (of CLISP fame)
supplied a corrected version of shiftf that no longer allowed
multiple-values in shiftf.

So until Jun 1997 or so, CMUCL did[1].  So there.  :-)

Ray


Footnotes: 
[1]  Well, I think it did.  It used multiple-value-bind to do store
     the values.  I don't have an old version to test this.