Prolog中DRY算术表达式的评估

时间:2014-05-25 11:38:05

标签: prolog refactoring dry arithmetic-expressions

我想在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).

如果只有它起作用,那就干涸了,但它却给了Syntax error: Operator expected

在这种情况下,Prolog是否有办法将运算符应用于参数?

1 个答案:

答案 0 :(得分:3)

由于以下几个原因,您几乎干的解决方案无效:

  • Formula =.. [Op, L, R]仅指二元运算符。你当然也想引用数字。

  • 根本不考虑参数LR

  • 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).