LSR 012 - 元组类型规范 ================================================================================ 基本信息 -------------------------------------------------------------------------------- - LSR 编号 012 - 标题 元组类型规范 - 作者 Ziyang-Bai - 状态 草案 - 类型 标准规范 - 创建日期 08-09-2026 - 归属项目 编译器、标准库 摘要 -------------------------------------------------------------------------------- 定义 Lamina 元组类型。元组是固定长度、按位置索引、创建后不可变的匿名积类型,可用于函数返回、临时组合和模式匹配 [1]_。本规范同时规定元组与分组、函数实参、数组及区间构造之间的语法边界。 技术规范 -------------------------------------------------------------------------------- 1. 范围 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组用于组合少量按位置区分的值。元组的长度和各位置元素类型共同组成其类型。元组字面量包含至少两个元素;分组、函数调用、数组和区间分别使用各自的语法规则。 2. 元组类型 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组类型由一组有序元素类型组成。 .. code-block:: text (int, text) (int, text, Expr) - 元组长度固定 - 元组元素可以是不同类型 - 元组类型由长度和每个位置的类型共同决定 - 元组值默认不可变 - 元组类型是结构类型;元素类型序列相同的两个元组类型相同 3. 元组字面量 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组字面量使用圆括号,并以逗号分隔元素。 .. code-block:: text let pair = (1, "one") let triple = (1, "x", true) - 非空元组按元素表达式推导类型 - 元组字面量至少包含两个元素 - 单元素圆括号表达式按分组表达式解析 - ``(a, b)`` 始终解析为二元素元组 - 函数名后紧跟的 ``f(a, b)`` 按函数调用解析 - ``std.interval_open(a, b)`` 是普通函数调用,其结果为开区间 [4]_ .. code-block:: text let a = (1) # 分组表达式,类型为 int 4. 元数 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组字面量的元数至少为二。``(value)`` 是分组表达式;``f()`` 是零实参函数调用。函数的返回语义由核心语言规范定义 [1]_。 5. 元组访问 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组元素按位置访问,索引从 1 开始,与 Lamina 现有线性代数索引规则保持一致。 .. code-block:: text let p = (10, "x") let a = p.1 let b = p.2 - 元组索引必须是编译期常量正整数 - 第一个元素的位置为 ``1`` - 访问位置超过元组长度是编译错误 - 元组位置访问读取创建元组时绑定在该位置的元素 6. 元组解构 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组可在 ``let`` 和 ``match`` 中解构。 .. code-block:: text let (x, y) = (1, 2) match value { (a, b) => a + b } - 解构模式长度必须与元组长度一致 - ``_`` 可忽略对应位置 - 解构绑定的变量类型由对应位置推导 - 解构保持原元组值,并为各位置创建对应绑定 7. 函数返回元组 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 函数可以返回元组作为单一返回值。 .. code-block:: text func divmod(a int, b int) -> (int, int) { return (a / b, a % b) } let (q, r) = divmod(10, 3) - Lamina 仍然是单返回值语言 - 多个按位置区分的结果应使用元组返回;元素类型可以相同或不同 - 多个同类型、无序数学结果应使用集合返回 [3]_ - 需要表达命名分支、成功或失败状态时应使用 ADT [2]_ 8. 相等性与哈希 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组按位置结构比较。 - 两个元组长度不同,则类型不同 - 两个同类型元组逐位置相等时,整体相等 - 只有所有元素可比较时,元组才支持 ``==`` - 只有所有元素可哈希时,元组才可作为哈希键 9. 求值与存储语义 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 元组字面量的元素表达式按源码从左到右各求值一次。元组值创建后,元素位置和元素绑定保持不变。 - 元组的不可变性是浅层不可变;元素若引用可变对象,该对象仍遵循自身语义 - 实现可以内联、装箱或共享元组存储;各种表示具有相同的求值顺序、结构相等和可观察生命周期行为 - 跨模块接口必须保留元组长度、元素顺序和每个位置的静态类型 10. 与数组、集合和区间的区别 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 * - 类型 - 长度 - 元素类型 - 顺序 - 主要用途 * - 元组 - 固定 - 可异构 - 有序 - 多值组合 * - 数组 - 可变或运行期长度 - 通常同构 - 有序 - 程序式序列 * - 集合 [3]_ - 运行期大小 - 同构 - 无序 - 去重数学集合 * - 区间 [4]_ - 两个端点 - 同构 - 有序边界 - 表示连续或离散范围 11. 诊断 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 实现至少应区分下列错误: - ``TupleArityMismatch``:解构模式长度与元组长度不同 - ``TupleIndexNotConstant``:位置访问不是编译期常量 - ``TupleIndexOutOfBounds``:位置不在 ``1`` 到元组长度之间 - ``TupleAssignment``:试图修改元组元素绑定 - ``TupleTypeMismatch``:目标元组类型与元素类型序列不兼容 错误名称可以映射到实现的统一诊断系统。 12. 兼容性 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``(a, b)`` 统一表示元组。原开区间写法 ``(a, b)`` 迁移为 ``std.interval_open(a, b)`` [4]_。 13. 引用 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. [1] :doc:`LSR-000 - Lamina 核心语言规范(草案) ` - 提供基础类型、函数返回和模式匹配语法 .. [2] :doc:`LSR-011 - 代数数据类型规范 ` - 定义 ADT;元组可作为 ADT 字段 .. [3] :doc:`LSR-013 - 集合类型规范 ` - 定义集合;集合元素可以是可哈希元组 .. [4] :doc:`LSR-017 - 区间类型规范 ` - 定义标准库区间构造函数和区间类型