3

简而言之,有什么区别?

(setq var1 `(,(get-internal-real-time)))
var1
-->(1358995178904535)
var1
-->(1358995178904535)

(setq var2 '(#.(get-internal-real-time)))
var2
-->(1358995195568422)
var2
-->(1358995195568422)

我认为也许“读取时评估”意味着它会在我每次读取变量时进行评估,但我想我错了,准引用评估也不会这样做。

4

3 回答 3

4

差异很重要的一个例子:

* (defun foo () `(,(get-internal-real-time)))
FOO
* (defun bar () '(#.(get-internal-real-time)))
BAR
* (foo)
(44577)
* (foo)
(47651)
* (bar)
(41929)
* (bar)
(41929)

如您所见,当您不直接使用该值时(如本(setq var1 ...)例所示),每次都会扩展准引号,返回不同的值。但是,使用读取时评估,它只被调用一次,一次又一次地返回相同的值。

于 2013-01-24T08:48:50.620 回答
4

如果您想单独查看读取时间效果,则使用 REPL 评估表单不是一个好主意。REPL 表示读取 EVAL 打印循环。每一段代码都将被读取、评估和打印。不只是阅读。

而是看到这个:

CL-USER > (read-from-string "`(,(get-internal-real-time))")
(LIST (GET-INTERNAL-REAL-TIME))

以上结果在一定程度上取决于实现,因为未定义反引号列表的读取版本。但效果是相似的:从 Lisp 阅读器返回的结果形式是LIST对子形式的调用(或等效形式)作为参数。

CL-USER > (read-from-string "'(#.(get-internal-real-time))")
(QUOTE (465370171))

上面在读取时执行表单并将值包含到表达式中,这是读取操作的结果。

于 2013-01-24T09:04:24.500 回答
3

“读取时评估”意味着每次读取代码本身时都会对其进行评估。当您输入var2REPL 时,您不会读取变量,而是访问它的值。因此,在您的情况下,两种形式都会产生相同的结果。

于 2013-01-24T04:42:57.480 回答