我在prolog列表上执行some exercises并且我已经阅读了this个问题,并看到了subtract/3实现。但我仍然有点困惑。
现在我想从给定列表中删除元素的所有出现次数,经过几次尝试后我得到了这个:
% --- del all X occurrences from a list
del_all_X(_, [], _).
% unbinded T2
del_all_X(X, [X|T], T2):-
del_all_X(X, T, T2).
%!. ERROR: see below
del_all_X(Y, [X|T], [X|T2]):-
dif(Y, X), % USE this instead of !
del_all_X(Y, T, T2).
这给了我这种输出:
25 ?- del_all_X(x, [x,a,b,x,d,e,x,x], X).
X = [a, b, d, e|_G4115].
回答:del_all_X(_,[],[])。
由于
编辑:在问题和代码中添加了更正和答案。
答案 0 :(得分:1)
根据我的理解,使用 cut 是不合适的,因为这可能会以意想不到的方式中断堆栈树的增长,因为它避免了使用不同值的第二个规则的统一已经统一的第一条规则。 learn prolog now - cut
使用 dif 是必不可少的,因为当搜索的元素(Y)不同于给定列表(X)的第一个时,它避免了第二个规则的统一,在此使用不同变量调用此元素的情况是不够的。 @false给出的例子澄清了。 见Using \== or dif?
% With ! and Without dif
[debug] ?- del_all_X(x, [x], [x]).
T Call: (7) del_all_X(x, [x], [x])
T Call: (8) del_all_X(x, [], [x])
T Fail: (8) del_all_X(x, [], [x])
T Redo: (7) del_all_X(x, [x], [x])
T Call: (8) del_all_X(x, [], [])
T Exit: (8) del_all_X(x, [], [])
T Exit: (7) del_all_X(x, [x], [x])
true .
更新版本:
del_all_X(_, [], []).
del_all_X(X, [X|T], T2):-
del_all_X(X, T, T2).
del_all_X(Y, [X|T], [X|T2]):-
% X \== Y
dif(Y, X),
del_all_X(Y, T, T2).
[debug] 7 ?- del_all_X(x, [x], [x]).
T Call: (7) del_all_X(x, [x], [x])
T Call: (8) del_all_X(x, [], [x])
T Fail: (8) del_all_X(x, [], [x])
T Redo: (7) del_all_X(x, [x], [x])
T Fail: (7) del_all_X(x, [x], [x])
false.