为什么 Common Lisp 不区分大小写?

问题描述 投票:0回答:4

定义像

(defun hi () "Hi!")
这样的函数并能够使用
(hi)
(HI)
(Hi)
调用它,或者
(setf a-number 5)
并能够使用
a-number
访问该号码是否有优势,
A-NUMBER
,还是
A-Number

如果有这样的优势,那为什么大多数其他语言都区分大小写?

common-lisp case-sensitive case-insensitive
4个回答
37
投票

在交互式会话中的代码中使用区分大小写的名称更容易出错:不仅需要获取字符,还需要正确区分大小写,并且可能有多个名称仅大小写不同的标识符。

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”。


17
投票

对于交互式会话,在定义 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

9
投票

(正如其他人所指出的,它实际上区分大小写,但标准的读者行为是将所有内容都大写。)

优点:

  • 你真的想让
    Hashtable
    HashTable
    命名不同的东西吗?
  • 由于 Common Lisp 提供了不同的命名空间,您也不需要大写来区分类、变量和函数名称(以及其他名称)。您可以毫无歧义地拥有一个类
    name
    和一个函数
    name
    Name
    甚至可以是变量的名称,最重要的是。
  • 如上一句所示,您可以在散文中将符号名称大写,就像任何其他单词一样。

3
投票

默认情况下,CL 中的阅读器会进行大小写转换,所有转义字符都会变成大写。您可以使用

readtable-case
自定义此行为。这是因为它很容易与遵循相同约定的其他语言交互。

© www.soinside.com 2019 - 2024. All rights reserved.