0
votes

I am trying to calculate this input:

evaluate({mul,{plus,{num,2},{num,3}},{num,4}}).

and get this as an answer:

20

But I cant get it working, here is my code:

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

Can you point out my mistakes and correct me, thank you.

1
The same problem as before, you have tuples of tuples instead of a list to operate on. This is going directly against the grain of how functional languages work. At a minimum you would want [mul, [plus, 2, 3], 4] or something similar and not a tuple of equivalent structure. If you do it this way you are essentially creating an S-expression evaluator (almost like a lisp interpreter). - zxq9
Isn't there anyway to change its format with the tuple_to_list - nothingness
Sure, and there is a way to swim the Pacific with water-wings, too. But I'd rather just get a new transportation device than fight the currents of nature alone. - zxq9

1 Answers

1
votes

First, define your syntax:

  • {num,Value} for a number,
  • {plus,Term1,Term2} for an addition,
  • {mul,Term1,Term2} for a multiplication,
  • and so on.

Second, solve individual cases:

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

in the shell:

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>

Although I used a lot the reverse polish notation, it does not apply in your example. The input should be (for your example) [ 2, 3, plus, 4, mul] and it can be solved like this:

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.

in the shell

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