有人可以解释这个谓词究竟是如何工作的吗?

时间:2016-05-11 12:38:06

标签: list prolog

所以我有以下谓词,它以符号列表作为第一个参数,然后输出这个列表并删除所有重复项:

removeDups([], []).
removeDups([H|T], [H|T1]) :-
   subtract(T, [H], T2),
   removeDups(T2, T1).

它按预期工作,但我不确定如何理解它。

到目前为止我所理解的是:

  1. 显然,首先将谓词设置为两个空列表作为参数
  2. 列表的头部和尾部已设置
  3. 我不明白减法部分在做什么,它从头部值中删除尾值?然后将其存储在临时变量T2
  4. 然后将T2的临时值存储到T1
  5. 我很困惑这里到底发生了什么,所以任何帮助都会非常感激!

2 个答案:

答案 0 :(得分:2)

谓词减法/ 3描述了第三个参数是没有第二个参数元素的第一个参数的关系,例如:

removeDups([],[]).

removeDups / 2的第一条规则是基本情况:

removeDups([H|T], [H|T1]) :-  % the head of list 1 is in the head of list 2
   subtract(T, [H], T2),      % T2 is the tail of list 1 without H
   removeDups(T2,T1).         % T1 is a duplicate free T2

您可以将其读作:没有重复项的空列表是空列表。第二个规则是关系的一般情况,其中第一个列表不为空。

T2

因此,减法/ 3的目标描述了一个列表H,其中包含除T T2之外的所有元素。由于通过递归,列表[]变得越来越短,您不可避免地会以基本案例 ?- X=1, subtract([1,2,3],[X],L). L = [2,3], X = 1 ?- subtract([1,2,3],[X],L), X=1. L = [2,3], X = 1 结束。这是第一条规则所描述的。从程序上讲,您需要基本案例,以便您的谓词可以终止。但是,正如@repeat所指出的,如果前两个参数包含自由变量,则使用subtract / 3可能会有问题。请考虑以下示例:

   ?- X=2, subtract([1,2,3],[X],L).
L = [1,3],
X = 2
   ?- subtract([1,2,3],[X],L), X=2.
no

可是:

removeDups([],[]).
removeDups([H|T], [H|T1]) :-
   safe_subtract(T, [H], T2),
   removeDups(T2,T1).

safe_subtract(As,Bs,Xs) :-
   ( ground(As+Bs) ->
     subtract(As,Bs,Xs) ;
     throw(error(instantiation_error,_))).

因此,如评论中所建议的那样,测试这些论点以进行充分的实例化是一个好主意:

{{1}}

答案 1 :(得分:1)

此过程指出removeDups(L,L1)

  • 第1条:如果L和L1都与空列表统一
  • ,则应该成功
  • 第2条:LL1都是包含至少一个元素的列表,每个列表的头部(H)与另一个列表的头部统一,然后{{3使用第一个参数的列表尾部(T)和仅包含头部的列表调用。此过程将第三个参数(T2)与包含T不带H元素的列表统一起来。然后,对removeDups/3的递归调用将相同的算法应用于结果列表(没有H)。递归调用至少有一个元素小于原始列表L。从递归调用返回时,T1应该没有重复(并且H也不在其中)。但是,由于removeDups的第三个参数是[H|T1],调用者将在第三个参数H中作为第三个列表的头部。