Status: Passed v4 (8-1), as amended, Dec-91; v5 reflects the amendmentIssue: INITIALIZATION-FUNCTION-KEYWORD-CHECKING
Reference: Draft 10.156
7.2.1.1 Initialization Arguments (p.7-6)
(which corresponds to CLtL-II 28.1.9.1, p.802)
7.2.1.2 Declaring the Validity of Initialization Arguments
(p.7-7) (which corresponds to CLtL-II 28.1.9.2, p.803)
7.3.5 Keyword Arguments in Generic Functions and Methods
(p.7-20) (which corresponds to CLtL-II 28.1.6.5, p.792)
Category: CHANGE
Edit History: Version 1, 10/2/91, Kim Barrett
Version 2, 10/8/91, Kim Barrett (Moon & JonL comments)
Version 3, 10/11/91, Kim Barrett (more Moon comments)
Version 4, 11/20/91, Kim Barrett
(clarify :allow-other-keys, make references to 10.156 draft)
Version 5, 11-Feb-92, Kent Pitman
("has no effect on" => "suppresses" per X3J13 meeting amendment)
Problem Description:
A careful reading of 88-002R indicates that users must specify
&ALLOW-OTHER-KEYS in the lambda-lists of methods for initialization functions
if the method also specifies &KEY, else risk having the generic function
keyword argument checking signal an error due to the presence of "slot
filling" initargs. (An error might not occur due to the presence of other
methods which already specify &KEY + &ALLOW-OTHER-KEYS).
Several implementors (and presumably users too) have misread the specification
as saying that &ALLOW-OTHER-KEYS in an applicable initialization method means
that initarg validation is suppressed for those protocols in which the method
takes part.
The result is that the need for and meaning of &ALLOW-OTHER-KEYS in
initialization methods differs significantly from one implementation to
another.
Proposal:
1. Change the syntax of the following generic functions to specify both &KEY
and &ALLOW-OTHER-KEYS:
ALLOCATE-INSTANCE class &key &allow-other-keys
INITIALIZE-INSTANCE object &key &allow-other-keys
MAKE-INSTANCE class &key &allow-other-keys
REINITIALIZE-INSTANCE object &key &allow-other-keys
SHARED-INITIALIZE object slot-names &key &allow-other-keys
UPDATE-INSTANCE-FOR-DIFFERENT-CLASS previous current
&key &allow-other-keys
UPDATE-INSTANCE-FOR-REDEFINED-CLASS object
added-slots discarded-slots
property-list
&key &allow-other-keys
It is of course possible to retain "&rest initargs" in the syntax description
when needed in the corresponding function description.
2. Clarify that the presence of &ALLOW-OTHER-KEYS in the lambda-list of an
applicable method relevant to the specified initarg validity checking for an
initialization protocol suppresses the validity checking.
3. Clarify that a true value for the initialization argument :ALLOW-OTHER-KEYS
disables initialization argument validation. Make the following changes Draft
10.156 in order make this clarification.
a. Remove the last sentence of the second paragraph of section 7.2.1.1
(p.7-6), which says
"Error checking of initialization argument names is disabled if the keyword
argument pair whose keyword is :ALLOW-OTHER-KEYS and whose value is non-NIL
appears in the initialization argument list."
b. Replace the last sentence of section 7.2.1.2 (p.7-7), which says
"The meaning of:ALLOW-OTHER-KEYS is the same here as when it is passed to an
ordinary function."
with
"Validity checking of initialization arguments is disabled if the value of
the initialization argument :ALLOW-OTHER-KEYS is true."
Editorial impact:
The syntax entries for seven functions need to be modified.
A small change to "Declaring the Validity of Initialization Arguments" is
needed in order to clarify the handling of &ALLOW-OTHER-KEYS in initialization
methods.
Rationale:
Since &ALLOW-OTHER-KEYS needs to be specified somewhere if &KEY is specified
by any of the applicable methods, it is better to have the generic function
specify it, rather than requiring programmers to remember to include it in
every initialization method that also specifies &KEY.
Examples:
(defclass test ()
((slot :initarg :slot-filler))
)
(defmethod initialize-instance :after ((x test) &key) nil)
(make-instance 'test :slot-filler 5)
-> currently might signal an error
-> returns instance of test under proposed change.
Current Practice:
Both Lucid 4.0 and IIM 3.4 specify only &REST in the lambda-lists of the
listed generic functions and the specified methods for those functions, with
the implication that user defined methods which specify &KEY must also specify
&ALLOW-OTHER-KEYS in order to inhibit keyword argument checking by the generic
function from signaling an error due to the presence of "slot filling"
initargs. However, because generic function keyword checking has not yet been
implemented in either Lucid 4.0 or IIM 3.4, users may not be aware of this
requirement. In fact, in IIM 3.4 there are system-supplied initialization
methods that fail to meet this requirement, so there are some implementors who
aren't aware of this problem either.
Franz Allegro 4.0 appears to have the same behavior as described above for
Lucid 4.0 and IIM 3.4. In particular, generic function keyword checking has
not yet been implemented.
Symbolics CLOS and Chestnut's Lisp-to-C translator both specify &KEY and
&ALLOW-OTHER-KEYS in the lambda-lists of the listed generic functions. In
addition, if an applicable method for one of the protocols specifies
&ALLOW-OTHER-KEYS then the specified initarg checking for the protocol is not
performed.
Macintosh Common Lisp 2.0b3c4 has "&KEY &ALLOW-OTHER-KEYS" in the lambda list
for MAKE-INSTANCE, but all the others just use "&REST". This asymmetry is an
oversight due to the fact that the method combination code special cases them,
and elides normal generic function keyword checking for all of them (hence it
has never appeared as a "bug"). MCL (like Symbolics and Chestnut) also
provides the additional behavior that if one of the applicable methods
specifies &ALLOW-OTHER-KEYS then the initarg checking for the protocol is not
performed.
Cost to Implementors:
Some possibly tricky code in the implementation may have to be reexamined. In
some implementations it looks like this may involve simply ripping out some
special cases.
Cost to Users:
Probably none in most cases. Since none of the implementations surveyed ever
signal an error for the described problem case, it is unlikely that any user
code exists which depends on an error being signaled.
Users can eliminate unnecessary &ALLOW-OTHER-KEYS from initialization methods
at their leisure, since its presence or absence has no effect.
However, those users who have made use of the fairly common but non-portable
meaning of &ALLOW-OTHER-KEYS in applicable methods as a means of suppressing
initarg validation would have to find some other mechanism for this purpose.
One possibility would be to define appropriate :AROUND or primary methods on
MAKE-INSTANCE that add :ALLOW-OTHER-KEYS T to the initialization arguments.
Performance Impact:
None.
Benefits:
Users and implementors will know what &ALLOW-OTHER-KEYS in an initialization
method's lambda-list means. Programmers writing initialization methods that
specify keywords won't have to remember to include &ALLOW-OTHER-KEYS
explicitly.
Aesthetics:
Requiring all initialization methods that specify &KEY to also specify
&ALLOW-OTHER-KEYS is clearly unaesthetic, so this change is an improvement.
Discussion:
Interestingly, for one reason or another, none of the implementations surveyed
perform generic function keyword checking (as opposed to initarg checking) for
the functions affected by this proposal.
The possibility of having &ALLOW-OTHER-KEYS in the lambda-list of an
applicable initialization method mean that initarg validation should be
inhibited was discussed, especially in light of the fact that several of the
implementations surveyed already provide this behavior. However, some people
questioned whether this was really such a good idea, being unmodular and
perhaps *too* convenient. Also, making such a change would add a real cost to
users who weren't expecting this extension, since they would have to examine
occurances of &ALLOW-OTHER-KEYS in initialization methods to decide whether
they were left over from the time when it was (at least theoretically) needed
to inhibit generic function keyword checking or actually there to do the new
thing.