List 删除prolog中的重复项

List 删除prolog中的重复项,list,prolog,failure-slice,program-slicing,List,Prolog,Failure Slice,Program Slicing,我对prolog相当陌生,目前正在阅读一本书,这本书为我提供了编写代码的实践示例。它让我负责删除重复项 注意:我已经阅读了其他stackoverflows,我知道如何删除重复项,但我不明白的是为什么我的代码不能工作。(对于其他堆栈溢出,我选择了不同的方法) 我已经创建了一个is_成员谓词,我相信它很好用 is_member(X, [Head,Tail]):- X == Head; is_member(X, Tail). 然后我的remove_duplicates谓词 remov

我对prolog相当陌生,目前正在阅读一本书,这本书为我提供了编写代码的实践示例。它让我负责删除重复项

注意:我已经阅读了其他stackoverflows,我知道如何删除重复项,但我不明白的是为什么我的代码不能工作。(对于其他堆栈溢出,我选择了不同的方法)

我已经创建了一个is_成员谓词,我相信它很好用

is_member(X, [Head,Tail]):-
    X == Head;
    is_member(X, Tail).
然后我的remove_duplicates谓词

remove_duplicates([Head|Tail], Without):-
    is_member(Head, Tail),
    remove_duplicates(Tail, Without);
    remove_duplicates(Tail, Head).
在我看来,这是有道理的,它检查头部是否是尾部的一部分,如果是,它不会将其添加到“无”列表中

否则它会

我显然遗漏了一些琐碎的东西


提前感谢

让我们先考虑一下
is_member/2
来简化任务

你可以这样写:

is_member(X, [Head,Tail]):- X == Head; is_member(X, Tail). 太好了!这是我们所期望的

那么,
a
是列表的成员吗

?- is_member(a, [a]). false. ?是联合会成员(a,[a])。 错。 这绝对是错误的

我建议您从这里开始,然后转到更复杂的定义。以系统的方式处理它:

  • 写下应该持有的东西
  • 尝试最一般的查询,查看您是否可以从程序中获得答案
  • 尝试具体的测试用例
  • 想想谓词的实际含义:可以在多个方向上使用谓词,在许多情况下,描述谓词的方式没有意义。例如,列表和元素都可以给定,在这种情况下,不需要“添加”或“删除”
  • 要查找程序中意外失败的原因,请使用以下定义来概括目标:

    :-op(950财年*)。 *_. 你现在可以写:

    is_member(X, [Head,Tail]):- ( * X == Head ; * is_member(X, Tail) ). is_成员(X,[头,尾]):- (*X==水头 *是_成员(X,尾部) ). 这是对原始程序的大量概括,事实上声明性地等价于:

    is_member(X, [Head,Tail]) :- true. is_成员(X,[头,尾]):-true。 上面的测试用例仍然失败,这表明程序仍然是特定的

    ?- is_member(a, [a]). false. ?是联合会成员(a,[a])。 错。
    回答得很好,谢谢你,我会接受你的建议。我也相信,我修正了错误。With:
    is_成员(X,[Head |)]:-X==Head这修复了具体的测试用例
    是成员(a,[a])
    ,是。但是,尝试一下测试用例的轻微泛化:
    ?-is_成员(a[X])。
    这仍然失败。总的来说,我只能建议避免使用非单调谓词,如
    (==)/2
    。它们只能在非常特殊的情况下安全地使用,在更一般的情况下会产生错误的答案。要表示两项相等,请使用
    (=)/2
    。它在所有方向上都正常工作。不应该是_成员(a[X])。失败?仔细想想:假设
    是_成员(a[X])
    失败。那么这就意味着,如果我们以声明的方式阅读它,那么这个查询就没有任何解决方案。然而,我们已经确定
    X=a
    是一个解决方案,因为
    是成员(a[a])
    必须成功!因此,由于更具体的案例
    是成员(a[a])
    成功,因此更一般的案例
    是成员(a[X])
    肯定不能失败。否则,这将意味着程序报告错误的答案。 ?- is_member(a, [a]). false. :- op(950,fy, *). *_. is_member(X, [Head,Tail]):- ( * X == Head ; * is_member(X, Tail) ). is_member(X, [Head,Tail]) :- true. ?- is_member(a, [a]). false.