[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Issue: DECLARE-TYPE-FREE (Version 6)
- To: cl-cleanup@SAIL.Stanford.EDU
- Subject: Issue: DECLARE-TYPE-FREE (Version 6)
- From: CL-cleanup@Sail.stanford.edu
- Date: 5 Dec 88 16:53 PST
- Cc: Masinter.pa@Xerox.COM
- Line-fold: NO
- Reply-to: CL-Cleanup@SAIL.Stanford.EDU
- Sender: masinter.pa@Xerox.COM
Here's a first pass at this writeup. I've convinced myself today that
the issue for type declarations is their extent, not their scope.
Only name bindings have scope; type declarations don't introduce
name bindings, they only introduce constraints on those bindings,
and the constraints are dynamic.
I better stop before I dig myself a bigger hole. This writeup
also attempts to fix some of the terminology of the "proposal"
part.
If you like this, the writeup needs to be extended with JAR's
examples of assignments that violate the declarations outside
of the scope but within the extent of the declaration, and should
say that they are "in error".
!
Issue: DECLARE-TYPE-FREE
References: CLtL p.158
DECLARATION-SCOPE
Category: CLARIFICATION/ADDITION
Edit history: Version 1, 18-Sep-88, Moon
Version 2, 22-Sep-88, Moon
(small edits to reflect mail discussion)
Version 3, 22-Sep-88, Masinter
Version 4, 27-Sep-88, JonL
Version 5, 30-Sep-88, Masinter (cost to implementors)
Version 6, 06-Oct-88, Pitman (minor edits in Discussion)
Version 7, 5-Dec-88, Masinter (scope->extent)
Problem description:
Section 9.2 of CLtL, p158, says that a declaration specifier like
(TYPE type var1 var2 ...) "... affects only variable bindings".
Since declarations can occur in contexts other than establishing
"variable bindings", most people interpret this statement to mean
that type declarations not in such context are either (1) completely
to be ignored, or (2) invalid CL syntax. Thus both of the following
forms would be suspect in that the type declarations could not have
any effect:
(if (and (typep x 'fixnum) (typep y 'fixnum))
(locally (declare (fixnum x y)) ;LOCALLY does not bind
...algorithm using x and y...) ; any variables.
...similar algorithm using x and y...)
(let ((y 'foo))
(setq y 10)
(let ((x 5)) ;'y' is not being bound in
(declare (fixnum y)) ; this particular context.
(incf y)
...random algorithm...))
Proposal (DECLARE-TYPE-FREE:ALLOW-DYNAMIC):
Specify that a type declaration does not only "affect variable bindings";
rather, type declarations are legal in all declarations; the interpretation
of a type declaration is that, within the extent of the form containing
the declaration, it is an error for the value of the declared variable not
to be of the declared type.
This is stronger constraint than what would be implied by wrapping
a THE form around every reference to the variable, including modifying
references by SETQ or SETF, and, for type declarations that also affect a
variable binding, around the computation of the initial value.
Rationale:
This proposal enables optimizing compilers to make use of the otherwise
ignored type information. Many people have often asked for it, and
there is no strong reason to forbid it.
Current practice:
Lucid Common Lisp allows "free" type declarations; under some
circumstances the compiler issues a warning message that such usage
is an extension to Common Lisp.
Cost to Implementors:
Implementations that might currently warn about such declarations
would have to remove the warning; otherwise, it is valid to ignore
type declarations.
Cost to Users:
None, this is a compatible addition.
Cost of non-adoption:
Common Lisp will be less self-consistent.
Benefits:
Programmers will be able to use type declaration to express their
intent, rather than having to manually insert THE wrappers around
every reference.
Esthetics:
It is a simpler interpretation for type declaration specifiers, with
fewer special cases; hence reduces the number of exceptions in the
language.
Discussion:
This issue has been discussed at the Fort Collins X3J13 meeting in
November 1987, and at length on the various electronic mailing lists.
At least one current implementation is able to generate more efficient
code when declarations are associated with a particular binding, since
it then has the option to choose type-specific specialized storage for
the runtime value of the variable. So, for example,
(let ((x v)) (declare (type float x)) (+ x x))
is sometimes more efficient than
(let ((x v)) (locally (declare (type float x)) (+ x x)))
However, the local type declarations allowed by this proposal do
provide some useful information, even if it is not the *most* useful.
It is possible for a sufficiently "smart" compiler to infer the
equivalent of a "binding declaration" when it can ascertain that the
type of the binding value -- 'v' above -- is commensurate with the
type locally declared over the scope of usage of the variable.
It may be useful for a compiler to issue a warning whenever it finds
nested type declarations referring to the same variable and the
intersection of the declared types is null.
Documentation might want to discuss the style implications of
nested declarations intersecting. The interesting cases are:
- An inner declaration could be a subtype of an outer one.
This is the most useful case and probably the only one to
be encouraged in code written by humans. e.g.,
(locally (declare (type number x))
(locally (declare (type integer x))
...use X as integer...))
- An outer declaration could be a subtype of an inner one.
This is useless but harmless. It might happen as the result
of certain macro situations. e.g.,
(locally (declare (type integer x))
(locally (declare (type number x))
...use X as integer...))
- Two types may only partially overlap. This would presumably
happen only as the result of a macro expansion.
(locally (declare (type fixnum x))
(locally (declare (type (or bit package) x))
...use X as BIT...))
----- End Forwarded Messages -----