Erlang递归

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 存储列表中的每个元素
  • 调用递归尾反转,确保最后一个元素被放入新列表的第一位置
  • 递归调用尾反向列表中的每个元素