假设下面的代码中有一个函数 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)
按预期工作。
关于common-lisp - 由两个管道包围的关键字符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56658671/