以一道编程题为例:
要求:编写一个列表反转程序,但不使用lists:reverse.
[1,2,3,...,5] ->[5,...,3,2,1]
示例1:
通过模式匹配,一个函数名实现。
注意:这里其实是两个函数(参数个数不同的两个同名函数)。
优点:代码简洁
缺点:可读性不高。明明是两个函数,却取了同一个名字,感觉怪怪的。
-module(test).
-export([my_reverse/1]).
my_reverse(L) -> my_reverse(L, []).
my_reverse([H|T], Result) -> my_reverse(T, [H|Result]);
my_reverse([], Result) -> Result.
示例2:
分层设计,将入口调用函数(my_reverse/1)和处理过程函数(middle_reverse/2)分开.
处理过程使用一个函数调用过程,内部通过if来进行判断进入不同的分支。
优点:代码分层,可读性强。
缺点:处理过程函数使用if,没有充分利用好erlang模式匹配的天性,而且那个true让人感觉怪怪的。
-module(test).
-export([my_reverse/1]).
my_reverse([]) -> [];
my_reverse(L) -> middle_reverse(L, []).
middle_reverse([H|T], ResultList) ->
if
T =:= [] -> [H|ResultList];
true -> middle_reverse(T, [H|ResultList])
end.
示例3:
分层设计,将入口调用函数(my_reverse/1)和处理过程函数(middle_reverse/2)分开.
处理过程通过两个函数入口模式匹配(而不是if)来实现。
优点:代码分层,可读性强。
缺点:无, Erlang风格,这不算缺点了,如果说有,就是这种风格没有if那么符合其他类C语言的阅读习惯。
-module(test).
-export([my_reverse/1]).
my_reverse([]) -> [];
my_reverse(L) -> middle_reverse(L, []).
middle_reverse([H|T], ResultList) when T =:= [] -> [H|ResultList];
middle_reverse([H|T], ResultList)-> middle_reverse(T, [H|ResultList]).
其实这三个编程示例,都是我先后不同时间对同一道题给出的答案。发现其中的变化,于是就整理了一下。
个人更为喜欢示例3这种风格的代码编写习惯,清晰简洁,而又符合Erlang本身的特性。