是否包含Prolog功能?

时间:2012-03-22 00:37:31

标签: prolog dcg

我正在尝试制作一个Prolog谓词iscontained/2iscontained(List, Search),如果true.列在给定的Search中,则会返回List,{ {1}}如果没有。如果它是一个输入的变量,那么它只返回它等于列表中的每个元素。

示例:

false.

我需要向正确的方向推,而不是要求伸出手,除非你知道快速的方法。感谢任何帮助。谢谢。

3 个答案:

答案 0 :(得分:3)

既然您已经提出了解决方案,我想提一件事:

经典版本:

member(Item, [Item|_List]).
member(Item, [_Head|List]) :- member(Item, List).

在找到最后一个元素后留下一个选择点,即:

?- member(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3;
false.

,而

member2(Item, [Head|List]) :-
    member2(List, Item, Head).

member2(_List, Item, Item).
member2([Head|List], Item, _PreviousHead) :-
    member2(List, Item, Head).

与最后一个元素同时处理空列表并允许优化:

?- member2(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3.

这是SWI-Prolog中使用的版本(当然还有Jekejeke Prolog和其他人)。它的作者是Gertjan van Noord。

这只是提醒一下,虽然实施member/2实施的练习非常出色,但不应该导致你之后不再使用内置插件,他们会这样做。经常微调和更有效率!

答案 1 :(得分:3)

请注意,经常提议的member/2谓词会接受根本没有列表的解决方案:

?- member(e,[e|nonlist]).
true.

在许多情况下这不是一个大问题,但是应该提到它。

仅允许列表的自然对称定义使用DCG:

... --> [] | [_], ... .

iscontained(Es, E) :-
   phrase((...,[E],...), Es).

...是非终端,表示任意序列。

虽然这对于这个小例子来说完全有点过头了,但它为你提供了一个更有趣模式的模板。像

iscontainedtwice(Es, E) :-
   phrase((...,[E],...,[E],...), Es).

答案 2 :(得分:1)

您需要考虑两种情况。我会把规则的正文留给你。

  • iscontained([A|Xs],A)
  • iscontained([X|Xs],A)

[编辑删除对空列表的引用:空列表不包含任何内容:如果遇到,则谓词失败。]