Erlang 从零 · 第 05 课(展开目录)
拆开一列,再筛一次
先用头尾模式拆 list,再用 list comprehension 筛出需要的值。
先拆 list,再筛出及格分数
模式里的 | 拆 list;comprehension 里的 || 分开结果与取值规则。
%% 清掉旧绑定,再放入原始分数
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]。
从第一行往下读
[First | Rest] = Scores只适用于非空 list;Rest是除第一个值外的整个 list。[100 | Rest]创建新 list,没有修改Rest或Scores。Score <- Scores从左到右取出每个分数,当前值暂时叫Score。- 逗号后的
Score >= 60是筛选条件;只有条件为true的值才进入Passed。
符号不是暗号
[ ]包住 list。
|在 list 模式中分开头和尾。
[New | Old]把一个新元素放到已有 list 的最前面。
||左边写要收集的结果,右边写取值和筛选规则。
<-从右边 list 依次取一个值,交给左边变量。
把名字和意思对上
Head
非空 list 的第一个元素。
Tail
去掉第一个元素后剩下的 list;它自己仍是 list。
空 list
[],里面没有元素,也是递归处理 list 时的停止位置。
list comprehension
从 list 依次取值,可以筛选或计算,再把结果收集成新 list。
这些写法为什么有用
list 是一串有顺序的值。[peach, plum, apricot] 的第一个元素是头,剩余 [plum, apricot] 是尾。
Erlang 写成 [Head | Tail]。竖线不是“或者”,它把 list 的头与尾分开。
空 list [] 没有头。用 [Head | Tail] 匹配空 list 会失败。
list comprehension 写成 [结果 || 值 <- list, 条件]。<- 依次取值,条件留下需要的项,整个表达式返回新 list。
合上答案,动手
拆开 [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
[Head | Tail]拆开非空 list。 - 2
Tail是剩余 list,不只是最后一个值。 - 3
||和<-组成 list comprehension,并返回新 list。