函数和宏都行不通

Neither a function nor a macro would do

考虑 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 适当地绑定变量及其值。然后评估模式中的代码。如果代码部分为真,则仅调用模式匹配器函数 pat-match


问题

问题是在函数中,它的所有参数都被求值。因此 letdeclare 部分中的 bindings 将被替换为类似 :
((v1 . val1)(v2 . val2)(v3 . val3))
不是
'((v1 . val1)(v2 . val2)(v3 . val3))
因此,它被视为代码,而不是列表。
所以,我被困在这里了。宏在这方面帮不了我。
任何帮助表示赞赏。

不是你要找的答案,但PROGV是一个特殊的运算符;它被授予在运行时修改变量动态绑定的能力; AFAIK,您不能简单地破解它以在 "dynamic function bindings" 上运行。 progv 的要点是使用评估的符号和值列表,这意味着您可以在运行时生成符号并将它们动态绑定到相应的值。

您也许可以找到 eval 的解决方案,但请注意,如果您将宏展开为 (eval ...),那么您将失去周围的词法上下文,这通常不是您想要的 ("eval" 在 null 词法环境中运行)。我推测您还可以有一个自定义代码遍历器,它在顶级表单上工作,但会在找到您的特殊运算符时重新组织它们,以将上下文带回,生成类似 (eval '(let (...) ...)).

的内容