Common lisp 公共lisp:匹配列表中的Acon?
我正在使用Steven Tanimoto的Common Lisp研究人工智能的各个要素,但我无法理解他的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
匹配程序。到目前为止,我们的想法是逐步改进自滚动列表匹配
,从“不太好”开始
(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