在Prolog中定义(数学)函数

时间:2013-08-24 15:08:41

标签: prolog operators user-defined-functions

我知道Prolog(逻辑编程)是关于返回true和false,并且函数是从列表,数字到布尔值返回任何内容的东西。最初,Prolog似乎没有功能的概念,而是依赖于统一,但你可以做以下事情:

?- X is log(42).
X = 3.7376696182833684.

所以似乎存在功能?或者这真的只是隐藏统一部分的某种语法糖?

如果它真的只是语法糖,那么如果我想定义一个像log2这样的数学'函数',我将如何进行呢?

当然我可以使用统一:

log2(X,Result) :- Result is log(X)/log(2).

但是说我想使用'语法糖函数风格',所以我可以写:

?- X is log2(8).
X = 3.0.

我怎样才能在Prolog中做到这一点?

2 个答案:

答案 0 :(得分:8)

Prolog是关于描述实体之间的关系。由于数学函数是一种特殊的关系(将输入与唯一定义的输出相关联),因此可以使用Prolog来描述这些函数。在您的示例中,实现此关系的谓词称为is/2(is)/2也被定义为Prolog中的中缀运算符,因此您可以编写:

?- X is log(42).

而不是前缀形式(当然也是可以接受的):

?- is(X, log(42)).

请注意is/2执行表达式的算术计算,并将第一个参数与结果统一起来。这与X与Prolog术语log(42)的统一不同。

请注意is/2不是真正的关系,因为你不能在另一个方向上使用它:

?- 0 is log(X).
ERROR: is/2: Arguments are not sufficiently instantiated

对此的解决方案是使用约束(例如,实数,称为CLP(R)),它可以在所有方向上工作。它们在许多现代Prolog系统中作为库或内置函数提供。

答案 1 :(得分:4)

所以它只是统一..(感谢mbratch和mat解释)

这就是我解决初始问题的方法,因此在使用自定义数学函数时,我的代码更具可读性:

:- op(900, xfy, <-).
R <- log2(Y) :- R is log(Y)/log(2), !.

% the two predicates below solves the problem with using mathematical operators
% together with self defined functions note that they should always be last
%
R <- X :-
    compound(X),
    X =..[OP, X2, X3],
    R2 <- X2,
    R3 <- X3,
    Expr =..[OP, R2, R3],
    R is Expr, !.
R <- X :- R is X, !.

然后我可以写:

?- X <- log2(8).
X = 3.0.

此外,最后两个谓词可以编写如下的化合物:

?- X <- 17*log2(8) - 2.
X = 49.0.

请注意,不允许您使用is / 2,因此我使用自己的&lt; - 运算符代替

来推翻它

编辑:添加了mat建议的语法糖,并添加了两个谓词来解决在将新定义的log2与其他数学运算符结合使用时出现的问题