所以我正在做一些prolog,并且遇到了一个我不明白为什么会出现的问题。这个问题实际上发生在我的一些方法中,但希望我能用这个方法中的一些指导来解决它。
RewriteBase /
这是我的代码
fill(3,a,L) -> L = [a,a,a]
答案 0 :(得分:2)
第一个条款应该是:
fill(0, _, []).
您的代码留下一个选择点(对于您的示例查询):当计数器达到零时,两个子句头与当前目标统一。只有尝试使用第二个子句,才能达到N1 >= 0
目标。此目标将失败(此时N1
为-1
)。因此,第二个条款将无法提供替代解决方案。但Prolog解释器在找到第一个解决方案时并不知道。因此,提出了第一个解决方案,然后Prolog顶级解释器等待您的输入。键入返回通常意味着您不希望Prolog推理引擎回溯并寻找替代解决方案。如果您输入一个分号,“;”,您将要求其他解决方案。
您可以将fill/3
谓词更改为不离开选择点。一个快速的解决方案是在第一个子句中添加一个剪切“!/ 0”:
fill(0, _, []) :-
!.
fill(N, A, [A| As]) :-
N > 0,
N1 is N - 1,
fill(N1, A, As).
切割是一个令人讨厌的小虫子,它始终是真的,但它用于它的副作用:扔掉选择点。
上面快速解决方案的一个问题是,削减通常会使代码减少声明并引入微妙(而不是那么微妙的错误)。在这种情况下,有一个明显更好的解决方案:只需交换两个子句的顺序:
fill(N, A, [A| As]) :-
N > 0,
N1 is N - 1,
fill(N1, A, As).
fill(0, _, []).
只有在第一个子句中的N > 0
测试失败时才会尝试第二个子句。但请注意,并非所有Prolog 顶级解释器都检测到查询没有(更多)解决方案。
但是这个解决方案也有自己的问题,这取决于Prolog系统以及它如何索引或不索引索引。你能发现它吗?我会给你一个提示:空间复杂性。