如何从Prolog中的另一个谓词调用谓词? [英] How to call a predicate from another predicate in Prolog?

查看:52
本文介绍了如何从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),则表示ab 之间存在称为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).

这里计算Z4gcd并返回其值,然后除以Y通过那个值,结果被实例化到X中.还有很多其他的函数,比如max/2sin/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
| ?-

请注意,这是一个简单的案例,我可能没有捕捉到正确执行 carcdr 序列的所有微妙之处.也可以使用 =..call 等,而不是离散术语 carcdr 使其更通用> 在参数中.例如,稍微更通用的 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屋!

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