我正在尝试解决this page列表构建部分的练习2:
编写程序以从列表中删除特定项目的所有引用。它应该有三个参数。你想要使用的清单, 要删除的项目以及生成的列表。
这是我提出的脚本:
delete_all([],Y,[]).
delete_all([X|T],Y,[X|Result]):-
X =\= Y, /* is X different than Y */
delete_all(T,Y,Result). /* if so then go find the rest */
delete_all([ThrowAway|Tail],Y,Result):- /* disgard the head */
delete_all(Tail,Y,Result). /* and look in the tail */
以下是应该给出的更正结果:delete_all([a,b,a,c,a,d],b,Result).
% delete_all([a,b,a,c,a,d],a,Result).
% Result = [b,c,d]
% delete_all([a,b,a,c,a,d],b,Result).
% Result = [a,a,c,a,d]
% delete_all([a,b,a,c,a,d],prolog,Result).
% Result = [a,b,a,c,a,d]
相反,我收到了这个错误:
| ?- delete_all([a,b,a,c,a,d],a,Result).
uncaught exception: error(type_error(evaluable,a/0),(=\=)/2)
我在ubuntu 16.04下使用gprolog。
谢谢
答案 0 :(得分:5)
首先,你在第一行收到关于singleton变量的警告,因为Y是一个单例,所以你需要替换为:
delete_all([],_,[]).
现在错误归因于=\=
仅用于算术,您需要使用\=
或甚至更好的iso谓词dif/2
来保持逻辑纯度
现在完整的代码:
delete_all([],_,[]).
delete_all([X|T],Y,[X|Result]):- dif(X,Y), delete_all(T,Y,Result).
delete_all([Y|Tail],Y,Result):- delete_all(Tail,Y,Result).
答案 1 :(得分:4)
使用模块if_/3
中的reif
提供更高效的答案:
delete([],_,[]).
delete([H|T],X,L):- if_(
H = X,
delete(T,X,L),
(L = [H|L1], delete(T,X,L1))
).
答案 2 :(得分:3)
您可以使用功能设计。您需要查看 foldl / 4 和差异列表(了解U-U,[In | U] -U和append_dl)。
delete_one(To_Remove, To_Remove, Cur, Cur).
delete_one(To_Remove, In, Cur, Next) :-
dif(To_Remove, In),
append_dl(Cur, [In|U]-U, Next).
append_dl(A-B, B-C, A-C).
delete_all(In, To_Remove, Out) :-
foldl(delete_one(To_Remove), In, U-U, Out-[]).
示例:
?- delete_all([a,b,a,c,a,d],a,Result).
Result = [b,c,d] ;
false.
?- delete_all([a,b,a,c,a,d],X,[b,c,d]).
X = a ;
false.
?- delete_all([Y,b,Y,c,Y,d],X,[b,c,d]).
Y = X,
dif(X,d),
dif(X,c),
dif(X,b) ;
false.