仓颉编程语言青少年基础教程:特殊数据类型Unit类型和Nothing类型)
仓颉编程语言青少年基础教程:特殊数据类型(Unit类型和Nothing类型)
仓颉编程语言中的Unit类型和Nothing类型是两种特殊的不可变类型。
Unit 类型,它有一个唯一的值:()。
Nothing 类型它不包含任何值。
Unit类型
对于那些只关心副作用而不关心值的表达式,它们的类型是 Unit。例如,print 函数、赋值表达式、复合赋值表达式、自增和自减表达式、循环表达式,它们的类型都是 Unit。
【这里说的副作用(side effect)在编程里是个完全中性的术语(不是贬义词😊哈),它只是客观描述一种现象:“表达式除了返回值外,还对外界产生可见影响。】
Unit 类型只有一个值,也是它的字面量:()。除了赋值、判等和判不等外,Unit 类型不支持其他操作。
下面是几个相关示例
1. 打印函数(print/println)
print 和 println 的作用是输出内容到控制台(副作用),不需要返回任何值,因此它们的类型是 Unit。示例:
main() {// 调用println后,返回值是Unit类型的()let res = println("你好,Unit类型") // 你好,Unit类型// 测试返回值println("println的返回值:${res}") // println的返回值:()println("println返回值和()判等:${res == ()}"); // 输出:println返回值和()判等:true
}
说明:println 的核心是 “输出内容”(副作用),返回的 () 仅表示 “执行完毕”,无实际意义。
编译运行截图:
2.赋值表达式、复合赋值表达式、自增和自减表达式、循环表达式,它们的类型都是 Unit。示例:
main() {var a = 0 let b = (a = 5) //赋值表达式a = 5 返回Unit;副作用:a被修改为5 println("a = ${a}" ) // 输出:y = 5println("b = ${b}" ) //输出: b = ()var x = 10 // 变量声明(不是赋值表达式) // 赋值表达式"x = 10"的类型是Unit,返回()let assign_res = (x += 3) //复合赋值表达式x += 3返回Unit;副作用:x被修改为13 println("x的新值:${x}") // 输出:x的新值:13println("赋值表达式的返回值:${assign_res}" ) // 输出:赋值表达式的返回值:()
}
3. 循环表达式(for、while、do-while)
循环的核心是 “重复执行代码块”(副作用,如多次打印、累计计算),整个循环表达式的类型是 Unit。以for为例的示例:
main() {// for循环的类型是Unit,返回()let loop_res = for (i in 1..4) {print("${i} ") // 副作用:打印1 2 3};println() // 换行println("循环表达式的返回值:${loop_res}" ) // 输出: 循环表达式的返回值:()
}
4.Unit 类型仅支持 赋值、判等(==)、判不等(!=),不支持其他操作(如算术运算、比较运算)。示例:
main() {let u1: Unit = () // 显式声明Unit类型变量let u2: Unit = ()// 允许:判等(Unit只有一个值,必然相等)println("u1 == u2:${ u1 == u2}") // 输出: u1 == u2:trueprintln("u1 != u2:${u1 != u2}") // 输出:u1 != u2:false// 允许:赋值let u3 = u1 // u3的值为()println("u3 =${u3}") // 输出:u3 =()// 不允许:其他操作(编译报错)// let sum = u1 + u2 // 错误:Unit不支持加法// let is_greater = u1 > u2 // 错误:Unit不支持比较
}
Nothing类型
Nothing 是一种特殊的类型,它不包含任何值,并且 Nothing 类型是所有类型的子类型(这当中也包括 Unit 类型)。
break、continue、return 和 throw 表达式的类型是 Nothing,程序执行到这些表达式时,它们之后的代码将不会被执行(后面代码不可达,因为流程被中断了)。return 只能在函数体中使用,break、continue 只能在循环体中使用。
• break:中断循环,跳出循环体;
• continue:中断当前循环迭代,直接进入下一次;
• return:返回值,中断函数执行,返回调用处;
• throw:抛出异常,中断当前执行流(用于错误处理)。
注意:目前编译器还不允许在使用类型的地方显式地使用 Nothing 类型。
示例 1:return 表达式(函数中)
若return 后面有表达式,将表达式的值作为整个函数的调用结果传递出去——将值返回给函数的调用者。中断函数执行,返回调用处。示例源码如下:
func get_number(flag: Bool): Int64 {if (flag) {return 10 // return // 以下代码不会执行(流程已被return中断) }return 20 // return
}main() {println(get_number(true)) // 输出:10println(get_number(false)) // 输出:20
}
运行截图:
示例 2:break 表达式(循环中)
break 会中断循环。源码如下:
main() {for(i in 1..=5) {if (i == 3) { //i等于3时break; // break // 以下代码不会执行 }println("i = ${i}");}
}
示例 3:continue 表达式(循环中)
continue 会跳过当前迭代。源码如下:
main() {for (i in 1..=5) {if(i % 2 == 0) {continue; // continue// 以下代码不会执行 }println("i = ${i}");}
}
示例 4:throw
抛出异常,中断当前执行流(用于错误处理)。源码如下:
// 定义一个可能抛出异常的除法函数
func divide(a: Int, b: Int): Int {if (b == 0) {// 当除数为0时,抛出异常(throw的类型是Nothing,后续代码不执行)throw NoneValueException("除数不能为0") // 假设throw可以携带错误信息(字符串类型)// 以下代码永远不会执行(因为throw中断了流程)}a / b // 正常情况返回除法结果
}main() {let num1 = 10;let num2 = 0; // 除数为0,会触发异常// 使用try-catch捕获并处理异常try {let result = divide(num1, num2);println("${num1} / ${num2} = ${result}"); // 若正常执行,打印结果} catch (e:NoneValueException) {// 捕获到throw抛出的异常,处理错误println("发生错误:${e}"); // 输出错误信息}// 异常被处理后,程序继续执行后续代码println("程序继续运行...");
}