为什么此查询不会终止?

时间:2018-07-18 04:34:47

标签: prolog

我编写了一个生成器,该生成器生成一串数字,并给出了它们的描述:

:- use_module(library(clpfd)).
some(_Int, 0) --> [].
some(Int, Count) --> {Count #> 0, Count1 #= Count - 1}, [Int], some(Int, Count1).

many([]) --> [].
many([some(X, N)|Rest]) --> some(X, N), many(Rest).

这在向前运行时有效:

?- phrase(many([some(0, 3), some(1, 2)]), Some).
Some = [0, 0, 0, 1, 1] ;
false.

好吧,它留下了一个选择点,但至少它首先给出了正确的结果。当要求为给定的数字字符串生成描述时,它将永远循环:

?- phrase(many([Some|Rest]), [0, 0, 0, 1, 1]).
OOPS

我在做什么错了?

1 个答案:

答案 0 :(得分:3)

对于您的问题,我将为您提供一些“可操作的”观点。迪克斯特拉原谅我。

问题的症结在于,有一种方法让您在many//2中什么也不做,然后再在some//2中什么也不做。 many//2的第一个子句很高兴不吃任何输入。但是,在第二个子句中,您假设some//2会消耗掉您的部分输入内容-但这不是必须的,然后您又回到了{{1} },它仍然不需要吃任何输入。因此,您再次回到many//2的第二个子句中,对many//2进行递归调用,输入的内容与开始时完全相同。这是你的循环!

解决方案是确保many//2确实可以正常工作:第一个子句必须存在:

some//2

这并不像将some(Int, 1) --> [Int]. some(Int, Count) --> {Count #> 0, Count1 #= Count - 1}, [Int], some(Int, Count1). 折叠在一起时所希望的那样积极,但是它确实有效并且终止:

some/2