8.0 KiB
09 · 集合与访问协议
0/22 项已确认。当前推进 09-01;本分类尚未完成选择。
本页整理原讨论的问题、验收要求和候选方案。勾选代表讨论中已确认的规则,不代表编译器或运行时已经实现。
09-01 能力如何组织
- 待讨论
确定下标、迭代、成员判断等能力独立提供、按类别打包,还是允许相互推导;明确组合约束。
09-02 下标接受什么
- 待讨论
确定位置、键、多维下标及其他选择器的支持范围,以及不支持的下标如何失败。
09-03 读取失败与缺失
- 待讨论
确定键不存在、无法读取时的行为,以及如何区分“缺失”和“存储的空值”。依赖「错误处理与结果类型」。
09-04 下标写入与删除
- 待讨论
确定是否分别支持、键不存在时如何处理,以及只读容器上的行为。
09-05 位置索引规则
- 待讨论
确定索引起点、可接受的索引值、负索引、越界与空集合行为。
09-06 文本索引单位
- 待讨论
确定字符串是否支持位置访问,以及访问单位和边界。依赖「字符串与文本」。
09-07 切片范围规则
- 待讨论
确定端点包含关系、默认端点、步长、反向切片、越界与非法步长行为。
09-08 切片结果语义
- 待讨论
确定副本、共享视图或惰性结果的选择规则,以及原集合变化的影响。
09-09 切片写入与删除
- 待讨论
确定支持范围、替换长度要求、重叠操作及失败后的集合状态。
09-10 长度与有限性
- 待讨论
确定哪些对象提供长度,未知或无限长度如何表达,长度是否允许通过遍历计算。
09-11 获得迭代器与重复遍历
- 待讨论
确定如何开始遍历,区分可重复遍历对象与单次消费对象,以及多个遍历是否独立。
09-12 取下一项与迭代结束
- 待讨论
确定元素、正常结束和读取失败的区别,以及结束后再次读取的行为。依赖「错误处理与结果类型」。
09-13 遍历内容与顺序
- 待讨论
确定映射等容器产出什么,各类容器承诺哪些顺序,以及顺序是否稳定。
09-14 遍历期间修改集合
- 待讨论
确定允许的修改、观察到的结果,以及冲突检测和失败行为。
09-15 提前结束与资源释放
- 待讨论
确定退出循环、异常和部分消费时的迭代器处理。依赖「资源管理与控制流」。
09-16 成员判断的含义
- 待讨论
确定判断键、值还是元素,采用何种匹配规则,以及缺失时的结果。依赖「值与相等性」。
09-17 成员判断的默认实现
- 待讨论
确定是否允许退回遍历,以及单次流、无限数据和遍历失败时的行为。
09-18 解包的数据来源
- 待讨论
确定解包依赖迭代、位置访问还是独立协议,以及消费顺序。
09-19 解包数量与失败
- 待讨论
确定数量不足、数量过多、剩余项捕获及无限输入的行为;明确失败时已消费数据和已绑定变量的状态。依赖「绑定与赋值」。
09-20 自定义容器如何接入
- 待讨论
确定用户需要提供哪些操作、哪些有默认行为,以及缺失或冲突如何报告。依赖「类型系统与定制协议」。
09-21 异步遍历的支持边界
- 待讨论
确定本轮是否支持;若支持,明确与同步遍历、取消和清理的关系。依赖「并发与异步」。
09-22 跨协议一致性验收
- 待讨论
检查索引、长度、切片、迭代、成员判断和解包之间的约束;核对相关分类决定,解决冲突。
当前问题的方案与语言对照
以下沿用原讨论材料;建议和参考语言的做法均不自动成为本语言规则。
当前仍是 09-01:下标、迭代、成员判断等能力如何组织。核心问题是:支持一种能力,是否自动获得其他能力?
下面的规则来自语言或标准库文档;其中的优缺点是我们的取舍分析,不代表已经确认的历史设计动机。
| 语言 | 相关规则与具体行为 | 好处、代价及启发 |
|---|---|---|
| Python | 能力分别定制,但有回退:没有 __contains__ 时,x in obj 会尝试迭代,再尝试旧式位置访问。因此 2 in iter([1, 2, 3]) 为真,同时消费迭代器到 2。标准库也提供 Sequence 等组合契约。数据模型、容器抽象 |
定制操作较少也能获得便利;但成员判断可能隐含消费和长时间搜索。说明“独立能力”“组合契约”“默认推导”可以分层存在。 |
| JS | 迭代通过 Symbol.iterator,与下标访问分开。{0: "a", length: 1} 能读取 [0],却不能直接用于 for...of。Map 通过 .has(k) 判断键是否存在;JS 的 in 检查对象属性,并非通用集合成员判断。迭代协议、属性判断、Map.has |
能力边界较明确;不同容器的查询接口也可能不同。启发是:统一语法与统一能力是两个决定。 |
| TS | 用静态类型分别表达能力,例如 ArrayLike<T> 描述数字下标和长度,Iterable<T> 描述可迭代;只有前者不保证满足后者。执行仍依赖生成的 JS、运行环境及编译配置,TS 没有独立运行时。对象类型、迭代类型 |
可以提前检查算法需要的能力;类型声明仍需与运行行为一致。我们可以先决定语义,再决定是否静态检查。 |
| Go | 内置下标适用于规定的类型,不能靠给任意结构体添加方法来重载 [];range 有独立规则,Go 1.23 起支持规定签名的迭代函数。例如通道可以被 range 遍历,却不能下标访问。语言规范 |
内置规则集中明确;自定义容器接入下标语法的空间较小。说明访问与遍历也可以采用不同的扩展机制。 |
| Rust | Index 与 IntoIterator 是分开的 trait。自定义类型只实现 Index,不会因此获得 for 遍历。通用搜索可显式写成 `iter.any( |
x |
这些语言都混合使用了多种机制,不能简单把整门语言归为某一个方案。我们当前仍选这三个方向之一:
- A.按类别打包:序列、映射等各自规定必需能力;特殊容器可能需要适配。
- B.能力独立:可下标不自动意味着可迭代,可迭代不自动意味着支持成员判断;通用搜索可以显式调用。
- C.能力独立并允许默认推导:例如没有专门成员判断时,自动遍历;具体回退规则在后续任务明确。
我建议 B:目前语言用途尚未确定,先独立表达能力,可以容纳数组、映射和单次输入流;常用能力仍可组合成契约。代价是自定义容器可能要多提供几个操作。这只是建议,尚未成为决定。
你倾向 A、B,还是 C?
讨论来源
《语言设计 09:集合与访问协议》,整理日期 2026-10-28。章节编号沿用原清单。