Functional programming 关于erlang和函数式编程的不重要问题

Functional programming 关于erlang和函数式编程的不重要问题,functional-programming,erlang,Functional Programming,Erlang,我偶然发现,我意识到我在非程序编程课上忘了很多东西 当我试图理解代码时,我觉得它太冗长了,所以我试图缩短它。这与原始代码的功能相同吗 merge([X|Xs], Ys) -> [X | merge(Ys, Xs)]; merge([], []) -> []. 。。。我以前从未使用过erlang,因此可能会出现一些语法错误:-)是的,它工作正常。而且它在表现上更优雅。但是,如果我学习正确,不使用Zs变量作为累加器会使它不是尾部递归的,因此效率较低。此外,与累加器一起使用倒档比按正确顺

我偶然发现,我意识到我在非程序编程课上忘了很多东西

当我试图理解代码时,我觉得它太冗长了,所以我试图缩短它。这与原始代码的功能相同吗

merge([X|Xs], Ys) -> [X | merge(Ys, Xs)];
merge([], []) -> [].

。。。我以前从未使用过erlang,因此可能会出现一些语法错误:-)

是的,它工作正常。而且它在表现上更优雅。但是,如果我学习正确,不使用Zs变量作为累加器会使它不是尾部递归的,因此效率较低。此外,与累加器一起使用倒档比按正确顺序将其附加在一起更有效。我相信,这就是为什么原文在某些情况下更为恰当的原因。但在效率无关紧要的地方,可读性应该胜过效率

也许:

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

merge([X|Xs], Ys, Zs) -> merge(Ys, Xs, [X|Zs]);
merge([], [], Zs) -> Zs.
这将把原文的效率与你的简明易懂结合起来。

你可以更进一步:

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

merge1([], [], Zs)             -> Zs.
merge1([X | Xs], [Y | Ys], Zs) -> merge1(Xs, Ys, [X, Y | Zs]).
这比feonixrift建议您不切换参数顺序(这违反了最小意外原则)有相当大的优势

给helper函数(在本例中为merge1)一个不同的名称也是一个很好的实践,因为这样更容易发现arity的变化。例如,如果未导出merge/2和merge1/3,则尤其如此。它基本上是说“我只是一个助手fn不要直接给我打电话!”


首先编写所需的terminator子句也很方便,因为这使递归的性质变得明确——只要阅读函数定义,就会知道这个fn在列表耗尽时终止。

如果我将列表与空列表合并,这段代码会返回原始列表吗?模式匹配在我看来并不完整。最初的任务是针对两个长度相同的列表Cube是正确的-如果您尝试在两个长度不等的列表上运行原始代码,它将失败。terminal子句在合并时匹配([]、[]、Zs)。如果Xs和Ys的长度不同,则会因一个列表在另一个列表之前耗尽而出错。