我们都知道成员的经典Prolog谓词:
member(X, [X|T]).
member(X, [Y|T]) :- member(X,Y).
我正在努力提出扩展成员谓词,我在列表(列表等)中搜索元素。例如:
member(4, [1,2,[3,4,[5]],[6,7,9]]).
TRUE
答案 0 :(得分:3)
我们可以通过三个规则来定义这样的谓词。 X
是列表L
的成员,而L
是具有以下内容的非空列表:
X
是它的第一个元素; X
是其第一个元素的成员(因此也是一个列表);或X
是列表其余部分(其“ tail ”)的成员。有了这三个条件,我们可以编写谓词rmember/2
(递归成员),例如:
rmember(X, [X|_]). %% (1)
rmember(X, [H|_]) :- %% (2)
rmember(X, H).
rmember(X, [_|T]) :- %% (3)
rmember(X, T).
第一个条件和第三个条件在简单的member/2
谓词中也存在,只有第二个条件对于递归成员检查是“唯一的”。
通过使谓词具有三个参数,我们可以略微提高上述效率,其中列表的尾部是第一个,搜索第二个元素,而列表的头是第三个。这是一种流行的方法,例如SWI-Prolog's member/2
implementation [swi-doc]。
这样做的好处是我们避免多次拆箱。我们还可以限制第二种情况的模式,以便仅针对非空子列表调用此模式:
rmember_(_, El, El).
rmember_(_, El, [H|T]) :-
rmember_(T, El, H).
rmember_([H|T], El, _) :-
rmember_(T, El, H).
然后我们可以根据rmember/2
来定义_rmember/3
:
rmember(X, [H|T]) :-
rmember_(T, X, H).