我是否遗漏了在LISP中使用符号的一些重要事实?

我是否遗漏了在LISP中使用符号的一些重要事实?,lisp,symbols,Lisp,Symbols,简而言之。以下是我在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 "ab

简而言之。以下是我在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:

有趣。我应该先定吗

 [14]> (setq a (internup "abc"))
 ABC

 [15]> (let ((abc 2))
 (eval '(+ 2 a)))

 *** - +: ABC is not a number
 The following restarts are available:

又错了。嗯,我一定错过了一些关于在LISP中插入符号的重要事实。您能帮助我吗?

Eval
在空词法环境中计算表单,即没有词法绑定。这与符号的实习无关。

你的问题与实习无关

第一个问题确实是由这样一个事实引起的,即读者总是将符号大写,因此您需要调用(intern“FOO”),以获得与“FOO”相同的结果

EVAL的问题是由于LET引入了在EVAL中不可见的词法绑定。如果你真的想这样做,你必须声明abc是特殊的,比如:

(let ((abc 2))
    (declare (special abc))
    (eval '(1+ abc)))
特殊声明将使变量具有动态绑定,而不是词法绑定(后者意味着绑定仅限于本地词法上下文,即LET表单内。通过特殊声明,变量可用于该表单中调用的任何对象)


请注意,使用特殊声明和eval是您应该非常小心的事情,您可能首先应该重新考虑eval的使用。很少有人真的需要使用它。在大多数情况下,您实际上是在寻找lambda函数的使用。

通用Lisp读取器的大小写敏感度由可读表决定:

(readtable-case *readtable*)
通常,读取器最初将以大写字母插入符号(除非显式转义字符)。因此:

(eq(实习生“foo”)“foo)
=>无

(eq(实习生“FOO”)“FOO)
=>T

(eq(实习生“FOo”)'fo\o)
=>T

您可以使用反引号语法为eval生成表单:

(let ((abc 2))
  (eval `(+ 2 ,abc)))

=>4

(setf(符号值a)2)
'ABC
设置为
2
。非常感谢。但使用lambda函数的确切含义是什么。我从事于数学符号求值器的工作,我无法想象与调用求值函数不同的方法。(eval(diff(make equation database)'x))eval将在空词汇环境中计算表达式。LET(通常)建立词汇绑定。因此,要从EVAL访问变量,它必须是一个动态绑定,因此需要为绑定或由DEFVAR或DEFPARAMETER建立的绑定进行特殊声明。只需澄清:该反引号形式相当于
(list(quote+)(quote 2)abc)
,其计算结果为list
(+2)
然后传递到
eval
。显式的
eval
调用从未看到变量
abc
(let ((abc 2))
  (eval `(+ 2 ,abc)))