我编写了一个生成器,该生成器生成一串数字,并给出了它们的描述:
:- 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
我在做什么错了?
答案 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