[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

list of proposed changes to Common Lisp



The following is the text, verbatim, of the handout I made available
this past Monday at the Common Lisp meeting.  One exception: in the entry
for page 293, the second occurrence of (DISPLACED-ARRAY-P NEW-ARRAY)
has been deleted because it was a typographical error.

------------------------------------------------------------------------
These are changes that I (Guy Steele) think are important but must not
be made without the general approval of the Common Lisp community.
Items that I think particularly important (because they correct
important flaws or resolve ambiguity in the specification) are marked
(*).

1 DELETE-SETF-METHOD takes the name of an access-fn and removes the SETF
data associated with that name.  DELETE-PACKAGE takes a package,
uninterns all symbols in that package, unuses all packages it uses, and
gets rid of the package.  An error is signalled if the package is used
by any other package.  Maybe other things, such as DELETE-TYPE (undoes a
DEFTYPE), UNDEFUN, UNDEFVAR, UNDEFCONSTANT, and so on are needed as
well.  One suggestion is to have a single special form UNDO, allowing
one to write such things as (UNDO DEFUN FOO), (UNDO DEFINE-SETF-METHOD
FOO), and so on (syntax negotiable).  Presumably (UNDO SETQ FOO) means
roughly the same as (MAKUNBOUND 'FOO)--or does it?  What of the scoping
of FOO?  We need some way to do these things, but I have no concrete
suggestion as yet.

(*) 47 Specify that, in a FUNCTION type specifier, following the &KEY
marker one should use items of the form (keyword type-specifier)
instead of just a type-specifier:
(DECLARE (FTYPE (FUNCTION (FUNCTION SEQUENCE &KEY (FROM-END T)
		           (START (INTEGER 0 ())) (END (INTEGER 0 ()))
			   (INITIAL-VALUE T))
		          T)
	        REDUCE))
Specify that such a declaration implies that no other keywords may be
used unless the declaration also contains &ALLOW-OTHER-KEYWORDS; in
other words, one must explicitly declare types for all keyword arguments
or else use &ALLOW-OTHER-KEYWORDS.  Specify that a type specifier for a
&REST argument indicates the type of each argument, not the type of a
rest-argument list (which is always a list, after all):
(DECLARE (FTYPE (FUNCTION (ARRAY &REST (INTEGER 0 ())) T) AREF))

(*) 51 Add a new function TYPE-SPECIFIER-P that is true of valid type
specifiers and false of all other Lisp objects.  Note that the use of
DEFSTRUCT and DEFTYPE can change the behavior of TYPE-SPECIFIER-P over
time.

(*) 56, 68  Clarify that using DEFCONSTANT to redefine any constant
described in the Common Lisp specification is an error.  Clarify that if
the user defines a constant, compiles code that refers to that constant,
and then redefines the constant, then behavior of the compiled code may
be unpredictable.  (Perhaps it ``is an error'' to execute such code.)

(*) 60  Specify that it is an error for two parameters (including supplied-p
parameters) in the same lambda-list to have the same (EQL) name.  (An
alternative is to say that it is not an error, and the effective binding
order is from left to right, as you would expect from the rules for init
forms.  This is no worse than LET*, but somehow does not appeal to me.
A possible compromise is that no two required arguments may have the
same name.)

82 Have a function XOR of any number of arguments that returns T if an
odd number of its arguments are non-NIL, and otherwise returns NIL.
This complements AND and OR (but there is no point in making it a
special form as all arguments must be evaluated).

(*) 107 Clarify that GET-SETF-METHOD and GET-SETF-METHOD-MULTIPLE-VALUE do
not perform macro-expansion on the given form, and that in most contexts
the usage should be (GET-SETF-METHOD (MACROEXPAND form env)).  Indeed,
the simplified example version of SETF given on page 108 should be
changed to:
(DEFMACRO SETF (REFERENCE VALUE &ENVIRONMENT ENV)
  (MULTIPLE-VALUE-BIND (...)
      (GET-SETF-METHOD (MACROEXPAND REFERENCE ENV))
    ...))
[Alternatively, we could specify that GET-SETF-METHOD should take an
environment as an additional, optional argument, but that would be a
change to the language rather than simply a clarification.]

(*) 113 Permit declarations before the body of a LABELS, FLET, or MACROLET.

(*) 120 In addition to DEFUN, the following macros should implicitly wrap a
BLOCK around their bodies: DEFMACRO, DEFSETF, DEFINE-SETF-METHOD, and
DEFTYPE.  This should be encouraged as a philosophy of style for
user-written macros.  Also, LABELS, FLET amd MACROLET should wrap
a block around the bodies of the locally defined functions.

(*) 130  Specify explicitly that anything in a TAGBODY other than a symbol,
integer, or list is an error.

(*) 130  Specify that it is an error for the same (EQL) tag to appear more
than once in the body of a TAGBODY.  (However, a TAGBODY may have the
same tag as another TAGBODY in which it nests, in which case the tag in
the outer TAGBODY is shadowed, as already specified.)

(*) 144 Delete the third paragraph of the description of MACRO-FUNCTION,
which specifies that MACRO-FUNCTION cannot be used to access macro
functions defined by MACROLET.  Change MACRO-FUNCTION to take an
optional environment argument so that it can get at macros defined by
MACROLET.  Specify that when SETF is used with MACRO-FUNCTION, only one
argument may be given to MACRO-FUNCTION.

(*) 145 Add a new function PARSE-BODY, taking arguments body, environment,
and documentation-allowed-p.  It pulls apart the body into three parts:
a list of DECLARE forms, a documentation string (or NIL if none), and
the body proper.  These are returned in the order body, declarations,
and doc-string as three values.  PARSE-BODY may perform macro-expansion
(using the given environment) in order to determine whether a macro-call
expands into a DECLARE form (or documentation string??).

145 Extend the syntax of an &BODY parameter to DEFMACRO to allow writing
&body (body-var [declarations-var [doc-string-var]]).  If only body-var
appears in parentheses, it means the same as a body-var with no
parentheses.  Otherwise, it means to give the original body to
PARSE-BODY (with documentation-allowed-p true iff the doc-string-var is
specified) and then bind the variables to the corresponding values
returned by PARSE-BODY.  This is purely a syntactic convenience for the
user of DEFMACRO so that he doesn't have to use &ENVIRONMENT and then
call PARSE-BODY himself.

(*) 145 Specify that the &REST or &BODY argument to a macro may be the very
list from the macro call, and not a copy, and therefore the user should
not perform destructive operations on it.  Similarly, a function that
takes as &REST argument should not destroy it because its top-level list
structure might might share with a list that the user gave as the last
argument to APPLY.

(*) 158 Specify that it is an error for more than one TYPE declaration for a
given variable to appear in a group of declarations (those all at the
head of the same body), or more than one FTYPE or FUNCTION declaration
for a given function name, or both an INLINE and a NOTINLINE declaration
for the same function.  Proclamations produce no such conflict; the
most recent proclamation supersedes all others.

(*) 159  Clarify that in the following example
(DEFUN FOO (X)
  (DECLARE (INLINE BAR))
  (BAR X)			    ;first
  (FLET ((BAR (Z) (BAR (+ Z 1))))   ;second
    (BAR X))			    ;third
  (BAR X))			    ;fourth
the first, second, and fourth calls to BAR are affected by the INLINE
declaration, but not the third one.

(*) 159 For consistency with the FUNCTION type specifier, change the
syntax of the FUNCTION declaration to (FUNCTION name arglist result-type)
with a note to the effect that types of multiple values are expressed as
(FUNCTION name arglist (VALUES result-type-1 result-type-2 ...)).

(*) 161 Specify that (THE type form) where type is not (VALUES ...) means
the same as (THE (VALUES type) form), and that in (THE (VALUES ...)
form) the form may return more values, but not fewer, than the number of
types specified in the (VALUES ...), and that any extra values are of
unrestricted type.

(*) 172  Revise the paragraph beginning ``As a verb'' to reflect the fact
that INTERN cannot take a symbol, only a string.  One ought to speak of
interning a name in a package, producing a symbol.

186  Modify the definition of IMPORT as follows:  if any symbol to be
imported has no home package, then IMPORT sets the home package of the
symbol to the specified package being imported to.

(*) 187  Modify description of DO-SYMBOLS to specify that it may execute the
body more than once for some symbols.

(*) 202 Define (LCM) to return 1 (the manual is incorrect in claiming that
the result should be infinity).

212 Change the branch cuts of the ATAN function to follow W. Kahan's
recommendations.  (Paul Penfield intends to recommend the same change to
the APL community.)

226 Add a function SIGNED-LDB that is like LDB but sign-extends the
extracted byte.

239 Change CHAR-EQUAL, CHAR-NOT-EQUAL, CHAR-LESSP, CHAR-GREATERP,
CHAR-NOT-LESSP, and CHAR-NOT-GREATERP to consider two characters to be
different if their bits attributes are different.

249 What is the effect of giving circular lists to MAP, MAPCAR, SOME,
EVERY, etc.?  Specify that there is an error?  Is it good style to write
(MAPCAR \#' CONS X (STAR Y)) for (MAPCAR \#' (LAMBDA (Z) (CONS Z Y)) X)
where (DEFUN START (X) (RPLACD X X) X)?  I recommend that this be
considered an error.

268 Have a function COPY that can copy any single object.  For a
structure, it would use the user-specified copy function, if any.  For a
CONS cell it would copy just that CONS.  Whether (EQ X (COPY X)) for X a
character or number is implementation-dependent.

(*) 275  Clarify that (TAILP NIL X) returns NIL for all lists X.  The second
sentence in the description of TAILP is incorrect.

283 Functions HASH-TABLE-REHASH-SIZE, HASH-TABLE-REHASH-THRESHOLD,
HASH-TABLE-SIZE, and HASH-TABLE-TEST each take a hash table and return
the appropriate current information.

(*) 293 Add a function ROW-MAJOR-AREF, taking an array and a single
subscript, that accesses an array element according to the row-major
ordering.  Add a function DISPLACED-ARRAY-P, which takes an array and
returns NIL and 0 if it is not displaced or the array displaced to and
the displaced-index-offset if it is displaced.  These allow certain code
efficiencies, and also allow array displacement to be explained in
terms of Lisp primitives:
(DEFUN AREF (ORIGINAL-ARRAY &REST SUBSCRIPTS)
  (LABELS ((FOO (ARRAY INDEX)
	     (MULTIPLE-VALUE-BIND (NEW-ARRAY OFFSET) (DISPLACED-ARRAY-P ARRAY)
	       (IF (NULL NEW-ARRAY)
	           (ROW-MAJOR-AREF ARRAY INDEX)
		   (MULTIPLE-VALUE-CALL #'FOO
		                        NEW-ARRAY
					(+ INDEX OFFSET)))))
      (FOO ORIGINAL-ARRAY
	   (APPLY #'ARRAY-ROW-MAJOR-INDEX ORIGINAL-ARRAY SUBSCRIPTS))))
As a bow to efficiency, note the fact that if array A is displaced to B
with offset M, and B is displaced to C with offset N, and B is not
adjustable, then DISPLACED-ARRAY-P of A might return either array B with
offset M or array C with offset (+ M N).  This generalizes to chains
of non-adjustable arrays.

(*) 295 Specify that ADJUST-ARRAY is another important exception to the
general rule about operating only on active elements of arrays.
(See proposed clarifications of ADJUST-ARRAY.)

(*) 297 Here are the interactions of ADJUST-ARRAY with displacement.
Suppose we are adjusting array A, which is perhaps displaced
to B before adjustment and perhaps to C after adjustment.
(1) Not displaced before or after.  The dimensions of A are altered, and
the contents rearranged as appropriate.  Additional elements of A are
taken from the :initial-element.  The use of :initial-contents causes
all old contents to be discarded.
(2) Not displaced before, but displaced afterwards to C.  As already
specified, none of the original contents of A appears in A afterwards,
but rather the contents of C without any rearrangement of C.
(3) Displaced beforehand to B, and afterward to C.  As in case (2), no
contents of B appear in A afterward.  If :DISPLACED-INDEX-OFFSET is not
specified in this case, it defaults to zero; the old offset (into B) is
not retained.
(4) Displaced beforehand to B, but not displaced afterward.  A gets a
new "data region", and contents of B are copied into it as appropriate
to maintain the existing old contents; additional elements of A are
taken from the :initial-element.  However, the use of :initial-contents
causes all old contents to be discarded.

(*) 297 Specify that the fill pointer is ignored for the purposes of
deciding whether a given element of a new array resulting from
ADJUST-ARRAY should take its value from the old array contents or from
the specified :INITIAL-ELEMENT.

(*) 307  Allow a call to DEFSTRUCT to have no slot-descriptions.

(*) 307  Specify that it is an error for two slots in a single DEFSTRUCT
to have the same name.  If structure A includes structure B, then
no additional slot of A may have the same name as any slot of B.

(*) 321 Modify EVAL to have an optional environment argument.

(*) 322  At end of second paragraph on *APPLYHOOK*, clarify that the apply
hook function is not used when special forms are evaluated.

(*) 328 Remove the requirement that *STANDARD-INPUT*, etc., must be
initially bound to synonym streams to *TERMINAL-IO*; demote this to the
level of an implementation suggestion.  This is to allow flexibility of
implementation, for example to allow UNIX [TM and all the usual
deferences that people for some reason pay to UNIX but not to Kleenex or
Coke or Star Wars] redirection to win.  (I don't mind noting the
trademark status of UNIX; it just bugs me that people who do so are not
so consistently diligent about other trademarks.)

425  Generalize FILE-LENGTH to accept any filename, not just an open
file-stream.  Let it take a keyword argument :ELEMENT-TYPE, defaulting
to STRING-CHAR for non-stream arguments and to the element-type of the
stream for a stream argument.

(*) 439 Clarify that if DISASSEMBLE is given a symbol whose function
definition is interpreted, that definition is indeed compiled and
then disassembled, but the resulting compiled definition does not
replace the interpreted one as the symbol's function definition.

439 COMPILEDP takes a function and returns non-NIL if it is a compiled
function, and NIL if it is not.  If the function is a symbol whose
compiled-function definition was installed by the COMPILE function, then
the non-NIL value returned is the interpreted definition that was
compiled.

439 UNCOMPILE takes a symbol and restores the previous interpreted
definition of that symbol if that symbol previously had an interpreted
definition and was then given to COMPILE; otherwise no action is taken.

440 Specify explicitly that one may trace macros as well as functions
(but not special forms).

(*) 443  Modify description of APROPOS to replace the words ``available in''
to ``accessible in,'' and specify that APROPOS on a given package finds
the same symbols that DO-SYMBOLS would.

447 The USER-NAME function returns a string identifying the user of the
Common Lisp system, or NIL if that cannot be determined.