当 ?x = a
且 ?y = b
时匹配,而下面两个列表:
(p ?x b ?y a)
(p ?y b c a)
当 ?x = ?y = c
时匹配。
图 15.1: 匹配函数。
> (match '(p a b c a) '(p ?x ?y c ?x))
((?Y . B) (?X . A))
T
> (match '(p ?x b ?y a) '(p ?y b c a))
T
> (match '(a b c) '(a a a))
当 match
函数逐个元素地比较它的参数时候,它把 binds
参数中的值分配给变量,这被称为绑定 (bindings)。如果成功匹配, match
函数返回生成的绑定;否则,返回 nil
。当然并不是所有成功的匹配都会产生绑定,我们的 match
函数就像 gethash
函数那样返回第二个值来表明匹配成功:
- 如果 x 和 y 在
eql
上相等那么它们匹配;否则, - 如果 x 是一个已绑定的变量,并且绑定匹配 y ,那么它们匹配;否则,
- 如果 y 是一个已绑定的变量,并且绑定匹配 x ,那么它们匹配;否则,
- 如果 y 是一个未绑定的变量,那么它们匹配,并且为 y 建立一个绑定;否则,
- 如果 x 和 y 都是
cons
,并且它们的car
匹配,由此产生的绑定又让cdr
匹配,那么它们匹配。
下面是一个例子,按顺序来说明以上六种情况:
'(p a ?w c ?y ( e e))
'((?v . a) (?w . b)))
((?Z . E) (?Y . D) (?X . C) (?V . A) (?W . B))
match
函数通过调用 binding
函数在一个绑定列表中寻找变量(如果有的话)所关联的值。这个函数必须是递归的,因为有这样的情况 “匹配建立一个绑定列表,而列表中变量只是间接关联到它的值: ?x
可能被绑定到一个包含 (?x . ?y)
和 (?y . a)
的列表”: