开发学院

您的位置:首页>教程>正文

教程正文

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 存储列表中的每个元素

  调用递归尾反转,确保最后一个元素被放入新列表的第一位置

  递归调用尾反向列表中的每个元素