From: David Bakhash
Subject: the `the' thingy
Date: 
Message-ID: <cxjpvh8fon5.fsf@hawk.bu.edu>
hey,

I'm a bit puzzled about declarations.  I understand how to declare the 
types of bound variables, e.g.:

(defun f (x)
  (declare (type integer x))
  (* x x))

But how do I just declare the return type of `f' to be of type
integer?  I guess I can do something like:

(defun f (x)
  (declare (type integer x))
  (the integer (* x x)))

But I was looking for a much nicer solution (i.e. one that could go in 
the declaration line).

thanks,

dave

From: Barry Margolin
Subject: Re: the `the' thingy
Date: 
Message-ID: <GCR81.63$152.620589@cam-news-reader1.bbnplanet.com>
In article <···············@hawk.bu.edu>, David Bakhash  <·····@bu.edu> wrote:
>But how do I just declare the return type of `f' to be of type
>integer?  I guess I can do something like:
>
>(defun f (x)
>  (declare (type integer x))
>  (the integer (* x x)))
>
>But I was looking for a much nicer solution (i.e. one that could go in 
>the declaration line).

You can't do it in the declaration line, you have to do it in a declaration
external to the function:

(declaim (ftype (function (integer) integer)
                f))

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Marco Antoniotti
Subject: Re: the `the' thingy
Date: 
Message-ID: <lw67j0ndax.fsf@galvani.parades.rm.cnr.it>
Barry Margolin <······@bbnplanet.com> writes:

> In article <···············@hawk.bu.edu>, David Bakhash  <·····@bu.edu> wrote:

> You can't do it in the declaration line, you have to do it in a declaration
> external to the function:
> 
> (declaim (ftype (function (integer) integer)
>                 f))
> 

How about using the '(values <typespec>*)' declaration?

In CMUCL I get

    * (defun f (x)
	(declare (type (mod 10) x)
		 (values fixnum))
	(+ x x 2))
    F
    * (compile 'f)
    F
    NIL
    NIL
    * (f 4)
    10
    * (f 3)
    8
    * (type-of #'f)
    (FUNCTION ((MOD 10)) (INTEGER 2 20))

Which is quite a type inference.  However

    * (defun m (x)
      (declare (type (mod 10) x)
	       (values (integer 2 17)))
      (+ x x 2))
    M
    * (compile 'm)
    M
    NIL
    NIL
    * (type-of #'m)
    (FUNCTION ((MOD 10)) (INTEGER 2 17))
    * (m 9)
    Invoking debugger...
    Starting server:

    >> Error: 20 is not of type (INTEGER 2 17)

    Leaving debugger.
    *

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
From: Erik Naggum
Subject: Re: the `the' thingy
Date: 
Message-ID: <3104737597985003@naggum.no>
* Marco Antoniotti
| How about using the '(values <typespec>*)' declaration?

  although that is quite elegant, it is unfortunately not ANSI Common Lisp:

    This type specifier [values] can be used only as the value-type in a
    FUNCTION type specifier or a THE special form.  It is used to specify
    individual types when multiple values are involved.

  I think the usage that CMUCL made of this type specifier and declaration
  should be actively considered for the review of ANSI Common Lisp.

#:Erik
-- 
  "Where do you want to go to jail today?"
			-- U.S. Department of Justice Windows 98 slogan
From: Marco Antoniotti
Subject: Re: the `the' thingy
Date: 
Message-ID: <lwzpgby4ak.fsf@galvani.parades.rm.cnr.it>
Erik Naggum <··@naggum.no> writes:

> * Marco Antoniotti
> | How about using the '(values <typespec>*)' declaration?
> 
>   although that is quite elegant, it is unfortunately not ANSI Common Lisp:
> 
>     This type specifier [values] can be used only as the value-type in a
>     FUNCTION type specifier or a THE special form.  It is used to specify
>     individual types when multiple values are involved.
> 
>   I think the usage that CMUCL made of this type specifier and declaration
>   should be actively considered for the review of ANSI Common Lisp.
> 

Yep!  I reviewed the HyperSpec and was quite disappointed.

Of course a "simple" solution would be to convince Franz and Harlequin
(and Bruno Haible :) ) to implement this extension to ANSI.

Since we are at it, we could also implement something like

	(declaim (declaration signals))

	(defun sometimes-I-err (x)
	   (declare (type integer x)
		    (values real)
		    (signals division-by-zero))
	   (if (zerop x)
	     (error 'division-by-zero)
	     (/ 1 x)))


Ain't Java Lispish? :)

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
From: Erik Naggum
Subject: Re: the `the' thingy
Date: 
Message-ID: <3104728276311269@naggum.no>
* David Bakhash
| But how do I just declare the return type of `f' to be of type integer?

  the declaration (ftype (function (integer) integer) f) would declare the
  type of the functional value of the symbol F (as opposed to the "normal"
  value you would declare with TYPE) to be a FUNCTION that takes and yields
  an INTEGER.  it is most useful as a top-level "declaration":

(declaim (ftype (function (integer) integer) f))

  the compiler is now free to assume a one-argument, one-valued function
  whenever F is invoked as a function, but it probably won't do it much
  good to know it takes and yields INTEGER objects, since the major savings
  are in not having to cons bignums.

  I have not seen much actual effect of these declarations on the compiled
  code, but they can often help document a system.

#:Erik
-- 
  "Where do you want to go to jail today?"
			-- U.S. Department of Justice Windows 98 slogan
From: Rainer Joswig
Subject: Re: the `the' thingy
Date: 
Message-ID: <joswig-2105981620290001@194.163.195.66>
In article <················@naggum.no>, Erik Naggum <··@naggum.no> wrote:

> * David Bakhash
> | But how do I just declare the return type of `f' to be of type integer?
> 
>   the declaration (ftype (function (integer) integer) f) would declare the
>   type of the functional value of the symbol F (as opposed to the "normal"
>   value you would declare with TYPE) to be a FUNCTION that takes and yields
>   an INTEGER.  it is most useful as a top-level "declaration":
> 
> (declaim (ftype (function (integer) integer) f))
> 
>   the compiler is now free to assume a one-argument, one-valued function
>   whenever F is invoked as a function, but it probably won't do it much
>   good to know it takes and yields INTEGER objects, since the major savings
>   are in not having to cons bignums.
> 
>   I have not seen much actual effect of these declarations on the compiled
>   code, but they can often help document a system.

Actually I would like to see compiler warnings/erros when such
type declarations are violated in the code like
in (f (make-array 'foo)).

-- 
http://www.lavielle.com/~joswig/
From: Barry Margolin
Subject: Re: the `the' thingy
Date: 
Message-ID: <1S_81.83$152.836170@cam-news-reader1.bbnplanet.com>
In article <·······················@194.163.195.66>,
Rainer Joswig <······@lavielle.com> wrote:
>Actually I would like to see compiler warnings/erros when such
>type declarations are violated in the code like
>in (f (make-array 'foo)).

A good implementation should do so.  I wouldn't be surprised if CMUCL does,
since it does lots of optimization and type-inferencing based on
declarations.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Rainer Joswig
Subject: Re: the `the' thingy
Date: 
Message-ID: <joswig-2105982225250001@194.163.195.66>
In article <···················@cam-news-reader1.bbnplanet.com>, Barry
Margolin <······@bbnplanet.com> wrote:

> In article <·······················@194.163.195.66>,
> Rainer Joswig <······@lavielle.com> wrote:
> >Actually I would like to see compiler warnings/erros when such
> >type declarations are violated in the code like
> >in (f (make-array 'foo)).
> 
> A good implementation should do so.  I wouldn't be surprised if CMUCL does,
> since it does lots of optimization and type-inferencing based on
> declarations.

I guess there aren't that many "good" implementations. Any reasons
for this?

-- 
http://www.lavielle.com/~joswig/
From: Barry Margolin
Subject: Re: the `the' thingy
Date: 
Message-ID: <TRi91.4$hF2.3580@cam-news-reader1.bbnplanet.com>
In article <·······················@194.163.195.66>,
Rainer Joswig <······@lavielle.com> wrote:
>In article <···················@cam-news-reader1.bbnplanet.com>, Barry
>Margolin <······@bbnplanet.com> wrote:
>
>> In article <·······················@194.163.195.66>,
>> Rainer Joswig <······@lavielle.com> wrote:
>> >Actually I would like to see compiler warnings/erros when such
>> >type declarations are violated in the code like
>> >in (f (make-array 'foo)).
>> 
>> A good implementation should do so.  I wouldn't be surprised if CMUCL does,
>> since it does lots of optimization and type-inferencing based on
>> declarations.
>
>I guess there aren't that many "good" implementations. Any reasons
>for this?

Because the tradition in Common Lisp has been to use declarations primarily
for optimization, and most implementations don't do heavy optimization.
They'll optimize simple integer and floating point expressions, and
recognize those declarations.  Type checking has generally been relegated
to runtime, with facilities like CHECK-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: Raymond Toy
Subject: Re: the `the' thingy
Date: 
Message-ID: <4n3ee3fwm8.fsf@rtp.ericsson.se>
Erik Naggum <··@naggum.no> writes:

> 
> (declaim (ftype (function (integer) integer) f))
> 
>   the compiler is now free to assume a one-argument, one-valued function
>   whenever F is invoked as a function, but it probably won't do it much
>   good to know it takes and yields INTEGER objects, since the major savings
>   are in not having to cons bignums.
> 
>   I have not seen much actual effect of these declarations on the compiled
>   code, but they can often help document a system.
> 

With CMUCL, such declarations can be put to very good effect.  If the
return type were single-float, then CMUCL can put that knowledge to
good use whenever f is called.  I believe knowing the parameter types
also helps, but not nearly as much.

Correct documentation is always good, but, with CMUCL, I avoid using
such declarations because the compiler is often smart enough to
determine the return type itself; you just need to declare the
argument types.  You have to be careful not to lie to the compiler.

Ray
From: David Bakhash
Subject: Re: the `the' thingy
Date: 
Message-ID: <cxjg1i3ff0d.fsf@hawk.bu.edu>
Erik Naggum <··@naggum.no> writes:

> (declaim (ftype (function (integer) integer) f))
> 
>   the compiler is now free to assume a one-argument, one-valued function
>   whenever F is invoked as a function, but it probably won't do it much
>   good to know it takes and yields INTEGER objects, since the major savings
>   are in not having to cons bignums.

Now I'm utterly confused between all the different ways of doing the
same thing in CL.  Since every function returns its last form,
wouldn't it be sufficient, in general, to wrap the last form in a
`the' statement:

(defun some-big-calculation (x y z)
  (do-this x)
  (then-this-on y)
  (the bignum (+ x y z)))

???

Also, the declaim thing above seems to require that you know the
arglist too.  i.e. I asked for a way to specify the RETURN type with a 
declaration, and now it seems as though, with the declaim above, you
need to also specify the function args as well.  In addition, this is
redundant, if you've already put that stuff in as `declare' statements 
in the function itself:

(defun f (x)
  (declare (type integer x))
  (...))

So, between `the', and then the `declaim', and the `declare', I'm
thoroughly confounded.

dave
From: Barry Margolin
Subject: Re: the `the' thingy
Date: 
Message-ID: <G2j91.5$hF2.3580@cam-news-reader1.bbnplanet.com>
In article <···············@hawk.bu.edu>, David Bakhash  <·····@bu.edu> wrote:
>Also, the declaim thing above seems to require that you know the
>arglist too.  i.e. I asked for a way to specify the RETURN type with a 

Why wouldn't you know the arglist of a function you're using?

>declaration, and now it seems as though, with the declaim above, you
>need to also specify the function args as well.  In addition, this is
>redundant, if you've already put that stuff in as `declare' statements 
>in the function itself:
>
>(defun f (x)
>  (declare (type integer x))
>  (...))

Sometimes external declarations can be useful to specify local behavior.
E.g.

(locally (declare (ftype (function (fixnum) fixnum) f))
  ...)

indicates that within this form you promise only to pass fixnums to F, and
expect that it will always return a FIXNUM.  Conceivably, if F looks like:

(declaim (inline f))
(defun f (x)
  (declare (type integer x))
  (if (typep x 'fixnum)
      (f-fixnum x)
      (f-general x)))

then any forms inside that scope that look like (f z) can be transformed
directly into (f-fixnum z).

I don't know if any existing compilers can do this (I'm sure someone will
chime in if they know of one), but the design of the CL declaration
mechanism was intended to support it.  Also, designers of type inferencing
systems will probably say that the local declaration is unnecessary, as
their systems can usually determine that Z is must be a fixnum all by
themselves.

>So, between `the', and then the `declaim', and the `declare', I'm
>thoroughly confounded.

Common Lisp frequently provides multiple ways to say the same thing.  There
are at least 3 simple ways to iterate over a list (MAPC, DOLIST, and LOOP).

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Raymond Toy
Subject: Re: the `the' thingy
Date: 
Message-ID: <4nu36idoq8.fsf@rtp.ericsson.se>
Barry Margolin <······@bbnplanet.com> writes:

> indicates that within this form you promise only to pass fixnums to F, and
> expect that it will always return a FIXNUM.  Conceivably, if F looks like:
> 
> (declaim (inline f))
> (defun f (x)
>   (declare (type integer x))
>   (if (typep x 'fixnum)
>       (f-fixnum x)
>       (f-general x)))
> 
> then any forms inside that scope that look like (f z) can be transformed
> directly into (f-fixnum z).
> 
> I don't know if any existing compilers can do this (I'm sure someone will
> chime in if they know of one), but the design of the CL declaration

With the definition of f above, CMUCL will transform (f z) into
(f-fixnum z) if CMUCL can prove that z really is a fixnum.

I'm not sure what CMUCL will do with the locally form you mentioned.

Ray