cut-fail 是一种误导你的反模式。在原文中这样说会更好:
bird(eagle).
bird(penguin).
flightless(penguin).
can_fly(X) :- bird(X), \+ flightless(X).
有关此问题的出色且更详细的讨论,请参阅@boris 的答案。
所以,你有这个数据库。我将把名字放进去,以便我能更好地理解它。
married(bill, hillary).
married(barack, michelle).
lovers(bill, michelle).
现在你想说的是,已婚的人彼此喜欢,除非他们出轨。好吧,最好在 Prolog 中定义这些术语,这样我们就可以用它们进行推理。创建我们需要用来定义我们的域的语言。看起来像这样:
cheating(Cheater, SpitedSpouse, Lover) :-
married(Cheater, SpitedSpouse),
lovers(Cheater, Lover),
SpitedSpouse \= Lover.
现在定义起来容易多了likes/2
!
likes(Husband, Wife) :- married(Husband, Wife), \+ cheating(Husband, Wife, _).
likes(Husband, Lover) :- cheating(Husband, _, Lover).
我们甚至可以正确定义不喜欢:
dislikes(SpitedSpouse, Lover) :- cheating(_, SpitedSpouse, Lover).
dislikes(Cheater, Spouse) :- cheating(Cheater, Spouse, _).
看看我们学到了什么:你真正拥有的是两个人之间的婚姻关系,或者是三个人之间的欺骗关系,而你的其他谓词只是这两个基本关系的投影。这很整洁,是吗?:)cheating/3
基本上是经典的“三角恋”。这表明我们可以让程序变得更有效:处理爱情四边形,当然!等等。
注意到一些有趣的事情了吗?这段代码不能“抓住” ——她不是michelle
和她一样有罪bill
吗?这强调了一个更大的问题:谓词的性别/方向限制。我认为有这样的具体名词有助于看到逻辑关系,但这是一个应该解决的危险捷径。处理逻辑的一种简单方法是创建这样的谓词:
spouse(X, Y) :- married(X, Y)
spouse(X, Y) :- married(Y, X).
当然你必须做更多的检查以确保你没有重复相同的人,但这并不难,然后改变你的变量以减少性别特异性。