11.5. Package Case-Sensitivity

11.5.1. User Package for the Case-sensitive World
11.5.2. Package Names
11.5.3. Gensyms and Keywords
11.5.4. Migration Tips
11.5.5. Using case-sensitive packages by default

CLISP supports programs written with case sensitive symbols. For example, with case sensitive symbols, the symbols cdr (the function equivalent to REST) and the symbol CDR (a user-defined type denoting a Call Data Record) are different and unrelated.

There are some incompatibilities between programs assuming case sensitive symbols and programs assuming the [ANSI CL standard] case insensitive symbols. For example, (eq 'KB 'Kb) evaluates to false in a case sensitive world and to true in a case insensitive world. However, unlike some commercial Common Lisp implementations, CLISP allows both kinds of programs to coexist in the same process and interoperate with each other. Example:

(DEFUN FOO () ...)
(in-package "NEW")
(defun bar () (old:foo))
(symbol-name 'bar) ; ⇒ "bar"

This is achieved through specification of the symbol case policy at the package level. A modern package is one that is declared to be both case-sensitive and case-inverted and which use the symbols from the CS-COMMON-LISP package.

A case-sensitive package is one whose DEFPACKAGE declaration (or MAKE-PACKAGE creation form) has the option (:CASE-SENSITIVE T). In a case-sensitive package, the reader does not uppercase the symbol name before calling INTERN. Similarly, the printer, when printing the SYMBOL-NAME part of a SYMBOL (i.e. the part after the package markers), behaves as if the readtable's case were set to :PRESERVE. See also Section 11.1.5, “Function EXT:PACKAGE-CASE-SENSITIVE-P.

A case-inverted package is one whose DEFPACKAGE declaration (or MAKE-PACKAGE creation form) has the option (:CASE-INVERTED T). In the context of a case-inverted package, symbol names are case-inverted: upper case characters are mapped to lower case, lower case characters are mapped to upper case, and other characters are left untouched. Every symbol thus conceptually has two symbol names: an old-world symbol name and a modern-world symbol name, which is the case-inverted old-world name. The first symbol name is returned by the function SYMBOL-NAME, the modern one by the function cs-cl:symbol-name. The internal functions for creating or looking up symbols in a package, which traditionally took a string argument, now conceptually take two string arguments: old-style-string and inverted-string. Actually, a function like INTERN takes the old-style-string as argument and computes the inverted-string from it; whereas the function cs-cl:intern takes the inverted-string as argument and computes the old-style-string from it. See also Section 11.1.4, “Function EXT:PACKAGE-CASE-INVERTED-P.

For a few built-in functions, a variant for the case-inverted world is defined in the CS-COMMON-LISP package, which has the nickname CS-CL:

returns the case-inverted symbol name.
work consistently with cs-cl:symbol-name.
convert a SYMBOL to a STRING and therefore exist in a variant that uses cs-cl:symbol-name instead of SYMBOL-NAME.
creates a case-inverted PACKAGE.

11.5.1. User Package for the Case-sensitive World

A package CS-COMMON-LISP-USER is provided for the user to modify and work in. It plays the same role as COMMON-LISP-USER, but for the case-sensitive world.

11.5.2. Package Names

The handling of package names is unchanged. Package names are still usually uppercase. The package names are also subject to (READTABLE-CASE *READTABLE*).

11.5.3. Gensyms and Keywords

Note that gensyms and keywords are still treated traditionally: even in a case-sensitive package,

(STRING= '#:FooBar '#:foobar)
⇒ T
(EQ ':KeyWord ':keyword)
⇒ T

We believe this has a limited negative impact for the moment, but can be changed some time in the future.

11.5.4. Migration Tips

The following practices will pose no problems when migrating to a modern case-sensitive world:

The following practices will not work in a case-sensitive world or can give problems:

  • Accessing the same symbol in both upper- and lowercase from the same source file.
  • Macros that create symbols in other packages than the original symbols.
  • Comparing SYMBOL-NAME return values with EQ.
  • Comparing (SYMBOL-NAME x) with (cs-cl:symbol-name y).

11.5.5. Using case-sensitive packages by default

CLISP supports a command-line option -modern that sets the *PACKAGE* initially to the CS-COMMON-LISP-USER package, and *PRINT-CASE* to :DOWNCASE.

For packages to be located in the modern (case-sensitive) world, you need to augment their DEFPACKAGE declaration by adding the option (:MODERN T), see Section 11.1.2, “Macro DEFPACKAGE.

These notes document CLISP version 2.49Last modified: 2010-07-07