List 为什么使用[H | T]作为参数而不是普通变量会导致谓词失败?

List 为什么使用[H | T]作为参数而不是普通变量会导致谓词失败?,list,prolog,List,Prolog,我正在创建一个谓词,以从列表中删除指定的元素,因此如果Ys是删除所有事件的结果,则remove(Xs,X,Ys)应保持不变 从X到X。我的初始失败谓词如下所示: remove([],_,[]). remove([H1|T1],H1,[H2|T2]) :- % e.g. [2,3] , 2, [3] remove(T1,H1,[H2|T2]). % remove first head -> [3], 2, [3] remove([H1|T1],Y,[H1|T2]) :- %

我正在创建一个谓词,以从列表中删除指定的元素,因此如果Ys是删除所有事件的结果,则remove(Xs,X,Ys)应保持不变 从X到X。我的初始失败谓词如下所示:

remove([],_,[]).
remove([H1|T1],H1,[H2|T2]) :- % e.g. [2,3] , 2, [3]
   remove(T1,H1,[H2|T2]).     % remove first head -> [3], 2, [3]
remove([H1|T1],Y,[H1|T2]) :-  % heads match e.g. [1,2,3], 2, [1,3]
   H1\==Y,
   remove(T1,Y,T2).           % remove heads -> [2,3], 2, [3]
这是失败的,但后来我注意到我有一个冗余的
[H2 | Y2]
,我可以使用一个变量,例如
Ys
。我做了这个改变,认为它仍然会失败,但它开始工作了。工作代码如下所示:

remove([],_,[]).
remove([H1|T1],H1,Ys) :-      % e.g. [2,3] , 2, [3]
   remove(T1,H1,Ys).          % remove first head -> [3], 2, [3]
remove([H1|T1],Y,[H1|T2]) :-  % heads match e.g. [1,2,3], 2, [1,3]
   H1\==Y,
   remove(T1,Y,T2).           % remove heads -> [2,3], 2, [3]

有人能解释一下为什么将
[H2 | T2]
更改为
Ys
会起作用吗?

在查询过程中的某个地方,出现了一种模式,
remove([H | T],H,[])
,它将与第二个版本的第二个子句
remove([H1 | T1],H1,Ys)
的开头相匹配,但与第一个版本的第二个子句的开头不匹配,
remove([H1 | T1],H1[H2 | T2])

如果使用第一个程序版本对查询运行trace,
remove([1,2,3,2],2,1,3])
,您会得到:

   Call: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep
   Call: (7) 1\==2 ? creep
   Exit: (7) 1\==2 ? creep
   Call: (7) remove([2, 3, 2], 2, [3]) ? creep
   Call: (8) remove([3, 2], 2, [3]) ? creep
   Call: (9) 3\==2 ? creep
   Exit: (9) 3\==2 ? creep
   Call: (9) remove([2], 2, []) ? creep
   Fail: (9) remove([2], 2, []) ? creep   <---- NOTE THIS FAILURE! (no clause match)
   Fail: (8) remove([3, 2], 2, [3]) ? creep
   Redo: (7) remove([2, 3, 2], 2, [3]) ? creep
   Fail: (7) remove([2, 3, 2], 2, [3]) ? creep
   Fail: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep
因此
H1=2
T1=[]
,但
[H2 | T2]
[]
不一致

但它将与第二个实现的第二条相匹配:

remove([H1|T1], H1, [H2|T2])...
remove([H1|T1], H1, Ys).
这里有,
H1=2
T1=[]
Ys=[]
。这里是第二个版本的跟踪:

[trace]  ?- remove([1,2,3,2],2,[1,3]).
   Call: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep
   Call: (7) 1\==2 ? creep
   Exit: (7) 1\==2 ? creep
   Call: (7) remove([2, 3, 2], 2, [3]) ? creep
   Call: (8) remove([3, 2], 2, [3]) ? creep
   Call: (9) 3\==2 ? creep
   Exit: (9) 3\==2 ? creep
   Call: (9) remove([2], 2, []) ? creep   <---- SUCCESS! (2nd clause match)
   Call: (10) remove([], 2, []) ? creep   <---- SUCCESS!
   Exit: (10) remove([], 2, []) ? creep
   Exit: (9) remove([2], 2, []) ? creep
   Exit: (8) remove([3, 2], 2, [3]) ? creep
   Exit: (7) remove([2, 3, 2], 2, [3]) ? creep
   Exit: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep
[trace]?-删除([1,2,3,2],2[1,3])。
调用:(6)删除([1,2,3,2],2[1,3])?爬行
呼叫:(7)1\==2?爬行
退出:(7)1\==2?爬行
调用:(7)删除([2,3,2],2,3])?爬行
调用:(8)删除([3,2],2,3])?爬行
呼叫:(9)3\==2?爬行
退出:(9)3\==2?爬行

调用:(9)删除([2],2,[])?screw@capelical您在使用SWI Prolog吗?测试查询remove([1,2,3,2],2[1,3])使用我的第一个代码返回false,使用第二个代码返回true。这很有意义。谢谢