读取时间eval宏与quasiquote

时间:2013-01-24 02:57:02

标签: lisp common-lisp

简而言之,有什么区别?

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

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

我认为也许通过“read-time eval”它意味着它会在每次读取变量时进行评估,但我想我错了,quasiquote eval也没有这样做。

3 个答案:

答案 0 :(得分: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 ...)情况),每次都会扩展准报价,返回不同的值。但是,使用读取时间eval,它只被调用一次,一次又一次地返回相同的值。

答案 1 :(得分:3)

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

相反看这个:

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))

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

答案 2 :(得分:2)

“read-time eval”意味着每次读取代码本身时都会对其进行评估。在REPL中输入var2时,如果没有读取变量,则可以访问其值。因此,在您的情况下,两种形式都会产生相同的结果。