Common lisp 公共lisp:匹配列表中的Acon?

Common lisp 公共lisp:匹配列表中的Acon?,common-lisp,Common Lisp,我正在使用Steven Tanimoto的Common Lisp研究人工智能的各个要素,但我无法理解他的匹配程序。到目前为止,我们的想法是逐步改进自滚动列表匹配,从“不太好”开始 (defun match1 (p s) (equalp p s)) 下面是match3: (defun match3 (p s) (cond ((null p) (null s)) ;null clause ((or (atom p) (atom s

我正在使用Steven Tanimoto的Common Lisp研究人工智能的各个要素,但我无法理解他的
匹配程序。到目前为止,我们的想法是逐步改进自滚动列表
匹配
,从“不太好”开始

(defun match1 (p s) (equalp p s))
下面是
match3

 (defun match3 (p s)
      (cond
        ((null p) (null s))            ;null clause
        ((or (atom p) (atom s)) nil)   ;atom clause
        ((equalp (first p) (first s))  ;equal CAR clause
         (match3 (rest p) (rest s)))   
        ((eql (first p) '?)            ; joker clause  
         (match3 (rest p) (rest s)))
        (t nil)))                      ;extremal clause
所谓的小丑条款应该匹配,即

(match3 '(a b ? d) '(a b c d))  ; yields t
但是下一个版本应该“匹配”这个

我引述

例如,这将允许(上述)表单不仅返回 true,但也返回
a
x
的关联以及
d
y
的关联。这样,如果将匹配项用作 条件在产生式规则中,规则的操作部分可以 操纵与模式中的变量元素匹配的值

…然后它继续谈论一些事情。然后重写
匹配

(defun4 match4 (p s)
      (cond
        ((and (null p) (null s))
         '((:yes . :yes)))
        ((or (atom p) (atom s)) nil)
        ((equalp (first p) (first s))
         (match4 (rest p) (rest s)))

        ((and
          (equalp (length (first p)) 2)
          (eql (first (first p)) '?)
          (let ((rest-match
                 (match4 (rest p) (rest s))))
            (if rest-match
                (acons (first (rest (first p)))
                       (first s)
                       rest-match)))))
        (t nil)))

…因此,如果有人能先告诉我为什么要将上述示例中的
(?x)
a
进行比较,这会有所帮助。基本上,我不清楚这里的目标是什么。如果有人能解释这背后的动机,我想我可以把代码拆开。否则,我就完全迷路了。

我有tanimoto的书,但最早要到明天才能拿到,但引用中提到的例子实际上是一个很好的例子:

这样,如果匹配被用作产生式规则中的条件,则规则的操作部分可以操作与模式中的变量元素匹配的值

这是一个很好的例子,说明这种匹配在哪里是有用的。它使规则编写者能够专注于领域知识,并将处理规则的算法分开


函数式编程的一些方法也大量使用模式匹配。不过,编程语言支持各不相同。普通的Lisp使您可以轻松地编写自己的代码

match3
引入了两个列表之间的简单模式匹配,其中第一个列表中的符号
可以匹配第二个列表中的任何单个符号。因此,函数返回
T
NIL
,以表示匹配过程的成功或失败

然后,在
match4
中引入了一种新的匹配,通过使用看似匹配的变量
(?x)
只是引入匹配变量的一种方式,在其他语言中,该变量可以写成
?x
或类似的形式。其思想是,此变量“捕获”第二个列表中匹配的符号,因此,例如,您可以稍后以类似以下方式使用它:

(match '(a (? x) (? y) (? x) b) '(a c d c b)) ; yes, since ‘c’ matches ‘?x’
(match '(a (? x) (? y) (? x) b) '(a c d e b)) ; no, since ‘c’ and ‘e’ are different
为了有效地使用此功能,当找到匹配项时,
match
函数必须给出的不仅仅是值
T
,而是成对的
(匹配变量,符号匹配)
,并用它建立找到的匹配项的关联列表。因此,
match4
在cond的最后一个分支中通过使用
acons
返回这样的列表(首先它得到
rest match
,而不是“aconses”它上面的匹配变量和找到的符号给出的对)。特殊配对
(:yes.:yes)
只是终止此匹配列表的一种方式


我想本书后面将介绍另一个版本的match函数,在该函数中找到的匹配项将用于流程的后续部分。

为什么我们要将(?x)与上面示例中的a进行比较,这会有所帮助。你是说这种模式匹配的动机是什么?这并不是你在比较它们,而是你会返回模式变量和它们的值之间的映射,这些以后会很有用。我插入你的
(匹配“(a(?)x)(?y)(?x)b);(a c d c b))
,然后得到
((x.c)(y.d)(x.c)(:是的))
,这是什么?重点是什么?这和比较两个列表的“相似性”有什么关系?对不起,我在这里说得太多了。@147pm你一直在用这个,不管你意识到与否。Lisp中的每个函数都接受一个参数列表。Common Lisp让您编写
(defun foo参数列表)(let((x(第一个参数列表))(y(第二个参数列表))…)
并自行解构参数列表,而不是编写
(defun foo(x y)…)
并检查函数调用的参数数量是否正确,并将参数列表的第一个元素绑定到x,第二个元素绑定到y。这实际上只是模式匹配。这是一个有用的工具。继续阅读;我希望这本书也会使用它。在函数
匹配4
中,您会得到这个结果,但稍后会得到(通过一些高级匹配)您将获得类似
((X.C)(Y.D)(:YES.:YES))的内容
,这是对变量的赋值,使匹配成为可能。换句话说,
X
Y
是变量:只有当它们在匹配过程中具有相同的值时,匹配才会得到满足。在我的第二个示例中,现在
match4
返回
((X.C)(Y.D)(X.E)(:YES.:YES))
,但在更高级的版本上,
match\n
将给出
NIL
,这是一个匹配错误,因为
X
有两个不同的值,
C
E
,这是不可能的。@Joshua Taylor,et al:谢谢你们两位的“Lisp知识/智慧”我看到alist在Lisp中使用了很多,需要摸索一下它的知识。我感觉在Tanimoto的书中有很多东西需要初学者学习,但是要想把它弄明白是很困难的。如果你有其他关于“深Lisp知识/智慧”的书(等)的建议,请告诉我。你能举个例子吗“…可以操作与模式中变量元素匹配的值?”@147pm我认为它并没有什么特别的含义。目前,只需将它作为
(let*((value'(ab c d))(x(第一个值))(y(第三个值))的缩写
(match '(a (? x) (? y) (? x) b) '(a c d c b)) ; yes, since ‘c’ matches ‘?x’
(match '(a (? x) (? y) (? x) b) '(a c d e b)) ; no, since ‘c’ and ‘e’ are different