如何在Prolog中返回列表? [英] How do I return a list in Prolog?

查看:107
本文介绍了如何在Prolog中返回列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这些事实:

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

我想找出谁是 sam 的父母,并将他们归还给他们,并按如下方式使用:

I wanted to find out who were sam's parents and return them in a list and as such used:

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

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

What I want to do now is ask the same question but with only one argument as such:

findParents(sam).

我尝试过:

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

但是这种方式Prolog只是回答"True".

but this way Prolog simply answers "True".

推荐答案

与序言有关的事情是,它与大多数语言有所不同(轻描淡写,如果每种语言都有):

The thing with prolog is that it's a little different than most languages (understatement, if there every was one):

  • 所有变量都在本地范围内.

  • All variables are locally scoped.

变量值一旦绑定(统一)就不变,除非回溯将其绑定.

Variable values are invariant once bound (unified), unless backtracking unbinds it.

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

Predicates do not return a value in the conventional sense. They either succeed or fail.

要从测试谓词中获取价值,您可以对谓词进行评估,并从谓词中传递一些东西.传递一个变量或绑定值都没有关系:被调用的谓词将成功或赋值,只要调用者将其与传递的内容统一即可.如果您传递了一个变量,并且被调用的谓词将其与一个非变量值统一起来,则您的变量将绑定到该值. (某种程度上)将其视为一种程序语言,其中每个函数都返回bool,并且所有参数值都通过引用传递.

To get value back from testing a predicate, you evaluate the predicate passing it something from your predicate. It doesn't matter if you pass it a variable or a bound value: the called predicate will succeed or value if what the caller has unifies with what you passed it. If you passed a variable, and the called predicate unifies it with a non-variable value, your variable is bound to that value. Think of it (somewhat) as if you had a procedural language where every function returned bool and all parameter values were passed by reference.

您尝试过的方法:

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

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

The variable L was unified with (was bound to) the list returned by findall/3. And then it went out of scope.

如果您想真正地执行具有返回(绑定)值的操作,则需要在其作用域内对其进行处理,或者将其与谓词一起调用并与该值统一因此将其传递给调用堆栈.或者,您可以将其声明为事实数据库并保存以备后用.

If you want to actually do something with that returned (bound) value, you need to deal with it where it's in-scope, or unify that value with something that that predicate was invoked with and thus pass it up the call stack. Or, you could assert it into the database of facts and save it for later.

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

The way prolog works is that the root predicate used to start your "program" defines a search tree in terms of the predicates in your database. Prolog's "engine" then performs a depth-first, left-to-right search of that tree. Your predicate succeeds when the engine gets to a leaf node of the search tree you defined. Backtracking into your predicate causes the engine to look for the next solution in the search tree.

因此,您想要以持久方式完成的任何事情都必须作为prolog引擎"评估谓词的副作用而发生.例如,print()总是仅成功执行一次(当您输入框时)...并且作为副作用打印您要打印的内容.回溯到印刷品不会撤消"印刷品,但是print()不会再次成功.

As a result, anything you want to accomplish in a persistent way has to occur as a side effect of the prolog "engine" evaluating a predicate. For instance print() always succeeds just once (when you enter the box)...and as a side effect prints whatever you asked it to print. Backtracking into the print doesn't "undo" the print, but print() doesn't succeed again.

这篇关于如何在Prolog中返回列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆