功能和宏都不会

时间:2017-06-23 11:54:23

标签: common-lisp eval backquote

考虑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

问题

问题是在函数中,它的所有参数都被评估。因此,bindingslet部分中的declare将被替换为类似: ((v1 . val1)(v2 . val2)(v3 . val3))

'((v1 . val1)(v2 . val2)(v3 . val3))
因此,它被视为代码,而不是列表 所以,我被困在这里。并且宏不会帮助我解决这个问题 任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:2)

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

您可能能够找到eval的解决方案,但请注意,如果您将宏扩展到(eval ...),那么您将松开周围的词汇上下文,这通常不是您想要的(" eval"在空词法环境中运行。我推测你也可以有一个自定义代码漫游器,它可以在顶层表单上运行,但是当它找到你的特殊运算符时重新组织它们,将上下文带回来,产生类似(eval '(let (...) ...))的东西。