Prolog中的DRY算术表达式评估 [英] DRY arithmetic expression evaluation in Prolog

查看:92
本文介绍了Prolog中的DRY算术表达式评估的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在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 and R 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆