我正在研究一个有问题的程序。在这个简短的例子中,错误是相同的:
编辑 代码错误
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
该跟踪部分的第一行和最后一行是相等的。
答案 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
相同。