Erlang - 递归后列表/元组层次结构的问题

时间:2011-10-31 14:38:18

标签: recursion erlang

这个递归的结果树不是我的意思,这可能证明我不完全理解递归中列表/元组的行为。如果有人可以解释我在这个例子中做错了什么,并解释了正确的思考方式我会非常感激。

move([],{Main, One, Two}) ->
    {Main, One, Two};
move([X|Xr], {Main, One, Two}) ->
    [{Main, One, Two}, move(Xr, single(X, {Main, One, Two}))].

期望的结果(一个包含3个元组的列表):

[{[a,b],[],[]}, {[a],[b],[]}, {[],[b],[a]}, {[b],[],[a]}]

实际结果(包含元组和列表的列表,包含元组和列表......):

[{[a,b],[],[]},[{[a],[b],[]},[{[],[b],[a]},[{[b],[],[a]}]]]]

2 个答案:

答案 0 :(得分:6)

你有两个问题:

  1. {@ 1}}代替|,如@nmichaels所述。
  2. 函数,返回列表,因此终止子句也必须返回一个列表。在您的示例中没有看到这一点,因为第一个问题隐藏了它。
  3. 结果代码如下:

    move/2

    我翻了条款的顺序,因为我个人更喜欢这样写。在这种情况下没有根本区别。我假设move([X|Xr], {Main, One, Two}) -> [{Main, One, Two} | move(Xr, single(X, {Main, One, Two}))]; move([], {Main, One, Two}) -> [{Main, One, Two}]. 返回一个元组。

    您实际上可以通过从single/2中删除元组的所有知识来优化此代码,因为它实际上从未使用内部结构。所以:

    move/2

答案 1 :(得分:0)

在撰写像这样的列表时,您希望使用|而不是,

move([X|Xr], {Main, One, Two}) ->
    [{Main, One, Two} | move(Xr, single(X, {Main, One, Two}))].

递归调用会返回一个列表,除非您使用|将它们展平,否则它将更深入地嵌套。它与模式匹配[X|Xr]中的概念相同,只是反向操作。