Prolog/规则
本节讨论规则,这是一种用于表示谓词何时为真的通用方法。
到目前为止,我们还没有真正进行任何编程,只是定义了对象及其属性。Prolog 编程的第一步是使用**规则**。通过规则,我们说明一个谓词为真,前提是其他谓词为真。规则看起来像这样
a :- b, c, d.
这意味着如果 b、c 和 d 为真,则 a 为真。如果我们有以下数据库,
a :- b, c, d. b. c. d :- e. e.
,如果我们询问 Prolog 是否 a 为真,
?- a.
Prolog 会将查询(或目标)a 生成**子目标** b、c 和 d。它可以直接看到 b 和 c 为真,因为它们被声明为事实,但 d 只有在 e 为真时才为真,这会导致另一个子目标 e。由于 e 也是一个事实,所以 Prolog 会回答 yes。
我们也可以使用包含项的谓词。
car(corvette) :- haswheels(corvette), haswindows(corvette).
说明一辆有轮子和窗户的 Corvette 是一辆汽车。这不是一个很有用的陈述,因为我们也可以简单地声明一辆 Corvette 是一辆汽车,用
car(corvette).
然而,我们可以在规则中使用变量。这样,我们可以例如声明,只要有轮子和窗户的东西都是一辆汽车
car(A) :- haswheels(A), haswindows(A). haswheels(corvette). haswindows(corvette).
第一行说明,为了使 car(A) 为真,haswheels(A) 和 haswindows(A) 必须为真。如果 Prolog 被问到一辆 Corvette 是否是一辆汽车
?- car(corvette).
它会将 A 绑定到 corvette,并得到子目标**haswheels(corvette)**和**haswindows(corvette)**。如果它能证明这两个目标都为真(它能),那么 car(corvette) 必须为真。在程序中使用变量时,重要的是要注意,变量在它所在的句子之外没有任何意义。如果两个句子使用变量 A,它不是同一个变量。例如
bird(A) :- hasfeathers(A). dog(A) :- barks(A).
第一行中的 A 只是表明谓词 bird 的项需要与谓词 hasfeathers 的项相同,它与第二行中的 A 无关。
现在我们可以回到我们的原始程序并添加一些规则。
human(david). human(john). human(suzie). human(eliza). man(david). man(john). woman(suzie). woman(eliza). parent(david, john). parent(john, eliza). parent(suzie, eliza). father(X,Y) :- parent(X,Y), man(X). mother(X,Y) :- parent(X,Y), woman(X).
我们可以询问 Prolog Eliza 的父亲是谁
?- father(X, eliza). X = john ; No
或者列出数据库中的所有父亲及其各自的孩子
?- father(Father, Child). Father = david Child = john ; Father = john Child = eliza ; No
?- mother(Mother,Child). Mother = suzie Child = eliza ; No
如果你使用过任何其他编程语言,你可能熟悉递归,它指的是函数调用自身。Prolog 特别适合递归,尽管在我们的例子中,它将是一个谓词引用自身,而不是一个函数。转到下一节,看看它是如何以及为什么完成的。