- Erlang 教程
- Erlang - 首页
- Erlang - 概述
- Erlang - 环境
- Erlang - 基本语法
- Erlang - Shell
- Erlang - 数据类型
- Erlang - 变量
- Erlang - 运算符
- Erlang - 循环
- Erlang - 决策
- Erlang - 函数
- Erlang - 模块
- Erlang - 递归
- Erlang - 数字
- Erlang - 字符串
- Erlang - 列表
- Erlang - 文件I/O
- Erlang - 原子
- Erlang - 映射
- Erlang - 元组
- Erlang - 记录
- Erlang - 异常
- Erlang - 宏
- Erlang - 头文件
- Erlang - 预处理器
- Erlang - 模式匹配
- Erlang - 保护条件
- Erlang - BIFS (内置函数)
- Erlang - 二进制
- Erlang - 函数 (Funs)
- Erlang - 进程
- Erlang - 邮件
- Erlang - 数据库
- Erlang - 端口
- Erlang - 分布式编程
- Erlang - OTP (开放电信平台)
- Erlang - 并发
- Erlang - 性能
- Erlang - 驱动程序
- Erlang - Web编程
- Erlang 有用资源
- Erlang - 快速指南
- Erlang - 有用资源
- 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]模式与一个或多个元素的列表匹配,长度为一的列表将定义为[X|[]],长度为二的列表将定义为[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的变量中。
然后我们递归调用tail_reverse,但是这次我们确保最后一个元素首先放入新列表中。
然后我们递归地为列表中的每个元素调用tail_reverse。