Prolog 中的 DRY 算术表达式求值 [英] DRY arithmetic expression evaluation in Prolog
问题描述
我想在 Prolog 中为算术编写评估谓词,我发现 这个:
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).
这很棒,但不是很干.
我还发现了 这个:
:- 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匹配.
Operator is here matched with _ and arguments are matched with Left and Right.
所以我想出了这个:
eval(Formula, Value) :-
Formula =.. [Op, L, R], Value is Op(L,R).
如果它只工作但它会给出 Syntax error: Operator expected
,那将是地狱般的干燥.
It would be DRY as hell if only it worked but it gives Syntax error: Operator expected
instead.
在这种情况下,Prolog 中有没有办法将运算符应用于参数?
Is there a way in Prolog to apply operator to arguments in such a case?
推荐答案
您的几乎 DRY 解决方案无法正常工作,原因如下:
Your almost DRY solution does not work for several reasons:
Formula =.. [Op, L, R]
仅指二元运算符.你当然也想引用数字.
Formula =.. [Op, L, R]
refers to binary operators only. You certainly want to refer to numbers too.
根本不考虑参数L
和R
.
Op(L,R)
不是有效的 Prolog 语法.
Op(L,R)
is not valid Prolog syntax.
从好的方面来说,您的尝试会为变量产生一个干净的实例化错误,而 positive/1
会失败并且 eval/2
循环至少比失败.
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.
由于您的操作符实际上与 (is)/2
使用的操作符相同,因此您可能需要先检查,然后才能重用 (is)/2
.p>
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(-).
请注意,number/1
因变量而失败 - 这会导致许多错误的程序.一个安全的选择是
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屋!