第 13 章:完成一个列表处理程序

最后写一个小程序:把 [1, 2, 3, 4, 5] 中每个数平方,保留大于 10 的结果,再把它们相加。这个任务会用到函数、列表、多态参数和输出。

先列出每一步的结果

步骤 结果
原始数据 [1, 2, 3, 4, 5]
每个数平方 [1, 4, 9, 16, 25]
保留大于 10 的数 [16, 25]
求和 41

这里先平方、再判断。若先按“大于 10”筛选原始数据,会把所有元素都删掉,得到不同结果。编写程序前先列出中间结果,能帮助你确认处理顺序。

完整程序

寻观「标准库」之书。

「平方」乃化「整数」而「整数」也。
「平方」者会「数」而「乘」于「数」于「数」也。

「大于十」乃化「整数」而「爻」也。
「大于十」者会「数」而「大于」于「数」于「一零」也。

「原始数据」乃「列」于「整数」也。
「原始数据」者(「列」【「一」,「二」,「三」,「四」,「五」】)也。

「平方结果」乃「列」于「整数」也。
「平方结果」者「态射」授以「整数」授以「整数」
    于「原始数据」于「平方」也。

「筛选结果」乃「列」于「整数」也。
「筛选结果」者「滤」授以「整数」于「大于十」于「平方结果」也。

「总和」乃「整数」也。
「总和」者「从左折叠」授以「整数」授以「整数」
    于「加」于「零」于「筛选结果」也。

「打印行」于(「字符串拼接」于『大于十的平方之和:』于
    (「整数表示」于「总和」))。

将它保存为练习包的入口,构建并运行,输出应为:

大于十的平方之和:41

对照三个列表函数的参数

「态射」 对原始列表的每个元素调用平方函数。它的普通参数顺序是“列表、转换函数”,两个类型参数分别指定输入元素和输出元素的类型。

「滤」 的普通参数顺序是“判断函数、列表”。它保留判断结果为 「阳」 的元素,因此 16 和 25 留下,其他值被移除。注意它与态射的参数顺序不同。

「从左折叠」 的普通参数依次是“合并函数、初始累计值、列表”。在本例中,从零开始,把 16 和 25 合并到累计值中,最终得到 41。

合并函数接收的顺序是“当前元素、此前的累计值”。因此本例的两次调用相当于 加 16 0加 25 16。加法交换参数不影响结果,但换成减法或字符串拼接时,顺序就不能忽略。

如何检查和修改程序

如果输出不对,先分别检查平方函数和判断函数,再检查三个列表操作的参数顺序。中间结果已经有独立名称,可以在某一步后增加输出,或者暂时把那一步换成已知的小列表,缩小排查范围。

尝试下面三个修改,每次只改一处:

  1. 把原始数据改成空列表,预期总和为 0。折叠没有元素可处理时,返回初始累计值。
  2. 恢复原始数据,把阈值改成 20,预期总和为 25。
  3. 恢复阈值 10,把求和改成求积:合并函数换成乘法,初始累计值换成 1,预期得到 400。记得同时修改输出说明。

初始累计值也是算法的一部分。求积时如果仍用零,即使列表不为空,最终结果也会变成零。

接下来做一个自己的练习

把平方和筛选函数移到第十章的数值工具模块,让入口只负责组织数据和输出。再增加一个返回列表长度的结果,与总和一起输出。这样能练习把计算拆成可复用函数,并用模块组织它们。

需要查询具体语法时,可以继续阅读语言规范;需要寻找列表函数时,可以阅读标准库的多态列实现。现在已经学过的模式匹配和递归,足以帮助你读懂其中的态射、筛选与折叠。

上一章 · 目录