From: Tunc Simsek
Subject: Type declarations
Date: 
Message-ID: <397F4D9E.ECF9ABC2@robotics.eecs.berkeley.edu>
Just couldn't figure this one out:

When I declare (type (double-float (0.0d0)) x)

it turns out that x has to be > 0.0d0.  Can I declare to that x is also
allowed to be equal to 0.0d0?

Thanks,
Tunc

From: Erik Naggum
Subject: Re: Type declarations
Date: 
Message-ID: <3173634227884978@naggum.net>
* Tunc Simsek <······@robotics.eecs.berkeley.edu>
| Just couldn't figure this one out:
| 
| When I declare (type (double-float (0.0d0)) x)
| 
| it turns out that x has to be > 0.0d0.  Can I declare to that x is also
| allowed to be equal to 0.0d0?

(double-float 0.0d0)

#:Erik
-- 
  If this is not what you expected, please alter your expectations.
From: Tunc Simsek
Subject: Re: Type declarations
Date: 
Message-ID: <397F56CB.49DDC702@robotics.eecs.berkeley.edu>
Hmm.  Let me give an example:



USER[114]: (defun foo (x)
              (declare (type (double-float (0.0d0)) x))
              (* 2 x))

FOO

USER[115]: (compile 'foo)

FOO
NIL
NIL

USER[116]: (foo 0.0d0)

Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER:
   0.0 is not of type (DOUBLE-FLOAT (0.0))


USER[117]: (values (lisp-implementation-type)
(lisp-implementation-version) (software-type))

"CMU Common Lisp"
"18c"
"Linux"

Thanks for any input,
tunc

Erik Naggum wrote:
> 
> * Tunc Simsek <······@robotics.eecs.berkeley.edu>
> | Just couldn't figure this one out:
> |
> | When I declare (type (double-float (0.0d0)) x)
> |
> | it turns out that x has to be > 0.0d0.  Can I declare to that x is also
> | allowed to be equal to 0.0d0?
> 
> (double-float 0.0d0)
> 
> #:Erik
> --
>   If this is not what you expected, please alter your expectations.
From: Barry Margolin
Subject: Re: Type declarations
Date: 
Message-ID: <N%If5.66$hY.4006@burlma1-snr2>
In article <·················@robotics.eecs.berkeley.edu>,
Tunc Simsek  <······@robotics.eecs.berkeley.edu> wrote:
>Hmm.  Let me give an example:
>
>
>
>USER[114]: (defun foo (x)
>              (declare (type (double-float (0.0d0)) x))
>              (* 2 x))
>
>FOO
>
>USER[115]: (compile 'foo)
>
>FOO
>NIL
>NIL
>
>USER[116]: (foo 0.0d0)
>
>Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER:
>   0.0 is not of type (DOUBLE-FLOAT (0.0))

You didn't do what Erik said.  He wrote:

(double-float 0.0d0)

but you wrote:

(double-float (0.0d0))

The parentheses are significant.

Common Lisp's use of parentheses in range declarations is modeled after the
mathemetical notation for ranges, which uses [] and ().  In mathematics,
(0, 10) means the range from 0 to 10, but not including 0 and 10, while [0,
10] means from 0 to 10, including 0 and 10; you can use either a
parenthesis or square bracket at either end of the range to indicate
whether that end is exclusive or inclusive.

In Common Lisp declarations the mathematical parentheses translate to
wrapping the endpoint in parentheses, while the brackets translate to
leaving out the parentheses.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Tunc Simsek
Subject: Re: Type declarations
Date: 
Message-ID: <397F6774.B0992C2D@robotics.eecs.berkeley.edu>
Barry Margolin wrote:
> 
> In article <·················@robotics.eecs.berkeley.edu>,
> Tunc Simsek  <······@robotics.eecs.berkeley.edu> wrote:
> >Hmm.  Let me give an example:
> >
> >
> >
> >USER[114]: (defun foo (x)
> >              (declare (type (double-float (0.0d0)) x))
> >              (* 2 x))
> >
> >FOO
> >
> >USER[115]: (compile 'foo)
> >
> >FOO
> >NIL
> >NIL
> >
> >USER[116]: (foo 0.0d0)
> >
> >Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER:
> >   0.0 is not of type (DOUBLE-FLOAT (0.0))
> 
> You didn't do what Erik said.  He wrote:
> 
> (double-float 0.0d0)
> 

oops.  my apologies.


> but you wrote:
> 
> (double-float (0.0d0))
> 
> The parentheses are significant.
> 
> Common Lisp's use of parentheses in range declarations is modeled after the
> mathemetical notation for ranges, which uses [] and ().  In mathematics,
> (0, 10) means the range from 0 to 10, but not including 0 and 10, while [0,
> 10] means from 0 to 10, including 0 and 10; you can use either a
> parenthesis or square bracket at either end of the range to indicate
> whether that end is exclusive or inclusive.

ok, got it.

> 
> In Common Lisp declarations the mathematical parentheses translate to
> wrapping the endpoint in parentheses, while the brackets translate to
> leaving out the parentheses.
> 
> --
> Barry Margolin, ······@genuity.net
> Genuity, Burlington, MA
> *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
> Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Tim Bradshaw
Subject: Re: Type declarations
Date: 
Message-ID: <ey3ittsa5sg.fsf@cley.com>
* Tunc Simsek wrote:
> Hmm.  Let me give an example:
> USER[114]: (defun foo (x)
>               (declare (type (double-float (0.0d0)) x))
>               (* 2 x))

There's a difference between parenthesized and non-parenthesized
limits.

	(x (a) (b)) is type x in (a,b) -- open interval
	(x a b)	    is type x in [a,b] -- closed interval

with the obvious half-open intervals.

(This is what Erik said).

--tim
From: Colin Walters
Subject: Re: Type declarations
Date: 
Message-ID: <85wvi8r0u2.church.of.emacs@meta.verbum.org>
Tunc Simsek <······@robotics.eecs.berkeley.edu> writes:

> Hmm.  Let me give an example:

It looks like Erik's suggestion works on my system:

* (defun foo (x)
  (declare (type (double-float 0.0d0) x))
  (* 2 x))
FOO
* (compile 'foo)
Compiling LAMBDA (X): 
Compiling Top-Level Form: 

FOO
NIL
NIL
* (foo 0.0d0)
0.0d0
* (values (lisp-implementation-type) (lisp-implementation-version))
"CMU Common Lisp"
"release x86-linux 2.4.20  1 June 2000 build 710"
*

I think you had extra parenthesis around the '0.0d0' which confused
Python.
From: Raymond Toy
Subject: Re: Type declarations
Date: 
Message-ID: <4n8zuowoif.fsf@rtp.ericsson.se>
>>>>> "Erik" == Erik Naggum <····@naggum.net> writes:

    Erik> * Tunc Simsek <······@robotics.eecs.berkeley.edu>
    Erik> | Just couldn't figure this one out:
    Erik> | 
    Erik> | When I declare (type (double-float (0.0d0)) x)
    Erik> | 
    Erik> | it turns out that x has to be > 0.0d0.  Can I declare to that x is also
    Erik> | allowed to be equal to 0.0d0?

    Erik> (double-float 0.0d0)

I suspect Tunc is having problems with the fact that cmucl is fairly
careful about signed zeros because some of the special functions use
that information.  (Consider what (log -0d0) should return when you
have support for signed zeroes.)

To do what you probably want, try

(or (double-float (0d0)) (member 0d0))

Some versions of CMUCL have a feature :negative-zero-is-not-zero where
(double-float 0d0) means the same thing as above.

Ray
From: Tunc Simsek
Subject: Re: Type declarations
Date: 
Message-ID: <397F6843.8F0A3AB8@robotics.eecs.berkeley.edu>
Raymond Toy wrote:
> 
> >>>>> "Erik" == Erik Naggum <····@naggum.net> writes:
> 
>     Erik> * Tunc Simsek <······@robotics.eecs.berkeley.edu>
>     Erik> | Just couldn't figure this one out:
>     Erik> |
>     Erik> | When I declare (type (double-float (0.0d0)) x)
>     Erik> |
>     Erik> | it turns out that x has to be > 0.0d0.  Can I declare to that x is also
>     Erik> | allowed to be equal to 0.0d0?
> 
>     Erik> (double-float 0.0d0)
> 
> I suspect Tunc is having problems with the fact that cmucl is fairly
> careful about signed zeros because some of the special functions use
> that information.  (Consider what (log -0d0) should return when you
> have support for signed zeroes.)
> 

actually yes, I was *also* worrying about -0d0.  specifically for (sqrt
-0.0d0)
returns -0.0d0 in my CMU so had stopped worrying about that in this
particular instance.


> To do what you probably want, try
> 
> (or (double-float (0d0)) (member 0d0))
> 
> Some versions of CMUCL have a feature :negative-zero-is-not-zero where
> (double-float 0d0) means the same thing as above.

For me, -0.0 0.0 should mean the same thing but (sqrt -0.0) should not
return #c(0.0 0.0)
or some family, and it does not in my particular CMUCL.  So far SQRT is
the only function
I'm concerned with, but I'll keep in my these *features* for future
reference.

> 
> Ray
From: Tunc Simsek
Subject: Re: Type declarations
Date: 
Message-ID: <397F6BD2.AFA605ED@robotics.eecs.berkeley.edu>
While this thread is alive; is it possible to ensure that #(0.0d0) is
read as
a (simple-array double-float (*))  (e.g. something similar to
*read-default-float-format*):


SHIFT[12]: #(0.0d0)

#(0.0)

SHIFT[13]: (type-of *)

(SIMPLE-VECTOR 1)

SHIFT[14]: (coerce #(0.0d0) '(simple-array double-float (*)))

#(0.0)

SHIFT[15]: (type-of *)

(SIMPLE-ARRAY DOUBLE-FLOAT (1))

SHIFT[16]: 

This is for convenience really.

Thanks,
Tunc
From: Barry Margolin
Subject: Re: Type declarations
Date: 
Message-ID: <hmKf5.74$hY.4176@burlma1-snr2>
In article <·················@robotics.eecs.berkeley.edu>,
Tunc Simsek  <······@robotics.eecs.berkeley.edu> wrote:
>While this thread is alive; is it possible to ensure that #(0.0d0) is
>read as
>a (simple-array double-float (*))  (e.g. something similar to
>*read-default-float-format*):

No.  #( always creates simple general vectors, not vectors specialized to
any type.

You're free to define your own reader macro for creating other types of
vectors or arrays.  For instance, here's a simple function that creates a
specialized vector if all the objects are of the same type:

(defun make-specialized-vector (list-of-objects)
  (let ((type (type-of (car list-of-objects))))
    (unless (every #'(lambda (x) (typep x type)) (cdr list-of-objects))
      (setq type 't))
    (make-array (length list-of-objects) :type type
                :initial-contents list-of-objects)))

(I know, it doesn't handle an empty list well, but works because of CL's
rule that (car nil) => NIL).

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Francis Leboutte
Subject: Re: Type declarations
Date: 
Message-ID: <o85boso8jjnsjk9691jqk0gksghaajh0o6@4ax.com>
Barry Margolin <······@genuity.net> wrote:

>In article <·················@robotics.eecs.berkeley.edu>,
>Tunc Simsek  <······@robotics.eecs.berkeley.edu> wrote:
>>While this thread is alive; is it possible to ensure that #(0.0d0) is
>>read as
>>a (simple-array double-float (*))  (e.g. something similar to
>>*read-default-float-format*):
>
>No.  #( always creates simple general vectors, not vectors specialized to
>any type.
>
>You're free to define your own reader macro for creating other types of
>vectors or arrays.  For instance, here's a simple function that creates a
>specialized vector if all the objects are of the same type:
>
>(defun make-specialized-vector (list-of-objects)
>  (let ((type (type-of (car list-of-objects))))
>    (unless (every #'(lambda (x) (typep x type)) (cdr list-of-objects))
>      (setq type 't))
>    (make-array (length list-of-objects) :type type
>                :initial-contents list-of-objects)))
>
>(I know, it doesn't handle an empty list well, but works because of CL's
>rule that (car nil) => NIL).

And it will not find a 'common' type which would be nice. For example, the
element-type will be T instead of double-float with this argument :
`(,(coerce 1 'double-float) 1)

BTW, is there a good reason for the expressed element type of an array not
to be available in ANSI CL?

--
Francis Leboutte
··@algo.be   www.algo.be   +32-(0)4.388.39.19
From: Raymond Toy
Subject: Re: Type declarations
Date: 
Message-ID: <4nhf96ky4m.fsf@rtp.ericsson.se>
>>>>> "Francis" == Francis Leboutte <··········@algo.be> writes:


    Francis> And it will not find a 'common' type which would be nice. For example, the
    Francis> element-type will be T instead of double-float with this argument :
    Francis> `(,(coerce 1 'double-float) 1)

But you can always make the function smarter to handle these cases,
right?

Something like, if every element is a fixnum or single-float, coerce
everything to single-float.  If it's fixnum, single-float, or
double-float, coerce everything to double-float, etc.

Ray
From: Tunc Simsek
Subject: Re: Type declarations
Date: 
Message-ID: <3985BB46.EC376445@robotics.eecs.berkeley.edu>
Here is my take on printing and reading arrays.  Say I declare a
specialized array:

> (make-array '(2) :element-type 'double-float)

#(0.0d0 0.0d0)

Since the returned object is readable, I get the impression that I can
type it in:

> #(0.0d0 0.0d0)

#(0.0d0 0.0d0)

but the two arrays are not the same as far as typing goes.  This is bad
in my
particular application since I rely on the typing.  I'm guessing that
the way
it is done now has other implications which doesn't show up at least in
my
application.  It'd be nice to know whether this ambiguity in the
readability
of arrays is really an ambiguity.

This also goes for the recent discussion on GENSYM and MAKE-SYMBOL.  For
example,
#:hello is readable but (NOT (EQ #:hello #:hello)).  Although in this
case the
reason why this is still correct was explained to me.


Regards,
Tunc

Raymond Toy wrote:
> 
> >>>>> "Francis" == Francis Leboutte <··········@algo.be> writes:
> 
>     Francis> And it will not find a 'common' type which would be nice. For example, the
>     Francis> element-type will be T instead of double-float with this argument :
>     Francis> `(,(coerce 1 'double-float) 1)
> 
> But you can always make the function smarter to handle these cases,
> right?
> 
> Something like, if every element is a fixnum or single-float, coerce
> everything to single-float.  If it's fixnum, single-float, or
> double-float, coerce everything to double-float, etc.

Hmm! Is there really a consistent notion of maximal or minimal type
amongst the
numbers in Common Lisp?
> 
> Ray
From: Barry Margolin
Subject: Re: Type declarations
Date: 
Message-ID: <Rgjh5.35$1L3.1333@burlma1-snr2>
In article <·················@robotics.eecs.berkeley.edu>,
Tunc Simsek  <······@robotics.eecs.berkeley.edu> wrote:
>Here is my take on printing and reading arrays.  Say I declare a
>specialized array:
>
>> (make-array '(2) :element-type 'double-float)
>
>#(0.0d0 0.0d0)
>
>Since the returned object is readable, I get the impression that I can
>type it in:
>
>> #(0.0d0 0.0d0)
>
>#(0.0d0 0.0d0)
>
>but the two arrays are not the same as far as typing goes.  This is bad
>in my
>particular application since I rely on the typing.  I'm guessing that
>the way
>it is done now has other implications which doesn't show up at least in
>my
>application.  It'd be nice to know whether this ambiguity in the
>readability
>of arrays is really an ambiguity.

In general, printed representations are a lossy representation for some
data types, especially arrays.  In addition to losing the element type, you
also lose the fill pointer, adjustability, indirection, and any other
attributes.  All you get are the currently active contents, nothing more.

For most applications, this isn't a problem.  It's rare that you need to
retain this stuff in a general manner.  If your application uses
specialized arrays, it generally creates them itself; if it needs to dump
the contents to a file, then when it's reading them back in it can create
the array first and then read the contents into it.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Pierre R. Mai
Subject: Re: Type declarations
Date: 
Message-ID: <87vgxmytxr.fsf@orion.bln.pmsf.de>
Barry Margolin <······@genuity.net> writes:

> In general, printed representations are a lossy representation for some
> data types, especially arrays.  In addition to losing the element type, you
> also lose the fill pointer, adjustability, indirection, and any other
> attributes.  All you get are the currently active contents, nothing more.

It seems to me that when *print-readably* is true, then only the fill
pointer, adjustability and displacement attributes of an array may be
discarded.  Especially the actual element type of an array is part of
the characteristics that are under consideration when determining
similiarity of arrays (see 3.2.4), and hence part of the attributes
that must be preserved by printing when *print-readably* is true.  See
my reply to the OP, for further particulars that I think are
relevant...

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Kent M Pitman
Subject: Re: Type declarations
Date: 
Message-ID: <sfwk8e11dyk.fsf@world.std.com>
"Pierre R. Mai" <····@acm.org> writes:

> Barry Margolin <······@genuity.net> writes:
> 
> > In general, printed representations are a lossy representation for some
> > data types, especially arrays.  In addition to losing the element type, you
> > also lose the fill pointer, adjustability, indirection, and any other
> > attributes.  All you get are the currently active contents, nothing more.
> 
> It seems to me that when *print-readably* is true, then only [...] may be
> discarded.

I have long argued that when *print-readably* is true, we should have required
that arrays print as #S(ARRAY :FILL-POINTER 3 :CONTENTS #(...) ...) or 
something like that.  There is not any really good reason for the printer to
fail in the *PRINT-READABLY* case, which is assumed to not be the normal 
interactive print mode but something more like Java serialization where you're
doing something that it matters to restore correctly.
From: Tunc Simsek
Subject: Re: Type declarations
Date: 
Message-ID: <3986FCD8.9EAB3A45@robotics.eecs.berkeley.edu>
Kent M Pitman wrote:
> 
> "Pierre R. Mai" <····@acm.org> writes:
> 
> > Barry Margolin <······@genuity.net> writes:
> >
> > > In general, printed representations are a lossy representation for some
> > > data types, especially arrays.  In addition to losing the element type, you
> > > also lose the fill pointer, adjustability, indirection, and any other
> > > attributes.  All you get are the currently active contents, nothing more.
> >
> > It seems to me that when *print-readably* is true, then only [...] may be
> > discarded.
> 
> I have long argued that when *print-readably* is true, we should have required
> that arrays print as #S(ARRAY :FILL-POINTER 3 :CONTENTS #(...) ...) or
> something like that.  There is not any really good reason for the printer to
> fail in the *PRINT-READABLY* case, 

By yesterdays explanation, I understood that print readably has to do
with
a similarity relation (I'm guessing EQL), so if that's right then you
cannot
print readably.

Please correct me if I'm wrong.
Tunc

> which is assumed to not be the normal
> interactive print mode but something more like Java serialization where you're
> doing something that it matters to restore correctly.
From: Barry Margolin
Subject: Re: Type declarations
Date: 
Message-ID: <lWDh5.12$PL5.617@burlma1-snr2>
In article <·················@robotics.eecs.berkeley.edu>,
Tunc Simsek  <······@robotics.eecs.berkeley.edu> wrote:
>By yesterdays explanation, I understood that print readably has to do
>with
>a similarity relation (I'm guessing EQL), so if that's right then you
>cannot
>print readably.

Without interning everything in some kind of massive hash table, it would
be virtually impossible to maintain EQL-ness for all data types.  It's done
for symbols by interning them in packages, and rational numbers naturally
have unambiguous printed representations (but floats don't, due to
round-off errors), so they can retain EQL-ness, but for other data types
the best you can hope for is similarity.  The equivalence predicate that
comes closest to that is EQUAL.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Pierre R. Mai
Subject: Re: Type declarations
Date: 
Message-ID: <87k8e0eis2.fsf@orion.bln.pmsf.de>
Tunc Simsek <······@robotics.eecs.berkeley.edu> writes:

> By yesterdays explanation, I understood that print readably has to
> do with a similarity relation (I'm guessing EQL), so if that's right
                                ^^^^^^^^^^^^^^^^^^
You are guessing wrongly.  The similarity relation that the "print
readably" operation is based on is exactly the one detailed in section
3.2.4.2.  There exists no predefined CL function that implements
exactly this similarity relationship.  The one that comes closest is
probably EQUAL, but surely not EQL, given that the similarity
relationship is used to describe the equivalence of objects that may
live in different cores.

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Raymond Toy
Subject: Re: Type declarations
Date: 
Message-ID: <4n4s56ktgi.fsf@rtp.ericsson.se>
>>>>> "Tunc" == Tunc Simsek <······@robotics.eecs.berkeley.edu> writes:

    Tunc> Here is my take on printing and reading arrays.  Say I declare a
    Tunc> specialized array:

    >> (make-array '(2) :element-type 'double-float)

    Tunc> #(0.0d0 0.0d0)

    Tunc> Since the returned object is readable, I get the impression that I can
    Tunc> type it in:

    >> #(0.0d0 0.0d0)

    Tunc> #(0.0d0 0.0d0)

The issue is that usually *print-readably* is NIL.  If you set it to
T, your make-array would either cause an error or print it out in a
different way.  Newer versions of CMUCL say:

* (setf *print-readably* t)
T
* (make-array 2 :element-type 'double-float)
#A(DOUBLE-FLOAT (2) (0.0d0 0.0d0))

(Older versions of CMUCL would error out saying it can't be printed
readably.)


Ray
From: Pierre R. Mai
Subject: Re: Type declarations
Date: 
Message-ID: <87ya2iyuuf.fsf@orion.bln.pmsf.de>
Tunc Simsek <······@robotics.eecs.berkeley.edu> writes:

> Here is my take on printing and reading arrays.  Say I declare a
> specialized array:
> 
> > (make-array '(2) :element-type 'double-float)
> 
> #(0.0d0 0.0d0)
> 
> Since the returned object is readable, I get the impression that I can
> type it in:
> 
> > #(0.0d0 0.0d0)
> 
> #(0.0d0 0.0d0)
> 
> but the two arrays are not the same as far as typing goes.  This is bad
> in my
> particular application since I rely on the typing.  I'm guessing that
> the way
> it is done now has other implications which doesn't show up at least in
> my
> application.  It'd be nice to know whether this ambiguity in the
> readability
> of arrays is really an ambiguity.

In general, if you want to have readable output, you should bind
*print-readably* to t before printing.  Under those circumstances the
implementation is required to print an Object O1 in such a way that
the read-back presentation will produce an Object O2 that is similiar
to O1, or raise an error of type print-not-readable if it can't do
this.[1]

Two objects O1 and O2 are similiar if they are "defined to be
equivalent under the similarity relationship."[2]  If we look at the
entry for similiarity we get referred to 3.2.4, and there especially
to section 3.2.4.2 Similiarity of Literal Objects:

<quote>
array 

     Two one-dimensional arrays, S and C, are similar if the length of
     S is similar to the length of C, the actual array element type of
     S is similar to the actual array element type of C, and each
     active element of S is similar to the corresponding element of C.

     Two arrays of rank other than one, S and C, are similar if the
     rank of S is similar to the rank of C, each dimension[1] of S is
     similar to the corresponding dimension[1] of C, the actual array
     element type of S is similar to the actual array element type of
     C, and each element of S is similar to the corresponding element
     of C.

     In addition, if S is a simple array, then C must also be a
     simple array. If S is a displaced array, has a fill pointer, or
     is actually adjustable, C is permitted to lack any or all of
     these qualities.
</quote>[3]

Add to this the following (non-normative) Note from the entry on
*print-readably*:

<quote>
Notes:

The rules for ``similarity'' imply that #A or #( syntax cannot be used
for arrays of element type other than t. An implementation will have
to use another syntax or signal an error of type print-not-readable.
</quote>[4]

This is backed up further by the normative entries on vector and array
printing in sections 22.1.3.7 and 22.1.3.8:

<quote>
If *print-readably* is true, the vector prints in an implementation-defined
manner; see the variable *print-readably*.
</quote>[5]

and 

<quote>
If *print-readably* is true, the array prints in an implementation-defined
manner; see the variable *print-readably*. In particular, this may be
important for arrays having some dimension 0.
</quote>[6]

Taking this in context it seems safe to draw the following
conclusions:

a) Printing of vectors and arrays with an array-element-type other
   than t while *print-readably* is true will have to preserve the
   element type in the printed representation, or will have to raise
   an error of type print-not-readable.  This is an issue of
   conformance.  If your implementation fails to conform, file a bug
   report.

b) Since no standardized external representation of arrays that
   preserves the element type exists, implementations will have to use
   their own implementation-defined representation if they don't want
   to raise an error.

c) Given that it is not an unreasonable thing to request of an
   implementor to make readable printing of arrays with specialized
   element types work, this becomes a quality of implementation
   issue.  Talk to your vendor, if this is an important feature to
   you.

If these conclusions are true, then the following function should be
usable to test the conformance and behaviour of implementations on
this issue:

(defun test-array-printing (type)
  (handler-case 
      (let* ((o1 (make-array 2 :element-type type))
	     (o1-ext (write-to-string o1 :readably t))
	     (o2 (read-from-string o1-ext)))
	(when (eql (array-element-type o1) t)
	  (error "Unsuitable element-type ~S got upgraded to ~S" type t))
	(values (eql (array-element-type o1) (array-element-type o2))
		(array-element-type o1)
		(array-element-type o2)
		o1-ext))
    (print-not-readable ()
      t)))

Given a type specifier that won't be upgraded to t, a conforming
implementation will return t as it's primary value.  A non-conforming
implementation will return nil.  If the implementation can actually
print arrays with element-types /= t, or thinks it can, then the 2nd and
3rd value will be the element-type of the original and the read-back
arrays, and the 4th value will be the external representation produced.

Of the implementations that I tested, only CMUCL and CLISP seem to be
conforming (and CLISP probably only by virtue of not providing any
specialized element-types except for the special base-char and bit
stuff), with CMUCL being able to correctly print and read back arrays
with specialized numeric element-types like single-float,
double-float, etc.  I'll have to investigate further and probably file
bug reports on the conformance issues...

Regs, Pierre.

Footnotes: 
[1]  Entry for *print-readably* in the HyperSpec
[2]  Glossary entry for "similiar" in the HyperSpec
[3]  Section 3.2.4.2 of the HyperSpec, entry on arrays
[4]  Entry for *print-readably* in the HyperSpec
[5]  Section 22.1.3.7 of the HyperSpec
[6]  Section 22.1.3.8 of the HyperSpec

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Barry Margolin
Subject: Re: Type declarations
Date: 
Message-ID: <mWih5.23$1L3.1255@burlma1-snr2>
In article <··································@4ax.com>,
Francis Leboutte  <··········@algo.be> wrote:
>And it will not find a 'common' type which would be nice. For example, the

I know.  I decided that probably isn't an important case.  You're most
likely to want a specialized array only in cases where all the elements are
of the same type.  Also, implementations generally don't have arrays
specialized to types that are intermediate in the type hierarchy (i.e. an
implementation is likely to have FIXNUM, SINGLE-FLOAT, and DOUBLE-FLOAT
arrays, but unlikely to have INTEGER, REAL, or NUMBER arrays).

>element-type will be T instead of double-float with this argument :
>`(,(coerce 1 'double-float) 1)

1 isn't of type double-float, so it wouldn't be the common type.  Are you
suggesing that it should create a double-float array and coerce the second
element to double-float automatically?

>BTW, is there a good reason for the expressed element type of an array not
>to be available in ANSI CL?

Do you mean the type that was specified in the call to MAKE-ARRAY, rather
than what it was upgraded to?  I guess no one ever thought that was needed.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Francis Leboutte
Subject: Re: Type declarations
Date: 
Message-ID: <rmpcossifckgtqtellrs5k8dlpn5qsnfkb@4ax.com>
I have posted the following yesterday to Barry only, which was not my
intention. I apologize to Barry.
F.

Barry Margolin <······@genuity.net> wrote:

>In article <··································@4ax.com>,
>Francis Leboutte  <··········@algo.be> wrote:
>>And it will not find a 'common' type which would be nice. For example, the
>
>I know.  I decided that probably isn't an important case.  You're most
>likely to want a specialized array only in cases where all the elements are
>of the same type.  Also, implementations generally don't have arrays
>specialized to types that are intermediate in the type hierarchy (i.e. an
>implementation is likely to have FIXNUM, SINGLE-FLOAT, and DOUBLE-FLOAT
>arrays, but unlikely to have INTEGER, REAL, or NUMBER arrays).
>
>>element-type will be T instead of double-float with this argument :
>>`(,(coerce 1 'double-float) 1)
>
>1 isn't of type double-float, so it wouldn't be the common type.  Are you
>suggesing that it should create a double-float array and coerce the second
>element to double-float automatically?

I know that double-float is not the super-type (that is why i use
'common'). I was just saying that making a specialized double-float array
(actually real array as you said) would be better than a T array.

>>BTW, is there a good reason for the expressed element type of an array not
>>to be available in ANSI CL?
>
>Do you mean the type that was specified in the call to MAKE-ARRAY, rather
>than what it was upgraded to?  

yes, the expressed type, not the actual one. I want this because I have
functions that generate widget specifications and dialogs from class
definitions, to make or edit Clos instances. In my current application
there are a lot of dialogs with thousand or more numeric widgets, I can't
imagine making and maintaining all these dialogs manually (using an
interface builder or programming each widget). I just need to declare the
right types in the class definitions. No problem for atomic numeric values,
I get the type from meta-data (slot definition). For arrays, I have to rely
on macros to be able to retrieve the expressed type. Instead of this, one
possibility would be to access the class prototype and get the expressed
type, which brings my question. 

>I guess no one ever thought that was needed.
 
hope I'm not flat broke.


--
Francis Leboutte
··@algo.be   www.algo.be   +32-(0)4.388.39.19
From: Kent M Pitman
Subject: Re: Type declarations
Date: 
Message-ID: <sfwlmyh1e4n.fsf@world.std.com>
Francis Leboutte <··········@algo.be> writes:

> BTW, is there a good reason for the expressed element type of an array not
> to be available in ANSI CL?

Storage?  It might force the array to be larger if several array element types
map to the same actual array element type.  It would mean part of the array
would have to encode the original information.  Statistically, it's uncertain
whether the need justifies the possible storage cost.  Further, it's not 
obvious what computation you'd want to do on it.  For example, suppose I have
created an array of element type FOO which has been upgraded to type T.
Unless you oblige everyone to really look at the expressed array element type
and oblige the system to type-check stores into it to make sure that it isn't
used for its upgraded "space", it's possible something will store things in it
that are not FOOs.  So if you then think you're being clever and, for example,
make a MAKE-LOAD-FORM or something that tries to reconstruct it as type FOO
instead of type T, it may not be able to hold its own elements...
From: Francis Leboutte
Subject: Re: Type declarations
Date: 
Message-ID: <9mifos8fkto67494go11u8f3nsequuvoes@4ax.com>
Kent M Pitman <······@world.std.com> wrote:

>Francis Leboutte <··········@algo.be> writes:
>
>> BTW, is there a good reason for the expressed element type of an array not
>> to be available in ANSI CL?
>
>Storage?  It might force the array to be larger if several array element types
>map to the same actual array element type.  It would mean part of the array
>would have to encode the original information.  Statistically, it's uncertain
>whether the need justifies the possible storage cost.  

In my applications and the ones I know, I am sure it will be negligible
considering the array sizes, the number of arrays, the whole memory need
and cost. In some cases, an implementation could also decide not to store
the expressed type, for example when the expressed and the actual type are
equal. Who would then bother about this improbable overhead?

>Further, it's not 
>obvious what computation you'd want to do on it.  For example, suppose I have
>created an array of element type FOO which has been upgraded to type T.
>Unless you oblige everyone to really look at the expressed array element type
>and oblige the system to type-check stores into it to make sure that it isn't
>used for its upgraded "space", it's possible something will store things in it
>that are not FOOs.  So if you then think you're being clever and, for example,
>make a MAKE-LOAD-FORM or something that tries to reconstruct it as type FOO
>instead of type T, it may not be able to hold its own elements...

Just ask the guy to be a bit more clever to take care of this clever
contrariwise example :-)

--
Francis Leboutte
··@algo.be   www.algo.be   +32-(0)4.388.39.19
From: Raymond Toy
Subject: Re: Type declarations
Date: 
Message-ID: <4nhf9bsnvt.fsf@rtp.ericsson.se>
>>>>> "Tunc" == Tunc Simsek <······@robotics.eecs.berkeley.edu> writes:

    Tunc> actually yes, I was *also* worrying about -0d0.
    Tunc> specifically for (sqrt -0.0d0) returns -0.0d0 in my CMU so
    Tunc> had stopped worrying about that in this particular instance.

Early versions of 18 returned #c(-0.0 0.0), I think.  Later versions
return -0.0 based on a suggestion from Kahan.

    >> To do what you probably want, try
    >> 
    >> (or (double-float (0d0)) (member 0d0))
    >> 
    >> Some versions of CMUCL have a feature :negative-zero-is-not-zero where
    >> (double-float 0d0) means the same thing as above.

    Tunc> For me, -0.0 0.0 should mean the same thing but (sqrt -0.0)
    Tunc> should not return #c(0.0 0.0) or some family, and it does
    Tunc> not in my particular CMUCL.  So far SQRT is the only
    Tunc> function I'm concerned with, but I'll keep in my these

Basically every basic function in CMUCL that has branch points/cuts
are implemented according to Kahan's paper "Much Ado about Nothing's
Sign", so CMUCL tries to honor the signedness of zeros.

I find that this usually only matters with log where (log -0.0)
returns (complex infinity pi) (because arg -0.0 is pi).

    Tunc> *features* for future reference.

You have to compile with the feature.  Adding that feature to
*features* won't do anything.

Ray