Erlang 从零 · 第 05 课(展开目录)
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 0525 分钟

拆开一列,再筛一次

先用头尾模式拆 list,再用 list comprehension 筛出需要的值。

01 · 先看完整例子

先拆 list,再筛出及格分数

模式里的 | 拆 list;comprehension 里的 || 分开结果与取值规则。

Erlang
%% 清掉旧绑定,再放入原始分数
f().
Scores = [92, 58, 76].

%% 拆出第一个分数,并在 Tail 前放入新值
[First | Rest] = Scores.
NewScores = [100 | Rest].

%% comprehension 依次取值,只收集及格分数
Passed = [Score || Score <- Scores, Score >= 60].

{First, Rest, NewScores, Passed}.
先对照结果
  • First 是 92,Rest 是 [58, 76]。
  • NewScores 是 [100, 58, 76],原来的 Scores 没有改变。
  • Passed 是 [92, 76]。
02 · 回头拆代码

从第一行往下读

  1. [First | Rest] = Scores 只适用于非空 list;Rest 是除第一个值外的整个 list。
  2. [100 | Rest] 创建新 list,没有修改 Rest 或 Scores。
  3. Score <- Scores 从左到右取出每个分数,当前值暂时叫 Score。
  4. 逗号后的 Score >= 60 是筛选条件;只有条件为 true 的值才进入 Passed。
03 · 认清新符号

符号不是暗号

[ ]

包住 list。

|

在 list 模式中分开头和尾。

[New | Old]

把一个新元素放到已有 list 的最前面。

||

左边写要收集的结果,右边写取值和筛选规则。

<-

从右边 list 依次取一个值,交给左边变量。

04 · 代码里的概念

把名字和意思对上

01

Head

非空 list 的第一个元素。

02

Tail

去掉第一个元素后剩下的 list;它自己仍是 list。

03

空 list

[],里面没有元素,也是递归处理 list 时的停止位置。

04

list comprehension

从 list 依次取值,可以筛选或计算,再把结果收集成新 list。

05 · 再说清楚

这些写法为什么有用

list 是一串有顺序的值。[peach, plum, apricot] 的第一个元素是头,剩余 [plum, apricot] 是尾。

Erlang 写成 [Head | Tail]。竖线不是“或者”,它把 list 的头与尾分开。

空 list [] 没有头。用 [Head | Tail] 匹配空 list 会失败。

list comprehension 写成 [结果 || 值 <- list, 条件]。<- 依次取值,条件留下需要的项,整个表达式返回新 list。

06 · 自己改一次

合上答案,动手

拆开 [61, 49, 88],再亲手写 comprehension,只留下大于等于 60 的分数。

练习起点
f().
Scores = [61, 49, 88].

%% 先补出头尾模式
[____ | ____] = Scores.

%% 再补出取值符号和及格线
Passed = [Score ____ Score ____ Scores, Score >= ____].

{First, Rest, Passed}.

目标结果: 得到 {61, [49, 88], [61, 88]}。

卡住了,再看提示

头尾变量是 First、Rest;comprehension 的三个空是 ||、<- 和 60。

运行过以后,再看一种答案
一种答案
f().
Scores = [61, 49, 88].

%% 头尾模式拆开非空 list
[First | Rest] = Scores.

%% comprehension 返回新的及格分数 list
Passed = [Score || Score <- Scores, Score >= 60].

{First, Rest, Passed}.
想一想:`Passed = [Score || Score <- Scores, Score >= 60]` 会修改 `Scores` 吗?

不会。comprehension 返回一个新 list;原来的 Scores 仍保持不变。

带走

记住三句

  1. 1

    [Head | Tail] 拆开非空 list。

  2. 2

    Tail 是剩余 list,不只是最后一个值。

  3. 3

    || 和 <- 组成 list comprehension,并返回新 list。

本课结束代码也跑过一次,就把这一课收好。