erlang迴圈結構 尾遞迴,列表解析

2021-09-01 22:53:32 字數 2035 閱讀 1792

最近看到一道erlang面試題,要求分別用尾遞迴,lists模組,列表解析找出0-9的偶數。

-module(test).  

-export([tail_loop/0, lists_func/0, list_comp/0]).

% 尾遞迴

tail_loop() ->

tail_loop( get_num(), ).

tail_loop(, list) ->

list;

tail_loop([f | other], list) ->

tail_loop( other, list ++ (if f rem 2 == 0 -> [f]; true -> end) ).

% lists模組

lists_func() ->

lists:foldl(fun(x, list) ->

if x rem 2 == 0 -> list ++ [x];

true -> list

endend, , get_num()).

% 列表解析

list_comp() ->

[x || x<- get_num(), x rem 2 == 0].

% 生成0到9的數字

get_num() ->

lists:seq(0,9).

我們知道,erlang不支援變數重複賦值,因而也不支援迴圈語句。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尾遞迴是通過引數來傳遞實際結果。普通遞迴用到的棧空間和列表的長度成正比,尾遞迴不需要再次申請棧空間。如果遞迴的次數過多,顯然尾遞迴比較合適。至於說哪個遞迴速度快,erlang說法有爭議

it depends. on solaris/sparc, the body-recursive function seems to be slightly faster, even for lists with very many elements. on the x86 architecture, tail-recursion was up to about 30 percent faster.

接下來看看erlang列表解析,看個例子:

1> [x || x <- [1,2,a,3,4,b,5,6]].

[1,2,a,3,4,b,5,6]

2> [x || x <- [1,2,a,3,4,b,5,6], x > 3].

[a,4,b,5,6]

3> [x || x <- [1,2,a,3,4,b,5,6], integer(x), x > 3].

[4,5,6]

4> [ || x <- [1,2,3], y <- [a,b]].

[,,,,,]

在erlang列表解析表示式中,|| 左邊用以生成列表元素,相當於構造器;右邊由賦值語句和條件語句構成,也可以只有賦值語句。

實際上,erlang列表解析在執行時會轉換成乙個臨時函式

% 列表解析

[expr(e) || e <- list]

% 解析成的臨時函式

'lc^0'([e|tail], expr) ->

[expr(e)|'lc^0'(tail, expr)];

'lc^0'(, _expr) -> .

總的來說,列表遞迴函式和尾遞迴加反轉沒有太大差別。因此,可以忽略列表函式的效能損失(r12b)。

參考

erlang雜記十二 再說尾遞迴

翻了一下list模組,看的時候,突然發現,尾遞迴其實是很容易展開成迴圈的。想起讀書時剛開始學程式,c語言,一直再糾結的乙個問題,就是如何讓乙個函式返回兩個引數的結果,哈哈,不要笑我。do sth sa,sb do sth ha ta la,hb tb lb,sa,sb do sth ta,tb,ha...

用尾遞迴優化Erlang的lists map

用尾遞迴優化erlang的lists map erlang的lists庫中的map函式是這樣寫的 spec map 2 fun d r d r map f,h t f h map f,t map f,when is function f,1 顯然這裡有個問題,f h map f,t 這句沒有用為遞迴...

一般遞迴 尾遞迴 迴圈遞迴

階乘的一般遞迴 int factorial int n 階乘的尾遞迴 int factorial tail int n,int res 階乘的迭代形式 int factorial loop int n 斐波那契數列的一般遞迴 int fibonacci int n 斐波那契數列的尾遞迴 int fi...