定义像
(defun hi () "Hi!")
这样的函数并能够使用 (hi)
或 (HI)
或 (Hi)
调用它,或者 (setf a-number 5)
并能够使用 a-number
访问该号码是否有优势, A-NUMBER
,还是A-Number
?
如果有这样的优势,那为什么大多数其他语言都区分大小写?
在交互式会话中的代码中使用区分大小写的名称更容易出错:不仅需要获取字符,还需要正确区分大小写,并且可能有多个名称仅大小写不同的标识符。
Common Lisp 区分大小写。只是默认情况下,Common Lisp 阅读器功能会将符号的所有未转义字符转换为大写。这也在 Common Lisp 标准中定义。预定义的 Common Lisp 符号在内部也是全部大写。
符号在内部是大写的:
CL-USER 3 > 'defparameter
DEFPARAMETER
默认的输入大小写无所谓:
CL-USER 4 > 'deFParameTER
DEFPARAMETER
CL-USER 5 > 'DEFPARAMETER
DEFPARAMETER
一个符号有一个大写的名字:
CL-USER 6 > (symbol-name 'defparameter)
"DEFPARAMETER"
CL包中有多少个符号:
CL-USER 7 > (length (apropos-list "" "CL"))
978
CL 包中的每个符号都是大写的吗?
CL-USER 8 > (every (lambda (symbol)
(every (lambda (c)
(eql c (char-upcase c)))
(symbol-name symbol)))
(apropos-list "" "CL"))
T
使用大写字母在旧机器上很常见。请记住,Common Lisp 的设计始于八十年代初期(1982 年),其目标是与早期的 Maclisp 兼容,并且当时有更多类型的计算机需要支持(例如所谓的迷你计算机和大型机)。旧计算机上使用的其他编程语言也使用大写标识符,如 COBOL 或 PL/1。
还要注意,Lisp 经常以交互方式使用,因此在交互式编程会话期间,要正确命名大小写更加困难。当 Lisp 阅读器使用默认大小写(此处为大写)并将所有输入转换为这种大小写时,会稍微容易一些。
Common Lisp 支持其他阅读器模式,您还可以转义符号:
|This is a Symbol with mixed CASE and spaces|
.
今天很多软件都是小写的,甚至是区分大小写的,首选小写。一些 Lisp 供应商提供了 Common Lisp 的非标准变体,默认情况下所有符号都是小写的,并且读者是大小写保留的。但这使得它与标准的 Common Lisp 不兼容,标准的 Common Lisp 期望
(symbol-name 'cl:defun)
是“DEFUN”而不是“defun”。
对于交互式会话,在定义 Common Lisp 标准时,不区分大小写曾经是默认设置。
但是,真正发生的是 Common Lisp 阅读器在驻留和评估之前将所有符号转换为大写。这是默认设置,但您可以根据需要随时更改它。
*readtable*
对象有一个属性,readtable-case,它控制读者如何实习和评估阅读的符号。你可以setf readtable-case
到:upcase
(默认),:downcase
,:preserve
,:invert
.
默认情况下,
readtable-case
设置为 :upcase
,这会导致所有符号都转换为大写。
如果你想要区分大小写,你应该做
(setf (readtable-case *readtable*) :invert)
=> :invert
乍一看,您可能认为选择 :preserve 选项会更好,但它有一些小问题:标准定义的所有符号都必须大写。因此,您将只对您定义的符号区分大小写,并且必须写:
* (DEFUN hi () "Hi!")
=> hi
* (SETF a-number 5)
=> a-number
* (HI)
=> ;error: the stored function is #'HI in the *readtable*, but by
; calling (HI) you try to acces a function named #'hi(downcase), which
; gives an error
* A-NUMBER
=> ;error: same for the variable
* (hi)
=> "Hi!"
* a-number
=> 5
:downcase
选项与默认选项相反,将所有内容转换为小写,不区分大小写。
但是使用
:invert
,您在源代码中编写的符号,如 defun
、setf
hi
函数,被转换为大写,并且 CamelCase
中的任何符号都像原始一样保留:
* (setf (readtable-case *readtable*) :invert)
=> :invert
* (defun Hi () "Hi!")
=> Hi
* (Hi)
=> "Hi!"
* (eq 'Hi 'hi)
=> nil
* (eq 'HI 'hi)
=> nil
* (eq 'Hi 'Hi)
=> t
(正如其他人所指出的,它实际上区分大小写,但标准的读者行为是将所有内容都大写。)
优点:
Hashtable
和HashTable
命名不同的东西吗?name
和一个函数name
。 Name
甚至可以是变量的名称,最重要的是。默认情况下,CL 中的阅读器会进行大小写转换,所有转义字符都会变成大写。您可以使用
readtable-case
自定义此行为。这是因为它很容易与遵循相同约定的其他语言交互。