[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Issue: FUNCTION-ARGUMENT-TYPE-SEMANTICS]
- To: cl-cleanup@sail.stanford.edu
- Subject: Issue: FUNCTION-ARGUMENT-TYPE-SEMANTICS]
- From: Masinter.pa@Xerox.COM
- Date: 10 Jun 88 02:20 PDT
Here is a (fairly random) subset of the mail text on this issue. This is partly
to jog your memory.
A careful reading of CLtL p. 47 suggests, at least to some folks, that (proclaim
'(function my-function (integer))) does *not* imply that it is an error to pass
a non-integer to my-function. I've enclosed most of the relevant mail on the
subject. My inclination is to specify in the standard that such declarations
mean what (apparently) almost everyone has taken them to mean, rather than what
CLtL says.
What does
(declare (function my-cons (float string) list) )
mean? It says that my-cons is a function that can "accept a floating-point
number and a string (among other things), and its result is an object of type
list...."
The problem is that the argument type declaration here is of absolutely no use.
That the declared function can accept a float and a string among other things
has no content. It doesn't say that it is illegal to pass a non-float as the
first argument. It says that if you pass a float, its ok, and if you pass a
non-float, it might be OK too. Isn't that the same as saying (function my-cons
(t t) list)?
It would be more valuable as far as I can see to say that a (function (float
string) list) is one to which *only* a float and a string can be passed. Perhaps
someone familiar with an implementation that pays attention to these
declarations can explain what they are used to denote?
2) On the specific issue at hand: I'm inclined to be more sympathetic to
allowing &REST <element-type>; function type specifiers are, after all, already
a specialized little language -- the &KEY arguments have a separate syntax which
only vaguely resembles the original lambda list syntax, for example.
3) Should the function type specifier also allow &ALLOW-OTHER-KEYS?
Here is some (old) mail from the Common Lisp mailing list which touches on some
related issues:
!
Date: 18 Apr 1986 16:07-EST
Subject: Type Specifier: (OR (FUNCTION ...) ...)
From: NGALL@G.BBN.COM
Question: What is the 'most informative' type specifier for the CL function
COPY-SEQ?
How 'bout? (function (sequence) sequence)
Unfortunately, this does not tell the reader nor the compiler that if the
argument is a list, then the result is also a list, and vice versa. So how
about this:
(or (function (list) list)
(function (vector) vector))
This is syntactically valid CL, and the definition of the OR and FUNCTION type
specifiers makes it meaningful. Unfortunately, it is not clear from pg. 158
whether or not the following is legal:
(proclaim '(ftype (or (function (list) list)
(function (vector) vector))
copy-seq))
It is not legal in VaxLisp, and my guess is that there aren't any
implementations that would do the right thing with it. So I would like to
propose that such a use of OR/FUNCTION be considered legal CL.
Without such a declaration, one is forced to either wrap (the <result-type> ...)
around all calls to such functions or to DECLARE a restricted version of
FUNCTION in the appropriate places, e.g., (defun foo (alist avector)
(declare (list alist)
(vector avector)
(function copy-seq (list) list))
(zap (copy-seq alist)
(let ()
(declare (function copy-seq (vector) vector))
(zoop (copy-seq avector))))
Either method is a real pain.
This use of OR would give CL something akin to Ada overloading. It allows the
overloading of multiple 'function type signatures' on a single function name.
Such overloading is already implicit throughout CL (esp. the seq. functions).
My proposal would merely allow a way of describing it.
-- Nick
!
Date: Mon, 4 Nov 85 22:29 EST
From: Daniel L. Weinreb <DLW@SCRC-QUABBIN.ARPA>
Subject: Declaring Functions
To: shebs%utah-orion@UTAH-CS.ARPA, common-lisp@SU-AI.ARPA
Message-ID: <851104222904.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
In-Reply-To: <8511012045.AA07112@utah-orion.ARPA>
Date: Fri, 1 Nov 85 13:45:55 MST
From: shebs%utah-orion@utah-cs.arpa (Stanley Shebs)
The notion of a function type is mentioned in two places: p. 47 of the
CLM, where the (function ...) type specifier is defined, and p. 158-159,
where (ftype ...) and (function ...) are defined as options to declare.
Are they intended to be the same?
Read page 159 more carefully. It explains that they have the same meaning, but
are syntactically different. "function" has the disadvantage that you can only
declare one thing per clause, unlike most other declarations, but the advantage
that it looks mildly like "defun".
If so, then the second definition
should say that keywords and a (values ...) type specifier are allowed.
If by keywords you mean &optional and friends, it isn't strictly necessary to
repeat that, although it would sure clear things up if there were a cross
reference in the book.
However, there appears to be a typo on page 159. The form following the phrase
"entirely equivalent to", which currently reads
(ftype (function arglist result-type1 result-type2 ...) name)
ought to read
(ftype (function arglist (values result-type1 result-type2 ...)) name)
in order to be consistent with page 47.
----- Next Message -----
Date: Wed, 2 Dec 87 21:42:47 PST
From: Pavel.pa
Subject: Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
In-reply-to: <871202-204108-1072@Xerox>
To: cl-cleanup@SAIL.STANFORD.EDU, sandra%orion@CS.UTAH.EDU
Message-ID: <871202-214253-1099@Xerox>
Larry says:
``I don't know what (declare (function my-cons (float string) list) ) means.''
It is usual in type theory for this to be read as an implication:
IF
you pass a float and a string to MY-CONS
THEN
MY-CONS is guaranteed to return a list.
More rigorously, a type theorist would see (function my-cons (float string)
list) as representing the set of all functions that, when applied to a float and
a string, return a list.
Under this view of types, we understand the constructor OR to be set-union (that
is, the type (OR t1 t2) represents the set of values in the union of the sets
represented by t1 and t2) and the AND constructor is thus set intersection.
Under this view, Nick Gall gives the wrong answer to his question about a
specific type for COPY-SEQ when he claims that a good one would be
(or (function (list) list)
(function (vector) vector))
Since this does not guarantee that COPY-SEQ will return a list when applied to a
list; in fact, a function in this type might very well bomb when presented with
a list. In general, ORing function types isn't very helpful. What he really
wants here is AND, not OR:
(and (function (list) list)
(function (vector) vector))
This represents the set of functions that both map lists to lists and vectors to
vectors.
Let me point out that I'm not claiming that this is how CLtL intends function
types to be interpreted, just that this meaning has proven very convenient for
most uses.
Pavel
----- Next Message -----
Date: Wed, 2 Dec 87 22:36:17 PST
From: Pavel.pa
Subject: Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
In-reply-to: <871202-222029-1111@Xerox>
To: cl-cleanup@SAIL.STANFORD.EDU, sandra%orion@CS.UTAH.EDU
Message-ID: <871202-223623-1122@Xerox>
That's right. Unless you know something about the types of the arguments, you
can assume nothing about the type of the result.
Pavel
----- Next Message -----
Date: Thu, 3 Dec 87 16:30 EST
Message-ID: <RAM.12355605918.BABYL@>
From: Ram@C.CS.CMU.EDU
To: Kent M Pitman <KMP@SCRC-STONY-BROOK.ARPA>, cl-cleanup@SAIL.STANFORD.EDU,
Masinter.pa, sandra%orion@CS.UTAH.EDU
Subject: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
In-reply-to: Msg of 3 Dec 1987 12:52-EST from Kent M Pitman <KMP at
STONY-BROOK.SCRC.Symbolics.COM>
My compiler cleanup proposal addresses a number of the issues being
discussed here. We already went around once on cl-cleanup about the
meaning function type.
In my initial proposal, I had assumed a strict interpretation of
function type. It was pointed out to me, that not only is CLTL very
clear about its non-restrictive interpretation, it is also very
difficult to use a strict interpretation within the framework of the
current type system.
Basically, the problem is that if you think about "function type
declarations" as being declarations about the type of the object which
is the function, then it isn't possible to use a strict
interpretation. If you attempt to do so, then there will be cases
where a type declaration is necessary for a program to be correct, and
removing declarations can cause a program to be incorrect. In
addition to problems with defining where declarations are necessary,
requiring declarations is also clearly in conflict with the stated
goals for declarations in Common Lisp.
Basically, the reason for this non-intuitive result is that a
declaration of a function's type actually makes a statement about what
definitions are legal, rather than what calls are legal. What a
compiler really wants to know is what calls are legal.
The solution I suggest in my proposal is to introduce a mechanism that
allows arbitrary information about a function definition to be bound
at compile time. You don't declare the function type, you just define
the function, with any appropriate argument type declarations.
Since you have asserted that calls to the function can be bound at
compile time, the compiler can apply any assertions on the formal
parameters to the actual parameters and use type information derived
from the definition as the type of the call result.
Early-binding of function names also allows many other optimizations
such as "inline expansion" and "block compilation".
Before people flame uncotrollably about the horror of static function
binding in Lisp, I will point out that I don't propose that static
function binding be required, or even that it necessarily be the
default. It is also worth noting that the extent to which static
binding is actually done once it has been allowed is an implementation
decision. Declaring static binding doesn't necessarily prevent
incremental redefintion or reduce safety, it might only cause better
compiler warnings to be generated.
If this capability exists, then function type declarations (and
function types) are more useless than they currently are (if that is
even possible).
Rob
P.S. My proposal is <ram>cprop.txt on c.cs.cmu.edu
----- Next Message -----
Date: 7 Dec 87 14:40 PST
From: Masinter.pa
Subject: Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
In-reply-to: Ram@C.CS.CMU.EDU's message of Thu, 3 Dec 87 16:30 EST
To: Ram@C.CS.CMU.EDU
cc: KMP@SCRC-STONY-BROOK.ARPA, cl-cleanup@SAIL.STANFORD.EDU, Masinter.pa,
sandra%orion@CS.UTAH.EDU
Ram: I've scanned your latest proposal, but it still doesn't seem to address the
minor issue at hand here:
What does
(declare (function (integer integer) t) foo)
imply?
We've discussed what it could mean, what it should mean, what CLtL says it
means, but I'd to hear about current practice. What, if anything, do current
implementations do with such declarations? Do any implementations pay attention
to the types of arguments in function declarations?
----- Next Message -----
Date: Thu, 3 Dec 87 12:52 EST
From: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
To: Masinter.pa
cc: cl-cleanup@SAIL.STANFORD.EDU, sandra%orion@CS.UTAH.EDU
In-Reply-To: <871202-204108-1072@Xerox>
Message-ID: <871203125256.0.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>
Date: 2 Dec 87 20:40 PST
From: Masinter.pa@Xerox.COM
...
(declare (function my-cons (float string) list) )
...
The problem is that the argument type declaration here is of absolutely
no use.
...
It would be more valuable as far as I can see to say that a
(function (float string) list)
is one to which *only* a float and a string can be passed. Perhaps
someone familiar with an implementation that pays attention to these
declarations can explain what they are used to denote?
In Maclisp, if you declared a function to take arguments (fixnum flonum),
for example, special tricks were allowed to be done with passing the arguments
without having to heap-cons them. You were required to only use this declaration
if you had made it available to the compiler at the time of compiling the
function
(so that it would have done the special tricks necessary to make the external
calling sequence work). The net effect was that the function had a naive entry
point (for people who didn't know about the declaration) and a magic entry point
for people who wanted to exploit the declaration information and bypass some
setup instructions.
In order to get this effect in CL, we have only to restrict the declaration of
a function to be exactly the declaration that the function was compiled under.
That is, there are a number of possible universes we could elect to be in:
* We could allow local function declarations to just say things we know to
be true, regardless of whether they were interesting. eg,
(PROCLAIM '(FUNCTION FOO (INTEGER) INTEGER))
(DEFUN FOO (X) (+ X 1))
could be matched in another file by
(LOCALLY (DECLARE (FUNCTION FOO (INTEGER) INTEGER)) ... (FOO ...) ...)
or (LOCALLY (DECLARE (FUNCTION FOO (FIXNUM) FIXNUM)) ... (FOO ...) ...)
or (LOCALLY (DECLARE (FUNCTION FOO (T) T)) ... (FOO ...) ...)
This would tend to thwart interesting compilations because nothing in the
declaration would tell you anything useful about how the function was
compiled.
* We could allow local function declarations only if they restrict the
declaration under which the function was compiled. eg,
(PROCLAIM '(FUNCTION FOO (INTEGER) INTEGER))
(DEFUN FOO (X) (+ X 1))
could be matched in another file by
(LOCALLY (DECLARE (FUNCTION FOO (INTEGER) INTEGER)) ... (FOO ...) ...)
or (LOCALLY (DECLARE (FUNCTION FOO (FIXNUM) FIXNUM)) ... (FOO ...) ...)
but not by
(LOCALLY (DECLARE (FUNCTION FOO (T) T)) ... (FOO ...) ...)
This might thwart some interesting compilations because you wouldn't know
everything about the way the function was compiled, but you'd know some
information.
* We could allow local function declarations only if they exactly match
the declaration under which the function was compiled. eg,
(PROCLAIM '(FUNCTION FOO (INTEGER) INTEGER))
(DEFUN FOO (X) (+ X 1))
could be matched in another file by
(LOCALLY (DECLARE (FUNCTION FOO (INTEGER) INTEGER)) ... (FOO ...) ...)
but not by
(LOCALLY (DECLARE (FUNCTION FOO (FIXNUM) FIXNUM)) ... (FOO ...) ...)
or (LOCALLY (DECLARE (FUNCTION FOO (T) T)) ... (FOO ...) ...)
This would have the best chance of getting interesting compilations, I think.
* We could, as I guess Pavel is suggesting (though I lost or missed the
original mail), allow multiple declarations of the same function, in which
case the information provided would be of an entirely different nature (in
what amounts to a DEFMETHOD style) than what it's used for in the previous
three bullet items.
Presumably there are some gains to be had from this style. I have no feel for
how useful they are. An example, though, would be:
(PROCLAIM '(FUNCTION FOO (LIST) LIST))
(PROCLAIM '(FUNCTION FOO (VECTOR) VECTOR))
which would let you compile
(LENGTH (FOO (THE LIST L)))
into
(SYSTEM:LENGTH-ROUTINE-FOR-THINGS-KNOWN-TO-BE-OF-TYPE-LIST (FOO L))
[Sigh. I'd have called it SYSTEM:LIST-LENGTH, but that's taken by CLtL for
something that doesn't mean what I think of as LIST-LENGTH. A poor naming
decision if you ask me...]
* This is a placeholder to remind readers that the likelihood that this list is
exhaustive is fairly low.
This really gets at the heart of the problem, which is:
* Are declarations just for compilation or do they serve some more abstract
higher level goal (eg, "documentation").
* How important is exact-typep information vs typep information.
* How much of a modularity violation (or documentation constraint) is it to
have to know the exact conditions under which a function was compiled.
* How important are optimal compilations?
----- Next Message -----
Date: Thu, 3 Dec 87 11:57:05 MST
From: sandra%orion@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8712031857.AA21459@orion.utah.edu>
Subject: Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
To: Kent M Pitman <KMP@stony-brook.scrc.symbolics.com>
Cc: Masinter.pa, cl-cleanup@sail.stanford.edu, sandra%orion@cs.utah.edu
In-Reply-To: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>, Thu, 3 Dec 87
12:52 EST
One reason for wanting to use a FUNCTION type specifier is that you may
only be concerned with how many arguments a function can take, and you
don't care at all about their types. Back when we were trying to
implement a CL compatibility package in PSL, we wanted to do the
matching of actual arguments to lambda variables at compile-time so we
could use the EXPR call protocol instead of the much slower NEXPR
protocol. (Basically, we had an EXPR entry point for every function
with a 1-1 correspondence between actual arguments and lambda
variables.) The problem is, you couldn't do the transformation on a
call unless you already knew something about the lambda list for the
function.
I agree that the argument type business is confusing and not very useful
in its current state. I'd like to say that
(LOCALLY (DECLARE (FTYPE (FUNCTION (INTEGER INTEGER) INTEGER) +))
(+ X Y))
is equivalent to
(THE INTEGER (+ (THE INTEGER X) (THE INTEGER Y)))
but I'm not sure that's exactly what CLtL is getting at.
-Sandra
-------
----- Next Message -----
Date: 03 Dec 87 11:23 PST
From: Dick Gabriel <RPG@SAIL.Stanford.EDU>
Subject: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
To: cl-cleanup@SAIL.Stanford.EDU
I'd like to reiterate what Pavel said: the declaration
(declare (function my-cons (float string) list) )
means that the function MY-CONS accepts two arguments, the first at least
of the type FLOAT (it can be a more general type), and the second at least
of the type STRING; it returns one value which is of the type LIST (it
could be more specific).
Unfortunately, it does not mean that if the two arguments are of types
FLOAT and STRING then the result is of type LIST, which would be
useful.
Lucid has a variant of this called RESTRICTIVE-FTYPE (or something),
which would mean MY-CONS assumes it receives two arguments of types
FLOAT and STRING and produces something of type LIST.
See page 47 (CLtL), the last complete paragraph, to see this.
-rpg-
----- Next Message -----
Date: Thu, 3 Dec 87 14:17 EST
From: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
To: sandra%orion@cs.utah.edu
cc: KMP@STONY-BROOK.SCRC.Symbolics.COM, Masinter.pa,
cl-cleanup@sail.stanford.edu
In-Reply-To: <8712031857.AA21459@orion.utah.edu>
Message-ID: <871203141725.5.KMP@RIO-DE-JANEIRO.SCRC.Symbolics.COM>
Date: Thu, 3 Dec 87 11:57:05 MST
From: sandra%orion@cs.utah.edu (Sandra J Loosemore)
One reason for wanting to use a FUNCTION type specifier is that you may
only be concerned with how many arguments a function can take, and you
don't care at all about their types. ...
Thanks for remembering to mention this issue. It pops into my head from time to
time
and then I always forget it before I get to the console.
Yes, the same style of issues as I raised in my last message applies to argument
number. eg, if I did
(PROCLAIM '(FUNCTION FOO (NUMBER NUMBER) NUMBER))
(DEFUN FOO (X Y) (+ X Y))
and later did:
(LOCALLY (DECLARE (FUNCTION FOO (FIXNUM &REST (LIST T)) FIXNUM)) ... (FOO ...)
...)
would I be within reason? ie, is there semantic impact to the &REST which goes
beyond
type declaring the rest of the arguments to be of type T? Am I also declaring
that the
function was in fact compiled believing that a &REST style argument pickup was
used
(and at the same point as I've specified it here). What about:
(PROCLAIM '(FUNCTION FOO (NUMBER &REST (LIST NUMBER)) NUMBER))
(DEFUN FOO (X &REST Y) (APPLY #'+ X Y))
and then later
(LOCALLY (DECLARE (FUNCTION FOO (NUMBER NUMBER &REST (LIST NUMBER)) NUMBER))
... (FOO ...at least two arguments...) ...)
In my CL conversion of Macsyma, I threw out all the *LEXPR declarations because
CL couldn't make any use of them and they were just clutter. (And they'd be
trivial
to re-conjure if they were ever needed.) But I felt funny as I did it because I
did
know I was throwing away information that would be interesting to some compilers
and that seemed sad, so I definitely agree that one way or another, this is a
real
issue.
----- Next Message -----
Date: 9 Dec 87 02:59 PST
From: Masinter.pa
Subject: Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
In-reply-to: Ram@C.CS.CMU.EDU's message of Tue, 8 Dec 87 14:21 EST
To: Ram@C.CS.CMU.EDU
cc: cl-cleanup@SAIL.STANFORD.EDU, sandra%orion@CS.UTAH.EDU
Message-ID: <871209-030006-1558@Xerox>
I think I understand and agree with most of what you say, in particular "I think
that we should either entirely flush the concept of "function types" or change
the theory behind them. The CLtL interpretation is well-defined, but not very
useful. "
There are two components to your proposal: (1) what is allowed (and what it
means), and (2) how it is described in the standard.
I like the part of your proposal which is to change the interpretation of
function declarations to mean an implicit assertion of argument and value types
(the "restrictive interpretation").
I like defining (declare (type (function (frob grid) bunker) x)) to mean
(funcall x y z) has implicitly means (the bunker (funcall (the function x)
(the frob y) (the grid z)))
I don't see, however, that there is much leverage to removing FUNCTION from the
section on type specifiers. It would do some violence to the otherwise useful
concept of
(deftype binary-arithmetic () '(function (number number) number))
to be used in
(declare (ftype binary-arithmetic x y z)) .
I don't see at all that (funcall #'foo x y) doesn't mean (the t (funcall #'foo
(the integer x) (the integer y)))) given (declare (function foo (integer
integer) t)).
In the type propagation rules, you can transform funcall and apply expressions
using the asserted value of the function argument, and the asserted value type
of #'name is derived from the asserted ftype of name.
In this interpretation, AND would distribute nicely,
Given (proclaim '(function foo (s1 t1) v1)) and (declare (function foo (s2 t2)
v2)) you could assert that
(foo x y) => (the (and v1 v2) (foo (the (and s1 s2) x) (the (and t1 t2) y))).
(OR doesn't distribute as nicely, e.g., given (declare (ftype (or (function (s1
t1) v1) (function (s2 t2) v2)) foo)), there isn't a simple way to describe the
type assertions made for (foo x y).
We might even want to explicitly allow FUNCTION declarations in THE
expressions, as in
(funcall (the binary-arithmetic x) y z).
----- Next Message -----
Date: Tue, 8 Dec 87 14:21 EST
Message-ID: <RAM.12356893261.BABYL@>
From: Ram@C.CS.CMU.EDU
To: Masinter.pa
Cc: cl-cleanup@SAIL.STANFORD.EDU, KMP@SCRC-STONY-BROOK.ARPA,
sandra%orion@CS.UTAH.EDU
Subject: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
In-reply-to: Msg of 7 Dec 1987 17:40-EST from Masinter.pa at Xerox.COM
Date: Monday, 7 December 1987 17:40-EST
From: Masinter.pa at Xerox.COM
To: Ram at C.CS.CMU.EDU
cc: KMP at SCRC-STONY-BROOK.ARPA, cl-cleanup at SAIL.STANFORD.EDU,
Masinter.pa at Xerox.COM, sandra%orion at CS.UTAH.EDU
Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
[...] What does (declare (function (integer integer) t) foo) imply?
We've discussed what it could mean, what it should mean, what CLtL
says it means, but I'd to hear about current practice. What, if
anything, do current implementations do with such declarations? Do
any implementations pay attention to the types of arguments in
function declarations?
Our current compiler totally ignores function type declarations.
I am working on a new compiler that currently gives function type
declarations a strict interpretation, i.e. the function must be called
only with two integer arguments. (I suspect that this is like the
RESTRICTIVE-FTYPE declarations that someone from Lucid mentioned.) At
least as an interpretation for FTYPE, this is clearly wrong. I intend
to at least rename this declaration, and perhaps entirely flush it as
a user-visible facility.
I think that we should either entirely flush the concept of "function
types" or change the theory behind them. The CLtL interpretation is
well-defined, but not very useful. The intuitive strict
interpretation is useful, but is not a type declaration, at least in
the sense used in CLtL.
The restrictive interpretation can be modeled as a sort of magic
syntactic shorthand for a bunch of THE declarations at the call site:
(the t (foo (the integer x) (the integer y)))
But under this interpretation, a "function type" isn't a type at all,
since it isn't in any sense the type of the function object being
called. It wouldn't be meaningful to declare a variable or value to
have a function type. A "function type declaration" would be a piece
of magic recognized by the implementation that constrains calls to a
particular function variable.
If we did this, then the concept of a "function type specifier" should
be flushed, since "function types" can't be used in any of the ways
real types can. The "function type" syntax would become part of the
syntax peculiar to a "function type declaration". (A minor beneficial
side-effect is that it would make obvious the restriction on function
types in TYPEP.)
One problem that I have with this interpretation is that it makes the
evaluation of the functional position even more peculiar than it
already is. Since a "function type declaration" would be purely
syntactic, it would only take effect when there was a syntactic match,
i.e. an obvious normal call to a declared function variable. It would
probably be incorrect to do this transformation:
(funcall #'foo x y) ==>
(the t (funcall #'foo (the integer x) (the integer y))))
Rob
----- Next Message -----
Date: Wed, 9 Dec 87 08:00:48 MST
From: sandra%orion@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8712091500.AA16131@orion.utah.edu>
Subject: Re: Issue: FUNCTION-TYPE-REST-LIST-ELEMENT, FUNCTION-DECLARATION issues
To: Masinter.pa
Cc: Ram@c.cs.cmu.edu, cl-cleanup@sail.stanford.edu, sandra%orion@cs.utah.edu
In-Reply-To: Masinter.pa@Xerox.COM, 9 Dec 87 02:59 PST
Date: 9 Dec 87 02:59 PST
From: Masinter.pa@Xerox.COM
Given (proclaim '(function foo (s1 t1) v1)) and (declare (function foo (s2 t2)
v2)) you could assert that
(foo x y) => (the (and v1 v2) (foo (the (and s1 s2) x) (the (and t1 t2) y))).
I disagree. The DECLARE should shadow the PROCLAIM; see p. 156 of
CLtL. Or is there another proposal in the works to change declaration
shadowing as well? :-)
-Sandra
-------
From: masinter.PA
Date: 16-Dec-87 1:32:02 PST
Subject: Current practice:argument types in function declarations
To: common-lisp@sail.stanford.edu
cc: masinter
The cleanup committee is considering various issues surrounding function
declarations, and, in particular, declarations of the types of arguments.
We've had considerable input about what such declarations could mean, should
mean, what CLtL says they mean. Rather than going over all of that, this is a
question about current practice:
What do current implementations actually do? What do current users actually use
have in their programs?
Is anyone aware of any (released? supported?) Common Lisp implementation that
pays any attention at all to the types of arguments, e.g., for which
(proclaim '(function my-function (list vector) t))
has any effect different from
(proclaim '(function my-function (t t) t))
?
Does anyone *have* any Common Lisp code which contains such declarations? What
is the intent of the declarations, other than as documentation?
-----------
Date: Wed, 16 Dec 87 06:50:49 PST
Message-Id: <8712161450.AA12099@decwrl.dec.com>
From: vanroggen%aitg.DEC@decwrl.dec.com
To: masinter.PA, VANROGGEN@decwrl.dec.com
Subject: RE: Current practice:argument types in function declarations
VAX LISP certainly does heed such proclamations when compiling calls
to the declared functions. And we do have such code in our system.
---Walter
-----------------------
Date: 16 Dec 87 12:42 PST
From: Masinter.pa
Subject: RE: Current practice:argument types in function declarations
In-reply-to: vanroggen%aitg.DEC@decwrl.dec.com's message of Wed, 16 Dec 87
06:50:49 PST
To: vanroggen%aitg.DEC@decwrl.dec.com
cc: masinter.PA
Sigh, I don't have a VAX LISP manual. In what way does it "heed such
proclaimations"?
For example, does VAX LISP assume that, given
(proclaim '(function my-function (integer symbol) t))
that it is an error to call
(my-function 'a-symbol 3)?
-----------------------
Date: Wed, 16 Dec 87 13:02:06 PST
Message-Id: <8712162102.AA07759@decwrl.dec.com>
From: vanroggen%aitg.DEC@decwrl.dec.com
To: Masinter.pa, VANROGGEN@decwrl.dec.com
Subject: RE: Current practice:argument types in function declarations
That's right--your example would be in error.
...
-----------------------
Date: Wed, 16 Dec 87 13:11 est
From: mike%acorn@LIVE-OAK.LCS.MIT.EDU
To: masinter.PA
Subject: Current practice:argument types in function declarations
Cc: common-lisp@sail.stanford.edu
From: masinter.PA@Xerox.COM
Date: 16 Dec 87 1:32:02 PST
>Is anyone aware of any (released? supported?) Common Lisp implementation that
>pays any attention at all to the types of arguments, e.g., for which
> (proclaim '(function my-function (list vector) t))
>has any effect different from
> (proclaim '(function my-function (t t) t))
> ?
>Does anyone *have* any Common Lisp code which contains such declarations?
>What is the intent of the declarations, other than as documentation?
First off, either signature tells you more than nothing at all, since
it fixes the number of arguments. Presumably, you have to check
the number of arguments as well as the types for really safe calls.
As for use, we are not using them currently, but plan to use them.
The goal is to generate "safe" calls for functions when compiling if
the type signature is unknown. If the type signature is known;
however, the checking burden is placed on the caller (and can be
minimized via type inference, etc.) and an unsafe call is generated.
The type signature can be known either via block compilation, or
by using function type proclamations. In any case if you ftype a function
and a call can be shown to contradict the proclamation, then you
should get a warning and a safe (slow) call.
The one difficulty with these things is that common lisp's type
language doesn't allow you to specify accurate types for things
like <. E.G.,
(proclaim '(ftype < (function (&rest ??) (or T nil))))
For ?? you'd like to say "zero or more non-complex numbers". You do
NOT want to say LIST here.
I am considering defining a (list-of ...) type specifier.
where the argument is a type. This cannot really be written in
common lisp, since it doesn't allow parameterized types in general.
But we as implementors can put it in place as an extension.
Mike Beckerle
Gold Hill Computers.
----------------------
Date: Wed, 16 Dec 87 18:13:25 GMT
Message-Id: <561.8712161813@csuna.cvaxa.sussex.ac.uk>
To: "masinter.PA" <@NSS.Cs.Ucl.AC.UK,@cvaxa.sussex.ac.uk:masinter.PA@xerox.com>
Subject: Re: Current practice:argument types in function declarations
POPLOG Common Lisp (POPLOG is a UK AI development environment) will
recognise function declarations in the next release, but only because
it is interested in knowing how many arguments and results a function
takes (especially the number of results).
John Williams (johnw@uk.ac.sussex.cvaxa)
----------------------
From: Brad Miller <miller@ACORN.CS.ROCHESTER.EDU>
Subject: Re: Current practice:argument types in function declarations
Original-Date: Thu, 17 Dec 87 03:05 EST
Organization: University of Rochester, Department of Computer Science
Postal-address: 401A CS Building, Computer Science Department, University of
Rochester, Rochester NY 14627
Phone: 716-275-1118
Date: 16 Dec 87 1:32:02 PST
From: masinter.PA@Xerox.COM
Does anyone *have* any Common Lisp code which contains such declarations?
What
is the intent of the declarations, other than as documentation?
All the code I write has such delcarations, including for the types of all
returned values. The immediate purpose is documentation since it's ignored on
the machine I happen to work on (a symbolics) but it's my hope that in future
the compiler/interpreter would complain about calls to the function that pass
the wrong type of argument at compile time, if it can tell. (runtime would
depend on OPTIMIZE SAFETY or some such, and probably local declarations inside
the defun or whatever).
Also, it could be used as a note to the debugger, since it could flag that an
argument was of an unexpected type if some other problem arises and it gets
invoked. (this would help track down the error).
But I'm a user, not an implementor: this is just what I hope to eventually get
out of it. As I said, right now it's just documentation so the next guy knows
what I expected the function to handle when I wrote it.
Brad Miller
------
miller@cs.rochester.edu {...allegra!rochester!miller}
Brad Miller
University of Rochester Computer Science Department
----------------------
From: <samalone@ATHENA.MIT.EDU>
Subject: Re: Current practice:argument types in function declarations
Date: Fri, 18 Dec 87 09:29:12 EST
Yes, I often proclaim functions to take arguments of specific types.
Usually this happens when I want to proclaim the return value of a
function and my sense of taste insists that I proclaim the types of the
arguments as well. However, none of the implementations I've used seem
to do much with the information.
There is one time when proclaiming the types of arguments to a function is
obviously useful: when compiling the function itself. True, one could
use declarations inside of the function to achive the same result, but
using a proclamation keeps all of the function's type specification in one
place.
Without repeating them, I'd also like to voice my support of the
comments made by Mike Bekerle and Brad Miller.
--Stuart A. Malone