251 lines
9.3 KiB
Markdown
251 lines
9.3 KiB
Markdown
# 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<T>` 的 `None` 表示其中没有 `T` 值,不要求使用空指针实现。[官方说明](https://doc.rust-lang.org/std/option/) | “没有目标对象”的语义不必绑定某种内存布局。 |
|
||
|
||
这里还有一个需要明确的设计边界:
|
||
|
||
1. **空引用例外**:名字可以绑定对象,也可以持有 `null`;`null` 不属于对象。
|
||
2. **统一对象模型**:`null` 是空值类的对象,用它表示“没有业务对象”。
|
||
|
||
你说的“没有对象”,更接近 **1**。这会成为之前“所有值都是类的实例”的一个明确例外;方案 **2** 则保留那条统一规则。两者都能实现先声明、后赋值。
|
||
|
||
**你希望 `null` 本身也不是对象,采用方案 1,对吗?**
|
||
|
||
## 讨论来源
|
||
|
||
《语言设计 03:值与类型》,整理日期 2026-10-28。章节编号沿用原清单。
|
||
|