如何在保持词汇背景的同时再次评估某些内容?
* (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.
如何在相同的词法范围内两次评估该表格?
如何按照我想要的次数(在相同的词汇范围内)?
与上一个问题相关 Why does SBCL eval function lose the macrolet it's running in?
答案 0 :(得分:6)
我可能会弄错,但这似乎是XY problem。我想你的例子很简单,你的请求的原因已经消失了。你为什么需要这个?
我不知道更多我在想你可以用宏来解决这个问题:
(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
可能效果很好。
答案 1 :(得分:1)
您无法使用eval来评估词汇范围内的表单。在eval上添加HyperSpec页面(强调添加):
Function EVAL
语法:
eval 表格⇒结果*
参数和值:
- 表格 - 表格。
- 结果 - 评估表格所产生的价值。
说明
评估当前动态环境 和null词法中的表单 环境 强>
虽然标准eval
不允许您指定词法环境,但某些实现可能以实现定义的方式提供此功能。例如
ext:eval-env
3.1. Evaluation
功能(EXT:EVAL-ENV形式和可选环境)。评估表格 在给定的词汇环境中,就好像表格是其中的一部分一样 环境来自的程序。