长期以来一直在为家庭作业做一个宏,但我们完全卡住了,我的老师时间有限,而且截止日期远远超过了限制。这是我们最后一次尝试解决这个问题。
说明如下:
我们将编写一个宏匹配模式,将参数 expr 与多个参数 pattern_i 进行匹配。如果成功,body_i 将在评估期间使用 pattern_i 中的自由变量进行评估。
模式是一个 s 表达式
它必须完全匹配
不能使用符号引号
Expr 应该只被评估一次
例子:
* (match-pattern '((foo bar) foo baz) ((car . car) `(:cons ,car ,car)) ((one two three) `(:three ,one ,two ,three))) (:THREE (FOO BAR) FOO BAZ)
到目前为止,我们的策略是这样的:
1
我们计划在宏中使用一个匹配函数来比较模式。(也许不完全正确,但你明白了)
(defun match (sexpr1 sexpr2)
(cond ((and (consp sexpr1) (consp sexpr2))
(and (match (first sexpr1) (first sexpr2))
(match (rest sexpr1) (rest sexpr2))))
((and (atom sexpr1) (atom sexpr2))
t)
(t nil)))
2
我们想针对 expr 循环所有模式,并通过将它们传递给我们的 match 函数,我们将返回 true 或 nil。如果它是真的,我们将 expr 分配给模式的主体。
(defmacro match-pattern (sexpr &body body)
(cond
((match sexpr (car (car body))) (print "sexpr shall match with body here"))
((null (cdr body)) nil)
(t `(match-pattern sexpr ,@(cdr body)))))
3
不知道匹配是如何工作的,我们尝试将#'mapcar 与匿名 lambda 函数结合使用,但没有比这更进一步。
这看起来是一种合理的方法吗?报价有很多问题。在描述的示例中,expr 上有一个引用,但正文中的模式中没有引用,这是为什么呢?为什么身体里有:三个和:缺点?