Erlang递归
精华
小牛编辑
118浏览
2023-03-14
递归是 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 存储列表中的每个元素
-
调用递归尾反转,确保最后一个元素被放入新列表的第一位置
-
递归调用尾反向列表中的每个元素