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 儲存列表中的每個元素
  • 呼叫遞回尾反轉,確保最後一個元素被放入新列表的第一位置
  • 遞回呼叫尾反向列表中的每個元素