加载中...
仓颉文档阅读-语言规约XVI: 常量求值

仓颉文档阅读-语言规约XVI: 常量求值

周二 10月 21 2025
1331 字 · 7 分钟

此样式内容, 表示文档原文内容

常量求值

const变量

const变量是一种特殊的变量, 它可以定义在编译时完成求值, 并且在运行时不可改变的变量

const变量与let/var声明的变量的区别是必须在定义时就初始化, 且必须用const表达式初始化

因此const变量的类型只能是const表达式支持的类型

let/var一样, const变量也支持省略类型

const表达式见下文定义

CANGJIE
const a: Int64 = 0                    // ok
const b: Int64                        // error, b 为初始化
const c = f()                         // error, f() 不是 const 表达式
const d = 0                           // ok, d 的类型是 Int64

func f(): Unit {}

const变量定义后可以像let/var声明的变量一样使用

let/var声明的变量不同, const由于在编译时就可以得到结果, 可以大幅减少程序运行时需要的计算

CANGJIE
const a = 0

main(): Int64 {
    let b: Int64 = a                  // ok
    print(a)                          // ok
    let c: VArray<Int64, $0> = []     // ok
    return 0
}

const变量可以是全局变量, 局部变量, 静态成员变量

const变量不能在扩展中定义

CANGJIE
const a = 0                           // ok

class C {
    const b = 0                       // error, const 成员字段必须由 static 修改
    static const c = 0                // ok

    var v: Int64

    init() {
        const d = 0                   // ok
        v = b + c + d
    }
}

extend C {
    const e = 0                       // error, const 不能在 extend 中定义
}

const变量可以访问对应类型的所有实例成员, 也可以调用对应类型的所有**非mut**实例成员函数

CANGJIE
struct Foo {
    let a = 0
    var b = 0

    const init() {}

    func f1() {}
    const func f2() {}
    mut func f3() {
        b = 123
    }
}

main(): Int64 {
    const v = Foo()
    print(v.a)                        // ok
    print(v.b)                        // ok
    v.f1()                            // ok
    v.f2()                            // ok
    v.f3()                            // error, f3 是 mut 函数
    return 0
}

const变量初始化后该类型实例的所有成员都是const的(深度const, 包含成员的成员), 因此不能被用于左值

CANGJIE
struct Foo {
    let a = 0
    var b = 0

    const init() {}
}

func f() {
    const v = Foo()
    v.a = 1                           // error
    v.b = 1                           // error
}

const修饰变量, 定义常量, 整个程序不允许修改次变量的值

const变量, 必须在定义时进行初始化

const可以修饰成员变量, 但必须是静态成员变量

const修饰一个实例, 此实例可以访问所有成员变量, 但只能访问非mut成员函数

const修饰一个实例, 此实例的所有成员变量默认会被const修饰, 禁止赋值(当左值)

const表达式

某些特定形式的表达式, 被称为const表达式, 这些表达式具备了可以在编译时求值的能力

const上下文中, 这些是唯一允许的表达式, 并且始终会在编译时进行求值

而在其它非const上下文, const表达式不保证在编译时求值

以下表达式都是const表达式

  1. 数值类型、BoolUnitRuneString类型的字面量(不包含插值字符串)

  2. 所有元素都是const表达式的array字面量(不能是 Array 类型), tuple字面量

  3. const变量, const函数形参, const函数中的局部变量

  4. const函数, 包含使用const声明的函数名、符合const函数要求的lambda、以及这些函数返回的函数表达式

  5. const函数调用(包含const构造函数), 该函数的表达式必须是const表达式, 所有实参必须都是const表达式

  6. 所有参数都是const表达式的enum构造器调用, 和无参数的enum构造器

  7. 数值类型、BoolUnitRuneString类型的算数表达式、关系表达式、位运算表达式, 所有操作数都必须是const表达式

  8. ifmatchtry、控制转移表达式(包含returnbreakcontinuethrow)、isas

    这些表达式内的表达式必须都是const表达式

  9. const表达式的成员访问(不包含属性的访问), tuple的索引访问

  10. const initconst函数中的thissuper表达式

  11. const表达式的const实例成员函数调用, 且所有实参必须都是const表达式

首先, 各类型的字面量都是const表达式

const修饰的各种函数、参数、变量等都是const表达式

各种元素是const表达式的运算表达式 等

const表达式应该不是很难区分, 除了let之外, 不能被修改的, 不能被当作左值的等

const上下文

const上下文是一类特定上下文, 在这些上下文内的表达式都必须是const表达式, 并且这些表达式始终在编译时求值

const上下文是指 const变量初始化表达式


Thanks for reading!

仓颉文档阅读-语言规约XVI: 常量求值

周二 10月 21 2025
1331 字 · 7 分钟