我想摆脱列表中的所有元组,例如.
我有这样的东西作为输入
test:stack({push, [{{mul,{plus,{num,2},{num,3}},{num,4}},[]}]}, []).
%% note: (returns wrong output because of the multiple tuples brackets)
如果我有这样的事情:
proj:stack({push, [mul,plus,{num,2},{num,3},{num,4}]}, []).
%% this would return:
%% [{push,{num,4}},{push,{num,3}},{push,{num,2}},
%% {push,plus},{push,mul}]
%% This is near to what I need.
我的代码是这样的:
stack({push, []}, StackList) -> StackList;
stack({push,[H|T]}, StackList) ->
stack({push, T}, [{push,H} | StackList]).
我希望实现这样的目标:
{push, {num, 4}}, {push, {num, 3}},
{push, {num, 2}}, {add}, {mul}, {pop}, {ret}
我想过使用过滤器来实现这个目标,但也许是其他的东西?
1> zxq9..:
评论太大了.咩...
这看起来很像你正在尝试构建一个堆栈机器,在这种情况下可能是一个计算器.在LYSE中有一个很好的RPN示例演练,我强烈建议你看一下.它没有处理这种特定的语法,但它演示了如何使用函数头中的匹配来累积一组消耗性操作.
您必须决定的是元素的语义.现在你有元组元组的元组 - 这不是元组的用途.形式的元组{Operation, Operand}
或{Operation, Operand1, Operand2}
完美的意义 - 它们在语义上是截然不同的 - 但是形式的元组{OperationZ, {OperationX, Operand}, {OperationQ, Operand1, Operand2}}
没有任何意义,因为元组的每个元素应该具有不同的含义.在这里,您刚刚嵌套了一堆元组,这些元组具有自己的意义到一个更大的元组中,而这个元组本身现在只是混淆了.
解决方案是使用列表,而不是元组.如果你更进一步,而不是使用"push/pop"作为他们自己的操作,考虑完全展开你的元组,并根据系统基础的规则集,按照自己的条件处理列表的每个元素.因此,而不是将值包装在{push, 4}
您的供应中,4
因为隐式操作总是推送(或弹出,取决于您的观点...更好,实际上,放弃这个概念,因为堆栈已经作为输入存在).
从上面的例子中提取:
[{push,{num,4}},{push,{num,3}},{push,{num,2}},{push,plus},{push,mul}]
会成为
[4, 3, 2, add, mul]
这可以解释为没有歧义,我们不需要混淆push
和num
标识符:
-module(rpn).
-export([calc/1]).
calc(List) ->
[Res] = lists:foldl(fun calc/2, [], List),
Res.
calc(mul, [N1, N2 | Stack]) -> [N1 * N2 | Stack];
calc(add, [N1, N2 | Stack]) -> [N1 + N2 | Stack];
calc(X, Stack) -> [X | Stack].
希望这说明不仅仅是困惑.请记住,您可以将所有内容都包含在元组中并匹配元组标记和值变量,但这不是必需的.上面的代码根本没有类型检查,但是如果你向元素添加标签(但不嵌套元组),那么你可以使用这些标签作为类型标记的形式(如果你收到错误的标签就会立即崩溃,或者跳过任何意想不到的事情) - 但这意味着您需要在语义上进一步备份:
[{num, 4}, {num, 3}, {num, 2}, {op, add}, {op, mul}]
刚刚玩这个有点使代码变得复杂到一定程度,我真的宁愿只使用防护装置,如果输入不好就会提前崩溃.