函数和宏都行不通
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
。
问题
问题是在函数中,它的所有参数都被求值。因此 let
和 declare
部分中的 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 (...) ...))
.
的内容
考虑 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
。
问题
问题是在函数中,它的所有参数都被求值。因此 let
和 declare
部分中的 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 (...) ...))
.