迷失在无限循环中

时间:2017-05-12 19:36:17

标签: prolog

我正在研究一个有问题的程序。在这个简短的例子中,错误是相同的:

编辑 代码错误

does_something(A, [Num], Sol) :-
    sort([Num|A], Sol).

correct(Solution) :-
    Solution = [1,2,3,4,5].

pred1(_, Solution, Solution) :- correct(Solution), !.
pred1(A, B, Solution) :-
    member(Num, A),
    does_something(B, [Num], B_aux),
    pred1(A, B_aux, Solution).

最后编辑:我想要的与谓词do_something无关,并且正确无误。这些仅仅是为了示例,但它与问题无关。我想知道的是,如果用Num调用谓词do_something是否给出了正确的解决方案。如果没有,那么它会尝试A的另一个成员,直到找到解决方案。如果它永远不会失败,没问题。我的问题是我不能用另一个Num调用did_something而不是A中的第一个。

?- pred1([1,2,3], [], S).

Call: (9) [user] does_something([1], [1], _G6045) ? creep
Call: (10) [system] sort([1, 1], _G6047) ? creep
Exit: (10) [system] sort([1, 1], [1]) ? creep
Exit: (9) [user] does_something([1], [1], [1]) ? creep
Call: (9) [user] pred1([1, 2, 3], [1], _G5943) ? creep
Call: (10) [user] correct([1]) ? creep
Call: (11) [system] [1]=[1, 2, 3, 4, 5] ? creep
Fail: (11) [system] [1]=[1, 2, 3, 4, 5] ? creep
Fail: (10) [user] correct([1]) ? creep
Redo: (9) [user] pred1([1, 2, 3], [1], _G5943) ? creep
Call: (10) [lists] lists:member(_G6052, [1, 2, 3]) ? creep
Exit: (10) [lists] lists:member(1, [1, 2, 3]) ? creep
Call: (10) [user] does_something([1], [1], _G6057) ? creep

该跟踪部分的第一行和最后一行是相等的。

1 个答案:

答案 0 :(得分:3)

明显的问题是你的A没有改变,这意味着在递归的每一步,你继续调用member(_GXXX, [1, 2, 3]),这将总是选择第一个元素,1。另一方面,您继续添加到列表和排序,但只添加1并排序,因此B保持在[1]

这就是您的代码所做的事情。你打算实现的是另一个问题,我无法通过查看这段代码来猜测你的意图: - (

顺便说一下,这个:

append(A, [X], A1), sort(A1, B)

应与

具有相同的效果
sort([X|A], B)

使用append/3时,您不必遍历列表。 (append/3应该被称为其他东西,因为使用它来附加列表通常是不必要的。虽然它可用于拆分......)

PS:如果你想继续从列表中获取一个元素,最简单的方法是选择第一个元素。这样做的谓词看起来像这样:

foo([], Result, ...).
foo([X|Xs], R, ...) :-
    foo(Xs, [X|R], ...).

所以你只需选择一个元素并将其放入另一个列表中。您不需要member/2。或者,您可以使用select/3,它不仅会获取元素,还会为您提供剩余项目的列表。但是,这个:

bar([], R, ...).
bar(Xs, R, ...) :-
    select(X, Xs, Xs0),
    bar(Xs0, [X|R], ...).

这与上面的foo相同。