如何在保留词汇上下文的同时再次评估某个内容?
* (defvar form '(+ 1 2))
form
* form
(+ 1 2)
* (eval form) ;; This loses the lexical scope (not an issue here)
3
对于需要词法范围的问题的示例,
(let ((a 1) (b 2)
(form '(+ a b)))
(print form)
(print (eval form)) )
(+ a b)
The variable A is unbound.
如何在同一词汇范围内对该形式进行两次评估?
如何根据需要(在相同的词汇范围内(进行多次eval?
与上一个问题相关为什么SBCL eval函数会丢失macrolet it';是磨合期吗?
我可能错了,但这似乎是一个XY问题。我想你的例子太简单了,以至于你提出要求的原因都消失了。你为什么需要这个?
在不知道更多的情况下,我想你可以用一个宏来解决这个问题:
(defun run (expr)
(funcall expr :run))
(defun src (expr)
(funcall expr :src))
(defmacro expr (&body rest)
`(let ((run (lambda () ,@rest))
(src ',@rest))
(lambda (m)
(case m
(:run (funcall run))
(otherwise src))))))
不引用代码,而是将其提供给expr
,它将创建一个对象。两个函数run
和src
接受这个对象,并在原始词法环境中运行它(因为我创建了一个thunk(或返回表达式的源。你的例子会被写成:
(let* ((a 1)
(b 2)
(form (expr (+ a b))))
(print (src form))
(print (run form)))
注意,我从let
更改为let*
,因为a
和b
都不可用于form
。因此,您得到的词法环境与您运行代码来代替expr
表单的情况相同
Eval既不使用一次也不使用两次。也许CLOS
也能发挥同样的作用。
不能在词法范围内使用eval来评估表单。引用eval上的HyperSpec页面(增加强调(:
功能EVAL
语法:
eval 表单&Rightarrow结果*
参数和值:
- form--一个表单
- 结果——形式的评估值
说明:
评估当前动态环境中的表单和null词法环境。
环境支持中的实施和评估
尽管标准eval
不允许您指定词法环境,但某些实现可能会以实现定义的方式提供此功能。例如
CLISP的ext:eval-env
3.1评估
功能(EXT:EVAL-ENV表单和可选环境(。评估表单在给定的词汇环境中,就好像形式是环境来源的程序。