gpt4 book ai didi

macros - 我如何构造这个 lisp 宏?

转载 作者:太空宇宙 更新时间:2023-11-03 18:56:37 26 4
gpt4 key购买 nike

我正在通过 l99 for lisp 学习 lisp。

这是来自 here ,我希望应用宏只是为了练习,用宏编写所有 ((x) (x (evaluate-boolean left bindings) (evaluate-boolean right bindings)))

(defun evaluate-boolean (expression bindings)
"Evaluates the boolean expression. Returns t or nil

expression := variable
| constant
| '(' operator expression expression ')'
| '(' not expression ')'
.
constant := 'true' | 'fail' .
variable := symbol .
operator := 'and' | 'or' | 'nand' | 'nor' | 'xor' | 'impl' | 'equ' .

bindings is a list of pairs (variable . constant)
"
(cond ((eq expression 'true) t)
((eq expression 'fail) nil)
((symbolp expression)
(let ((pair (assoc expression bindings)))
(if pair
(progn
(assert (member (cdr pair) '(true fail)))
(eql 'true (cdr pair)))
(error "No variable named ~A in the bindings." expression))))
((atom expression) (error "Invalid atom ~A in the expression." expression))
(t (case (length expression)
((2) (destructuring-bind (op subexpression) expression
(case op
((not) (not (evaluate-boolean subexpression bindings)))
(otherwise (error "Invalid operator ~A in ~A" op expression)))))
((3) (destructuring-bind (op left right) expression
(case op
((and) (and (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((or) (or (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((nand) (nand (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((nor) (nor (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((xor) (xor (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((impl) (impl (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((equ) (equ (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
(otherwise (error "Invalid operator ~A" op)))))
(otherwise (error "Invalid expression ~A" expression))))))

我已经尝试了一些方法,但它们似乎都给出了报告缺少变量的错误。

我将如何实现宏

  • 作为defmacro,或者
  • evaluate-boolean 函数中使用 macrolet

我通常先用 defundefmacro 测试东西,然后用 flet 替换它。对此有何建议?

最佳答案

因为你没有说你尝试了什么,我不知道你做错了什么,但我猜你可能试图用宏调用替换 CASE 中的个别案例?这不起作用,因为外部宏 (CASE) 在内部宏之前展开,因此内部宏不能用于为外部宏生成语法(除非专门编写外部宏允许这样做,但这里不是这种情况)。

所以解决方案是编写一个宏,为您生成整个 CASE。像这样的东西:

(macrolet ((ops-case (op-sym (&rest ops))
`(case ,op-sym
,@(loop for op in ops
collect `((,op) (,op (evaluate-boolean left bindings)
(evaluate-boolean right bindings))))
(otherwise (error "Invalid operator ~A" ,op-sym)))))
(ops-case op (and or nand nor xor impl equ)))

虽然我不相信这真的是个好主意。像这样的一次性宏往往会使您的代码更难理解,而且这也不会显着缩短代码。通常您会希望使用宏来抽象化代码中多次出现的模式。

更通用的方法可能是这样的:

(defmacro ecase-template (keyform template &body cases)
`(ecase ,keyform
,@(loop for case in cases
collect (sublis `((_ . ,case)) template))))

这通过用 case 中的值替换模板中的下划线来生成 case 表达式。例如:

CL-USER> (macroexpand-1 '(ecase-template op
((_) (_ (evaluate-boolean left bindings)
(evaluate-boolean right bindings)))
and or nand nor xor impl equ))
(ECASE OP
((AND)
(AND (EVALUATE-BOOLEAN LEFT BINDINGS) (EVALUATE-BOOLEAN RIGHT BINDINGS)))
((OR)
(OR (EVALUATE-BOOLEAN LEFT BINDINGS) (EVALUATE-BOOLEAN RIGHT BINDINGS)))
((NAND)
(NAND (EVALUATE-BOOLEAN LEFT BINDINGS) (EVALUATE-BOOLEAN RIGHT BINDINGS)))
((NOR)
(NOR (EVALUATE-BOOLEAN LEFT BINDINGS) (EVALUATE-BOOLEAN RIGHT BINDINGS)))
((XOR)
(XOR (EVALUATE-BOOLEAN LEFT BINDINGS) (EVALUATE-BOOLEAN RIGHT BINDINGS)))
((IMPL)
(IMPL (EVALUATE-BOOLEAN LEFT BINDINGS) (EVALUATE-BOOLEAN RIGHT BINDINGS)))
((EQU)
(EQU (EVALUATE-BOOLEAN LEFT BINDINGS) (EVALUATE-BOOLEAN RIGHT BINDINGS))))

关于macros - 我如何构造这个 lisp 宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37534842/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com