如何从Prolog中的另一个谓词调用谓词? [英] How to call a predicate from another predicate in Prolog?
问题描述
所以我刚开始使用 Prolog,我想知道两件事:
So I just started Prolog and I was wondering two things:
1) 是否有内置函数(或者它们都称为谓词?)用于简单的事情,例如最多 2 个数字或一个数字的正弦等......如果是这样,我如何访问它们?
1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?
2) 如何从另一个谓词调用谓词?我写了两个谓词,称为 car 和 cdr.car 返回列表的头部,cdr 返回没有头部的列表.但现在我想在 cdr 上调用 car.以下是一些说明示例:
2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:
car([3,4,5,5], H). would return H = 3
cdr([3,4,5,5],L). would return L = [4,5,5]
我要问的是我该怎么做:
and what I am asking is how can I do this:
car(cdr[3,4,5,5]))
??
推荐答案
正如其他人所指出的,Prolog 中的谓词之所以这样称呼是有原因的:它们实际上不是函数.许多 Prolog 新手开始尝试将他们在其他语言中知道的功能映射到 Prolog,但通常会失败.Prolog 是一种与大多数其他语言截然不同的编程工具.所以这有点像长期使用各种各样的锤子,然后有人递给你一把扳手,你会想为什么它不是一把好锤子.
As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions. Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.
在 Prolog 中,谓词是一种声明实体之间关系的方法.如果您说foo(a, b)
,则表示a
和b
之间存在称为foo
的关系.您可能已经看过以下示例:knows(joe, jim).
和 knows(jim, sally).
并且您可以定义一个关系,例如:
In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b)
it means there's a relationship between a
and b
called foo
. You've probably seen the examples: knows(joe, jim).
and knows(jim, sally).
And you can define a relation, like:
remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).
或者类似的东西.
谓词不返回值.它要么成功,要么失败.如果您有一系列由逗号分隔的谓词(和"关系)并且 Prolog 遇到一个失败的谓词,它会备份(回溯)到最近的先前谓词,它可以通过其参数的不同实例化和移动再次成功再次转发.
A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.
只是为了增加一点混乱,Prolog 中有一些谓词专门用于计算算术表达式.这些行为类似于函数,但它们是特例.例如:
Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:
X is Y / gcd(Z, 4).
这里计算Z
和4
的gcd
并返回其值,然后除以Y
通过那个值,结果被实例化到X中.还有很多其他的函数,比如max/2
,sin/1
等等,你可以看看它们在文档中.
Here, gcd
of Z
and 4
is computed an its value returned, and then Y
is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2
, sin/1
, etc. You can look them up in the documentation.
算术比较运算符也以这种方式起作用(使用 =:=/2
、>/2
、</2
、等与数字表达式).所以如果你说:
Arithmetic comparative operators function this way as well (using =:=/2
, >/2
, </2
, etc with numeric expressions). So if you say:
X < Y + Z
Prolog 将考虑对这些参数进行数值评估,然后进行比较.
The Prolog will consider numerical evaluation of these arguments and then compare them.
话虽如此,Prolog 确实允许嵌入术语结构.你可以有类似的东西:
So having said all that, Prolog does allow embedding of term structures. You could have something like:
car(cdr([1,2,3]))
作为一个术语.Prolog 不会解释它.解释留给程序员.然后我可以创建一个谓词来定义对这些术语的评估:
as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:
car([H|_], H).
cdr([_|T], T).
proc_list(car(X), Result) :-
proc_list(X, R1),
car(R1, Result), !.
proc_list(cdr(X), Result) :-
proc_list(X, R1),
cdr(R1, Result), !.
proc_list(X, X).
上述子句中的删减可防止在我不想要时回溯到 proc_list(X, X)
.
The cut in the above clauses prevents backtracking to proc_list(X, X)
when I don't want it.
那么:
| ?- proc_list(car(cdr([1,2,3])), R).
R = 2
yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).
R = 3
yes
| ?-
请注意,这是一个简单的案例,我可能没有捕捉到正确执行 car
和 cdr
序列的所有微妙之处.也可以使用 =..
和 call
等,而不是离散术语 car
和 cdr
使其更通用> 在参数中.例如,稍微更通用的 proc_list
可能是:
Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car
and cdr
. It can also be made more general using =..
and call
, etc, instead of discrete terms car
and cdr
in the parameters. For example, a slightly more general proc_list
might be:
proc_list(Term, Result) :-
Term =.. [Proc, X], % Assumes terms have just one argument
member(Proc, [car, cdr]), % True only on recognized terms
proc_list(X, R1), % Recursively process embedded term
ProcCall =.. [Proc, R1, Result], % Construct a calling term with Result
call(ProcCall), !.
proc_list(X, X).
这种处理术语的技术确实脱离了 Prolog 最擅长的关系行为,而是倾向于函数行为,但了解 Prolog 的工作原理.
This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.
这篇关于如何从Prolog中的另一个谓词调用谓词?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!