仓颉编程语言复合数据类型(下)
一、元组类型(Tuple)
1.1 元组的基本概念
元组(Tuple)是仓颉语言中将多个不同类型的值组合成一个复合值的轻量级数据结构。元组的主要特点包括:
- 固定长度:一旦创建,元组的大小不可改变
- 类型异构:可以包含不同类型的元素
- 不可变性:创建后内容不可修改
- 有序性:元素按定义顺序排列,通过位置索引访问
1.2 元组的定义与初始化
仓颉中定义元组使用圆括号()
将元素括起来,元素间用逗号分隔:
// 基本元组定义 let tuple1 = (1, "hello", true) // 类型为(Int64, String, Bool) // 显式类型标注 let tuple2: (Int32, Float64) = (100, 3.14) // 空元组 let empty = () // 类型为Unit
带标签的元组可以给元素命名,提高代码可读性:
let person = (name: "Alice", age: 30, isStudent: false)
1.3 元组的访问与解构
索引访问(从0开始):
let first = tuple1[0] // 获取第一个元素(Int64类型) let second = tuple1[1] // 获取第二个元素(String类型)
解构赋值可以将元组元素解构到多个变量:
let (num, str, flag) = tuple1 // num = 1, str = "hello", flag = true
部分解构使用下划线_
忽略不需要的元素:
let (_, name, _) = person // 只获取name字段
1.4 元组的应用场景
- 函数多返回值:
func getStats(arr: Array<Int64>): (min: Int64, max: Int64, avg: Float64) { // 计算并返回多个统计值 return (minVal, maxVal, avgVal) }
- 临时组合数据:
let coordinates = (x: 10.5, y: 20.3)
- 模式匹配:
match point { case (0, 0) => println("原点") case (_, 0) => println("X轴上") case (0, _) => println("Y轴上") case _ => println("其他位置") }
二、数组类型(Array)
2.1 数组的基本特性
仓颉中的数组(Array)是同类型元素的可变长度集合,具有以下特点:
- 类型统一:所有元素必须是相同类型
- 动态扩容:长度可动态增长
- 随机访问:通过索引高效访问任意元素
- 堆分配:存储在堆内存中
2.2 数组的定义与操作
数组定义:
// 空数组 let emptyArr: Array<Int64> = [] // 字面量初始化 let numbers = [1, 2, 3, 4, 5] // 类型推断为Array<Int64> // 构造函数初始化 let zeros = Array<Int64>(size: 10, repeat: 0) // 10个0的数组
基本操作:
// 访问元素 let first = numbers[0] // 索引从0开始 // 修改元素 numbers[1] = 20 // 修改第二个元素 // 获取长度 let len = numbers.size() // 添加元素 numbers.push(6) // 末尾添加元素 // 删除元素 let last = numbers.pop() // 移除并返回最后一个元素
2.3 数组的遍历
for-in循环:
for num in numbers { println(num) }
带索引遍历:
for (index, value) in numbers.enumerate() { println("索引${index}的值是${value}") }
高阶函数式操作:
// 映射 let squares = numbers.map { x => x * x } // 过滤 let evens = numbers.filter { x => x % 2 == 0 } // 归约 let sum = numbers.reduce(0) { acc, x => acc + x }
2.4 多维数组
仓颉通过数组嵌套实现多维数组:
// 二维数组 let matrix: Array<Array<Int64>> = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] // 访问元素 let center = matrix[1] // 5
三、区间类型(Range)
3.1 区间的概念与类型
区间(Range)表示一个有固定步长的数值序列,常用于循环和切片操作。仓颉提供两种区间:
-
左闭右开区间:
start..end
- 包含start,不包含end
- 如
1..4
表示1,2,3
-
闭区间:
start..=end
- 包含start和end
- 如
1..=4
表示1,2,3,4
3.2 区间的创建与使用
基本创建:
let range1 = 1..10 // 1到9 let range2 = 1..=10 // 1到10 let range3 = 10..1:-1 // 10到2,步长-1
指定步长:
let range4 = 0..10:2 // 0,2,4,6,8 let range5 = 10..0:-2 // 10,8,6,4,2
区间运算:
// 包含判断 if range1.contains(5) { ... } // 区间交集 let overlap = range1.intersect(range2) // 区间合并 let merged = range1.union(range2)
3.3 区间的应用
for循环:
for i in 1..10 { println(i) // 打印1到9 }
数组切片:
let arr = [0,1,2,3,4,5] let slice = arr[1..4] // [1,2,3]
边界检查:
func isValid(index: Int64): Bool { return index in 0..array.size() }
四、Unit类型
4.1 Unit类型的概念
Unit类型是仓颉中表示"无有意义值"的特殊类型,类似于其他语言中的void
。其特点包括:
- 唯一值:
()
,称为unit值 - 表示只有副作用没有返回值的表达式
- 用于函数返回值、变量类型等场景
4.2 Unit的使用场景
无返回值函数:
func greet(name: String): Unit { println("Hello, ${name}!") }
赋值表达式:
let x = (y = 10) // x的类型是Unit,值为()
流程控制结构:
// if表达式的分支返回Unit let result = if condition { doSomething() } else { doSomethingElse() }
4.3 Unit的特性
- 类型推断:当表达式没有明确返回值时,编译器会推断为Unit类型
- 操作限制:仅支持判等(==, !=)操作
- 模式匹配:可以匹配unit值
()
match someUnitValue { case () => println("got unit") }
五、Nothing类型
5.1 Nothing类型的概念
Nothing是仓颉类型系统的特殊底层类型,表示"永远不会正常返回"的计算。关键特性:
- 没有值:无法创建Nothing类型的实例
- 是所有类型的子类型(bottom type)
- 用于表示非正常终止的操作
5.2 Nothing的使用场景
异常抛出:
func fail(message: String): Nothing { throw Exception(message) }
无限循环:
func infiniteLoop(): Nothing { while true { // do something } }
程序终止:
func exit(code: Int64): Nothing { sys.exit(code) }
5.3 Nothing的特性与应用
-
类型系统作用:
- 作为所有类型的子类型,可以"安全"地出现在任何需要具体类型的地方
- 保证类型系统的完备性
-
与Unit的区别:
- Unit表示"有值但无意义",Nothing表示"无值"
- Unit值可以传递,Nothing无法实例化
-
模式匹配:
func safeParse(str: String): Int64 or Nothing { // 可能返回Int64或抛出异常 } let result = match safeParse(input) { case num: Int64 => num case _: Nothing => 0 // 处理异常情况 }
六、类型对比与应用指南
6.1 类型特性对比表
类型 | 可变性 | 元素类型 | 长度 | 典型用途 |
---|---|---|---|---|
元组 | 不可变 | 异构 | 固定 | 临时数据组合、多返回值 |
数组 | 可变 | 同质 | 可变 | 数据集合、算法处理 |
区间 | 不可变 | 同质 | 固定 | 循环控制、范围表示 |
Unit | - | - | - | 副作用操作、无返回值函数 |
Nothing | - | - | - | 非正常终止、异常处理 |
6.2 选择指南
-
需要组合不同类型数据:
- 使用元组,特别是需要保持数据结构简单时
- 示例:函数返回多个不同类型的值
-
处理同类型数据集合:
- 使用数组,特别是需要动态增删元素时
- 示例:存储用户列表、计算数据集统计量
-
表示数值范围:
- 使用区间,特别是循环控制和切片操作时
- 示例:遍历数组索引、生成数值序列
-
处理无返回值操作:
- 使用Unit类型,特别是只有副作用的函数
- 示例:打印日志、修改外部状态
-
处理非正常流程:
- 使用Nothing类型,特别是会中断程序正常执行的操作
- 示例:抛出异常、终止程序
6.3 最佳实践建议
-
元组使用建议:
- 元素不超过5个,否则考虑使用结构体
- 对重要元组使用标签提高可读性
- 避免深层嵌套元组
-
数组优化技巧:
- 预分配足够容量减少扩容开销
- 批量操作优先使用高阶函数
- 只读场景考虑使用不可变视图
-
区间注意事项:
- 注意开闭区间差异
- 检查步长方向与区间方向一致
- 大区间考虑惰性求值
-
Unit/Nothing使用:
- 明确区分无返回值与不会返回
- 不要显式创建Nothing实例
- 合理处理可能返回Nothing的函数
结语
仓颉编程语言的复合数据类型系统设计精良,从固定结构的元组到灵活多变的数组,从简洁的范围表达到特殊的Unit和Nothing类型,每种类型都有其明确的定位和适用场景。深入理解这些类型的特性和差异,能够帮助开发者编写出更加高效、健壮的仓颉代码。在实际开发中,应根据数据特性和操作需求,合理选择最适合的数据类型,并遵循语言的最佳实践,以充分发挥仓颉类型系统的优势。
更多推荐
所有评论(0)