Erlang 从零 · 第 11 课(展开目录)
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 1130 分钟
一层一层取数据
从 map 里的 list 读取值,再产生更新后的嵌套结构。
01 · 先看完整例子
读取并更新课程积分
最后同时查看课程名与新积分。
Erlang
Student = #{
name => <<"A-Qing">>,
courses => [#{title => <<"Erlang">>, points => 8}]
},
%% 先取课程 list,再匹配第一项
[Course | _] = maps:get(courses, Student),
Title = maps:get(title, Course),
%% 更新内层后,再放回外层 map
UpdatedCourse = Course#{points := 9},
Updated = Student#{courses := [UpdatedCourse]},
{Title, maps:get(points, hd(maps:get(courses, Updated)))}.先对照结果
- 得到
{<<"Erlang">>,9};Student中的原积分仍为 8。
02 · 回头拆代码
从第一行往下读
- 先把嵌套读取拆成多个有名字的步骤。
- 内层课程 map 更新后,外层也要放入新课程 list。
- 所有更新都生成新 term。
03 · 认清新符号
符号不是暗号
maps:get(Key, Map)读取 map 中指定键的值。
Map#{key := value}更新已经存在的键。
[Head | Tail]匹配非空 list 的第一项与剩余部分。
04 · 代码里的概念
把名字和意思对上
嵌套 term
一个集合中继续放其他集合,如 map 里放课程 list。
map 更新
从旧 map 产生带新值的新 map;原值不改变。
05 · 再说清楚
这些写法为什么有用
真实数据常由 map、list 和 tuple 叠在一起。先匹配外层,再处理内层,别一眼吞下整棵树。
maps:get/2 读取键。更新 map 使用 #{key := value},它返回新 map。
list 的头尾模式能取第一项。若 list 可能为空,应写出空 list 分支。
06 · 自己改一次
合上答案,动手
把 #{profile => #{city => <<"Xi'an">>}} 的城市改为 <<"Chengdu">>。
练习起点
Person = #{profile => #{city => <<"Xi'an">>}},
Profile = maps:get(____, Person),
Person#{profile := Profile#{city := ____}}.目标结果: 新 map 的城市是 <<"Chengdu">>。
卡住了,再看提示
外层键是 profile,新值是一个 binary。
运行过以后,再看一种答案
一种答案
Person = #{profile => #{city => <<"Xi'an">>}},
Profile = maps:get(profile, Person),
%% 先更新内层,再放回外层
Person#{profile := Profile#{city := <<"Chengdu">>}}.想一想:`Map#{key := value}` 会直接改掉 `Map` 吗?
不会。它返回新 map;旧变量仍指向旧值。
带走
记住三句
- 1
嵌套数据要分层读取。
- 2
:=更新已存在的 map 键。 - 3
旧 term 不会被原地修改。
本课结束代码也跑过一次,就把这一课收好。