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的最后一个子句中用尽(但我将其留给读者练习)。