好吧,您的 takeout 谓词可能如下所示:
takeout( X, [X|R], R ).
takeout( X, [F|R], [F|S] ) :-
takeout( X, R, S ).
SWI-Prolog 有一个有用的谓词trace。
第一种情况:
X = [1, 2, 3] ;
Redo: (10) takeout(3, _G477, _G485) ? creep
Call: (11) takeout(3, _G480, _G483) ? creep
Exit: (11) takeout(3, [3|_G483], _G483) ? creep
Exit: (10) takeout(3, [_G479, 3|_G483], [_G479|_G483]) ? creep
Call: (10) perm([], [_G479|_G483]) ? creep
Fail: (10) perm([], [_G479|_G483]) ? creep
Redo: (11) takeout(3, _G480, _G483) ? creep
Call: (12) takeout(3, _G486, _G489) ? creep
Exit: (12) takeout(3, [3|_G489], _G489) ? creep
Exit: (11) takeout(3, [_G485, 3|_G489], [_G485|_G489]) ? creep
Exit: (10) takeout(3, [_G479, _G485, 3|_G489], [_G479, _G485|_G489]) ? creep
Call: (10) perm([], [_G479, _G485|_G489]) ? creep
Fail: (10) perm([], [_G479, _G485|_G489]) ? creep
Redo: (12) takeout(3, _G486, _G489) ? creep
Call: (13) takeout(3, _G492, _G495) ? creep
Exit: (13) takeout(3, [3|_G495], _G495) ? creep
Exit: (12) takeout(3, [_G491, 3|_G495], [_G491|_G495]) ? creep
Exit: (11) takeout(3, [_G485, _G491, 3|_G495], [_G485, _G491|_G495]) ? creep
Exit: (10) takeout(3, [_G479, _G485, _G491, 3|_G495], [_G479, _G485, _G491|_G495]) ? creep
Call: (10) perm([], [_G479, _G485, _G491|_G495]) ? creep
Fail: (10) perm([], [_G479, _G485, _G491|_G495]) ? creep
Redo: (13) takeout(3, _G492, _G495) ? creep
Call: (14) takeout(3, _G498, _G501) ? creep
Exit: (14) takeout(3, [3|_G501], _G501) ? creep
Exit: (13) takeout(3, [_G497, 3|_G501], [_G497|_G501]) ? creep
Exit: (12) takeout(3, [_G491, _G497, 3|_G501], [_G491, _G497|_G501]) ? creep
Exit: (11) takeout(3, [_G485, _G491, _G497, 3|_G501], [_G485, _G491, _G497|_G501]) ? creep
第二种情况:
X = [1, 2, 3] ;
Redo: (8) takeout(1, _G451, [2, 3]) ? creep
Call: (9) takeout(1, _G532, [3]) ? creep
Exit: (9) takeout(1, [1, 3], [3]) ? creep
Exit: (8) takeout(1, [2, 1, 3], [2, 3]) ? creep
Exit: (7) perm([1, 2, 3], [2, 1, 3]) ? creep
所以,谓词枚举的顺序其实很重要。在第一种情况下,您产生了许多具有未知值的状态。最好(尽可能)列出一份纸质清单,运行trace 并画出实际情况。
但简而言之,在第一种情况下,您会产生大量带有takeout 事实的未知变量,这些变量无法与perm 匹配。