# 03 · 值与类型 13/30 项已确认。当前推进 03-14;null 是否为对象仍未确认。其余分类中的类型、赋值和条件规则须与本章已有决定核对。 本页整理原讨论的问题、验收要求和候选方案。勾选代表讨论中已确认的规则,不代表编译器或运行时已经实现。 ## 03-01 动态类型 - [x] 已确认 操作根据运行时对象的类型检查;不要求执行前通过静态类型检查。不适用的类型组合在运行时失败。 ## 03-02 名字与对象绑定 - [x] 已确认 变量名绑定对象,类型属于对象;`b = a` 共享对象,重新绑定 `a` 不改变 `b`。 ## 03-03 隐式转换政策 - [x] 已确认 需要转换类型时必须显式写出;不靠自动转换接受不匹配的操作数,例如 `"41" + 1` 报 `TypeError`。 ## 03-04 数值类型与支持范围 - [x] 已确认 对外统一为 `Number`,覆盖整数与有理数,大小自动调整;不引入无穷大、`NaN`、虚数,正负零视为同一个数。精确性及异常运算另见下项。 ## 03-05 整数性质与循环次数 - [x] 已确认 记录数值是否为整数;按次数循环要求正整数,零、负数和非整数不满足要求。具体错误形式交由 03-29 统一。 ## 03-06 字符串算术操作 - [x] 已确认 确定字符串拼接、减法与重复运算的支持范围。 **已确认规则:**两个 String 可以用 + 拼接,不支持字符串减法;后续已修订为支持 String * 整数值 Number,完全等价于 duplicate,包含相同的参数检查与失败行为。 ## 03-07 数值精确性 - [x] 已确认 确定有理数存储和四则运算是否始终精确,是否允许舍入。 **已确认规则:**`1 / 3` 精确保存为 `1/3`;`1/3 + 1/3` 得到 `2/3`;`1/3 * 3` 得到整数 `1`。如何显示另由 03-09 决定。 ## 03-08 数值异常 - [x] 已确认 确定除零等不成立的数值运算如何失败,哪些情况交给平台模块。 **已确认规则:**`1 / 0`、`0 / 0`、`1 / (1 - 1)` 都抛出算术错误,停止本次表达式求值。具体错误名称、捕获和传播机制由【错误与异常】及 03-29 对齐。 ## 03-09 数值输入与显示 - [x] 已确认 确定小数文字表示什么数、循环小数如何显示,以及显示后能否无损读回。依赖【词法与语法】。 **已确认规则:**数值按精确值解释,默认输出最简分数,分母为正;整数直接显示为整数,零显示为 `0`。 ## 03-10 基本类型清单 - [x] 已确认 确定本轮内置哪些类型,以及明确不提供哪些类型。 **已确认规则:**本轮提供 `Number`、`String`、`Boolean`、空值类、`List`、`Map`、`Tuple`、`Set`、`Bytes`、函数类、类型对象所属的类。具体类名暂定。 空值类的对象地位在 03-14 被重新提出,仍待确认;不能据此宣布 null 已确定为对象。 ## 03-11 字符串的值模型 - [x] 已确认 确定字符单位、Unicode 处理及索引单位;补齐空字符串等边界。 **已确认规则:**合法 Unicode 标量序列;保留原码点、不自动规范化;默认按码点计数,字素簇使用专门接口;索引从零开始、支持负索引、单个索引越界报错;普通正向切片左闭右开、越界截断、空范围返回空字符串。 创建或解码时拒绝非法编码和孤立代理项,不自动替换或丢弃;原始数据用 Bytes 保存。 ## 03-12 字符串重复方法 - [x] 已确认 确定名称、次数参数、零和负数、错误行为及返回值。 **已确认规则:**`s.duplicate(n)` 返回重复后的 `String`,不修改接收者。`n` 必须是非负整数值的 `Number`;零次返回空字符串,负数、非整数及其他类型报错,不做隐式转换。 ## 03-13 布尔值与条件转换 - [x] 已确认 确定布尔值是否独立于数字,以及条件位置接受布尔值还是其他值。依赖【控制流】。 **已确认规则:**`Boolean` 独立于 `Number`;条件表达式只接受 `Boolean` 对象。`true`、`false` 可以作为条件,数字、字符串、容器、空值等直接作为条件均报 `TypeError`。具体控制流语法由【控制流】对齐。 ## 03-14 空值与缺失 - [ ] 待讨论 确定是否区分空值、缺失、未初始化和无返回值,以及误用时的行为。 ## 03-15 复合值规则 - [ ] 待讨论 为选中的容器、元组、记录或枚举等确定成员类型限制、缺失成员及递归结构规则。 ## 03-16 用户定义类型的能力 - [ ] 待讨论 确定用户能定义哪些类型,哪些能力仅供内置类型使用。依赖【对象与类型模型】。 ## 03-17 类型身份与兼容性 - [ ] 待讨论 确定按名字还是结构认类型、如何处理子类型,以及哪些类型可以互相替代。 ## 03-18 运行时类型查询 - [ ] 待讨论 确定如何取得类型、检查类型及检查能力;明确精确类型与子类型检查的区别。 ## 03-19 显式转换接口 - [ ] 待讨论 确定转换入口、支持的转换、可能丢失信息的转换及失败行为。 ## 03-20 泛型与容器类型约束 - [ ] 待讨论 决定是否支持参数化类型或带成员约束的容器;支持则规定运行时如何检查。 ## 03-21 可选类型标注 - [ ] 待讨论 决定是否提供;提供则明确其用途及是否影响运行行为。 ## 03-22 顶级类型与顶级类 - [ ] 待讨论 分别决定是否存在能容纳所有值的类型,以及是否存在统一祖先类。 ## 03-23 可变性与共享 - [ ] 待讨论 确定哪些对象可变,以及多个名字共享对象时能观察到什么变化。 ## 03-24 复制语义 - [ ] 待讨论 确定赋值之外是否提供复制、浅复制和深复制,以及循环引用如何处理。 ## 03-25 相等与身份 - [ ] 待讨论 确定内容相等和同一对象如何区分,以及不同类型之间如何比较。 ## 03-26 哈希与键的限制 - [ ] 待讨论 确定哪些值可作集合成员或映射键,保证相等、哈希和可变性规则一致。 ## 03-27 参数与返回值的绑定 - [ ] 待讨论 确定传参、返回、重新绑定及修改对象的可见效果。依赖【函数与调用】。 ## 03-28 显式引用能力 - [ ] 待讨论 决定能否直接取得并传递“变量存储单元”的引用;不支持也可完成此项。 ## 03-29 类型相关错误契约 - [ ] 待讨论 统一类型不匹配、值不合法、转换失败等情况的错误分类。依赖【错误与异常】。 ## 03-30 跨分类一致性验收 - [ ] 待讨论 用一组正常和失败示例核对类型、转换、对象、运算、函数与控制流规则,消除冲突和阻塞。 ## 当前问题的方案与语言对照 以下沿用原讨论材料;建议和参考语言的做法均不自动成为本语言规则。 可以,**你要的空状态表示“变量位置存在,但当前没有指向对象”**。 不过,“避免回收”这里需要区分两件事: ```text result = null ……之后…… result = calculate() ``` 这是**先保留名字,之后再绑定对象**。前面还没有计算结果对象,因此没有对象需要保活。名字什么时候有效,由作用域规则决定。 如果已经有对象,情况不同: ```text a = 某个对象 b = a a = null ``` 在采用强引用与自动回收的模型中,`b` 仍持有该对象,就不能提前回收它;如果所有有效强引用都消失,对象才可能被回收。**把变量设成 `null` 会解除它原来的引用,不会保护原对象。**具体回收机制属于【运行时与内存管理】,尚未确定。 各语言也区分“空状态”和“对象保活”: | 语言 | 空状态怎样表达 | 对我们的启发 | |---|---|---| | **Python** | `None` 本身是一个对象,名字绑定到它。[对象模型](https://docs.python.org/3/reference/datamodel.html#objects-values-and-types) | 可以保持所有可绑定值都是对象的统一规则。 | | **JS / TS** | `null` 是独立的原始值,不是对象;TS 另有静态类型约束。[JS 规范](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-ecmascript-language-types)、[TS 文档](https://www.typescriptlang.org/tsconfig/strictNullChecks.html) | 可以在语言层面明确允许“无对象”的值。 | | **Go** | 指针变量可以为 `nil`,表示没有指向对象,变量本身仍存在。[语言规范](https://go.dev/ref/spec#The_zero_value) | 接近你描述的“位置存在、目标为空”。 | | **Rust** | `Option` 的 `None` 表示其中没有 `T` 值,不要求使用空指针实现。[官方说明](https://doc.rust-lang.org/std/option/) | “没有目标对象”的语义不必绑定某种内存布局。 | 这里还有一个需要明确的设计边界: 1. **空引用例外**:名字可以绑定对象,也可以持有 `null`;`null` 不属于对象。 2. **统一对象模型**:`null` 是空值类的对象,用它表示“没有业务对象”。 你说的“没有对象”,更接近 **1**。这会成为之前“所有值都是类的实例”的一个明确例外;方案 **2** 则保留那条统一规则。两者都能实现先声明、后赋值。 **你希望 `null` 本身也不是对象,采用方案 1,对吗?** ## 讨论来源 《语言设计 03:值与类型》,整理日期 2026-10-28。章节编号沿用原清单。