区分大小写 Common Lisp

Case Sensitivity Common Lisp

我正在尝试使 sbcl 区分大小写,但没有成功。 有谁知道问题可能是什么? mentions here and here 这是可能的。

我是 运行

(setf (readtable-case *readtable*) :invert)
(defun hi () "Hi!")
(HI)
(HI)
"Hi!"

repl 内部如下。

"C:\Program Files\Steel Bank Common Lisp.2.15\sbcl.exe" --core "C:\Program Files\Steel Bank Common Lisp.2.15\sbcl.core"

编辑: 因此,如果您在 Common Lisp 中调用不区分大小写的函数,它会恢复到程序其余部分区分大小写的旧行为我目前没有找到阻止这种情况的方法。

; in: Hi2
;     (|Hi2|)
;
; caught style-warning:
;   undefined function: Hi2
;
; compilation unit finished
;   Undefined function:
;     Hi2
;   caught 1 STYLE-WARNING condition

debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002C77BE3}>:
  The function COMMON-LISP-USER::|Hi2| 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.

Common Lisp 总是区分大小写。符号有名称,只是字符串。但是,很少有东西使事情看起来不区分大小写。要掌握这些是什么,你需要稍微了解一下系统是如何读取代码的。

当系统读取表单时,它必须从文本表示中创建一个 Lisp 对象。例如,如果 reader 从一个字符串中读取,例如:(hello world),那么结果应该是一个包含两个符号的列表。这些符号的名称是什么?这就是 reader 具有一定灵活性的地方。默认行为是 reader 到 upcase 从输入中读取的名称。 reader 获取输入 "hello" 和 "world",然后 upcases 这些到 "HELLO" 和 "WORLD",然后实习生那些。正如您所发现的,这是由可读案例控制的。有几种不同的可能性,即 :upcase、:downcase、:preserve 和 :invert。 :Preserve 和 :invert 可以方便地用于互操作性代码。

函数是否区分大小写是没有意义的。可读大小写仅影响 reader 如何将文本输入转换为符号名称。听起来您想要做的是确保在阅读代码时可读案例是 :preserve 或 :invert 。请注意,如果 readtable-case 是 :invert,那么所有小写的名称都会大写,所有大写的名称都会小写,其他所有内容都会保留。我指出这一点是因为在您的示例 (defun hi () "Hi!") 中,文本 "hi" 将被大写,并且您定义的符号函数的名称为 "HI"。然后,当你写 (HI) 时,reader 将生成一个名为 "hi" 的符号列表,它不能是相同的符号。


到目前为止提供的代码并不像您的示例所显示的那样工作,而且它看起来不像是复制粘贴的 REPL 脚本。当我 运行 您显示的代码时,这是我看到的(和期望的):

* (setf (readtable-case *readtable*) :invert)

:invert
* (defun hi () "hello")

hi

(hi) 有效,因为 reader 仍然反转并给你一个名为 "HI" 的符号,正如预期的那样:

* (hi)

"hello"

但是写 (HI) 不会,因为 reader 反转并给你一个名为 "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")

现在,在交互式测试中,您 do 需要清楚自己是否卡在调试器中,因为某些设置(如 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) 工作得很好。它必须重置回一些 "standard" 值,以使程序员的生活更轻松。但是,在进入 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] 

您的示例不起作用:

* (setf (readtable-case *readtable*) :invert)

:invert
* (defun hi () "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:
  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] 

请注意,0] 表示我们处于级别 0 的调试器中,它具有正常的可读情况。退出调试器,通过键入 0 查看打印的指令,我们回到顶级侦听器 - 可读的情况仍然是 :invert.

如果您阅读 SBCL 打印的内容:(invokable by number or by possibly-abbreviated name)。然后你看到 0[ABORT]。所以你按数字调用它。只需键入 0 和 return。您还可以键入 abort.

向调试器输入 HELP 可以解释...

如果你编译一个包含以下内容的文件

(setf (readtable-case *readtable*) :invert)
(defun hi () "Hi!")
(HI)

,那么第一种形式对编译时环境没有影响,因为编译器不执行那段代码。它只是编译它。 reader 没有改变。它会在加载代码时更改。请参阅 EVAL-WHEN 以在编译时执行顶级代码。