CLHS: Issue INITIALIZATION-FUNCTION-KEYWORD-CHECKING Writeup

#

## Issue INITIALIZATION-FUNCTION-KEYWORD-CHECKING Writeup

    Status: Passed v4 (8-1), as amended, Dec-91; v5 reflects the amendment
    Issue:          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.

Copyright 1996-2005, LispWorks Ltd. All rights reserved.