Erlang遞歸

遞歸是 Erlang 的重要組成部分。首先,讓我們通過實現階乘程式來瞭解簡單的遞歸。

示例

-module(helloworld).
-export([fac/1,start/0]).

fac(N) when N == 0 -> 1;
fac(N) when N > 0 -> N*fac(N-1).

start() ->
   X = fac(4),
   io:fwrite("~w",[X]).
對於上面的例子,有以下幾點需要注意 -
  • 我們首先定義一個函數 fac(N);
  • 我們可以通過定義遞歸函數 fac(N) 遞歸;
上面的代碼的輸出結果是 -
24

實用方法遞歸

在本節中,我們將詳細瞭解不同類型的遞歸及其在 Erlang 中的使用。

長度遞歸

以遞歸一個更有效的方法可以用於確定一個列表的長度,現在來看看一個簡單的例子。列表中有多個值,如[1,2,3,4]。
讓我們用遞歸的方法來看看如何能夠得到一個列表的長度。

示例

-module(helloworld).
-export([len/1,start/0]).

len([]) -> 0;
len([_|T]) -> 1 + len(T).

start() ->
   X = [1,2,3,4],
   Y = len(X),
   io:fwrite("~w",[Y]).
以下是上述程式需要說明的一些關鍵點 -
  • 第一個函數 len([]) 用於特殊情況的條件:如果列表為空。
  • [H|T] 模式來匹配一個或多個元素的列表,如長度為1的列表將被定義為 [X|[]],而長度為 2 的列表將被定義為 [X|[Y|[]]] 。
    注意,第二元素是列表本身。這意味著我們只需要計數第一個,函數可以調用它本身在第二元素上。在列表給定每個值的長度計數為 1 。
上面的代碼的輸出結果是 -
4

尾部遞歸

要瞭解尾遞歸是如何工作的,讓我們來瞭解下麵的代碼在上一節中是如何工作的。

語法

len([]) -> 0;
len([_|T]) -> 1 + len(T).
回答 1 + len(Rest) 需要 len(Rest) 。函數 len(Rest) 根據需要自行調用另一個函數的結果。該補充將得到堆積,直到最後一個被發現,然後才會計算最終結果。尾遞歸旨在通過減少它們,以消除這種操作堆疊。
為了達到這個目的,我們將需要保持一個額外的臨時變數作為函數的一個參數。上述臨時變數有時被稱為累加器並用來存儲計算的結果,因為它們會限制調用增長。
讓我們來看看尾遞歸的一個例子 -

示例

-module(helloworld).
-export([tail_len/1,tail_len/2,start/0]).

tail_len(L) -> tail_len(L,0).
tail_len([], Acc) -> Acc;
tail_len([_|T], Acc) -> tail_len(T,Acc+1).

start() ->
   X = [1,2,3,4],
   Y = tail_len(X),
   io:fwrite("~w",[Y]).
上面的代碼的輸出結果是 -
4

重複(複本)

讓我們來看看遞歸的例子。這一次我們寫一個函數,它接受一個整數作為其第一個參數,然後有一個其他子句作為其第二個參數。它將由整數指定創建多個副本的列表。
讓我們來看看這個例子如下 -
-module(helloworld).
-export([duplicate/2,start/0]).

duplicate(0,_) ->
   [];
duplicate(N,Term) when N > 0 ->
   io:fwrite("~w,~n",[Term]),
   [Term|duplicate(N-1,Term)].
start() ->
   duplicate(5,1).
上面的代碼的輸出結果是 -
1,
1,
1,
1,
1,

列表反轉

有無止境的在 Erlang 中使用遞歸。讓我們現在快速地來看看如何使用遞歸來反轉列表的元素。
下麵的程式可用於實現此目的。

示例

-module(helloworld).
-export([tail_reverse/2,start/0]).

tail_reverse(L) -> tail_reverse(L,[]).

tail_reverse([],Acc) -> Acc;
tail_reverse([H|T],Acc) -> tail_reverse(T, [H|Acc]).

start() ->
   X = [1,2,3,4],
   Y = tail_reverse(X),
   io:fwrite("~w",[Y]).
上面的代碼的輸出結果是 -
[4,3,2,1]
以下是上述程式需要說明的一些關鍵點 -
  • 我們再次使用臨時變數 Acc 存儲列表中的每個元素
  • 調用遞歸尾反轉,確保最後一個元素被放入新列表的第一位置
  • 遞歸調用尾反向列表中的每個元素

上一篇: Erlang模組 下一篇:無