【问题标题】:Calculate input with atoms, erlang用原子计算输入,erlang
【发布时间】:2015-04-27 08:19:46
【问题描述】:

我正在尝试计算这个输入:

评估({mul,{plus,{num,2},{num,3}},{num,4}})。

并得到这个答案:

20

但我不能让它工作,这是我的代码:

evaluate(List) -> 
[Res] = lists:foldl(fun evaluate/2, [], tuple_to_list(List)),
Res.
evaluate({num,X},Stack) -> [X|Stack];
evaluate(plus,[N1,N2|Stack])->[N1+N2|Stack];
evaluate(mul,[N1,N2|Stack])->[N1*N2|Stack];
evaluate([{Optr, Num1, Num2}],Stack) ->
evaluate(Num1,Stack),evaluate(Num2,Stack),evaluate(Optr,Stack).

你能指出我的错误并纠正我吗,谢谢。

【问题讨论】:

  • 和以前一样的问题,你有元组的元组而不是一个列表来操作。这直接违背了函数式语言的工作原理。至少你会想要[mul, [plus, 2, 3], 4] 或类似的东西,而不是等效结构的元组。如果你这样做,你实际上是在创建一个 S 表达式评估器(几乎就像一个 lisp 解释器)。
  • 反正没有用 tuple_to_list 改变它的格式
  • 当然,还有一种用水翼游过太平洋的方法。但我宁愿买一个新的交通工具也不愿独自对抗大自然的潮流。

标签: erlang evaluation


【解决方案1】:

首先,定义你的语法:

  • {num,Value} 表示数字,
  • {plus,Term1,Term2} 用于添加,
  • {mul,Term1,Term2} 用于乘法,
  • 等等。

二、解决个案:

evaluate({num,Value}) -> Value;
evaluate({plus,Term1,Term2}) -> evaluate(Term1) + evaluate(Term2);
evaluate({mul,Term1,Term2}) -> evaluate(Term1) * evaluate(Term2).

在外壳中:

1> E = fun E({num,Value}) -> Value;
1> E({plus,Term1,Term2}) -> E(Term1) + E(Term2);             
1> E({mul,Term1,Term2}) -> E(Term1) * E(Term2)  
1> end.
#Fun<erl_eval.30.90072148>
2> E({mul,{plus,{num,2},{num,3}},{num,4}}).
20
3>

虽然我使用了很多反向波兰符号,但它不适用于您的示例。输入应该是(对于你的例子)[ 2, 3, plus, 4, mul],它可以像这样解决:

evaluate(plus,[A,B|Rest]) -> [A+B|Rest];
                             % pop operands,perform  the operation and push the result
evaluate(mul,[A,B|Rest]) -> [A*B|Rest];
evaluate(A,Acc) when is_number(A) -> [A|Acc]. % push operand on the stack

evaluate(Exp) -> [Res] = lists:foldl(evaluate/2,[],Exp), Res.

在外壳中

22> E = fun E(plus,[A,B|Rest]) -> [A+B|Rest];   
22> E(mul,[A,B|Rest]) -> [A*B|Rest];            
22> E(A,Acc) -> [A|Acc]                         
22> end.                                        
#Fun<erl_eval.36.90072148>
23> Eval = fun(Exp) -> [Res] = lists:foldl(E,[],Exp), Res end.
#Fun<erl_eval.6.90072148>
24> Eval([2,3,plus,4,mul]).                                   
20

【讨论】:

    猜你喜欢
    • 2012-09-25
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 2018-04-15
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多