From: Amy Caplan
Subject: understanding 'the' decl
Date: 
Message-ID: <3m5kcr$bkc@nkosi.well.com>
I have a problem with the 'the' declaration:  suppose, given
the wide variety of commonlisp datatypes (esp. float and array flavors)
that some implementation supports a particular type, but for ease
of implementation some operators that could return this type actually
return a more general type.   Then, if one does 
	(the expected-type (operation ...))
it seems like the code will fail.  But how can one write portable
code this way?   Presumably this is not a problem, but why not?

I have some trouble thinking of a really plausible example, so let's
be hypothetical.  The best example I can think of:
-	An implementation allows the creation of simple-arrays,
-	you can pass simple-arrays to all routines
- 	A CL map/sequence operation accepts simple-arrays,
	but for ease of implementation (since it has to deal with
	all manner of arrays) it always returns a 'boxed'(?) flavor of
	array.  
-	(dosomethingwith
          (the (simple-array single-float (*))
            (lisp-builtin-map-operator #'func input-simple-array)))
	should now fail?

Another simpler example:  on some machine (powerpc?) that has
distinct short-float and single-float types, let's say short float
is supported; I can make an array of them, retrieve two elements,
pass them to all math functions, *but for ease of implementation*
some math function(s) always return single-floats regardless of
whether they are passed short or single floats.  Then,
	(the short-float (* x y))
would be in error even if x,y are both short-floats?

Is this situation
- not possibile by language definition?  (why)
- possible, but the compiler is in error?
- the programmer is in error?
- i am in error, and fully broken in fact?
From: Barry Margolin
Subject: Re: understanding 'the' decl
Date: 
Message-ID: <3mc764$6sh@tools.near.net>
In article <··········@nkosi.well.com> ····@well.sf.ca.us (Amy Caplan) writes:
>I have a problem with the 'the' declaration:  suppose, given
>the wide variety of commonlisp datatypes (esp. float and array flavors)
>that some implementation supports a particular type, but for ease
>of implementation some operators that could return this type actually
>return a more general type.   Then, if one does 
>	(the expected-type (operation ...))
>it seems like the code will fail.  But how can one write portable
>code this way?   Presumably this is not a problem, but why not?

If you can't be sure of the return type, then code that uses such
declarations is incorrect and non-portable.  The only portable use of
declarations is when the language definition specifies that a function must
return objects of a particular type.  Of course, the implementation may
return objects of a more *specific* type than the language requires
(e.g. if the language says that it must return INTEGER, it could return
FIXNUM), but it mustn't return a more general type.

>I have some trouble thinking of a really plausible example, so let's
>be hypothetical.  The best example I can think of:
>-	An implementation allows the creation of simple-arrays,
>-	you can pass simple-arrays to all routines
>- 	A CL map/sequence operation accepts simple-arrays,
>	but for ease of implementation (since it has to deal with
>	all manner of arrays) it always returns a 'boxed'(?) flavor of
>	array.  
>-	(dosomethingwith
>          (the (simple-array single-float (*))
>            (lisp-builtin-map-operator #'func input-simple-array)))
>	should now fail?

The only CL mapping function that can return an array is MAP, and it takes
a parameter that specifies the type of the array.  If you write

(the (simple-array single-float (*))
  (map '(simple-array single-float (*)) #'func input-simple-array))

then you can reasonably expect it to work.

Maybe an example closer to what you're looking for is REVERSE.  The
language specifies that when this creates a new vector, it's always a
simple array, so it should be safe to write:

(the (simple-array single-float (*)) (reverse input-simple-array))

>Another simpler example:  on some machine (powerpc?) that has
>distinct short-float and single-float types, let's say short float
>is supported; I can make an array of them, retrieve two elements,
>pass them to all math functions, *but for ease of implementation*
>some math function(s) always return single-floats regardless of
>whether they are passed short or single floats.  Then,
>	(the short-float (* x y))
>would be in error even if x,y are both short-floats?
>
>Is this situation
>- not possibile by language definition?  (why)

The language specifies that arithmetic functions will return the same type
as the parameters when possible.  P.289 of CltL2 says, "Therefore when two
small floating-point numbers are combined, the result will always be a
small floating-point number."  P.291 describes the general rule: "In
general, then, the type of the result of a numerical function is a
floating-point number of the largest format among all the floating point
arguments to the function...."

>- possible, but the compiler is in error?
>- the programmer is in error?
>- i am in error, and fully broken in fact?

The multiplication code is correct, and the compiler is in error if (*
small-float small-float) ever returns a single-float (when they are
distinct types, of course).
-- 
Barry Margolin
BBN Planet Corporation, Cambridge, MA
······@bbnplanet.com