English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Erlang 再帰

再帰はErlangの重要な部分です。まず、 factorial プログラムを実装することで簡単な再帰を実現する方法を見てみましょう。

-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つまたは複数の要素のリストをマッチングし、長さが1のリストは[X|[]]と定義され、長さが 2 のリストは[X|[Y|[]]]と定義されます。  

  • 注意、2番目の要素はリスト自体です。これは、1番目の要素のみをカウントし、関数が2番目の要素で自分自身を呼び出す必要があることを意味します。リストの各値の長さをカウントする場合、 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

複本

このように再帰の例を見てみましょう。今度は、整数を第1引数として、他の要素を第2引数として受け取る関数を書きます。それから、整数で指定されたテーマの複本のリストを作成します。

このような一例を見てみましょう-

-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' という名前の変数に格納します。

    その後、tail_reverse を再帰的に呼び出しますが、このたびは最後の要素をまず新しいリストに配置します。

    その後、リストの各要素に対して tail_reverse を再帰的に呼び出します。