为何我的Erlang RPN计算器代码报‘Illegal guard expression’错误?
Erlang RPN计算器守卫表达式错误问题
我编写了一个简单的Erlang逆波兰表示法(RPN)计算器代码:
-module('Kalkulator_ONP'). -author("user"). %% API -export([onp/1]). onp(Expression) -> onp(string:tokens(Expression, " "),[]). onp([], [Result]) -> Result; onp([NumberString|Rest], Stack) when is_integer(string:to_integer(NumberString)) -> Number = string:to_integer(NumberString), onp(Rest, [Number|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "+" -> onp(Rest, [Number1+Number2|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "-" -> onp(Rest, [Number1-Number2|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "*" -> onp(Rest, [Number1*Number2|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "/" -> onp(Rest, [Number1/Number2|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "sqrt" -> onp(Rest, [math:sqrt(Number)|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "^" -> onp(Rest, [math:pow(Number1, Number2)|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "sin" -> onp(Rest, [math:sin(Number)|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "cos" -> onp(Rest, [math:cos(Number)|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "tan" -> onp(Rest, [math:tan(Number)|Stack]).
其中onp([NumberString|Rest], Stack) when is_integer(string:to_integer(NumberString)) ->这一行被IntelliJ标红,提示Illegal guard expression错误,请问此处存在什么问题?
问题原因
string:to_integer/1不属于守卫允许的内置函数:Erlang的守卫表达式(guard)有严格的语法限制,仅允许使用特定的内置函数(如is_integer/1、is_list/1等),普通函数调用不能出现在守卫中。- 返回值逻辑错误:
string:to_integer/1的返回值不是单纯的整数,解析成功时返回{Integer, 剩余字符串},失败时返回error,用is_integer/1判断这个元组或原子本身逻辑就不成立。
修正方案
把数字解析逻辑从守卫移到函数体内部,用case语句处理返回结果,同时确保整个字符串都是有效数字(剩余字符串为空):
-module('Kalkulator_ONP'). -author("user"). %% API -export([onp/1]). onp(Expression) -> onp(string:tokens(Expression, " "),[]). onp([], [Result]) -> Result; onp([NumberString|Rest], Stack) -> case string:to_integer(NumberString) of {Number, ""} -> onp(Rest, [Number|Stack]); _ -> error({invalid_token, NumberString}) end; onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "+" -> onp(Rest, [Number2 + Number1|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "-" -> onp(Rest, [Number2 - Number1|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "*" -> onp(Rest, [Number2 * Number1|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "/" -> onp(Rest, [Number2 / Number1|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "sqrt" -> onp(Rest, [math:sqrt(Number)|Stack]); onp([Operator|Rest], [Number1, Number2|Stack]) when Operator == "^" -> onp(Rest, [math:pow(Number2, Number1)|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "sin" -> onp(Rest, [math:sin(Number)|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "cos" -> onp(Rest, [math:cos(Number)|Stack]); onp([Operator|Rest], [Number|Stack]) when Operator == "tan" -> onp(Rest, [math:tan(Number)|Stack]).
额外说明:原代码中二元运算符的操作数顺序错误——逆波兰表达式里,栈顶第一个元素是右操作数,第二个是左操作数,比如3 4 +需要计算3+4,原代码的Number1+Number2会得到4+3(结果碰巧一致,但减法、除法会出错),所以调整为Number2 + Number1才符合逻辑。
内容的提问来源于stack exchange,提问作者jon
相关产品推荐
相关产品推荐

