我正在尝试制作一个Prolog谓词iscontained/2
:iscontained(List, Search)
,如果true.
列在给定的Search
中,则会返回List
,{ {1}}如果没有。如果它是一个输入的变量,那么它只返回它等于列表中的每个元素。
示例:
false.
我需要向正确的方向推,而不是要求伸出手,除非你知道快速的方法。感谢任何帮助。谢谢。
答案 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)
[编辑删除对空列表的引用:空列表不包含任何内容:如果遇到,则谓词失败。]