最近接触erlang,一直在看文档和源码,终于自己尝试写点简单代码,却意外发现erlang里的编程之美。一直写C++,用惯了while,for这些循环语句。而erlang不支持变量重复赋值,因而也不支持循环语句。erlang能使用的循环结构只有递归和列表解析。erlang这里主要用的是优化的尾递归。
先看下erlang递归和尾递归的区别,如下例子:
% 递归
loop(0) ->
1;
loop(N) ->
N* loop(N-1).
% 尾递归
tail_loop(N)->
tail_loop(N,1).
tail_loop(0, R)->
R;
tail_loop(N, R) ->
tail_loop(N-1,N *R).
erlang尾递归是通过参数来传递实际结果。普通递归用到的栈空间和列表的长度成正比,尾递归不需要再次申请栈空间。
而我为了从list里取出一对,用递归手动写了个for再实现自己的fun(为了用for,其实只是递归,而不是尾递归):
break()->put(break,true).
for(List,Max,Max,Fun) -> [Fun(List,Max)];
for(List,I,Max,Fun) ->
case get(break) of
true->erase(break),[];
_->[Fun(List,I)|for(List,I+1,Max,Fun)]
end.
check_two_card(List)->
Fun=fun(List,N)->
case lists:nth(N,List)==lists:nth(N+1, List)of
true->break(),
{ok,{lists:nth(N, List),lists:nth(N,List)}};
_->false
end
end,
for(List,1,length(List)-1, Fun).
而带我的哥们看了之后,给了下面的实现,利用尾递归加列表,进行匹配。
get_pair([],ResOut)->ResOut;
get_pair([I|[I|ResIn]],ResOut)->
get_pair(ResIn,[[I,I]|ResOut]);
get_pair([H|ResIn],ResOut)->
get_pair(ResIn,ResOut).
再看看自己的冗余低效代码,打击之余,看到了erlang里的编程之美。erlang里的精髓还待学习。前路漫漫,多发现一些编程之美!!!