Cesarini和Thomson撰写的Erlang编程的第90页上有一个没有详细讨论的示例。我是函数式编程和递归思维的新手,所以我对以这种方式解决问题并不熟悉。

“例如,以下函数通过交织合并两个(相同长度的)列表
他们的价值观:

merge(Xs,Ys) -> lists:reverse(mergeL(Xs,Ys,[])).

mergeL([X|Xs],Ys,Zs) ->  mergeR(Xs,Ys,[X|Zs]);
mergeL([],[],Zs) ->  Zs.

mergeR(Xs,[Y|Ys],Zs) ->  mergeL(Xs,Ys,[Y|Zs]);
mergeR([],[],Zs) ->  Zs.


这是如何运作的?谢谢!

最佳答案

首先调用此函数:

merge(Xs,Ys) -> lists:reverse(mergeL(Xs,Ys,[])).


传递给mergeL的空列表[]是累加器-这就是答案的来源。请注意,第一个函数调用mergeL-左合并。

让我们假装此函数的调用方式如下:

merge([1, 2, 3], [a, b, c])


两个长度相同的列表。然后,第一个函数调用mergeL:

mergeL([X|Xs],Ys,Zs) ->  mergeR(Xs,Ys,[X|Zs]);
mergeL([],[],Zs) ->  Zs.


左合并中有2个子句。对带有参数的mergeL的调用将按自上而下的顺序匹配这些子句。

这些子句中的第二个具有三个参数-其中的前两个是空列表[]。但是,第一次调用mergeL时,这两个列表不是空的,它们是列表Xs和Ys,因此第一个子句匹配。

让我们打破比赛。这是对mergeL的调用:

mergeL([1、2、3],[a,b,c],[])

它以以下方式匹配第一个子句:

X = 1
Xs = [2, 3]
Ys = [a, b, c]
Zs = []


这是由于列表的特殊形式:

[X | Xs]


这意味着将X与列表的开头(单个项)匹配,并使Xs成为列表的尾部(列表)。

然后,我们建立新的函数调用。我们可以将值X添加到列表Zs的开头,就像我们对其进行模式匹配的方式一样,因此我们得到了第一个mergeR调用:

mergeR([2,3],[a,b,c],[1])

最后一个参数是一个单项列表,该列表是通过在空列表的开头添加一个项引起的。

这会一直持续到最后。

实际上,mergeL的最后一个子句是多余的。根据定义,此功能将在mergeR的最后一个子句中用尽(但我将其留给读者练习)。

09-11 08:11