-->

后缀表达式列表评估(Postfix expression list evaluation)

2019-08-21 19:18发布

我已经写了一个程序,从递归表达式列表评估序言修复后的表达。 例如,假设下面的列表:

[+,1,2]

它应该返回3.他们的方式我构建我的断言是,直到它到达列表的末尾,以便它读取值向后递归调用自身。 (相同从左到右读这张表:[2,1,+])。

我的问题是,当我试图通过递归调用所有的值返回多个值突然消失。

下面的代码:

eval_list([Head|Tail],_,Result):-
   Tail==[], % last element of list
   Result=Head,
   write(Head),
   write(' was stored in Result!\n').

eval_list([Head|Tail],Store1,Result):-
      eval_list(Tail,Store2, NewResult),
      (\+integer(Store2))
   ->
      % if no integer is bound to Store2, bind Store1 to Head
      Store1=Head,
      Result is NewResult,
      write(Head),
      write(' is stored value!\n')
   ;  (integer(Store2)) ->
    % if an integer is bound to store2, we perform operation specified by the Head with the stored number
      X is Store2+NewResult,
      Result is X,
      write('performed operation!\n')
   ;
      % if doesnt catch either of these states the program is broken
      (  print('something broke\n'),
         print(Store1),
         nl,
         print(Store2),
         nl,
         print(Head),
         nl,
         print(Result),
         nl
      ).

我得到以下的输出:

?- eval_list([+,1,2],X,Result).
2 was stored in Result!
1 is stored value!
something broke
_G1162
_L147
+
_G1163
true.

我不明白为什么我的价值观消失,或者是否有更好的方法来评估名单。

Answer 1:

您的编程技巧的几点建议。 您应该使用头部匹配和统一,而不是明确的统一在您的谓词定义的身体,和if-else结构。 你也应该避免没有尾递归递归的,除非你的算法本质上是递归(有序树的遍历,例如)。 这将使得代码更容易写,阅读和理解。 现在,我甚至不觉得像调试代码,但它看起来像你的Store2永远不会被绑定到一个整数,并始终将是一个绑定变量,无论你的程序有什么样的输入。

现在,你的程序。 目前尚不清楚你想要达到的目的。 如果你只是想评价形式的列表[Arithmetic_operator, Operand1, Operand2] ,这将是更容易编写:

arith_eval(Expression_list, Result) :-
    Arithmetic_expr =.. Expression_list, % look up what =.. stands for!
    Result is Arithmetic_expr.

我没有看到你正在使用这种过于复杂的方法的需要。

如果您希望能够评估任意复杂的表达式,写在修复后,固定运营商元数(所以你可以说2, 3, + ,而不是2, 4, 1, + ,为7总和):

  • 阅读您输入一个元素
    • 推动元件到堆栈的顶部
    • 尽量减少堆栈:
      • 弹出操作和操作数,如果在堆栈的顶部
      • 评估
      • 推结果返回堆栈的顶部
  • 当输入为空,你的筹码是你的结果

你可以明确地定义不同的运营商(在这里,只有效果+-是这样的:

eval_stack([+,A,B|Tail],[Result|Tail]) :-
    number(A), number(B),
    !,
    Result is B + A.
eval_stack([-,A,B|Tail],[Result|Tail]) :-
    number(A), number(B),
    !,
    Result is B - A.
eval_stack(Stack,Stack).

注意无论是运营商如何您堆栈的顶部相匹配,当有它下面的操作数应用,推动将结果返回到堆栈,或堆栈保持不变。

你可以从你输入你的压栈:

evaluate([Next|Rest], Stack, Result) :-
    eval_stack([Next|Stack],NewStack),
    evaluate(Rest,NewStack,Result).
evaluate([],Result,Result). % end of input

所以,现在你可以调用此方法:

?- evaluate([2,3,+,3,6,-,+],[],Result).
Result = [2].

?- evaluate([2,3,4,-,-,5,+],[],Result).
Result = [8].

?- evaluate([2,3,4,-,-,5,+,1,3,2,-],[],Result).
Result = [1,1,8].

所以,这两个谓词, evaluate(Input,Stack,Result) ,并eval_stack(Stack,NewStack)是所有你需要评估的有效后修复算法只固定元数运算符的表达式。



文章来源: Postfix expression list evaluation