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

标签 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) 给出了一个错误,如

*** - 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/

相关文章:

.net - pdb 文件实际上是做什么的?

wolfram-mathematica - 如何为符号设置值

list - Common Lisp 从列表中返回关联作为新列表

c++ - ld : duplicate symbols for architecture x86_64 when defining a global var in a header

java - Unresolved Java DatePickerDialog 方法

objective-c - Objective-C : Inline function - symbol not found

lisp - 如何在 LISP 中定义一个函数,该函数传递两个 Form,然后随机执行它们

macros - 宏: value is not of type LIST

http - 如何在 Common Lisp 中读取 HTTP cookie?