2011-05-26 95 views
4

比方说,我有这些事实:如何在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"

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

但心不是正好返回:

+1

不可能。不要。除了布尔值之外,Prolog没有返回值。 – 2011-05-27 06:56:46

回答

2

如果只希望用户看到它 类似,你可以打印清单。请记住,在序言中,没有功能,因此没有“返回值”。你可以通过编写foo(Args,Return)来模拟一个函数,但是你总是可以像foo(X,sam)那样调用它 - 有时它会给你想要的东西,有时它不会,有时它会崩溃。

+0

虽然这是我的问题。我以前在很多语言中编写过程序,但我无法理解它应该如何工作。我不需要它打印,但我需要相同的结果,我会调用list_parents“函数”。 – porlognewbie 2011-05-26 17:35:58

+0

好吧,只需将谓词list_parents与要存储列表的变量一起调用即可。像list_parents(sam,List)。那么prolog会将列表与萨姆父母的名单统一起来。如果它使得它更容易,你可以想象它是List = list_parents(sam)的等价物,但它不是真的。 – 2011-05-26 18:49:01

5

与序言的事情是,它比大多数语言有点不同(轻描淡写,如果每发生一个):

  • 所有变量都局部范围。

  • 一旦绑定(统一),变量值是不变的,除非回溯解除绑定。

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

  • 为了从测试谓词中获得价值,您可以评估谓词,从谓词中传递它。无论你传递一个变量还是一个绑定值,都没有关系:被调用的谓词将成功,或者如果调用者已经与传递它的内容相结合,那么它将会被赋值。如果您传递了一个变量,并且被调用的谓词将其与一个非变量值进行了统一,则您的变量将被绑定到该值。想一想(有点),就好像你有一种程序语言,每个函数都返回bool,并且所有参数值都是通过引用传递的。

你尝试过什么工作:

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

变量L是统一用(注定要)通过findall/3返回的列表。然后它超出了范围。

如果你想真正一些与返回(绑定)值,你需要处理它的地方是在范围内,或统一的东西,值是谓语与调用,因此通过它调用堆栈。或者,您可以将其断言到事实数据库中并保存以备后用。

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

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

2

func库提供SWI-Prolog中具有返回值的函数的语法。在这个例子中,你可以通过编写writeln(list_parents $ sam)打印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).