Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

the `the' thingy

8 views
Skip to first unread message

David Bakhash

unread,
May 20, 1998, 3:00:00 AM5/20/98
to

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

Barry Margolin

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

In article <cxjpvh8...@hawk.bu.edu>, David Bakhash <ca...@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, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.

Erik Naggum

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

* 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

Marco Antoniotti

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

Barry Margolin <bar...@bbnplanet.com> writes:

> In article <cxjpvh8...@hawk.bu.edu>, David Bakhash <ca...@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

Erik Naggum

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

* 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.

Rainer Joswig

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

In article <31047282...@naggum.no>, Erik Naggum <c...@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/


Raymond Toy

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

Erik Naggum <c...@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

Barry Margolin

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

In article <joswig-2105...@194.163.195.66>,

Rainer Joswig <jos...@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.

Rainer Joswig

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

In article <1S_81.83$152.8...@cam-news-reader1.bbnplanet.com>, Barry
Margolin <bar...@bbnplanet.com> wrote:

> In article <joswig-2105...@194.163.195.66>,
> Rainer Joswig <jos...@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/


David Bakhash

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

Erik Naggum <c...@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

Marco Antoniotti

unread,
May 21, 1998, 3:00:00 AM5/21/98
to

Erik Naggum <c...@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? :)

Barry Margolin

unread,
May 22, 1998, 3:00:00 AM5/22/98
to

In article <joswig-2105...@194.163.195.66>,
Rainer Joswig <jos...@lavielle.com> wrote:
>In article <1S_81.83$152.8...@cam-news-reader1.bbnplanet.com>, Barry
>Margolin <bar...@bbnplanet.com> wrote:
>
>> In article <joswig-2105...@194.163.195.66>,
>> Rainer Joswig <jos...@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

unread,
May 22, 1998, 3:00:00 AM5/22/98
to

In article <cxjg1i3...@hawk.bu.edu>, David Bakhash <ca...@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).

Raymond Toy

unread,
May 22, 1998, 3:00:00 AM5/22/98
to

Barry Margolin <bar...@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

0 new messages