0

我的讲师给了我们这个示例程序来查看代码,而我总体上理解了递归函数,是这一行我不太明白它的含义

all_different([H | T]) :- member(H, T), !, fail.

从递归函数中提取:

all_different([H | T]) :- member(H, T), !, fail.
all_different([_ | T]) :- all_different(T).
all_different([_]).

我所理解的只是它将一个列表分成一个 Head H 和一个 Tail T 并检查 H 是否包含在 T 中......我的问题是,它是什么“!” 而“失败”呢?

4

1 回答 1

3

这些东西对于 Prolog 来说是非常基础的。

fail是必不可少的。它强制 Prolog 将当前分支视为失败并启动回溯。

!被称为“切割”。它将 Prolog 提交到当前分支。或者,它会根据当前规则修剪选择点的踪迹。

结合起来,在 Prolog-ese 中,这表示“如果列表的头部出现在列表的尾部,则无需寻找任何其他答案,并且失败。” 因此,如果列表的任何元素出现在列表的其余部分中,您将立即失败,没有回溯的机会。这实际上并不是那么可怕,它只是意味着 Prolog 不会再浪费时间试图确定列表是否是“all_different”。回溯将在呼叫站点正常恢复。

重要的是这些按此顺序排列。如果你在失败后试图削减,你永远不会成功,因为回溯已经开始了。如果省略切割,则如果列表中有任何满足该属性的子列表,谓词将返回 true。最后一个子句保证任何非空列表都是这种情况,它断言具有一个元素的列表满足该属性。如果你忽略了失败,你只会为子列表中的每个列表元素获得一个成功,再加上一个尾部。我鼓励您尝试使用谓词,进行这些更改并查看效果,因为它将大大有助于说明剪切和失败的目的。

于 2013-05-01T19:15:03.630 回答