Skip to content

变量声明

本章介绍 YaoXiang 中变量声明的核心语法。如果你有其他编程语言的经验,你会发现 YaoXiang 的变量系统非常简洁——所有声明共享同一个语法模型。

统一语法模型

YaoXiang 的设计哲学是"万物皆统一"。无论是声明一个整数、定义一个函数,还是创建一个类型,它们都使用同一套语法:

name: type = value

这是 YaoXiang 最核心的设计理念。看几个例子就能感受到这种一致性:

yaoxiang
// 变量声明
x: Int = 42
name: String = "YaoXiang"

// 函数定义
add: (a: Int, b: Int) -> Int = a + b

// 类型定义
Point: Type = { x: Float, y: Float }

语法规范中变量声明的形式定义是:

('mut')? Identifier (':' TypeExpr)? '=' Expr

翻译成人话就是:可以有一个可选的 mut 关键字,然后是变量名,接着是可选的 : 类型,最后是 = 值。这个结构贯穿全语言,学一次就够。

不可变变量(默认行为)

在 YaoXiang 中,所有变量默认不可变。一旦赋值,就不能再改变。这是语言的安全设计。

yaoxiang
x = 10
// x = 20   // 编译错误!x 是不可变的

使用 = 声明的变量,编译器会沿着作用域链向外查找同名的变量。如果找到了,就给它赋值;如果找不到,就在当前作用域内创建一个新的不可变变量。

yaoxiang
x = 1       // 外层作用域没有 x,所以声明为新变量
x = 2       // 找到了外层的 x,尝试赋值 → 编译错误!x 不可变

这看起来有点反直觉——如果你学过其他语言,可能会想"既然能找到为什么不能赋值?"。这是因为 YaoXiang 把安全性放在第一位:默认不可变意味着你不用担心某个变量在代码的某个角落被意外修改。

mut 可变变量

当你确实需要修改变量时,用 mut 关键字显式声明:

yaoxiang
mut counter = 0
counter = counter + 1   // 可以修改
counter = 100           // 也可以

mut 有几条重要规则:

规则一mut 是显式新声明,编译器不会去外层作用域查找同名变量。

yaoxiang
mut x = 10      // 在当前作用域创建新的可变变量 x
mut x = 20      // 编译错误!同作用域内 x 已经声明过

规则二mut 声明的变量不能与外层作用域的变量同名(禁止遮蔽)。

yaoxiang
x = 10
{
    mut x = 20   // 编译错误!x 已经在外层声明,不允许遮蔽
}

规则三:同一作用域内,每个名字只能声明一次——无论用 = 还是 mut

yaoxiang
x = 10
mut x = 20   // 编译错误!x 已经声明过

这些规则确保每个变量名在当前作用域内是唯一的,你永远不会遇到同名变量到底指向谁的困惑。

类型推断 vs 显式类型注解

YaoXiang 使用 Hindley-Milner(HM)类型推断算法。编译器可以从你写的值自动推断出类型,大多数情况下不需要手动写类型。

yaoxiang
x = 42              // 编译器推断为 Int
name = "YaoXiang"   // 推断为 String
pi = 3.14159        // 推断为 Float
is_valid = true     // 推断为 Bool

当你想要明确标注类型时(比如为了提高代码可读性,或者编译器无法推断时),使用 : Type 语法:

yaoxiang
count: Int = 100
greeting: String = "Hello"
ratio: Float = 0.618

两种写法完全等价。你可以从省略类型开始写代码,在需要时再补上类型注解。这让原型开发非常快,同时又不会牺牲最终代码的类型安全。

基本类型一览

YaoXiang 内置了几种基本类型,覆盖日常编程的绝大多数场景。

Int(整数)

yaoxiang
a = 42              // 十进制
b = 0o52            // 八进制(0o 前缀)
c = 0x2A            // 十六进制(0x 前缀)
d = 0b101010        // 二进制(0b 前缀)
e = 1_000_000       // 可以用下划线分隔数字,方便阅读

Float(浮点数)

yaoxiang
pi = 3.14159
speed = 2.998e8         // 科学计数法:2.998 × 10^8
tiny = 1.6e-19

String(字符串)

yaoxiang
name = "YaoXiang"
empty = ""              // 空字符串
escape = "Hello\nWorld" // 支持转义:\n 换行、\t 制表符、\\ 反斜杠、\" 双引号
unicode = "\u{4F60}\u{597D}"  // Unicode 转义

Bool(布尔)

yaoxiang
is_ready = true
is_done = false

布尔值通常用在条件判断中:

yaoxiang
if is_ready {
    print("开始处理")
}

变量作用域

作用域决定了变量的可见范围。YaoXiang 的作用域规则非常简单:每个 {} 块创建一个新的作用域

基本规则

yaoxiang
{
    x = 10
    print(x)   // 可以访问:x 在当前作用域内
}
// print(x)    // 错误:x 在作用域外不可见

内层可以访问外层的变量:

yaoxiang
outer = "我在外面"
{
    print(outer)   // 可以访问外层的 outer
    inner = "我在里面"
}
// print(inner)    // 错误:inner 在作用域外不可见

函数参数的作用域

yaoxiang
greet: (name: String) -> Void = {
    print("你好, " + name)
    // name 在这个函数体内部可见
}
// name 在函数体外不可见

块表达式

YaoXiang 的 {} 块也是表达式,可以返回值:

yaoxiang
result = {
    x = 10
    y = 20
    return x + y   // 返回 30 给上一作用域
}
// result 的值是 30
// x 和 y 在块外不可见

关于块返回值的详细说明,请参考后续的函数章节。这里你只需要记住:大括号创建作用域,内层看得到外层,外层看不到内层

小结

你已经掌握了 YaoXiang 变量系统的核心概念:

概念要点
统一语法模型name: type = value,变量、函数、类型都用它
默认不可变x = 10 之后 x 不能改
可变变量mut 显式声明 mut x = 10
禁止遮蔽同一名字在同一作用域只能声明一次
类型推断HM 算法自动推断,也可以写 : Type 明确标注
作用域每个 {} 创建一个作用域,内可看外,外不可看内

接下来你可以继续学习基本类型的更多细节,或者直接进入控制流章节。