如何从Prolog中的另一个谓词调用谓词?

时间:2014-03-13 09:15:30

标签: prolog

所以我刚开始Prolog,我想知道两件事:

1)是否内置函数(或者它们都被称为谓词?)用于简单的事情,例如最多2个数字,或数字的正弦等等......如果是这样,我该如何访问它们?

2)如何从另一个谓词中调用谓词?我写了两个叫做car和cdr的谓词。 car返回列表的头部,cdr返回没有头部的列表。但是现在我想在cdr上打电话。以下是一些澄清的例子:

car([3,4,5,5], H). would return H = 3

cdr([3,4,5,5],L). would return L = [4,5,5]

我要问的是我该怎么做:

car(cdr[3,4,5,5]))

...

3 个答案:

答案 0 :(得分:10)

正如其他人所指出的那样,Prolog中的谓词被称为出于某种原因:它们实际上不是函数。 Prolog的许多新手开始试图将他们熟悉的其他语言功能映射到Prolog,但它通常都失败了。 Prolog是一种与大多数其他语言截然不同的编程工具。所以这有点像长时间使用各种锤子,然后让别人给你扳手,你想知道为什么它不会成为一把好锤子。

在Prolog中,谓词是在实体之间声明关系的一种方法。如果您说foo(a, b),则表示ab之间存在称为foo的关系。您可能已经看过以下示例:knows(joe, jim).knows(jim, sally).您可以定义关系,例如:

remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).

或类似的东西。

谓词不会返回值。它要么成功要么失败。如果你有一系列以逗号分隔的谓词(一个“和”关系)并且Prolog遇到一个失败的谓词,它会备份(回溯)到最近的先前谓词,它可以通过不同的参数实例化和移动再次成功再次前进。

只是为了增加一点混乱,Prolog中有一些专门用于评估算术表达式的谓词。这些功能就像功能一样,但它们都是特例。例如:

X is Y / gcd(Z, 4).

此处,gcdZ的{​​{1}}计算返回的值,然后将4除以该值,并将结果实例化为X.还有其他各种功能,例如Ymax/2等。您可以在文档中查找它们。

算术比较运算符也以这种方式运行(使用sin/1=:=/2>/2等数字表达式)。所以如果你说:

</2

Prolog将考虑对这些论点进行数值评估,然后对它们进行比较。

所以说了这么多,Prolog确实允许嵌入术语结构。你可以有类似的东西:

X < Y + Z

作为一个术语。 Prolog不会解释它。解释留给程序员。然后我可以创建一个谓词来定义这些术语的评估:

car(cdr([1,2,3]))

上述条款的删除可以防止在我不需要时回溯到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)

请注意,这是一个简单的案例,我可能没有捕捉到执行| ?- 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=..等代替参数中的离散项callcar,也可以更加通用。例如,稍微更一般的cdr可能是:

proc_list

这种处理术语的技巧确实远离了Prolog最擅长的关系行为,并且倾向于功能行为,但是要了解Prolog的工作原理。

答案 1 :(得分:3)

Prolog对计算有着非常的态度......

您不会在参数之间定义功能,但关系。我所知道的最相似和众所周知的语言是SQL。将谓词视为表(或存储过程,当某些计算未由数据库引擎预定义时)。

car([H|_],H).
cdr([_|T],T).

car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).

但是因为列表&#39;语法是语言的核心部分,更好的定义可能是

car_of_cdr([_,X|_], X).

无论如何,我认为你应该花一些时间在一些Prolog教程上。 SO info page有更多信息......

答案 2 :(得分:-1)

:- use_module(support).

这意味着该模块将使用其他模块中编写的谓词。

<module_name>:<predicate_name>(<atoms / Variables>).

这样您就可以在另一个模块中调用谓词。