Lisp 读取时间评估宏与准注释

Lisp 读取时间评估宏与准注释,lisp,common-lisp,Lisp,Common Lisp,简言之,有什么区别 (setq var1 `(,(get-internal-real-time))) var1 -->(1358995178904535) var1 -->(1358995178904535) (setq var2 '(#.(get-internal-real-time))) var2 -->(1358995195568422) var2 -->(1358995195568422) 我认为“读取时间评估”可能意味着每次读取变量时它都会求值,但我猜我错了

简言之,有什么区别

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

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

我认为“读取时间评估”可能意味着每次读取变量时它都会求值,但我猜我错了,而Quasikote eval也不会这样做。

“读取时间评估”意味着每次读取代码时都会求值。在REPL中输入
var2
时,如果不读取变量,则访问其值。因此,在您的情况下,两种形式都会产生相同的结果。

一个差异很重要的示例:

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

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

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

相反,请看以下内容:

CL-USER > (read-from-string "`(,(get-internal-real-time))")
(LIST (GET-INTERNAL-REAL-TIME))
上述结果在一定程度上取决于实现,因为未定义反报价列表的读取版本。但效果是类似的:从Lisp阅读器返回的结果表单是调用
列表
(或等效项),子表单作为参数

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

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

请注意,
bar
确实调用了
get internal real time
一次,但它在读取时会这样做。这是一个重要的细节,尤其是当您编译要稍后加载的文件时,以及当您希望
.
下面的表达式使用动态绑定时。@acelent No,
bar
从不调用
获取内部实时
,读卡器调用该函数,并用读取时的值替换条所看到的值。这与在REPL中使用
(read)
相同吗?在REPL中:
(setf h'hi)>#(read)
返回
hi
,而
>,(read)
返回
h