首页 > 其他分享 >Erlang 学习之第三天 . 函数,模块,递归,数字,字符串

Erlang 学习之第三天 . 函数,模块,递归,数字,字符串

时间:2024-02-05 11:36:38浏览次数:17  
标签:调用 函数 递归 sum 模块 fac Erlang

Erlang 函数

Erlang是一种众所周知的函数式编程语言,因此您将看到许多关于函数如何在Erlang中工作的重点。本章介绍如何使用Erlang中的函数完成所有操作。

直接上实例: 定义函数

add(X,Y) -> 
   Z = X+Y, 
   io:fwrite("~w~n",[Z]). 
start() -> 
   add(5,6).
结果打印为11

直接上实例: 匿名函数  匿名函数是一个函数,但它没有与任何名称相关联。在 Erlang 中有工具可以用来定义匿名函数。以下的程序是一个匿名函数的一个实例。

start() -> 
   Fn = fun() -> 
      io:fwrite("Anonymous Function") end, 
   Fn().
结果打印为 Anonymous Function


函数使用序列 在 Erlang 中函数也都有保护序列的能力。这些都不算什么它只不过是一个表达式,只有当评估(计算)为 true 时函数才运行。
实例:
add(X) when X>3 ->     io:fwrite("~w~n",[X]).  start() ->     add(4).

上面的代码的输出结果是  4
如果 add 函数被调用为 add(3),该程序将会出现错误。
 

Erlang 模块

模块是在单个文件中以单个名称重新组合的一组函数。此外,Erlang中的所有函数都必须在模块中定义。模块中定义的每个其他函数都需要使用 Module: Function (Arguments) 的形式来调用。

Erlang 递归

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

普通递归语法实例1:

-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]).    输出结果是  24   4*3*2*1  

在这个示例中,fac/1函数计算了输入参数为4的阶乘,即4!。阶乘的计算规则是将给定的整数与比它小的所有正整数相乘,直到1为止。

  1. N等于4时,fac/1函数首先判断N不等于0,然后根据第二个定义分支,将4乘以fac(N-1)。这里N-1是3。
  2. 然后,函数继续递归调用fac/1函数来计算3的阶乘。在计算3的阶乘时,函数会将3乘以fac(N-1),即2。
  3. 接着,函数继续递归调用fac/1函数来计算2的阶乘。在计算2的阶乘时,函数会将2乘以fac(N-1),即1。
  4. 然后,函数继续递归调用fac/1函数来计算1的阶乘。在计算1的阶乘时,函数会将1乘以fac(N-1),即0。
  5. 最后,当N等于0时,递归调用结束,函数返回1。

根据阶乘的计算规则,4! = 4 × 3 × 2 × 1 = 24。因此,最终的结果是24。

普通递归语法实例2:

-module(recursion_demo).
-export([sum/1, test_normal/0]).

 

% 普通递归求列表的和
sum([]) -> 0;
  sum([H|T]) -> H + sum(T).

% 测试普通递归
test_normal() ->
  List = [1, 2, 3, 4, 5],
  Result = sum(List),
  io:format("Sum of the list: ~p~n", [Result]).

根据相加的计算规则,5+4+3+2+1  结果是15

 

尾递归语法实例:

-module(tail_recursion_demo).
-export([sum/1, test_tail/0]).

 

% 尾递归求列表的和
sum(List) -> sum(List, 0).

sum([], Acc) -> Acc;
  sum([H|T], Acc) -> sum(T, H + Acc).

% 测试尾递归
test_tail() ->
  List = [1, 2, 3, 4, 5],
  Result = sum(List),
  io:format("Sum of the list: ~p~n", [Result]).

根据相加的计算规则,5+4+3+2+1  结果是15

 

优缺点说明:

普通递归和尾递归在Erlang中的实现方式略有不同,以下是它们的语法和优缺点:

  1. 普通递归:

    • 语法:普通递归是通过函数调用自身来实现的。在函数体内部,需要有一个递归终止条件,以防止无限递归。
    • 优点:
      • 实现简单,易于理解。
      • 适用于大多数递归场景。
    • 缺点:
      • 对于大规模数据或者递归层次较深的情况,可能会导致栈溢出。
      • 每次递归调用都需要保留函数调用栈,消耗内存较大。
  2. 尾递归:

    • 语法:尾递归是一种特殊的递归形式,其递归调用是函数体的最后一个操作,并且这个调用的返回值直接返回给函数的调用者。尾递归调用不会在函数返回之前执行其他操作。
    • 优点:
      • 在Erlang中,尾递归可以被优化为迭代,不会导致栈溢出,因此更适合处理大规模数据或递归层次深的情况。
      • 函数调用的开销较小,节省内存空间。
    • 缺点:
      • 有时候不太直观,对于一些复杂的逻辑可能需要重新设计以使用尾递归。

         尾递归在Erlang中是一种重要的优化手段,可以有效避免普通递归中可能出现的栈溢出问题,提高程序的稳定性和性能。

尾递归函数定义:

  • 尾递归函数的定义需要满足两个条件:函数体内部的递归调用是函数体的最后一个操作,并且递归调用的返回值直接返回给函数的调用者。
  • 定义格式:
            • func_name(Parameters, Accumulator) ->
                % 递归终止条件
                if
                  Termination_condition -> Accumulator;
                  true -> func_name(NewParameters, NewAccumulator) % 尾递归调用
              end.

 尾递归的调用: 1,在尾递归函数中, 递归调用通常是 在 true 分支的 if 表达式中进行的 

         2,尾递归调用的返回值直接返回给函数的调用者,而不是要进行其他的操作,或者对返回的值进行进一步处理

参数传递: 1,尾递归函数通常使用一个累加器 (Acc) 参数来保存中间的结果,每次递归调用时,都会跟新累加器的值.

       2,参数的传递,通常需要包含原始参数 以及累加器的参数, 这样在每次的递归调用时 都可以传递跟新后的参数.

-module(tail_recursion).
-export([length/1, start/0]).

length(List) -> length(List, 0).
length([], Acc) -> Acc;
length([_|T], Acc) -> length(T, Acc + 1).

start() ->
  List = [1, 2, 3, 4, 5],
  Size = length(List),
  io:format("Length of the list: ~w~n", [Size]).

 

Erlang 数字

eralng中  数字有两种类型,  整数,浮点数

Erlang 字符串

通过将字符串文本括在引号中,可以在Erlang中构造一个字符串文字。需要使用双引号(例如“ Hello World”)构造Erlang中的字符串。





























标签:调用,函数,递归,sum,模块,fac,Erlang
From: https://www.cnblogs.com/dw166/p/18007456

相关文章

  • Nginx--安装模块
    一 安装系统自带模块#进入安装目录[root@localhost~]#cdnginx-1.18.0/#查看原来的编译选项[[email protected]]#nginx-V#查看安装的模块[[email protected]]#./configure--help#以http_v2_module为例[[email protected]]#./confi......
  • PyTorch下,使用list放置模块,导致计算设备不一的报错
    报错在复现Transformer代码的训练阶段时,发生报错:RuntimeError:Expectedalltensorstobeonthesamedevice,butfoundatleasttwodevices,cuda:0andcpu!解决方案通过next(linear.parameters()).device确定model已经在cuda:0上了,同时输入model.forward()的......
  • 在PowerShell中管理Windows映像主要涉及到DISM模块的Cmdlets。这些Cmdlets提供了一系
    在PowerShell中管理Windows映像主要涉及到DISM模块的Cmdlets。这些Cmdlets提供了一系列功能,包括挂载(加载)、卸载(卸下)映像,添加或删除驱动程序,应用更新等。以下是一些常用的Cmdlets和它们的参数,以及相应的实例。常用CmdletsMount-WindowsImage-ImagePath:指定WIM文件的路径。-I......
  • 洛谷题单指南-递推与递归-P1002 [NOIP2002 普及组] 过河卒
    原题链接:https://www.luogu.com.cn/problem/P1002题意解读:从A(0,0)点走到B(n,m)点,只能向右或者向下,C点以及其控制点不能走。解题思路:根据题意,此题要么递归(DFS),要么递推(动态规划)先分析数据规模,最大从起点到终点要走40步,每个步有2种走法,一共240种路径,DFS会超时,且方案数必须用longlong......
  • c++20模块化编程与传统区别
    传统:main.cpp+a.cpp(存放定义)+a.h(存放声明)c++20:main.cpp+a.cppm(存放定义,在定义前面写export即可)模块化编程好处:不再需要修改了函数到对应修改声明,两头跑编译更快,模块只在修改后才重新编译模块化编程举例://my_module.cppmimport<iostream>;exportm......
  • 【洛谷 P2249】【深基13.例1】查找(向量+二分查找+递归)
    【深基13.例1】查找题目描述输入个不超过的单调不减的(就是后面的数字不小于前面的数字)非负整数,然后进行次询问。对于每次询问,给出一个整数,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出。输入格式第一行个整数和,表示数字个数和询问次数。第二行......
  • Shell 避免无限递归
    在编写Shell脚本时,有时会产生我们不期望的递归。比如说,我曾经写过一个脚本,名为foo.sh。foo.sh的内容如下:functionfoo{#TODO}foo然后我在.zshrc里设置了别名:aliasfoo="source~/foo.sh"现在,当我在终端运行foo时,就会得到如下错误:/Users/undefined443/foo......
  • SpringBoot 多模块开发 笔记(一)
    多模块开发简易版dao层也可以说是Mapper层web层将controller放在这一层还有统一返回类型和自定义异常也在放在这里启动类也放在这里model层也就是数据对象比如常见的User类server层业务逻辑层或者说service层更好创建步骤创建一个正常的Spr......
  • Linux基础47 Ansible之ad-hoc, 命令模块(command, shell, script), 软件管理模块(yum,
    Ansible之ad-hoc一、什么是ad-hoc1.什么是ad-hocad-hoc简而言之就是“临时命令”,执行完即结束,并不会保存2.ad-hoc使用场景可以用作查看远程机器的进程,或者磁盘,或者拷贝文件3.ad-hoc命令使用[root@m01~]#ansibleweb01-mshell-a'free-m'web01|CHANGED|rc=......
  • erlang学习笔记一
    Elang是一种函数式编程语言,具有一些独有的数据类型和数据结构.以下是Erlang中的常见数据类型和数据结构.1.Atom(原子):Atom是一个不可变的符号常量,用于表示标识符和常量.Atom以小写字符开头,可以包含字母,数字,下划线和@符号.例如:ok,hello,true。2.NUmber(数字):数字可以是......