由两个竖线括起来的关键字符号

keyword symbol enclosed by two pipes

假设下面代码中有一个函数fun,我的目标是在下面计算expr2

(defun fun (&key (x nil)) x)
(defparameter expr1 (list 'fun :x 2))
(defparameter expr2 (list 'fun (intern "x" "KEYWORD") 2))

正如预期的那样,(eval expr1) 给出了 2,但是 (eval expr2) 给出了类似

的错误

*** - FUN: illegal keyword/value pair :|x|, 2 in argument list. The allowed keywords are (:X) The following restarts are available: ABORT :R1 Abort main loop

为什么会出现这个错误?以及如何修复它?

原因是通常在 Common Lisp 中,每个符号在读取时都会被翻译成大写字母(这是标准行为,可以更改),因此:

(defun fun (&key (x nil)) x)
(defparameter expr1 (list 'fun :x 2))

实际读作:

(DEFUN FUN (&KEY (X NIL)) X)
(DEFPARAMETER EXPR1 (LIST 'FUN :X 2))

intern 获取一个字符串作为第一个参数并且不对其进行转换,因此在您的示例中 "x" 被保留为符号 :x,这与符号不同:X(这就是错误的原因)。请注意,当在 REPL 中打印带有小写字母的符号时,它会被管道字符 (|) 包围,就像在 |x| 中一样,因此,当再次读取时,小写字符不会发生变化:

CL-USER> :x
:X
CL-USER> :|x|
:|x|
CL-USER> (format t "~a" :|x|)
x
NIL

要解决你的问题,你可以直接将字符串写成大写:

(defparameter expr2 (list 'fun (intern "X" "KEYWORD") 2))

然后 (eval expr2) 按预期工作。

注意\|是符号中的转义字符:

? 'foo\xBAR
FOO\xBAR

? '|This is a symbol|
|This is a symbol|

? ':|This is a keyword symbol with spaces and Capital letters!!!|
:|This is a keyword symbol with spaces and Capital letters!!!|

? 'what|? wow |this| also works|?
|WHAT? wow THIS also works?|