当前位置:  开发笔记 > 编程语言 > 正文

从事实中返回名称列表

如何解决《从事实中返回名称列表》经验,为你挑选了1个好方法。

我正在学习prolog,我正试图从我所做的声明中返回一个名单.

例:

person(sam). 
person(tom). 
person(holly).

我想要归还任何亲自申报的人的姓名.我试过这样做:

people([]).
people([X | XS]) :-
    person(X),
    people(XS).

它有效,有点,它添加sam到列表,然后sam无限增加而不是切换tom,然后holly然后结束.有人能指出我正确的方向吗?



1> Willem Van O..:
自定义实施

例如,您可以使用a member/2和accumulator 来解决此问题:

people(L) :-
    people([],L).
people(L,[X|R]) :-
    person(X),
    \+member(X,L),
    people([X|L],R).
people(L,[]) :-
    \+ (person(X),\+ member(X,L)).

或者,如果你知道如何使用cut(!),你可以使用@ CapelliC的版本:

people(L) :-
    people([],L).
people(L,[X|R]) :-
    person(X),
    \+member(X,L),
    !,
    people([X|L],R).
people(L,L).

因此,每次你寻找一个person/1 X不是它的成员L.如果您再也找不到此人,则选择最后一个条款.在这种情况下,空列表[]向后传播,并且对于调用堆栈上的每个元素,特定X内容将添加到前面.

使用findall/3内置

然而,遵循ISO标准的Prolog变体有内置findall/3:

findall(+Template, :Goal, -Bag)

您可以按如下方式使用它:

Template是你想要获得的数据的仿函数(这可以是变量)X;

Goal是谓词(或谓词的列表等),应该是满意的.Prolog将在内部致电Goal; 和

Bag 是输出:结果列表.

如果你使用这个:

people(L) :-
    findall(X,person(X),L).

它将生成所有person/1s 的列表:

?- findall(X,person(X),L).
L = [sam, tom, holly].

还有其他高阶谓词可以保证唯一性等.

语义差异

请注意,findall/3我们自己的people/1方法在语义上并不相同.实际上,如果你的数据库包含一个人两次,它将是两倍findall/3.此外,我们自己people/1将按各种可能的顺序列举列表.


@CapelliC:通常我都会提出同样的建议,但是由于切割会产生多方向谓词的副作用,所以我开始不经常使用它们.我已将您的版本包含在答案中(当然还有对评论的引用).
推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有