假设下面的代码中有一个函数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:非法的关键字/值对:| x |,参数列表中的2。 允许的关键字是(:X)可以使用以下重新启动:ABORT:R1中止主循环
为什么会出现此错误?以及我该如何解决?
答案 0 :(得分:7)
原因是通常在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
,与符号{{1}不同}(这就是错误的原因)。请注意,在REPL中打印带有小写字母的符号时,与:X
中一样,它由管道字符(|
)包围,因此,再次阅读时,小写字符不变:
|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))
会按预期工作。
答案 1 :(得分:5)
请注意,\
和|
是符号中的转义字符:
? '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?|