第48章 序列与集合协议族:为什么 for-in 什么都吃得下
Sequence、IteratorProtocol、Collection 与惰性求值:自己造一个能被 for-in、map、filter 直接使用的类型
3 分钟阅读
前七篇是按"你接下来要做什么"排的:先装上工具链,再学语法,然后学类型、内存、并发、测试,最后动手做东西。这个顺序适合学习,但会留下一个副作用——同一个概念家族的成员被分散在好几章里。
举一个真实的例子。你在第 19.1 节第一次见到"计算属性",当时它只是"给结构体加个算出来的字段"的一个小技巧。接着你在第 19.2 节见到属性观察器、19.3 节见到 lazy、19.4 节见到类型属性、19.7 节见到属性包装器、第 21 章又见到扩展里的计算属性——它们其实是一家人,但你从来没有在一页里同时看到过它们。
这不是漏写,而是"按场景排序"必然的代价。这一篇就是来还这笔账的:五章,每章收口一个概念家族。
| 章 | 收口什么 | 原来散在 |
|---|---|---|
| 48 | 序列协议族:IteratorProtocol、Sequence、Collection | 第 10 章、第 23 章、第 29 章 |
| 49 | 数值协议族与格式化:Numeric、BinaryInteger、FormatStyle | 第 4 章、第 24 章、第 38 章 |
| 50 | 属性与下标的全部形态 | 第 19 章、第 15B 章、第 21 章 |
| 51 | 标准库算法工具箱:zip、stride、reduce(into:) | 各处零散出现 |
| 52 | 反射与内存布局:Mirror、MemoryLayout | 第 21 章、第 24 章、第 29 章 |
这一篇不引入新语法,所以有两种读法:
如果某一章里的链接指向你还没读过的章节,不必回头补——那些章节只是该概念第一次出现的地方,本篇的正文已经把需要的前提讲全了。
Sequence 和 Collection 的区别,以及自己写的类型该遵循哪一个。IteratorProtocol 手写一个能 for ... in 的类型,并知道它为什么是"一次性"的。Numeric、BinaryInteger、FixedWidthInteger、FloatingPoint 之间选对约束,而不是逢数就写 Int。FormatStyle 把数字、货币、百分比和日期格式化到位,而不是手拼字符串。zip、stride、sequence(first:next:)、reduce(into:) 替掉一半的手写循环。Codable,还是该在编译期用 KeyPath 和宏解决。Sequence、IteratorProtocol、Collection 与惰性求值:自己造一个能被 for-in、map、filter 直接使用的类型
Numeric、BinaryInteger、FixedWidthInteger、FloatingPoint 各自保证什么,以及 FormatStyle 怎样把数字变成人看的文字
把散落在第19章、第15B章、第21章的属性与下标收进一张图:存储、计算、观察器、lazy、类型属性、包装器、静态下标与动态成员
把散落在各章的标准库函数收成一箱工具:配对、递推、归约成结构、查找判定、切分分块,以及 lazy 惰性管道
自定义描述、LosslessStringConvertible、Mirror、CustomReflectable、dump、MemoryLayout 与 withUnsafeBytes:Swift 在运行时到底保留了哪些类型信息