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

Ric*_*ard 2 erlang recursion

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

move([],{Main, One, Two}) ->
    {Main, One, Two};
move([X|Xr], {Main, One, Two}) ->
    [{Main, One, Two}, move(Xr, single(X, {Main, One, Two}))].
Run Code Online (Sandbox Code Playgroud)

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

[{[a,b],[],[]}, {[a],[b],[]}, {[],[b],[a]}, {[b],[],[a]}]
Run Code Online (Sandbox Code Playgroud)

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

[{[a,b],[],[]},[{[a],[b],[]},[{[],[b],[a]},[{[b],[],[a]}]]]]
Run Code Online (Sandbox Code Playgroud)

rvi*_*ing 6

你有两个问题:

  1. |不是,像@nmichaels所提到的那样.
  2. 该函数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}].
Run Code Online (Sandbox Code Playgroud)

我翻了条款的顺序,因为我个人更喜欢用这种方式写它们.在这种情况下没有根本区别.我假设single/2返回一个元组.

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

move([X|Xr], Tuple) ->
    [Tuple | move(Xr, single(X, Tuple))];
move([], Tuple) ->
    [Tuple].
Run Code Online (Sandbox Code Playgroud)