假设我有这些事实:
parent(bob, sam). %bob is sam's parent
parent(sara, sam). %sara is sam's parent
Run Code Online (Sandbox Code Playgroud)
我想知道谁是山姆的父母并将他们归还给一份清单,因此使用:
list_parents(P, L) :- findall(Parent, parent(Parent, P), L).
Run Code Online (Sandbox Code Playgroud)
我现在要做的是问同样的问题,但只有一个论点:
findParents(sam).
Run Code Online (Sandbox Code Playgroud)
我试过了:
findParents(Name) :- list_parents(Name, L).
Run Code Online (Sandbox Code Playgroud)
但这样Prolog只会回答"True".
prolog的事情是,它与大多数语言略有不同(轻描淡写,如果每一个都是一个):
所有变量都是局部范围的.
变量值一旦绑定(统一)就不变,除非回溯取消绑定.
谓词不会返回传统意义上的值.他们要么成功要么失败.
要从测试谓词中获取值,请评估谓词从谓词中传递一些内容.如果您将变量或绑定值传递给它并不重要:如果调用者与您传递的内容统一了,则被调用的谓词将成功或值.如果传递了一个变量,并且被调用的谓词将其与非变量值统一,则您的变量将绑定到该值.想想(有点),好像你有一个过程语言,其中每个函数返回bool并且所有参数值都通过引用传递.
你尝试过的工作:
findParents(Name) :- list_parents(Name, L).
Run Code Online (Sandbox Code Playgroud)
变量L与返回的列表统一(已绑定)findall/3.然后它超出了范围.
如果你想对返回的(绑定)值实际执行某些操作,则需要在范围内处理它,或者将该值与调用该谓词的内容统一,从而将其传递给调用堆栈.或者,您可以将其断言到事实数据库中并保存以供日后使用.
prolog的工作方式是用于启动"程序"的根谓词根据数据库中的谓词定义搜索树.Prolog的"引擎"然后执行该树的深度优先,从左到右的搜索.当引擎到达您定义的搜索树的叶节点时,您的谓词会成功.回溯到谓词会导致引擎在搜索树中查找下一个解决方案.
因此,您希望以持久方式完成的任何事情都必须作为评估谓词的prolog"引擎"的副作用发生.例如,print()总是只成功一次(当你进入盒子时)...并且副作用会打印你要求它打印的任何内容.回溯到打印不会"撤消"打印,但print()不会再次成功.
如果只想让用户看到它,您可以打印该列表,如下所示:
findParents(Name):-
list_parents(Name,L),
print(L).
Run Code Online (Sandbox Code Playgroud)
但这并不完全是回归。请记住,在序言中,没有函数,因此没有“返回值”。你可以通过编写 foo(Args,Return) 来模拟一个函数,但你总是可以像 foo(X,sam) 一样调用它 - 有时它会给出你想要的,有时不会,有时会崩溃。
| 归档时间: |
|
| 查看次数: |
12426 次 |
| 最近记录: |