Prolog中的一阶谓词逻辑:使用签名和算术术语

问题描述

我正在使用Prolog中的术语和签名(一阶谓词逻辑)。

我已获得签名(∅,Z,{add(2),sub(2),mult(2)})。因此没有变量,常量是整数,并且功能是“加”,“子”和“多”。

目标是写谓词“ calc / 2”,该谓词采用一个术语(基于上面的签名)并根据整数的加法,减法和乘法的通常定义进行计算。示例:

?- calc( add(sub(8,2),mult(4,-3)),N).
N = -6

((((8-2)+(4 ∗ -3))= -6)

问题与 this question 类似,但有一个很大的不同,就是我需要避免使用= ..运算符来查找函数名称。相反,我想利用Prolog在规则参数上使用模式匹配的事实,这是我完全坚持的。要注意的另一件事是,“ add”,“ sub”和“ mult”不应被视为谓词。

我使用= ..运算符的第一个解决方案是(借助上面链接的线程的答案):

op(+,add).
op(-,sub).
op(*,mult).

calc(Term,N) :-
    calc2(Term,Expr),N is Expr.

calc2(N,N) :- integer(N).
calc2(Term,Expr) :-
    Term =.. [Op_str,Comp1,Comp2],op(Op,Op_str),calc2(Comp1,Expr1),calc2(Comp2,Expr2),Expr =.. [Op,Expr1,Expr2].

但是由于这不是我正在寻找的解决方案类型,因此对我的问题没有太大帮助。

我可以很容易地执行单个计算(例如calc(add(1,N)),但是我要处理比这更复杂的事情。

解决方法

要使用模式匹配并避免使用univ运算符= ..,可以像这样重写calc2 / 2:

calc2(add(Op1,Op2),Expr1 + Expr2) :- 
    calc2(Op1,Expr1),calc2(Op2,Expr2).
calc2(sub(Op1,Expr1 - Expr2) :-
    calc2(Op1,Expr2).
calc2(mult(Op1,Expr1 * Expr2) :-
    calc2(Op1,Expr2).

这使代码更直观,其中可以通过单独的子句处理其他情况(例如,幂)。另外,现代的编译器可以优化生成的代码。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...