当前位置: 首页 > 文档资料 > Erlang 中文教程 >

递归

优质
小牛编辑
131浏览
2023-12-01

递归是Erlang的重要组成部分。 首先让我们看看如何通过实现阶乘程序来实现简单的递归。

例子 (Example)

-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)来定义递归函数。

上述计划的输出是 -

输出 (Output)

24

递归的实用方法

在本节中,我们将详细了解不同类型的递归及其在Erlang中的用法。

长度递归

通过一个用于确定列表长度的简单示例,可以看到更实用的递归方法。 列表可以有多个值,例如[1,2,3,4]。 让我们使用递归来看看我们如何获得列表的长度。

Example

-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。

上述计划的输出将是 -

Output

4

尾递归

要了解尾递归的工作原理,让我们理解上一节中的以下代码是如何工作的。

Syntax

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

1 + len(Rest)的答案需要找到len(Rest)的答案。 然后函数len(Rest)本身需要找到另一个函数调用的结果。 添加将被堆叠,直到找到最后一个,然后才会计算最终结果。

尾递归旨在通过在它们发生时减少它们来消除这种堆叠操作。

为了实现这一点,我们需要在函数中保存一个额外的临时变量作为参数。 上述临时变量有时称为累加器,并作为存储计算结果的地方,以限制我们的调用增长。

让我们看一下尾递归的例子 -

Example

-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]).

上述计划的输出是 -

Output

4

Duplicate

我们来看一个递归的例子。 这一次让我们编写一个函数,它以整数作为第一个参数,然后将任何其他术语作为第二个参数。 然后,它将创建一个由整数指定的术语副本的列表。

让我们看一下这个例子的样子 -

-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).

上述计划的输出将是 -

输出 (Output)

1,
1,
1,
1,
1,

列出逆转

在Erlang中没有可以使用递归的界限。 现在让我们快速看看如何使用递归来反转列表的元素。 以下程序可用于实现此目的。

例子 (Example)

-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]).

上述计划的输出将是 -

输出 (Output)

[4,3,2,1]

关于上述计划需要注意以下事项 -

  • 我们再次使用临时变量的概念将List的每个元素存储在一个名为Acc的变量中。

  • 然后我们递归调用tail_reverse ,但这一次,我们确保最后一个元素首先放在新列表中。

  • 然后我们递归地为列表中的每个元素调用tail_reverse。