如何删除所有事件?

问题描述 投票:1回答:2

我试图理解为什么代码1工作正常但代码2输出错误:

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
list prolog
2个回答
1
投票

考虑查询,

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

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

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

也就是说,它试图统一[] = [d, c, b, a | _free_ ]。这是不可能的,因为[]不是'自由变量'

然而,我的术语可能是错的......但我相信其实质是存在的。


3
投票

你提出的两个谓词 - code 1code 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处理器。

那么哪些查询要写?

  • 从最常见的查询开始: ? - 删除(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]。坏!

通过在第二个子句中添加目标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).
© www.soinside.com 2019 - 2024. All rights reserved.