天天看点

Erlang编程风格的对比

以一道编程题为例:

要求:编写一个列表反转程序,但不使用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本身的特性。