要简短。这是我几次尝试实习并在clisp中使用符号。
[1]> (setq sym (intern "foo"))
|foo|
[2]> (eq sym 'foo)
NIL
为什么???
[3]> (defun internup (me &optional (package *package*))
(intern (string-upcase me) package))
INTERNUP
[4]> (eq 'abc (internup "abc"))
T
可能必须要做好准备。
[12]>(let ((abc 2))
(eval '(+ 2 abc)))
*** - EVAL: variable ABC has no value
The following restarts are available:
确定
[18]> (let ((abc 2))
(eval '(+ 2 'abc)))
*** - +: ABC is not a number
The following restarts are available:
有趣。我应该在之前设置它吗。
[14]> (setq a (internup "abc"))
ABC
[15]> (let ((abc 2))
(eval '(+ 2 a)))
*** - +: ABC is not a number
The following restarts are available:
又错了。嗯,我必须遗漏一些关于LISP实习符号的重要事实。你能救我吗?
答案 0 :(得分:3)
Eval
评估 null lexical environment 中的表单,即没有词法绑定。这与符号的实习无关。
答案 1 :(得分:3)
你的问题与实习无关。
第一个问题确实是因为读者总是将符号大写,所以你需要调用(实习“FOO”)以获得与'foo相同的结果。
EVAL的问题是由于LET引入了一种在EVAL中不可见的词法绑定。如果你真的希望这个工作,你必须声明abc是特殊的,如下:
(let ((abc 2))
(declare (special abc))
(eval '(1+ abc)))
特殊声明将导致变量具有动态绑定,而不是词法绑定(后者意味着绑定仅限于本地词汇上下文,即在LET形式内。使用特殊声明,变量可用于任何事物从那种形式调用。)
请注意,使用特殊声明和eval是您应该非常小心的,您应该首先重新考虑使用EVAL。您实际需要使用它是非常罕见的。在大多数情况下,你实际上是在寻找lambda函数的使用。
答案 2 :(得分:2)
Common Lisp阅读器的区分大小写由可读表决定:
(readtable-case *readtable*)
通常,阅读器最初将以大写形式实习符号(除非您明确地转义字符)。因此:
(eq (intern "foo") 'foo)
=> NIL
(eq (intern "FOO") 'foo)
=> Ť
(eq (intern "FOo") 'fo\o)
=> Ť
您可以使用反引用语法为eval构建表单:
(let ((abc 2))
(eval `(+ 2 ,abc)))
=> 4