Common Lisp总是区分大小写。符号有名称,它们只是字符串。但是,几乎没有什么东西可以让事情看起来不区分大小写。要掌握这些是什么,您需要对系统如何读取代码有所了解。
当系统读取一个表单时,它必须从文本表示中创建一个 Lisp 对象。例如,如果阅读器正在读取如下字符串:(hello world),那么结果应该是两个符号的列表。这些符号的名称是什么?这就是读者有一些灵活性的地方。默认行为是让读者大写从输入中读取的名称。读者获得输入“hello”和“world”,然后将它们大写为“HELLO”和“WORLD”,然后将它们实习。正如您所发现的,这由 readtable 案例控制。有几种不同的可能性,即:upcase、:downcase、:preserve 和:invert。 :Preserve 和 :invert 可以方便地用于互操作性代码。
函数是否区分大小写是没有意义的。 readtable case 仅影响阅读器如何将文本输入转换为符号名称。听起来您想要做的是确保在您阅读代码时 readtable-case 是 :preserve 或 :invert 。请注意,如果 readtable-case 是 :invert,则所有小写名称都会大写,所有大写名称都会小写,其他所有内容都将保留。我指出这一点是因为在您的示例 (defun hi () "Hi!") 中,文本“hi”将被大写,并且您定义函数的符号将具有名称“你好”。然后,当你写(HI)时,阅读器会生成一个名为“hi”的符号列表,不能是同一个符号。
目前提供的代码与您的示例显示的工作方式不同,而且它看起来不像是复制粘贴的 REPL 脚本。这是我在运行您显示的代码时看到(和期望)的:
* (setf (readtable-case *readtable*) :invert)
:invert
* (defun hi () "hello")
hi
编写 (hi) 有效,因为阅读器仍然会反转并给您一个名为“HI”的符号,正如预期的那样:
* (hi)
"hello"
但写成 (HI) 不会,因为读者会反转并给你一个名为“hi”的符号,正如预期的那样:
* (HI)
; in: HI
; (|hi|)
;
; caught style-warning:
; undefined function: HI
;
; compilation unit finished
; Undefined function:
; HI
; caught 1 STYLE-WARNING condition
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
("undefined function")
现在,在交互式测试中,您确实需要清楚自己是否卡在调试器中,因为某些设置(如 readtable-case)可能会在调试器中更改为了方便。例如,
* (setf (readtable-case *readtable*) :invert)
:invert
* (defun hi () "hello")
hi
* (HI)
; in: HI
; (|hi|)
;
; caught style-warning:
; undefined function: HI
;
; compilation unit finished
; Undefined function:
; HI
; caught 1 STYLE-WARNING condition
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
("undefined function")
0] TOP
我们输入 TOP 以退出调试器。您可以输入 ? 以获取可用命令的列表。现在我们回到顶层 REPL,我们可以看到 (HI) 将产生相同的结果。这一次,我们也将尝试在调试器中执行 (HI):
* (HI)
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SYMBOL-FUNCTION |hi|)
0] (HI) ;; within the debugger
"hello" ;; "HI" must have been read as "HI", not "hi"
0] TOP
在调试器中,(HI) 工作得很好。它必须重置为一些“标准”值,以使程序员的生活更轻松。但是,进入 TOP 后,我们又回到了 REPL,(HI) 将再次失败:
* (HI)
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SYMBOL-FUNCTION |hi|)
0]