Prolog中的DRY算术表达式评估 [英] DRY arithmetic expression evaluation in Prolog
问题描述
我想在Prolog中编写算术评估谓词,结果发现此:
eval(A + B,CV):-eval(A,AV),eval(B ,BV),CV是AV + BV。
eval(A-B,CV):-eval(A,AV),eval(B,BV),CV是AV-BV。
eval(A * B,CV):-eval(A,AV),eval(B,BV),CV为AV * BV。
eval(数字,数字):-数字(数字)。
哪个很棒,但不是很干。
我还发现了此 :
:-op(100,fy,neg),op(200,yfx,and),op(300,yfx ,要么)。
正数(公式):-
原子(公式)。
正(公式):-
公式= .. [_,Left,Right],
正(左),
正(右)。
?-正((p或q)和(q或r))。
是
?-正(p和(负q或r))。
否
此处的运算符与_匹配,并且参数与Left和Right匹配。 / p>
所以我想到了:
eval(公式,值):-
公式= .. [Op,L,R],值为Op(L,R)。
如果它只能工作,但会产生语法错误:运算符应该是
。
在这种情况下,Prolog中是否可以将运算符应用于自变量?
您的DRY解决方案由于以下几个原因而无法正常工作:
-
公式= .. [Op,L,R]
仅指二进制运算符。您当然也想引用数字。 -
自变量
L
和完全不考虑R
。 -
Op(L,R)
无效的Prolog语法。
在加法方面,您的尝试会为变量产生清晰的实例化错误,而 positive / 1
将失败,而 eval / 2
循环,这至少比失败要好。
由于您的运算符实际上与(is)/ 2
使用的运算符相同,因此您可能要先检查然后重用(是)/ 2
。
eval2(E,R):-
isexpr(E),
R是E.
isexpr(BinOp):-
BinOp = .. [F,L,R],
admissibleop(F),
isexpr(L),
isexpr(R)。
isexpr(N):-
数字(N)。
可接受(*)。
admissibleop(+)。
%admissibleop(/)。
admissibleop(-)。
请注意, number / 1
失败变量-导致许多错误的程序。一个安全的替代方法是
t_number(N):-
仿函数(N,_,0),
号(N)。
I wanted to write evaluating predicate in Prolog for arithmetics and I found this:
eval(A+B,CV):-eval(A,AV),eval(B,BV),CV is AV+BV.
eval(A-B,CV):-eval(A,AV),eval(B,BV),CV is AV-BV.
eval(A*B,CV):-eval(A,AV),eval(B,BV),CV is AV*BV.
eval(Num,Num):-number(Num).
Which is great but not very DRY.
I've also found this:
:- op(100,fy,neg), op(200,yfx,and), op(300,yfx,or).
positive(Formula) :-
atom(Formula).
positive(Formula) :-
Formula =.. [_,Left,Right],
positive(Left),
positive(Right).
?- positive((p or q) and (q or r)).
Yes
?- positive(p and (neg q or r)).
No
Operator is here matched with _ and arguments are matched with Left and Right.
So I came up with this:
eval(Formula, Value) :-
Formula =.. [Op, L, R], Value is Op(L,R).
It would be DRY as hell if only it worked but it gives Syntax error: Operator expected
instead.
Is there a way in Prolog to apply operator to arguments in such a case?
Your almost DRY solution does not work for several reasons:
Formula =.. [Op, L, R]
refers to binary operators only. You certainly want to refer to numbers too.The arguments
L
andR
are not considered at all.Op(L,R)
is not valid Prolog syntax.
on the plus side, your attempt produces a clean instantiation error for a variable, whereas positive/1
would fail and eval/2
loops which is at least better than failing.
Since your operators are practically identical to those used by (is)/2
you might want to check first and only then reuse (is)/2
.
eval2(E, R) :-
isexpr(E),
R is E.
isexpr(BinOp) :-
BinOp =.. [F,L,R],
admissibleop(F),
isexpr(L),
isexpr(R).
isexpr(N) :-
number(N).
admissibleop(*).
admissibleop(+).
% admissibleop(/).
admissibleop(-).
Note that number/1
fails for a variable - which leads to many erroneous programs. A safe alternative would be
t_number(N) :-
functor(N,_,0),
number(N).
这篇关于Prolog中的DRY算术表达式评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!