Proposed ANSI Changes
This page is a listing of proposed and wishlist revisions to ANSI Common Lisp. It is not a forum for pie-in-the sky thoughts about future Lisps (for which, see Lisp - Next Generation) or extra functionality that could be standardized (see Proposed Extensions To ANSI.)

For clarifications and errata, see ANSI Clarifications and Errata.

  • Un-deprecate REMOVE-IF-NOT, DELETE-IF-NOT.

  • Issue UNDEPRECATE-IF-NOT: Un-deprecate all *-if-not functions.

  • Issue REMOVE-SET: Remove SET (already deprecated).

  • Issue CONSTANTLY-MULTIPLE-VALUES: Extend CONSTANTLY to return multiple values if given other than 1 argument.

  • Issue PRINTING-SPACE: Change the behavior of character printing such that invisible graphic characters such as space can be printed by name. The ~:C format directive does this already.

  • Issue PRINT-OBJECT-RETURNS: The requirements that PRINT-UNREADABLE-OBJECT returns nil and that user-defined methods for PRINT-OBJECT must return the object don't fit well together. The example in PRINT-UNREADABLE-OBJECT demonstrates the problem: It is in error because it returns nil from PRINT-OBJECT, in the assumption that the return value of PRINT-UNREADABLE-OBJECT is usable as a return value of PRINT-OBJECT. It would be a simplification if returning nil from PRINT-OBJECT were allowed, or if PRINT-UNREADABLE-OBJECT were specified to return the object. (By contrast, DESCRIBE-OBJECT may return anything.)

    The :REPORT option of DEFINE-CONDITION defines a method for PRINT-OBJECT, so the issue affects that too. In particular, (:REPORT "foo") defines a method that typically returns the string "foo", rather than the required condition object.

  • Issue BOOLEAN-RETURNS: Many functions are specified to return true when they could just as easily return T. Since most (all?) implementations already return T for these functions, tighten the standard so this is required. Why would this be a good thing? Issue MACROEXPAND-RETURN-VALUE changed the language to the opposite direction. (Actually, that issue just noted the inconsistency; the proposed solution there would change the requirement to 'true'. Another possible solution would be to change everything else to require T.) It would be a good thing because it would remove a gratuitous and unnecessary incompatibility between implementations, which would make it slightly easier to write portable programs. GCL ansi-tests would have been noticeably easier to write had all the predicates returned T for true. -- Paul Dietz

  • Issue NO-NEXT-METHOD: NO-APPLICABLE-METHOD is specified to be called/signalled only when there are no applicable methods. However, there is an error situation for built-in method combinations that is not covered by this: when there is no primary method. Specify an analogous NO-PRIMARY-METHOD generic-function/condition pair.

  • Issue UNDEPRECATE-REQUIRE: [ may be contentious ] Undeprecate single-argument require, reflecting its continuing usage by Lisp implementors to load optional bolt-on modules that are supplied with the implementation. This is not supposed to be a means for the user to load his own or third-party libraries, for which a real DEFSYSTEM is a better solution. Note that a real DEFSYSTEM is outside the scope of this page. If cl:require is actually removed, implementations can still have ext:require, which doesn't seem too bad if the names of the modules are already not portable. Alternatively some parts of the REQUIRE mechanism might be specified -- eg. *REQUIRE-HOOK* or *REQUIRE-HOOKS*. You're right. REQUIRE should be removed and implementations that use it can have EXT:REQUIRE or something

  • Issue TYPE-OF-BIGNUM: The definition of TYPE-OF implies that BIGNUM or FIXNUM cannot be the types returned (due to requirement 1 and the presence of UNSIGNED-BYTE in figure 4-2.) This was probably not intended. Fix this.

  • Issue COMPILER-MACRO-IMPLICIT-BLOCK. Specify that DEFINE-COMPILER-MACRO should establish an implicit block around the body.

  • Issue SXHASH-NEGATIVE-ZERO: SXHASH and the file compiler are affected by a loose specification of similarity with respect to negative zeros. It would appear that an implementation is permitted to dump negative zeros as positive ones (and vice versa), to the extent that (defconstant foo 0.0) (defvar *bar* (eql foo foo)) need not return true; also, it requires (sxhash 0.0) to be equal to (sxhash -0.0) even though (equal 0.0 -0.0) is false. Specify that negative zeros are not similar to positive zeros.

  • Issue IMAGPART-NEGATIVE-ZERO: The IMAGPART and COMPLEX functions are inconsistent in their treatment of objects of type (REAL * (0)): (complex -2.0) returns an object whose imaginary part is (coerce 0 'single-float), while (imagpart -2.0) returns (* 0 -2.0), which is different in implementations supporting negative zeros. This has ramifications in the treatment of branch cuts for real numbers.

  • Issue FORMAT-VERBATIM: FORMAT should offer a directive that prints a string verbatim to the output stream, character by character, ignoring printer settings such as *PRINT-CIRCLE* and *PRINT-LEVEL*; i.e., one that corresponds to WRITE-STRING and not PRINC or PRIN1.

    The section on Formatted Output almost reads as if ~A is supposed to ignore printer settings when printing strings ("If arg is a string, its characters will be output verbatim"); however, under this interpretation, ~S will also ignore those variables when printing strings, since it's specified as "just like ~A, but arg is printed with escape characters", while it is clearly desirable to honor printer settings in ~S. So, at least some clarification is needed here.

    Consider the following code snippet.

    (defparameter *separator* ",")

    (defstruct foo (a 'a) (b 'b))

    (defmethod print-object ((foo foo) stream) (print-unreadable-object (foo stream) (format stream "~A~A~A" (foo-a foo) *separator* (foo-b foo))))

    (let ((*print-circle* t)) (print (list (make-foo) (make-foo))))

    The intended output is (#<a,b> #<a,b>). However, in at least one CL implementation, the output will be (#<a#1=,b> #<a#1#b>), i.e., the printer will detect the shared structure and use sharpsign notation instead of printing the string verbatim. [Side note: There's no way to tell for sure where the printed representation of the object the #1= refers to ends, so the output is not very useful.] It's hard to argue that this output is non-conforming because of the wording in the description of ~S. So I don't think there's a way to write this print-object method without resorting to an explicit write-string (or copy-seq, but this will cons needlessly; or using a symbol, which is counter-intuitive). It's a pity format has this limitation.

    Issue PRINC-READABLY seems to be related to this.

  • Issue DEFCONSTANT-REDEFINE: Change the behavior of DEFCONSTANT so that it assigns a value to the given symbol only if that symbol is not already bound (much like DEFVAR)

    I think that's a bad idea. DEFCONSTANT is only problematic for values that cannot be compared with EQL but only, for example, with EQUAL. This may lead to the situation that one wants to use, for example, constant strings, but every time the respective DEFCONSTANT form is reevaluated an error is issued because two EQUAL strings are not necessarily EQL. Here is another proposal: Add a TEST keyword to DEFCONSTANT that allows programmers to specify how they intend to use the constant, i.e. under what equivalence semantics. In the case of string constants they can say, for example: (DEFCONSTANT +example+ "example" :test #'equal). The idea here is that this is a promise to the compiler that the rest of the program does not rely on the EQL identity of the value of +example+. In turn, if the value of +example+ is indeed changed to another value that is not EQUAL in a subsequent DEFCONSTANT form the compiler can issue a warning / error as before.

  • Issue COMPILE-FILE-EXTENSIONS: Change COMPILE-FILE to allow implementation-defined keys (much like SBCL / CMUCL's use of :TRACE-FILE or LispWorks's :LOAD; I'm sure other implementations have similar extensions)

  • Issue FORMAT-LOGICAL-BLOCK-PREFIX-SUFFIX: Allow ~~ (Tilde) in the prefix and suffix segments of ~<...~:> (Logical Block). Currently, those segments cannot contain any format directives, so the corresponding output strings cannot contain tilde characters. It is not necessary to allow other directives (~%) or parameters (~V~, ~1~) to fix this.

  • Issue CONDITIONS-NOT-EXTERNALIZABLE: Clarify the intention and interaction between MAKE-LOAD-FORM, that specifies primary methods on conditions to signal an error, and that specifies that the file compiler uses MAKE-LOAD-FORM to externalize conditions. Taken together with this implies that given a portable program and a conforming implementation standardized conditions can never appear as externalized objects in compiled code, which probably was not the intention.


    • Clarify that standardized conditions cannot be externalized.
    • Allowing (but not requiring) implementations to use something else then MAKE-LOAD-FORM to externalize standardized conditions.
    • Allowing implementations to define methods on MAKE-LOAD-FORM for standard conditions that signal an error only if the real class of the condition is not a standardized condition.

  • Issue MAP-INTO-SAMPLE-DEFINITION: The notes section on MAP-INTO section give an example of how it could be implemented; the example is incorrect in the way it handles the fill-pointer of result-sequence. MAP-INTO is specified to ignore the fill-pointer when deciding how many iterations to perform, and afterwards change it to the number of iterations performed.

  • Issue KEYWORD-TYPE: KEYWORD and KEYWORDP are inconsistent (and the former is inconsistent with the glossary definition of 'keyword'.) A symbol is in the KEYWORD type if it is accessible in the package, but KEYWORDP is true if the symbol has the package named KEYWORD as its home package. The latter was probably intended. Fix this by either prohibiting importing (and shadow importing) of symbols into the keyword package, or force the home package of the symbol to be changed when this is done.

  • Issue MAKE-CONDITION-ERROR: MAKE-CONDITION should be allowed to signal an error on type arguments that do not name classes, like (or type-error program-error).
  • Issue PATHNAME-PRINT-READABLY: NAMESTRING, PARSE-NAMESTRING, PATHNAME et al use (in the examples sections) a readable syntax for printing pathnames: #S(PATHNAME ...). It should be specified as such, instead of requiring #P"..." which is not always readable.
  • PRINT-UNREADABLE-OBJECT's specification, if taken literally, requires that an ugly space be printed after the type description but before the closing bracket if type is true, identity is false, and the forms don't print anything. This may not have been intended; change so that the space is not printed in this situation (and the mirror case with identity being true.)

  • The glossary entry for "single escape" includes this parenthetical comment: "In the standard readtable, slash is the only single escape." This should reference "backslash", not "slash".

  • ARITHMETIC-ERROR-OPERATION is specified to return a function designator in Arguments and Values, but a list in Description. Those types are disjoint; presumably the description is wrong.

  • Section (Sharpsign Asterisk) states that an error of type READER-ERROR is signaled if [...] "n is greater than one, but no bits were specified." This should be "n is greater than or equal to one, but no bits were specified."

  • *PRINT-READABLY* states that the printed form should be readable within the "standard readtable". This implies that the printed representation is not allowed to be expressed in terms of user-defined reader macros. Although it leads to "normalized" representations, it can be considered overly restrictive if the printed representation is only read in when the user-defined readtable is in effect (reading and writing become asymmetric). Proposal: remove the restriction on "standard readtable", but perhaps "encourage" users to give representations that work in the "standard readtable". c.l.l March 7, 2007

  • Section 23.1.2 (Effect of Readtable Case on the Lisp Reader) states: "When the readtable case is :invert, then if all of the unescaped letters in the extended token are of the same case, those (unescaped) letters are converted to the opposite case." The term "extended token" is not well defined, but presumably means the entire symbol token, including package name, separators, and symbol name. This has the (likely unintended) consequence that "common-lisp-user::Foo" references package "common-lisp-user" instead of "COMMON-LISP-USER". This should be amended to treat the package name and symbol name parts of the token separately. As a point of information, LispWorks 4.4.6 appears to be faithful to the standard, whereas CLisp 5.1 uses the proposed behavior.

  • The dictionary entry for mapc and company discusses 'result-type' in the text ("result-type specifies the type of the resulting sequence."), however none of these functions appear to implement the functionality of allowing the user to specify the result-type in the actual function specifications. It has been speculated that this is an erroneous copy and paste from the entry for map.
  • COMPLEMENT is specified to take a FUNCTION, while most other higher-order operators in CL take designators for functions. (Additionally, the Notes section for COMPLEMENT is incorrect, since APPLY takes a function designator.) For similarity with the rest of the language, COMPLEMENT should take a function designator.
  • NCONC has a few tiny bugs in its specification. First, it would be nicely specified as a right fold instead of a left fold, i.e. (nconc list-1 list-2 . lists) == (nconc list-1 (nconc list-2) . lists) instead of (nconc (nconc list-1 list-2) . lists) — an overly literal reading of the left-folding definition leads to quadratic evaluation time (though optimizations are possible). Second, the example (setq x '(a b c)) (setq y '(d e f)) (nconc x y) flies in the face of Section 3.7.1 Modification of Literal Objects. As for me, I'd like to see a note somewhere that NCONC is very seldom a good idea, since its time complexity class is no better than APPEND, its space complexity class also is no better than APPEND in the common case where no one else is sharing the side-effected list, and its bug complexity class is way higher than APPEND. If the small enhancement factor due to APPEND vs NCONC is a limiting resource in your program, you have a big problem and are probably using the wrong data structure. I'd like to see the use of NCONC explicitly discouraged. If it weren't for legacy code that may rely on it, I would make the order or even existence of its side-effects made explicitly unspecified, so that APPEND be a valid implementation of NCONC.
  • The standard should provide a list of all forms that provide an implicit NIL block around their bodies, for reference. The current wording in CLHS individual pages is inconsistent, which makes it hard to find a list of such forms with a search. At least these forms put implicit NIL blocks around their bodies: DO, DO*, PROG, PROG*, LOOP, DOLIST, DOTIMES, DO-SYMBOLS, DO-ALL-SYMBOLS, DO-EXTERNAL-SYMBOLS
  • CLHS, on Sharpsign Dot, does not specify what happens if the form prefixed by #. returns no values. The most popular answer, and arguably the most useful, is for nothing to be read, so that '(#.(values) foo) => (FOO). SBCL, Clozure CL, Allegro CL, and LispWorks all do this. It should accordingly be required by the standard.
  • RENAME-FILE does not specify what happens when a file named new-name already exists. Several implementations add a third optional (sometimes keyword) if-exists parameter to RENAME-FILE that is used to specify what happens (typical values are :error and :overwrite). This de-facto extension to CL should be standardized.
  • The function FIND makes it impossible to find NIL in a sequence since NIL will be returned regardless of the input sequence. The suggestion is to add a second returned variable that is T if the element was found and NIL if it was not - like in GETHASH. (The usual way to deal with this is to use MEMBER instead.)
Please put outright extensions (not fixups) in Proposed Extensions To ANSI.