如何在Prolog中返回列表?

时间:2011-05-26 17:18:01

标签: list prolog

让我说我有这些事实:

parent(bob, sam). %bob is sam's parent
parent(sara, sam). %sara is sam's parent

我想知道谁是 sam 的父母,并将其归还给一个列表并使用:

list_parents(P, L) :- findall(Parent, parent(Parent, P), L).

我现在要做的是问同样的问题,但只有一个论点:

findParents(sam).

我试过了:

findParents(Name) :- list_parents(Name, L).

但这样Prolog只回答"True"

3 个答案:

答案 0 :(得分:8)

与prolog相关的是它与大多数语言略有不同(轻描淡写,如果每一种语言都是如此):

  • 所有变量都是本地范围的。

  • 变量值在绑定(统一)后是不变的,除非回溯取消绑定。

  • 谓词不会返回传统意义上的值。他们要么成功要么失败。

  • 要从测试谓词中获取值,您可以评估谓词从谓词中传递一些内容。如果你传递一个变量或一个绑定值并不重要:如果调用者已经与你传递的内容统一了,那么被调用的谓词将成功或值。如果传递了一个变量,并且被调用的谓词将其与非变量值结合,则您的变量将绑定到该值。想想(有点),好像你有一个过程语言,其中每个函数返回bool并且所有参数值都通过引用传递。

您尝试过的工作:

findParents(Name) :- list_parents(Name, L).

变量L与findall/3返回的列表统一(已绑定)。然后它超出了范围。

如果你想用返回的(绑定的)值实际某些东西,你需要在它的范围内处理它,或者将该值与该谓词被调用的东西统一起来。从而将其传递给调用堆栈。或者,您可以将其断言到事实数据库中并保存以供日后使用。

prolog的工作方式是用于启动“程序”的根谓词根据数据库中的谓词定义搜索树。 Prolog的“引擎”然后执行该树的深度优先,从左到右的搜索。当引擎到达您定义的搜索树的叶节点时,您的谓词会成功。回溯到谓词会导致引擎在搜索树中查找下一个解决方案。

因此,您希望以持久方式完成的任何事情都必须作为评估谓词的prolog“引擎”的副作用。例如print()总是只成功一次(当你进入盒子时)...并且副作用会打印你要求它打印的任何内容。回溯到打印中不会“撤消”打印,但print()不会再次成功。

答案 1 :(得分:2)

如果只想让用户看到它,你可以打印列表 类似的东西:

findParents(Name):-
   list_parents(Name,L),
   print(L).

但这并没有完全恢复。记住,在prolog中,没有函数,因此没有“返回值”。你可以通过编写foo(Args,Return)来模拟一个函数,但你可以像foo(X,sam)一样调用它 - 有时候它会给你想要的东西,有时它会不会,有时它会崩溃。

答案 2 :(得分:2)

func库为SWI-Prolog中返回值的函数提供了语法。在此示例中,您可以通过编写sam

来打印writeln(list_parents $ sam)的所有父母
:- initialization(main).
:- use_module(library(func)).

main :- writeln(list_parents $ sam).

list_parents(P, L) :- findall(Parent, parent(Parent, P), L).
parent(bob, sam). %bob is sam's parent
parent(sara, sam). %sara is sam's parent

同样,您可以定义一个具有多个参数的函数,例如:

% return a item at an index in a list.
nth0((Index,List),ToReturn) :-
    nth0(Index,List,ToReturn).

...然后像这样使用它:

example :-
    ListIndex = (nth0 $(0,[1,2,3,4])), %returns 1, which is the first item in this list
    writeln(ListIndex).