在Prolog中定义(数学)函数

在Prolog中定义(数学)函数,prolog,operators,user-defined-functions,Prolog,Operators,User Defined Functions,我知道Prolog(逻辑编程)是关于返回true和false的,函数是返回列表、数字、布尔值等任何内容的函数。起初,Prolog似乎没有函数的概念,而是依赖于统一,但您可以做如下事情: ?- X is log(42). X = 3.7376696182833684. 那么,似乎存在函数?或者这真的只是某种隐藏统一部分的语法糖分 如果它真的只是语法上的糖分,那么如果我想定义一个像log2这样的数学“函数”,我该怎么做呢 当然,我可以使用统一: log2(X,Result) :- Result i

我知道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.
?- X <- log2(8).
X = 3.0.

如何在Prolog中实现这一点?

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

?- X is log2(8).
X = 3.0.
?- X <- log2(8).
X = 3.0.
?-X是日志(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系统中使用。

因此它只是一种统一。。(感谢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, !.

:-op(900,xfy,您也可以在子句head中使用新定义的中缀运算符:
R
op
指令很有趣,可以为您提供一些有趣和有用的语法方法来表示谓词。
是一个内置谓词,因此您无法更改
是什么定义。
是什么。:)有一个不推荐使用的指令
算术函数
,它将执行您想要的操作。假设您的
log2/2
谓词存在,则指令
:-算术函数(log2/1).
将使您的第二个示例正常工作。我不确定为什么它会被弃用,但它似乎在6.2.6中仍然有效。我想知道这种弃用,还有一些事情要问Jan W。Dennis m.喜欢对Amzi采取的方法!Prolog是用中缀语法定义“is”(比如
iz/2
)的替代方法并构造规则来评估所需的任何附加函数。