我想在 Prolog 中编写算术评估谓词,我发现 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).
这很棒,但不是很干。
我还发现了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
此处运算符与 _ 匹配,参数与 Left 和 Right 匹配。
所以我想出了这个:
eval(Formula, Value) :-
Formula =.. [Op, L, R], Value is Op(L,R).
如果它能工作,那就太干了,但它却给出了语法错误:需要运算符
。
在这种情况下,Prolog 有没有办法将运算符应用于参数?
最佳答案
您的几乎 DRY 解决方案因以下几个原因而不起作用:
Formula =.. [Op, L, R]
仅指二元运算符。您当然也想引用数字。参数
L
和R
根本不考虑。Op(L,R)
不是有效的 Prolog 语法。
从好的方面来说,您的尝试会为变量产生一个干净的实例化错误,而 positive/1
会失败并且eval/2
循环至少比失败要好。
因为您的运算符实际上与 (is)/2
使用的运算符相同您可能想先检查然后再重用 (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(-).
请注意number/1
变量失败 - 这会导致许多错误的程序。一个安全的替代方案是
t_number(N) :-
functor(N,_,0),
number(N).
关于prolog - Prolog 中的 DRY 算术表达式求值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23854857/