引言
仓颉编程语言作为一门现代化的编程语言,提供了丰富而严谨的基本数据类型系统。这些数据类型不仅是构建程序的基础,更是理解仓颉语言设计哲学的重要窗口
1. 整数类型 (Integer Types)
1.1 有符号整数类型
仓颉语言提供了多种有符号整数类型,每种都有其特定的位宽和表示范围:
cangjie
// 有符号整数类型示例
let int8: Int8 = 127 // 8位有符号整数,范围:-128 到 127
let int16: Int16 = 32767 // 16位有符号整数,范围:-32,768 到 32,767
let int32: Int32 = 2147483647 // 32位有符号整数,范围:-2^31 到 2^31-1
let int64: Int64 = 9223372036854775807 // 64位有符号整数,范围:-2^63 到 2^63-1
let intNative: IntNative = 100 // 平台相关的有符号整数类型
1.2 无符号整数类型
无符号整数类型只能表示非负值,提供了更大的正数范围:
cangjie
// 无符号整数类型示例
let uint8: UInt8 = 255 // 8位无符号整数,范围:0 到 255
let uint16: UInt16 = 65535 // 16位无符号整数,范围:0 到 65,535
let uint32: UInt32 = 4294967295 // 32位无符号整数,范围:0 到 2^32-1
let uint64: UInt64 = 18446744073709551615 // 64位无符号整数,范围:0 到 2^64-1
let uintNative: UIntNative = 100 // 平台相关的无符号整数类型
1.3 整数字面量的多种表示方式
仓颉语言支持多种进制的整数表示:
cangjie
// 不同进制的整数表示
let decimal = 42 // 十进制
let binary = 0b101010 // 二进制:42
let octal = 0o52 // 八进制:42
let hexadecimal = 0x2A // 十六进制:42
// 使用下划线分隔符提高可读性
let largeNumber = 1_000_000_000 // 十亿
let binaryWithSeparator = 0b1010_1010 // 二进制分隔
// 显式类型后缀
let explicitInt8 = 100i8 // 明确指定为Int8类型
let explicitUInt64 = 0xFFu64 // 明确指定为UInt64类型
1.4 字符字节字面量
仓颉语言支持ASCII字符的字节表示:
cangjie
// 字符字节字面量示例
let asciiX = b'x' // UInt8类型,值为120
let asciiNewline = b'\n' // UInt8类型,值为10
let asciiUnicode = b'\u{78}' // UInt8类型,值为120 (0x78)
let asciiCalculation = b'\u{90}' - b'\u{66}' + b'x' // 字节运算
2. 浮点类型 (Floating-Point Types)
2.1 浮点类型概述
仓颉语言提供了三种精度的浮点类型:
cangjie
// 浮点类型示例
let float16: Float16 = 3.14f16 // 16位浮点数,精度约3位
let float32: Float32 = 3.14159f32 // 32位浮点数,精度约6位
let float64: Float64 = 3.14159265359 // 64位浮点数,精度约15位
// 自动类型推断
let autoFloat = 3.14 // 默认推断为Float64
2.2 浮点数字面量
支持十进制和十六进制表示:
cangjie
// 十进制浮点数字面量 有小数时可以省略e
let decimalFloat = 3.14159 // 标准十进制表示
let scientificNotation = 2.5e3 // 科学计数法:2500.0
let negativeExponent = 1.5e-2 // 负指数:0.015
let noIntegerPart = .123e2 // 无整数部分:12.3
// 十六进制浮点数字面量,必须有p
let hexFloat = 0x1.1p0 // 十六进制:1.0625
let hexPower = 0x1p2 // 十六进制幂:4.0
let hexFraction = 0x.2p4 // 十六进制分数:2.0
// 显式类型后缀
let explicitFloat32 = 3.14f32 // 明确指定为Float32
let explicitFloat64 = 2.5e3f64 // 明确指定为Float64
3. 布尔类型 (Boolean Type)
3.1 布尔字面量
布尔类型是逻辑运算的基础:
cangjie
// 布尔字面量
let trueValue: Bool = true // 真值
let falseValue: Bool = false // 假值
// 布尔运算
let logicalAnd = true && false // 逻辑与:false
let logicalOr = true || false // 逻辑或:true
let logicalNot = !true // 逻辑非:false
// 复合赋值
var boolVar = true
boolVar &&= false // 复合逻辑与赋值
boolVar ||= true // 复合逻辑或赋值
4. 字符类型 (Character Type)
4.1 Rune类型
仓颉语言使用Rune类型表示Unicode字符:
cangjie
// 字符字面量
let singleChar: Rune = r'a' // 单个字符
let doubleQuoteChar: Rune = r"b" // 双引号字符
// 转义字符
let backslash: Rune = r'\\' // 反斜杠
let newline: Rune = r'\n' // 换行符
let tab: Rune = r'\t' // 制表符
// Unicode字符
let chineseChar: Rune = r'\u{4f60}' // 中文字符"你"
let chineseChar2: Rune = r'\u{597d}' // 中文字符"好"
// 字符比较
let isGreater = r'a' > r'b' // 字符比较:false
let isEqual = r'a' == r'a' // 字符相等:true
5. 字符串类型 (String Type)
5.1 字符串字面量
仓颉语言提供了多种字符串表示方式:
cangjie
// 单行字符串
let emptyString: String = "" // 空字符串
let singleQuoteString = 'Hello Cangjie' // 单引号字符串
let doubleQuoteString = "Hello Cangjie" // 双引号字符串
let escapedString = "Hello\nCangjie" // 转义字符串
// 多行字符串
let multilineString = """
Hello,
Cangjie
Programming Language
"""
let multilineSingleQuote = '''
Another
Multiline
String
'''
// 原始字符串(不处理转义)
let rawString = #"Hello\nCangjie"# // 输出:Hello\nCangjie
let multiHashString = ###"Hello"### // 多井号原始字符串
5.2 插值字符串
插值字符串是仓颉语言的强大特性:
cangjie
// 基本插值
let name = "Cangjie"
let version = 1.0
let message = "Welcome to ${name} ${version}"
// 复杂插值表达式
let radius = 5.0
let area = "Circle area: ${let PI = 3.14159; PI * radius * radius}"
// 多变量插值
let x = 10
let y = 20
let sum = "Sum of ${x} and ${y} is ${x + y}"
5.3 字符串操作
字符串支持多种操作:
cangjie
// 字符串拼接
let str1 = "Hello"
let str2 = "Cangjie"
let combined = str1 + " " + str2 // "Hello Cangjie"
// 字符串比较
let isEqual = str1 == str2 // 相等比较
let isNotEqual = str1 != str2 // 不等比较
// 字符串方法
let contains = str2.contains("ang") // 包含检查
let splitResult = str2.split("a") // 字符串分割
6. 数组类型 (Array Types)
6.1 引用类型数组 (Array)
Array是仓颉语言中最常用的数组类型:
cangjie
// 数组声明和初始化
let emptyArray: Array<Int64> = [] // 空数组
let numberArray = [1, 2, 3, 4, 5] // 数字数组
let stringArray: Array<String> = ["a", "b", "c"] // 字符串数组
// 构造函数初始化
let sizedArray = Array<Int64>(5, repeat: 0) // [0, 0, 0, 0, 0]
let functionArray = Array<Int64>(3, {i => i * 2}) // [0, 2, 4]
// 尾随闭包语法
let functionArray2 = Array<Int64>(3){i => i * 2} // [0, 2, 4]
// 数组访问
let firstElement = numberArray[0] // 第一个元素
let slice1 = numberArray[0..3] // 切片:[1, 2, 3]
let slice2 = numberArray[..3] // 从开始到索引3:[1, 2, 3]
let slice3 = numberArray[2..] // 从索引2到结束:[3, 4, 5]
// 数组修改
var mutableArray = [1, 2, 3]
mutableArray[0] = 10 // 修改元素
// mutableArray: [10, 2, 3]
// 数组遍历
for (element in numberArray) {
println("Element: ${element}")
}
// 数组大小
let arraySize = numberArray.size // 获取数组长度
6.2 值类型数组 (VArray)
VArray是固定长度的值类型数组:
cangjie
// VArray声明和初始化
let varr1: VArray<Int64, $3> = [1, 2, 3] // 固定长度3的数组
let varr2 = VArray<Int64, $5>({i => i * 2}) // 使用函数初始化
let varr22 = VArray<Int64, $5>{i => i * 2} // 使用函数初始化,同时使用尾随闭包
let varr3 = VArray<Int64, $4>(repeat: 0) // 重复值初始化
// VArray操作
let element = varr1[1] // 访问元素:2
var mutableVarr: VArray<Int64, $3> = [1, 2, 3]
mutableVarr[2] = 10 // 修改元素
let varrSize = varr1.size // 获取长度:3
7. 元组类型 (Tuple Type)
7.1 元组基础
元组允许将不同类型的值组合在一起:元组至少是2维的,可以有多个元素,每个元素可以是不同的类型。
cangjie
// 元组声明和初始化
let point: (Int64, Int64) = (10, 20) // 二维点坐标
let person: (String, Int64, Bool) = ("Alice", 25, true) // 人员信息
// 元组访问
let x = point[0] // 第一个元素:10
let y = point[1] // 第二个元素:20
let name = person[0] // 姓名:Alice
let age = person[1] // 年龄:25
// 命名元组
let fruit: (name: String, price: Int64) = ("apple", 5)
let fruitName = fruit[0] // 通过索引访问
// fruit.name 不可用,命名只是类型注解
7.2 元组的多重赋值
元组支持多重赋值操作:
cangjie
// 多重赋值
var a: Int64
var b: Int64
(a, b) = (1, 2) // a = 1, b = 2
// 交换值
(a, b) = (b, a) // a = 2, b = 1
// 忽略某些值
(a, _) = (3, 4) // a = 3, 忽略4
(_, _) = (5, 6) // 忽略所有值
_ = (5, 6) // 也可以通过_ 忽略所有值
8. 区间类型 (Range Type)
8.1 区间基础
区间类型用于表示有序序列:
cangjie
// 区间字面量
let range1 = 0..10 // 左闭右开区间:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let range2 = 0..=10 // 左闭右闭区间:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let range3 = 10..0 : -2 // 递减区间:[10, 8, 6, 4, 2]
// 带步长的区间
let stepRange1 = 0..10 : 2 // 步长为2:[0, 2, 4, 6, 8]
let stepRange2 = 0..=10 : 3 // 步长为3:[0, 3, 6, 9]
// 构造函数创建区间
let constructedRange = Range<Int64>(0, 10, 1, true, true, false) // 左闭右开区间:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8.2 区间操作
区间支持多种操作:
cangjie
// 区间遍历
for (i in 0..5) {
println("Index: ${i}")
}
// 区间包含检查 目前不支持这种写法
// let isInRange = 5 in 0..10 // 检查5是否在区间内
// let isNotInRange = 15 in 0..10 // 检查15是否在区间内
// 空区间
let emptyRange1 = 10..0 : 1 // 空区间
let emptyRange2 = 0..10 : -1 // 空区间
9. Unit类型和Nothing类型
9.1 Unit类型
Unit类型表示不关心值的表达式:
cangjie
// Unit类型示例
let unitValue: Unit = () // Unit类型的唯一值
var x = 5
let assignment: Unit = (x = 10) // 赋值表达式的类型是Unit
let printResult: Unit = print("Hello") // print函数的返回类型是Unit
// Unit类型操作
let isEqual = () == () // Unit相等比较:true
let isNotEqual = () != () // Unit不等比较:false
9.2 Nothing类型
Nothing类型是所有类型的子类型:
cangjie
// Nothing类型示例
func alwaysThrows(): Int64 {
throw Exception("This function always throws" // 返回类型是Nothing
)
}
func infiniteLoop(): Int64 {
while (true) {
// 无限循环,永远不会返回
}
return 0
}
// break、continue、return表达式的类型都是Nothing
func exampleFunction(): Int64 {
if (true) {
let v = return 42 // return表达式类型是Nothing
}
return 0
}
10. 基本操作符详解
10.1 赋值操作符
赋值操作符是仓颉语言中最重要的操作符之一:
cangjie
// 基本赋值
var a = 10
a = 20 // 简单赋值
// 多重赋值(元组赋值)
var x: Int64
var y: Int64
(x, y) = (1, 2) // x = 1, y = 2
// 交换值
(x, y) = (y, x) // x = 2, y = 1
// 忽略某些值
(x, _) = (3, 4) // x = 3, 忽略4
(_, _) = (5, 6) // 忽略所有值
// 注意:赋值表达式不能用于条件判断
// if (a = 5) { } // 编译错误,赋值表达式类型是Unit
10.2 算术操作符
cangjie
// 基本算术运算
let sum = 10 + 5 // 加法:15
let difference = 10 - 5 // 减法:5
let product = 10 * 5 // 乘法:50
let quotient = 10 / 3 // 除法:3(整数除法)
let remainder = 10 % 3 // 取余:1
let power = 2 ** 3 // 幂运算:8
// 浮点运算
let floatSum = 3.14 + 2.86 // 浮点加法:6.0
let floatProduct = 3.14 * 2.0 // 浮点乘法:6.28
// 字符串拼接
let string1 = "Hello"
let string2 = "Cangjie"
let combined = string1 + " " + string2 // "Hello Cangjie"
10.3 关系操作符
cangjie
// 数值比较
let lessThan = 5 < 10 // true
let lessEqual = 5 <= 5 // true
let greaterThan = 10 > 5 // true
let greaterEqual = 10 >= 10 // true
let equal = 5 == 5 // true
let notEqual = 5 != 10 // true
// 字符串比较
let strCompare = "abc" < "def" // true(字典序比较)
// 元组比较
let tupleEqual = (1, 2) == (1, 2) // true
// let tupleEqual = (1, 2) == (1, "String") // false 只能相同类型的元组(长度和各个位置的类型都一样)比较
10.4 逻辑操作符
cangjie
// 逻辑运算
let logicalAnd = true && false // false
let logicalOr = true || false // true
let logicalNot = !true // false
// 短路求值
func expensiveOperation(): Bool {
println("This is expensive!")
return true
}
let shortCircuit = false && expensiveOperation() // 不会执行expensiveOperation
let shortCircuit2 = true || expensiveOperation() // 不会执行expensiveOperation
// 逻辑运算的完整示例
func isEven(a: Int64): Bool {
if (a % 2 == 0) {
println("${a} 是偶数")
true
} else {
println("${a} 不是偶数")
false
}
}
main() {
// 短路求值演示
let result1 = isEven(2) && isEven(20) // 两个函数都会执行
let result2 = isEven(3) && isEven(30) // 只执行第一个函数,第二个不执行
let result3 = isEven(4) || isEven(40) // 只执行第一个函数,第二个不执行
let result4 = isEven(5) || isEven(50) // 两个函数都会执行
}
10.5 位运算操作符
cangjie
// 位运算的详细示例
main() {
// 位运算
let bitwiseNot = !10 // 按位求反:-11
println("!10 = ${bitwiseNot}")
let leftShift = 5 << 2 // 左移:20
println("5 << 2 = ${leftShift}")
let rightShift = 20 >> 2 // 右移:5
println("20 >> 2 = ${rightShift}")
let bitwiseOr = 10 | 15 // 按位或:15
println("10 | 15 = ${bitwiseOr}")
let bitwiseXor = 10 ^ 15 // 按位异或:5
println("10 ^ 15 = ${bitwiseXor}")
// 按位与
let bitwiseAnd = 10 & 15 // 按位与:10
println("10 & 15 = ${bitwiseAnd}")
// 复合位运算赋值
var bits = 10
bits <<= 2 // 左移赋值:40
println("bits <<= 2 = ${bits}")
bits >>= 1 // 右移赋值:20
println("bits >>= 1 = ${bits}")
bits &= 15 // 按位与赋值:4
println("bits &= 15 = ${bits}")
let a: Int64 = 10 // 二进制:1010
let b: Int64 = 15 // 二进制:1111
// 按位与:1010 & 1111 = 1010 (10)
let andResult = a & b
println("按位与:${a} & ${b} = ${andResult}")
// 按位或:1010 | 1111 = 1111 (15)
let orResult = a | b
println("按位或:${a} | ${b} = ${orResult}")
// 按位异或:1010 ^ 1111 = 0101 (5)
let xorResult = a ^ b
println("按位异或:${a} ^ ${b} = ${xorResult}")
// 按位求反:!1010 = 1111111111111111111111111111111111111111111111111111111111110101 (-11)
let notResult = !a
println("按位求反:!${a} = ${notResult}")
// 左移:1010 << 2 = 101000 (40)
let leftShiftResult = a << 2
println("左移:${a} << 2 = ${leftShiftResult}")
// 右移:1010 >> 1 = 101 (5)
let rightShiftResult = a >> 1
println("右移:${a} >> 1 = ${rightShiftResult}")
// 移位规则说明
println("注意:右操作数不能为负数,且不能超过操作数位宽")
}
10.6 复合赋值操作符
cangjie
main() {
// 复合赋值
var value = 10
value += 5 // 加法赋值:15
println("value += 5 = ${value}")
value -= 3 // 减法赋值:12
println("value -= 3 = ${value}")
value *= 2 // 乘法赋值:24
println("value *= 2 = ${value}")
value /= 4 // 除法赋值:6
println("value /= 4 = ${value}")
value %= 4 // 取余赋值:2
println("value %= 4 = ${value}")
value **= 3 // 幂运算赋值:8
println("value **= 3 = ${value}")
// 位运算复合赋值
value <<= 2 // 左移赋值:32
println("value <<= 2 = ${value}")
value >>= 1 // 右移赋值:16
println("value >>= 1 = ${value}")
value &= 15 // 按位与赋值:0
println("value &= 15 = ${value}")
value |= 10 // 按位或赋值:10
println("value |= 10 = ${value}")
value ^= 5 // 按位异或赋值:15
println("value ^= 5 = ${value}")
}
10.7 自增自减操作符
cangjie
main() {
// 自增自减
var counter = 5
counter++ // 后置自增:counter = 6
counter-- // 后置自减:counter = 5
// ++表达式的返回值是Unit
let result = counter++
println("result = ${result}")
}
10.8 操作符优先级和结合性
仓颉语言中的操作符遵循特定的优先级和结合性规则:
cangjie
// 操作符优先级示例(从高到低)
main() {
let a = 2 + 3 * 4 // 先乘后加:2 + (3 * 4) = 14
let b = 2 * 3 + 4 // 先乘后加:(2 * 3) + 4 = 10
let c = 5 + 3 * 2 ** 3 // 幂运算 > 乘法 > 加法:5 + (3 * (2 ** 3)) = 29
let d = 10 & 15 | 20 // 按位与 > 按位或:(10 & 15) | 20 = 10 | 20 = 30
let e = 5 < 10 && 3 > 1 // 关系运算 > 逻辑运算:(5 < 10) && (3 > 1) = true
// 使用括号明确优先级
let f = (2 + 3) * 4 // 先加后乘:(2 + 3) * 4 = 20
println("a = ${a}, b = ${b}, c = ${c}, d = ${d}, e = ${e}, f = ${f}")
}
10.9 特殊操作符
10.9.1 区间操作符
区间操作符用于创建序列:
cangjie
main() {
// 区间操作符
let range1 = 0..10 // 左闭右开区间
let range2 = 0..=10 // 左闭右闭区间
let range3 = 0..10 : 2 // 带步长的区间
// 区间在循环中的应用
for (i in 0..5) {
println("索引:${i}")
}
}
10.9.2 Coalescing操作符
Coalescing操作符用于Option类型的解构:
cangjie
main() {
// Coalescing操作符
let someValue = Option<Int64>.Some(42)
let noneValue = Option<Int64>.None
let result1 = someValue ?? 0 // 42(Some值)
let result2 = noneValue ?? 0 // 0(默认值)
// 短路求值
let expensiveDefault = Option<Int64>.None ?? {
=>
println("计算默认值1")
100
}() // 会执行默认值计算
let someExpensive = Option<Int64>.Some(50) ?? {
=>
println("计算默认值2")
100
}() // 不会执行默认值计算
}
11. 类型转换和兼容性
11.1 数值类型转换
cangjie
main() {
// 整数类型转换
let int8Value: Int8 = 100
let int16Value: Int16 = Int16(int8Value) // 8位转16位
let int32Value: Int32 = Int32(int16Value) // 16位转32位
let int64Value: Int64 = Int64(int32Value) // 32位转64位
// 浮点类型转换
let float32Value: Float32 = 3.14f32
let float64Value: Float64 = Float64(float32Value) // 32位转64位
// 整数转浮点
let intToFloat: Float64 = Float64(42) // 整数转浮点
let floatToInt: Int64 = Int64(3.14) // 浮点转整数(截断)
}
11.2 字符和字符串转换
cangjie
main() {
// 字符转换
let charValue: Rune = r'A'
let uint32Value: UInt32 = UInt32(charValue) // Rune转UInt32
let intValue: Int64 = 65
let runeValue: Rune = Rune(intValue) // Int64转Rune
// 字符串转换
let byteValue: Byte = "A" // 字符串转Byte(ASCII字符)
let runeFromString: Rune = "B" // 单字符字符串转Rune
}
12. 实际应用示例
12.1 数学计算程序
cangjie
// 计算圆的面积和周长
func calculateCircle(radius: Float64): (area: Float64, circumference: Float64) {
let PI: Float64 = 3.14159265359
let area = PI * radius * radius
let circumference = 2.0 * PI * radius
return (area, circumference)
}
main() {
let radius = 5.0
let (area, circumference) = calculateCircle(radius)
println("半径为 ${radius} 的圆:")
println("面积:${area}")
println("周长:${circumference}")
}
12.2 数组操作程序
cangjie
// 数组排序和查找
func findMaxAndMin(numbers: Array<Int64>): (max: Int64, min: Int64) {
if (numbers.size == 0) {
return (0, 0)
}
var max = numbers[0]
var min = numbers[0]
for (i in 1..numbers.size) {
if (numbers[i] > max) {
max = numbers[i]
}
if (numbers[i] < min) {
min = numbers[i]
}
}
return (max, min)
}
main() {
let numbers = [3, 7, 1, 9, 2, 8, 5]
let (max, min) = findMaxAndMin(numbers)
println("数组:${numbers}")
println("最大值:${max}")
println("最小值:${min}")
}
12.3 字符串处理程序
cangjie
// 字符串统计和分析
func analyzeString(text: String): (charCount: Int64, wordCount: Int64, lineCount: Int64) {
let charCount = text.size
// 计算单词数(简单实现)
let words = text.split(" ")
let wordCount = words.size
// 计算行数
let lines = text.split("\n")
let lineCount = lines.size
return (charCount, wordCount, lineCount)
}
main() {
let sampleText = """
Hello Cangjie Programming Language
This is a sample text
For demonstration purposes
"""
let (chars, words, lines) = analyzeString(sampleText)
println("文本分析结果:")
println("字符数:${chars}")
println("单词数:${words}")
println("行数:${lines}")
}
13. 最佳实践和注意事项
13.1 类型选择建议
-
整数类型选择:
- 一般情况使用
Int64
,范围足够大且是默认类型 - 内存敏感场景考虑使用
Int32
或Int16
- 无符号场景使用对应的
UInt
类型
- 一般情况使用
-
浮点类型选择:
- 一般计算使用
Float64
,精度最高 - 内存受限场景使用
Float32
- 特殊场景(如机器学习)考虑
Float16
- 一般计算使用
-
数组类型选择:
- 固定长度的引用类型数组使用
Array<T>
- 固定长度且性能敏感使用
VArray<T, $N>
- 固定长度的引用类型数组使用
13.2 性能考虑
cangjie
// 性能优化示例
func optimizedArrayOperation() {
// 预分配数组大小
let size = 1000
let array = Array<Int64>(size, repeat: 0)
// 使用VArray避免堆分配
let varr: VArray<Int64, $10> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// 避免频繁的类型转换
let intValue: Int64 = 42
let floatValue: Float64 = Float64(intValue) // 显式转换
}
13.3 错误处理
cangjie
// 安全的数组访问
func safeArrayAccess<T>(array: Array<T>, index: Int64): Option<T> {
if (index >= 0 && index < array.size) {
return Option<T>.Some(array[index])
} else {
return Option<T>.None
}
}
// 安全的数值转换
func safeIntConversion(value: Float64): Option<Int64> {
if (value >= Float64(Int64.Min) && value <= Float64(Int64.Max)) {
return Option<Int64>.Some(Int64(value))
} else {
return Option<Int64>.None
}
}