考虑this问题。这里的基本问题是代码:
(progv '(op arg) '(1+ 1)
(eval '(op arg)))
此处的问题是progv
将值与变量绑定为变量的symbol-value
而不是symbol-function
。但是,这很明显,因为我们没有明确建议哪些值是函数。
因此,为了解决这个问题,我想到了根据值的类型手动动态地将变量绑定到它们的值。如果值为fboundp
,那么它们应绑定到变量的symbol-function
。限制是match-if
不能是macro
。它必须是function
,因为它由funcall
调用。
微距:functioner
:
(defmacro functioner (var val)
`(if (and (symbolp ',val)
(fboundp ',val))
(setf (symbol-function ',var) #',val)
(setf ,var ,val)))
功能:match-if
:
(defun match-if (pattern input bindings)
(eval `(and (let ,(mapcar #'(lambda (x) (list (car x))) bindings)
(declare (special ,@ (mapcar #'car bindings)))
(loop for i in ',bindings
do (eval `(functioner ,(first i) ,(rest i))))
(eval (second (first ,pattern))))
(pat-match (rest ,pattern) ,input ,bindings))))
这里,let
部分以词法(假设)声明所有变量。然后declare
声明他们special
。然后functioner
恰当地绑定变量及其值。然后评估模式中的代码。如果代码部分为true,则仅调用模式匹配器函数pat-match
。
问题是在函数中,它的所有参数都被评估。因此,bindings
和let
部分中的declare
将被替换为类似:
((v1 . val1)(v2 . val2)(v3 . val3))
不
'((v1 . val1)(v2 . val2)(v3 . val3))
因此,它被视为代码,而不是列表
所以,我被困在这里。并且宏不会帮助我解决这个问题
任何帮助表示赞赏。
答案 0 :(得分:2)
不是您要找的答案,但PROGV
是一个特殊的操作员;它被授予在运行时修改变量的动态绑定的能力; AFAIK,你不能简单地破解它来操作"动态功能绑定"。
progv
的要点是使用已计算的符号和值列表,这意味着您可以在运行时生成符号并将它们动态绑定到相应的值。
您可能能够找到eval
的解决方案,但请注意,如果您将宏扩展到(eval ...)
,那么您将松开周围的词汇上下文,这通常不是您想要的(" eval"在空词法环境中运行。我推测你也可以有一个自定义代码漫游器,它可以在顶层表单上运行,但是当它找到你的特殊运算符时重新组织它们,将上下文带回来,产生类似(eval '(let (...) ...))
的东西。