LSR 012 - 元组类型规范

基本信息

  • LSR 编号 012

  • 标题 元组类型规范

  • 作者 Ziyang-Bai

  • 状态 草案

  • 类型 标准规范

  • 创建日期 08-09-2026

  • 归属项目 编译器、标准库

摘要

定义 Lamina 元组类型。元组是固定长度、按位置索引、创建后不可变的匿名积类型,可用于函数返回、临时组合和 let 解构 [1]。本规范同时规定元组与分组、函数实参、数组及区间构造之间的语法边界。

技术规范

1. 范围

元组用于组合少量按位置区分的值。元组的长度和各位置元素类型共同组成其类型。元组字面量包含至少两个元素;分组、函数调用、数组和区间分别使用各自的语法规则。

2. 元组类型

元组类型由一组有序元素类型组成。

(num, text)
(num, text, num)
  • 元组长度固定

  • 元组元素可以是不同类型

  • 元组类型由长度和每个位置的类型共同决定

  • 元组值默认不可变

  • 元组类型是结构类型;元素类型序列相同的两个元组类型相同

  • 数学位置的基本类型统一为 num,不因整数、有理数、符号表达式或近似值的内部表示而形成不同元组类型

  • (int, int) 等标注表示各数学位置的值约束,基本类型仍为 (num, num);约束不构成独立的静态重载签名

3. 元组字面量

元组字面量使用圆括号,并以逗号分隔元素。

let pair = (1, "one")
let triple = (1, "x", true)
  • 非空元组按元素表达式推导类型

  • 元组字面量至少包含两个元素

  • 单元素圆括号表达式按分组表达式解析

  • (a, b) 始终解析为二元素元组

  • 函数名后紧跟的 f(a, b) 按函数调用解析

  • std.interval_open(a, b) 是普通函数调用,其结果为开区间 [4]

let a = (1)

a 是基本类型为 num 的分组表达式结果,值满足整数约束。

4. 元数

元组字面量的元数至少为二。(value) 是分组表达式;f() 是零实参函数调用。函数的返回语义由核心语言规范定义 [1]。

5. 元组访问

元组元素按位置访问,索引从 1 开始,与 Lamina 现有线性代数索引规则保持一致。

let p = (10, "x")
let a = p.1
let b = p.2
  • 元组索引必须是编译期常量正整数

  • 第一个元素的位置为 1

  • 访问位置超过元组长度是编译错误

  • 元组位置访问读取创建元组时绑定在该位置的元素

6. 元组解构

元组可在 let 中解构。

let (x, y) = (1, 2)
  • 解构绑定的位置数必须与元组长度一致

  • _ 可忽略对应位置

  • 解构绑定的变量类型由对应位置推导

  • 解构保持原元组值,并为各位置创建对应绑定

7. 函数返回元组

函数可以返回元组作为单一返回值。

func divmod(a int, b int) -> (int, int) {
    return (a // b, a % b)
}

let (q, r) = divmod(10, 3)
  • Lamina 函数返回单个值

  • 多个按位置区分的结果应使用元组返回,支持同构与异构的元素组合

  • 无序、按结构相等去重的同类数学结果使用集合返回 [3];需要顺序或重数的结果使用向量或由具体接口定义的组合

  • 普通数学函数直接返回值,失败沿 LSR-018 [2] 的错误传播规则处理

  • 示例中 int 是各参数和返回位置的整数值约束,不是独立基本类型;调用和返回均须校验约束,静态无法确定时在运行期检查,未决时报 Inconclusive

  • divmod 要求除数非零;确定违反约束或无定义的运算沿错误路径传播,不能以元组包装掩盖错误

8. 相等性与哈希

元组的 == 和 != 返回 bool,按位置递归进行结构比较,不构造数学关系。

  • 两个元组长度不同,则类型不同

  • 两个同类型元组逐位置结构相同时,整体相等

  • 递归标准与 std.cas.same_structure 一致;元组中的 num 及数学容器直接使用内部结构比较,不调用会构造关系的 ==,也不调用有限预算的 === 或数学证明

  • 精确数字叶按精确数值比较,不依赖小整数、大整数或有理数等内部表示;近似节点保留表示值、近似类别和目标工作精度等结构区别,并与精确数字叶区别

  • 普通 bool、text、rule 和固定状态值使用各自的布尔结构相等规则;嵌套元组递归遵循本节

  • 只有所有元素具有上述结构比较语义时,元组才支持 == 和 !=

  • 只有所有元素可哈希时,元组才可作为哈希键;哈希必须与结构比较一致,不得把证明预算或可变证明状态纳入键

9. 求值与存储语义

元组字面量的元素表达式按源码从左到右各求值一次。元组值创建后,元素位置和元素绑定保持不变。

  • 元组的不可变性是浅层不可变:位置绑定不变;若元素是显式引用对象,其对象状态仍遵循该引用类型自身语义

  • vector、matrix、set、array、table 等值语义容器作为元素时,元组保留创建时的值;修改原来源的 var 根路径不得改变元组内的值

  • 元组位置、let 绑定和只读闭包不提供可写子路径,即使元组本身绑定到 var,也不能经 tuple.1[...] 修改其中的容器;可将元素值绑定为独立 var 后修改该独立值

  • 实现可以内联、装箱、共享、复制或利用唯一所有权;各种表示具有相同的求值顺序、结构相等和值语义,不要求可观察的容器对象身份

  • is 仅适用于显式引用对象,不能用于观察元组或其中数学容器的共享方式

  • 跨模块接口必须保留元组长度、元素顺序和每个位置的静态类型

10. 与数组、集合和区间的区别

类型

长度

元素类型

顺序

主要用途

元组

固定

可异构

有序

多值组合

数组

可变或运行期长度

通常同构

有序

程序式序列

集合 [3]

运行期大小

同构

无序

去重数学集合

区间 [4]

两个端点

同构

有序边界

表示实数集合范围,不由整数端点推断为离散范围

11. 诊断

实现至少应区分下列错误:

  • TupleArityMismatch:解构绑定的位置数与元组长度不同

  • TupleIndexNotConstant:位置访问不是编译期常量

  • TupleIndexOutOfBounds:位置不在 1 到元组长度之间

  • TupleAssignment:试图修改元组元素绑定或经元组位置写入值语义子路径

  • TupleTypeMismatch:目标元组类型与元素类型序列不兼容

错误名称可以映射到实现的统一诊断系统。

12. 兼容性

(a, b) 统一表示元组。原开区间写法 (a, b) 迁移为 std.interval_open(a, b) [4]。

13. 引用