【问题标题】:Neither a function nor a macro would do函数和宏都不行
【发布时间】:2017-06-23 11:54:23
【问题描述】:

考虑this 问题。这里的基本问题是代码:

(progv '(op arg) '(1+ 1)
 (eval '(op arg)))

这里的问题是progvvalue 绑定到 variable 作为变量的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))
因此,它被视为代码,而不是列表。
所以,我被困在这里。宏在这方面对我没有帮助。
任何帮助表示赞赏。

【问题讨论】:

    标签: common-lisp eval backquote


    【解决方案1】:

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

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-19
    • 2015-10-01
    • 2011-08-09
    • 2020-06-08
    • 1970-01-01
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    相关资源
    最近更新 更多