Erlang 从零 · 第 13 课(展开目录)
01 · 先打开 erl02 · 先认常见 term03 · 分清两种文字04 · 变量只接一次05 · 拆开一列,再筛一次06 · 把文字安全变成整数07 · 用 case 选一条路08 · 让函数继续走09 · 把代码放进模块10 · 条件必须说真话11 · 一层一层取数据12 · 文字先说清编码13 · 让函数子句排好队14 · 带着累加器往前走15 · 先看值,再选路16 · 给模块立规矩17 · 让 rebar3 管项目18 · 让结果有固定形状19 · 把磁盘当成会失败的邻居20 · 把函数交给 list21 · record 留在院里22 · 先写模块之间的约定23 · 把 term 形状写出来24 · 小测试与整段路25 · 把应用磨成命令26 · 先把小项目圈住27 · 把真实文件洗干净28 · 公开入口越少越稳29 · 把约定留在源码旁30 · 打包,也留下线索31 · 按最初任务交卷
ERLANG · 基础 · LESSON 1335 分钟
让函数子句排好队
在模块中用模式和 guard 写多个命名函数子句。
01 · 先看完整例子
保存为 fare.erl
运行 c(fare). 后依次调用三种输入。
Erlang
-module(fare).
-export([fee/1]).
%% 具体的儿童规则放在前面
fee(Age) when is_integer(Age), Age >= 0, Age < 12 ->
{ok, 0};
fee(Age) when is_integer(Age), Age >= 0 ->
{ok, 20};
fee(_) ->
{error, invalid_age}.先对照结果
fare:fee(9).得到{ok,0}。fare:fee(18).得到{ok,20}。fare:fee(<<"nine">>).得到{error,invalid_age}。
02 · 回头拆代码
从第一行往下读
- 三个子句都属于
fee/1,所以前两条以分号结束。 - guard 先确认整数,再检查年龄范围。
- 最后的下划线接住所有未匹配输入。
03 · 认清新符号
符号不是暗号
fee(Age) when ...定义带 guard 的函数子句。
;同一函数还有下一条子句。
.当前函数的全部子句结束。
04 · 代码里的概念
把名字和意思对上
函数子句
同一个 name/arity 的不同入口,由模式与 guard 区分。
guard
when 后可快速检查类型与范围的一组安全表达式。
05 · 再说清楚
这些写法为什么有用
Erlang 命名函数放在模块里。同名、同 arity 的子句必须连在一起,用分号隔开。
运行时从上往下找第一条模式和 guard 都通过的子句。
最具体的规则在前,兜底规则在后。最后一个子句用句点结束。
06 · 自己改一次
合上答案,动手
写出 weather:label/1 的晴天与兜底子句。
练习起点
label(sunny) ->
____;
label(_) ->
____.目标结果: 晴天返回 <<"sunny">>,其他输入返回 <<"unknown">>。
卡住了,再看提示
两个空都填写 binary。
运行过以后,再看一种答案
一种答案
%% 具体 atom 放在兜底前
label(sunny) ->
<<"sunny">>;
label(_) ->
<<"unknown">>.想一想:同一个函数的两条子句中间为什么不能用句点?
句点表示函数定义已经结束;下一条同名同 arity 定义会被当作重复函数而编译失败。
带走
记住三句
- 1
函数由 name 与 arity 共同识别。
- 2
同一函数子句必须相邻。
- 3
分号续子句,句点收函数。
本课结束代码也跑过一次,就把这一课收好。