文章目录
模块
1. 概念
在这之前我们执行所有命令都是在
erlang shell
中运行的,每次只运行了一行代码,但是假如我们想一次运行多行代码怎么办呢?这里就用到了模块
模块的本质就是我们把一个事物所有相关的方法或定义,都写在一个以
.erl
结尾文本中,它就是一个模块
比如矩形有两个公式:
- 公式1:矩形面积 = 长 * 宽
- 公式2:周长 = (长 + 宽) * 2
当我们把这两个公式写在一个 名为
rectangle.erl
的文件中时,它就是一个模块了。这样我们再想算矩形的面积时,就不用重复的去写相同的代码了
2. 定义
-
以
.erl
结尾的文件 -
假设模块名是
rectangle
,文件内第一行必须是%% 这个模块的文件名:rectangle.erl -module(rectangle)
%%
开头的代表注释,可以理解为备注,在运行代码时,该部分不会被编译,所以可以随便写,这里的注释写的是当前这个模块的文件名-module(rectangle)
是固有写法,让erlang执行该模块的代码时,知道这是哪个模块,所以模块名必须和文件的名字一致,并且是模块的第一行代码下面我们都已矩形这个例子进行举例
函数
1. 概念
函数可以理解为数学里的公式,给对应的变量传递数值后,可以得到计算后的结果,或让代码执行一段对应的逻辑
2. 定义
函数名(参数1, 参数2, 或者没有参数) ->
第一行代码,
第二行代码.
- 函数名对应了公式的名字
()
括号内是传递的参数->
固定写法,写上就是了,
假设有多行代码时,用 逗号 进行分割- 当这个函数(公式)结束后,用
》
3. 案例解释
案例1:求矩形面积
矩形面积 = 长 * 宽
area = length * width
那么代码里怎么写呢?
%% 计算矩形面积
area(Length, Width) -> Length * Width.
案例2:求矩形周长
矩形面积 = (长 + 宽) * 2
perimeter = (length * width) * 2
那么代码里怎么写呢?
%% 计算矩形周长, 写法1
perimeter(Length, Width) -> (Length + Width) * 2.
%% 计算矩形周长,写法2
perimeter(Length, Width) ->
Param1 = Length + Width,
Param * 2.
函数的导出
1. 概念
比如我家里有钻石、螺丝刀、扳手,我告诉你我有扳手和螺丝刀
有一天你家里在装修,需要和我借用扳手我直接借给你了
有一天你问我:“哎!你有钻石吗?”,我说:“没有”
假设 钻石、螺丝刀、扳手 是三个函数
我告诉你我有扳手和螺丝刀
,就是导出声明
,就是别人都知道,也可以随便用的函数。有变成基础的可以理解为公开方法(public)
2. 定义
%% 格式1:导出一个函数,且该函数不需要传递参数
-export([函数名/0]).
%% 格式2:导出一个函数,且该函数需要传递1个参数
-export([函数名/1]).
%% 格式3:导出一个函数,且该函数需要传递3个参数
-export([函数名/3]).
%% 格式4:导出多个函数, 用逗号分隔不同的函数
-export([函数1/0], [函数2/5], [函数3/2]).
3. 案例:一个完整的矩形模块
%% 模块名:rectangle.erl
%% 矩形相关公式
-module(rectangle).
%% 对外公开的函数,这里只对外公开计算面积的函数
-export([area/2]).
%% 计算矩形面积
area(Length, Width) -> Length * Width.
%% 计算矩形周长
perimeter(Length, Width) -> (Length + Width) * 2.
编译
1. 概念
现在我们文件
rectangle.erl
中写的是我们的代码,但是电脑是看不懂的,就比如在中国我们写字用中文,在美国写字用英文,美国人看不懂中文一样,需要翻译一下。翻译的这个过程就是编译
2. 怎么编译
win + r 运行命令窗口
%% 先进入要编译的文件夹的目录;或者先打开文件夹,然后 shfit+右键——在此处打开 powershell 窗口
> cd C:\Work\Erlang
>
%% 运行erlang shell
> erl
> Eshell Vx.x (abort with ^G)
>
%% 编译 rectangle.erl
> c(rectangle).
%% 提示 perimeter 这个函数内部没有调用,也没有导出
rectangle.erl:12: Warning: function perimeter/2 is unused
%% 编译成功
{ok,rectangle}
在 erlang shell 中调用
c(模块名).
就可以编译模块了,编译成功后,与模块同目录中会多出一个rectangle.beam
的文件,扩展名.beam
就是erlang可以运行的模块了
模块的调用
现在erlang可运行的模块已经编译出来了,但是怎么运行呢?
%% 先进入要编译的文件夹的目录
> cd C:\Work\Erlang
>
%% 运行erlang shell
> erl
> Eshell Vx.x (abort with ^G)
>
%% 求面积:长=12,宽=10
> rectangle:area(12, 10).
120
%% 求面积:长=12132,宽=34234
> rectangle:area(12132, 34234).
415326888
>
%% 求周长:长=10,宽=20
> rectangle:perimeter(10, 20).
%% 这里由于没有导出这个函数,所以报错了
** exception error: undefined function rectangle:perimeter/2
相同函数名,不同参数(重载)
1. 定义
比如矩形包括长方形和正方形,他们的面积都是 长* 宽,但是因为正方形两个边都一样长
所以正方形也可以的面积公式 = 边长 * 边长,我们看代码的实现
%% 模块名:rectangle.erl
%% 矩形相关公式
-module(rectangle).
%% 对外公开的函数,这里只对外公开计算面积的函数
-export([area/1]).
%% 计算长方形面积
area({rectangle, Length, Width}) -> Length * Width,
%% 计算正方形面积
area({square, Length}) -> Length * Length.
函数
area
有两个子函数,一个对应了正方形面积公式,另一个对应了矩形的面积公式,相同函数名用,
进行分割,最后用.
结束,代表整个函数结束了
2. 调用
> erl
> c(rectangle).
{ok,rectangle}
> rectangle:area({rectangle, 2, 3}).
6
> rectangle:area({square, 2}).
4
当一个函数有多个子参数时,erlang会从上向下 用子函数的参数与传递的参数执行模式匹配,直到匹配成功,触发内部逻辑
比如调用rectangle:area({square, 2}).
时
erlang 尝试第一个子函数的参数进行模式匹配:{rectangle, Length, Width} = {square, 2}.
匹配失败,
erlang 尝试第二个子函数的参数进行模式匹配:{square, Length}={square, 2}.
等式成立,执行该子函数中的方法:Length * Length.
假若所有的子函数都匹配失败,则会报错
发现了没有,调用参数里默认有一个原子
rectangle
,square
这就是原子的另一个作用:匹配子函数,与表明子函数的具体用途