如何清除所有事件?

时间:2019-03-06 14:01:50

标签: list prolog

我试图理解为什么代码1可以正常工作,但是代码2输出false:

remove(X,[],[]).
remove(X,[X|Y],Z):-remove(X,Y,Z). % [X|Y] is the input list
remove(X,[F|Y],[F|Z]):-remove(X,Y,Z). % code 1


remove(X,[],[]).
remove(X,[X|Y],Z):-remove(X,Y,Z). % [X|Y] is the input list
remove(X,[F|Y],Z):-remove(X,Y,[F|Z]). % code 2

2 个答案:

答案 0 :(得分:3)

您提供的两个谓词-code 1 code 2-都破了。

您没有注意到的原因是:查询


#1 ) 考虑在this previous "answer"中显示的查询:

?- remove(x, [x,a,b,c,x,d], R).
R = [a,b,c,d]                      % okay

好吗?是的,但是可能会有更多答案。让我们按;

;  R = [a,b,c,x,d]                 % BAD!
;  R = [x,a,b,c,d]                 % BAD!
;  R = [x,a,b,c,x,d]               % BAD!
;  false.                          % (no more answers)

这三个答案无效,因为每个R都包含一些x

最下面的样子:不要只看一些一些查询答案。查看所有查询答案!


#2 ) Prolog程序包含不同类型的子句:事实,规则和查询。

查询是程序中非常重要的部分(如果不是最重要的部分)。

查询既是文档又是规范。最重要的是,它们使您可以将程序开发的“机械”部分委派给Prolog处理器。

那要写哪些查询?

  • 以最普遍的查询开头:

    ?- remove(A,B,C).

  • 您希望成功的查询:

    ?- remove(x,[x,a,x,p],[a,p]).   % x is first element
    ?- remove(x,[a,x,p,x],[a,p]).   % x is last element
    ?- remove(x,[a,x,p],[a,p]).
    
  • 您期望失败的查询

    ?- \+ (remove(x,[a,x,p],Ls), dif(Ls,[a,p])).
    
  • 地面查询:

    ?- remove(x,[],[]).
    
  • 非地面查询(带有变量的查询):

    ?- remove(X,[a,b,a,c,d,c,a,b],Xs).
    

最重要的是: 没有查询,您不是在编写代码,而是在编写文本。


#3 )现在,我们来解决code 1:看看两个递归子句!

remove(X,[X|Y],Z) :- remove(X,Y,Z).
remove(X,[F|Y],[F|Z]) :- remove(X,Y,Z).

第一个规则将X与第一个列表[X|Y]相关。好吧!

第二个规则既不X也不[F|Y] [F|Z]。不好!<​​/ p>

通过向第二个子句添加目标dif/2,我们可以建立该连接。


#4 )完成!这是谓词remove/3的完整代码:

remove(_X, [], []).
remove(X, [X|Y], Z) :-
   remove(X, Y, Z).
remove(X, [F|Y], [F|Z]) :-
   dif(X, F),
   remove(X, Y, Z).

答案 1 :(得分:1)

考虑查询,

?- remove(x, [x,a,b,c,x,d], R).

代码2的问题在于,在某些时候,提取第二个列表中的所有元素后,它变为空。此时,在递归时,唯一可能的选择是第一个子句,因为第2和第3个子句要求列表具有头,但不是因为它为空。

因此,它尝试与第一个执行统一。现在,前两个谓词很好,但最后一个有问题。

即,它尝试统一[] = [d, c, b, a | _free_ ]。这是不可能的,因为[]不是“自由变量”

但是我的术语可能是错误的...但是我相信本质就在那里。