#

## Issue ALLOW-OTHER-KEYS-NIL Writeup

    Issue:        ALLOW-OTHER-KEYS-NIL
    Forum:	      Cleanup
    References:   :ALLOW-OTHER-KEYS (pp62-63)
    Category:     CLARIFICATION/CHANGE
    Edit history: 22-Aug-90, Version 1 by Pitman
    	      23-Aug-90, Version 2 by Pitman (merge RWK's comments)
    	      23-Aug-90, Version 3 by Pitman (merge Moon's comments)
    	      13-Mar-91, Version 4 by Pitman (comments from JonL, Barmar)
    Status:	      For Internal Discussion

    Problem Description:

      CLtL specifies that a keyword argument pair of :ALLOW-OTHER-KEYS is
      always permissible when the value is non-null, in which case all other
      keyword arguments in that actual call are allowed regardless of the
      formal &KEY parameter).  It doesn't specify any particular meaning
      when the value for :ALLOW-OTHER-KEYS is null; consequently such an
      actual argument pair will be in error unless there is a formal &KEY
      parameter of that name to receive it.

      The fact that :ALLOW-OTHER-KEYS NIL either does not work or does not
      work reliably causes some coding to be more cumbersome than necessary.
      For example, a function that might be written as:
        (DEFUN FOO-MEMBER (ITEM LIST PERMISSIVE-P &REST OPTIONS)
          (APPLY #'MEMBER ITEM LIST :ALLOW-OTHER-KEYS PERMISSIVE-P OPTIONS))
      must in fact be written as:
        (DEFUN FOO-MEMBER (ITEM LIST PERMISSIVE-P &REST OPTIONS)
          (IF PERMISSIVE-P
    	  (APPLY #'MEMBER ITEM LIST :ALLOW-OTHER-KEYS T OPTIONS)
    	  (APPLY #'MEMBER ITEM LIST OPTIONS)))
      because :ALLOW-OTHER-KEYS NIL is not given the `obvious' meaning.

      Some people have raised concerns about the permissibility and semantics
      of :ALLOW-OTHER-KEYS (including :ALLOW-OTHER-KEYS NIL) if either
      &ALLOW-OTHER-KEYS is used or an explicit &KEY argument such as
      ALLOW-OTHER-KEYS is specified.  Some clarification about such issues
      is probably warranted.

    Proposal (ALLOW-OTHER-KEYS-NIL:PERMIT):

      1. Define that :ALLOW-OTHER-KEYS is always permitted as an argument
         to any function which has specified &KEY in the lambda list of its
         definition.

         If the value is non-NIL, then other non-matching keywords are
         also tolerated (i.e., ignored). If the value is NIL, then other
         non-matching keyword are not tolerated (i.e., an error should be
         signalled in accordance with rules for argument mismatches
         established by other proposals) unless &ALLOW-OTHER-KEYS was used.

      2. Clarify that if the receiving argument list specifies an argument which
         would be flagged by :ALLOW-OTHER-KEYS, then :ALLOW-OTHER-KEYS has both
         its special-cased meaning (identifying whether additional keywords are
         permitted) and its normal meaning (data flow into the function in
         question).

    Rationale:

      1. There can't be any reasonable use for :ALLOW-OTHER-KEYS as a keyword
         to designate `real' information coming into the function since the
         keyword is already reserved just in case the value it carries with
         it will be non-NIL.  As such, there is no ambiguity about the
         programmer's intent in the case of :ALLOW-OTHER-KEYS NIL.  Failing
         to admit :ALLOW-OTHER-KEYS NIL just makes it unnecessarily clumsy
         to write functions like FOO-MEMBER (see Problem Description).
         It also defeats the purpose of there being a value associated with
         :ALLOW-OTHER-KEYS in the first place.

      2. This allows functions which do their own keyword processing on &REST
         arguments to respect this flag, as well as being conceptually the most
         uniform meaning.

    Test Case:

      #1: ((LAMBDA (&KEY) T) :ALLOW-OTHER-KEYS NIL)

      #2: (DEFUN FOO-MEMBER (ITEM LIST PERMISSIVE-P &REST OPTIONS)
    	(APPLY #'MEMBER ITEM LIST :ALLOW-OTHER-KEYS PERMISSIVE-P OPTIONS))
          (FOO-MEMBER 'X '(Z Y X) NIL)

      #3: ((LAMBDA (&KEY ALLOW-OTHER-KEYS) ALLOW-OTHER-KEYS)
           :ALLOW-OTHER-KEYS 6 :FRED 7)

      #4: ((LAMBDA (&KEY ALLOW-OTHER-KEYS) ALLOW-OTHER-KEYS)
           :ALLOW-OTHER-KEYS NIL :FRED 7)

      #5: ((LAMBDA (&KEY ((:ALLOW-OTHER-KEYS FOO))) FOO)
           :ALLOW-OTHER-KEYS 6 :FRED 7)

    Current Practice:

      #1: Symbolics Genera 8.0 and Sun Common Lisp 3.0.1 signal an error.
          Symbolics Genera 8.1 returns T, which is consistent with proposal
          PERMIT.

      #2: Symbolics Genera 8.0 and Sun Common Lisp 3.0.1 signal an error.
          Symbolics Genera 8.1 returns (X), which is consistent with proposal
          PERMIT.

      #3: Sun Common Lisp 3.0.1 signals an error.
          Symbolics Genera 8.0 and 8.1 return 6, which is consistent with
          proposal PERMIT.

      #4: Symbolics Genera 8.0, Symbolics Genera 8.1, and Sun Common Lisp 3.0.1
          signal an error, which is consistent with proposal PERMIT.

      #5: Sun Common Lisp 3.0.1 signals an error.
          Symbolics Genera 8.0 and 8.1 return 6, which is consistent with
          proposal PERMIT.

    Cost to Implementors:

      Relatively small.

    Cost to Users:

      None.  Currently, a valid user program must avoid stepping on this
      error situation.

    Cost of Non-Adoption:

      See aesthetics.

    Benefits:

      See aesthetics.

    Aesthetics:

      This simplifies the user model by making the value associated with
      :ALLOW-OTHER-KEYS be what controls whether other keys are permitted,
      rather than by making the presence of the sequence ``:ALLOW-OTHER-KEYS T''
      in the arglist what controls it.  In the status quo, the description of
      how :ALLOW-OTHER-KEYS works is like no other keyword in the language.

    Discussion:

      Pitman, RWK, and Moon support this proposal.

      RWK comments: ``Together with my addenda above, [this] proposal
       means that &KEY without &ALLOW-OTHER-KEYS implies a "hidden"
       keyword argument of :ALLOW-OTHER-KEYS that the &KEY processing
       checks.  In all other regards, it is a perfectly ordinary keyword
       argument.''

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