lisp - Common Lisp EVAL 函数引用

标签 lisp common-lisp eval

我的问题很简单(可能具有误导性)。

在 Common Lisp 中,当我运行以下命令时,我得到了相应的结果:

(eval '''boo) => 'boo

另一方面,如果我运行以下命令,我会得到一些稍微不同的东西。

(eval (eval '''boo)) => boo

我的问题是:如果第一个命令的 eval 从 variable-symbol 中“削掉”两个引号并在输出中留下一个标记,这两个嵌套怎么可能eval函数一共去掉三个引号?

这特别令人困惑,因为以下会导致错误:

(eval 'boing) => ERROR. BOING is unbound. 

最佳答案

'boo(quote boo) 的缩写。在代码中,quote 是一种特殊形式,它只计算它的参数,仅此而已。因此 boo。当这个值被传递时它是数据而不是代码但是为了创建符号 foo 你需要 quote

'''boo(quote (quote (quote boo))) 的缩写。评估它时,它的行为与以前完全一样,它变成了 (quote (quote boo)),这是一个包含两个元素的列表,其中第二个元素是一个包含两个元素的列表。

因为 eval 是一个函数,它首先计算参数,然后计算结果,就像函数应该做的那样。因此 (quote (quote foo)) 在第一次评估后变为 (quote foo) 并且 eval 取消第二次留下符号

如果 eval 得到一个符号 foo,这意味着它应该得到全局命名空间中变量 foo 绑定(bind)的值。因此:

(defparameter *test* 5)
(eval '*test*)
; ==> 5

因为参数是 (quote *test*),在评估后变成了 *test*eval 查看符号并获取值 5,这就是结果。如果 *test* 没有绑定(bind),你会得到你得到的错误。

(defparameter *test-symbol* '*test)
(eval *test-symbol*)

这里也一样。因为它是一个函数 *test-symbol* 被评估为符号 *test*,这就是 eval 看到的并且它获取值 5

(defparameter *result* (eval '''foo))
*result*
; ==> (quote foo) but often the REPL shows 'foo
(consp *result*)
; ==> t
(length *result*)
; ==> 2
(car *result*)
; ==> quote
(cadr *result*)
; ==> foo

有时我看到初学者做类似'('(a) '(b))的事情。这是一个错误,因为在评估时你最终得到列表 ((quote (a)) (quote (b))) 作为数据,这很少是意图。当使用像 list 这样的函数时,参数会被评估,你需要适本地引用:

(list '(a) *result* '(b))
; ==> ((a) (quote foo) (b))

关于lisp - Common Lisp EVAL 函数引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42887151/

相关文章:

lisp - 可视化编程工具

emacs - 使用 Paredit 包装现有表达式

lisp - 用普通的 lisp 编程语言将文件中的单词读入嵌套列表

Javascript - 根据变量调用函数名称

scheme - 用 Lisp 编写正式语言解析器

lisp - 变量没有在 lisp 循环中递增

ruby - 之前未声明时,在 eval 之后未定义的局部变量或方法

PHP 验证约束列表

tree - Lisp中树结构的定义

package - 如何使用字符串在包中查找变量并更改它?