Mic*_*ahl 5 operators prolog user-defined-functions
我知道Prolog(逻辑编程)就是返回true和false,并且函数是从列表,数字返回到布尔值的东西.最初,Prolog似乎没有功能的概念,而是依赖于统一,但你可以做以下事情:
?- X is log(42).
X = 3.7376696182833684.
Run Code Online (Sandbox Code Playgroud)
所以似乎存在功能?或者这真的只是隐藏统一部分的某种语法糖?
如果它真的只是语法糖,那么如果我想定义像log2这样的数学"函数",我将如何进行呢?
当然我可以使用统一:
log2(X,Result) :- Result is log(X)/log(2).
Run Code Online (Sandbox Code Playgroud)
但是说我想使用'语法糖函数风格',所以我可以写:
?- X is log2(8).
X = 3.0.
Run Code Online (Sandbox Code Playgroud)
我怎么能在Prolog中做到这一点?
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
Run Code Online (Sandbox Code Playgroud)
对此的解决方案是使用在所有方向上工作的约束(例如,实数,称为CLP(R)).它们在许多现代Prolog系统中作为库或内置函数提供.
小智 5
所以这只是统一..(感谢 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, !.
Run Code Online (Sandbox Code Playgroud)
然后我可以写:
?- X <- log2(8).
X = 3.0.
Run Code Online (Sandbox Code Playgroud)
此外,最后两个谓词可以编写如下复合词:
?- X <- 17*log2(8) - 2.
X = 49.0.
Run Code Online (Sandbox Code Playgroud)
请注意,不允许你弄乱 is/2,因此我通过使用我自己的 <- 运算符来推翻它
编辑:添加了 mat 建议的语法糖,并添加了两个谓词,修复了将新定义的 log2 与其他数学运算符结合使用时出现的问题