模拟基本错误,Erlang

时间:2015-02-23 22:32:00

标签: erlang

我有一个错误,我不明白为什么。 所以,如果我输入:

  

凸出:计算值([{推,{NUM,2}},{推,{NUM,3}},{加},{推,{NUM,4}},{MUL}])

代码:

calc(List) -> 
[Res] = lists:foldl(fun calc/2, [], List),
Res.

calc({plus}, [N1, N2 | Stack]) -> [N1 + N2 | Stack];
calc({mul}, [N1, N2 | Stack]) -> [N1 * N2 | Stack];
calc({push,{num,X}}, Stack) -> [X | Stack].

我得到20的输出(完全正是我想要的)。

但如果我有这样的输入:

  

PROJ:计算值([{推,{NUM,2}},{推,{NUM,3}},{加},{弹出},{保留},{推,{NUM,4}}, {MUL},{弹出},{RET}])。

代码:

calc(List) -> 
[Res] = lists:foldl(fun calc/2, [], List),
Res.

calc({plus},{pop},{ret}, [N1, N2 | Stack]) -> [N1 + N2 | Stack];
calc({mul},{pop},{ret}, [N1, N2 | Stack]) -> [N1 * N2 | Stack];
calc({push,{num,X}}, Stack) -> [X | Stack].

我收到错误:

  

异常错误:没有匹配proj的函数子句:calc({pop},[5])

我是er lang的新手,为什么会发生这种情况,我该如何解决?

1 个答案:

答案 0 :(得分:3)

折叠,贴图或过滤器的每次迭代仅消耗列表中的一个元素。这里有三个代表单个操作的元素:{plus},{pop},{ret}。您必须将其包装在单个元组{{plus},{pop},{ret}}中,或者记住堆栈计算机在每个操作结束时隐式执行 {pop}{ret} - 所以这两项操作可以放弃。

考虑到这一点,您的代码应该以第一种方式阅读,或者像这样:

calc({{plus},{pop},{ret}}, [N1, N2 | Stack]) -> [N1 + N2 | Stack];
calc({{mul},{pop},{ret}}, [N1, N2 | Stack]) -> [N1 * N2 | Stack];
calc({push,{num,X}}, Stack) -> [X | Stack].

您的输入应为:

[{push,{num,2}},{push,{num,3}},{{plus},{pop},{ret}},{push,{num,4}},{{mul},{pop},{ret}}]

传递给map函数的函数必须是arity 2,这里你在同一个函数定义中混合了arity 4的两个子句和arity 2的一个子句 - 这在开头是不合法的。

在任何情况下,您所描述的系列都是堆栈计算机固有的,不需要拼写出来。这就是为什么您的实现看起来比大多数示例更复杂。