Common lisp 由两个管道包围的关键字符号

Common lisp 由两个管道包围的关键字符号,common-lisp,symbols,Common Lisp,Symbols,假设下面的代码中有一个函数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)给出了如下错误 ***-乐趣:非法关键字/值对:| x |,参数列表中有2个。 允许的关键字为(:X)

假设下面的代码中有一个函数
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)
给出了如下错误

***-乐趣:非法关键字/值对:| x |,参数列表中有2个。 允许的关键字为(:X)以下重新启动可用:中止:R1中止主循环


为什么会发生这种错误?我该如何修复它呢?

原因是,通常在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?|