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
[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