仓颉-基础语法
标识符
仓颉编程语言的标识符分为普通标识符和原始标识符两类,它们遵从不同的命名规则。
普通标识符不能和仓颉关键字相同,其取自以下两类字符序列:
- 由 XID_Start 字符开头,后接任意长度的 XID_Continue 字符。
- 由一个_开头,后接至少一个 XID_Continue 字符。
以下每行字符串都是不合法的普通标识符:
1 | ab&c // & 不是 XID_Continue 字符 |
原始标识符是在普通标识符或仓颉关键字的首尾加上一对反引号,主要用于将仓颉关键字作为标识符的场景。
例如,以下每行字符串都是合法的原始标识符:
1 | `abc` |
我看和其他语言基本保持一致。简单理解为慎用已存在的关键字作为标识符;不要用中文标识符、数字开头即可。
程序结构
通常,开发者会在扩展名为 .cj 的文本文件中编写仓颉程序,这些程序和文件也被称为源代码和源文件。在程序开发的最后阶段,这些源代码将被编译为特定格式的二进制文件。
在仓颉程序的顶层作用域中,可以定义一系列的变量、函数和自定义类型(如 struct、class、enum 和 interface 等),其中的变量和函数分别被称为全局变量和全局函数。如果要将仓颉程序编译为可执行文件,需要在顶层作用域中定义一个 main 函数作为程序入口,它可以有 Array
变量
在仓颉编程语言中,一个变量由对应的变量名、数据(值)和若干属性构成,开发者通过变量名访问变量对应的数据,但访问操作需要遵从相关属性的约束(如数据类型、可变性和可见性等)。
变量定义的具体形式为:修饰符 变量名: 变量类型 = 初始值
const 变量
是一种特殊的变量,它以关键字 const 修饰,定义在编译时完成求值,并且在运行时不可改变的变量。
值类型和引用类型变量
从编译器实现层面看,任何变量总会关联一个值(一般是通过内存地址/寄存器关联),只是在使用时,对有些变量,将直接取用这个值本身,这被称为值类型变量;而对另一些变量,将这个值作为索引、取用这个索引指示的数据,这被称为引用类型变量。值类型变量通常在线程栈上分配,每个变量都有自己的数据副本;引用类型变量通常在进程堆中分配,多个变量可引用同一数据对象,对一个变量执行的操作可能会影响其他变量。
作用域
现代编程语言引入了“作用域”的概念及设计,将名字和程序元素的绑定关系限制在一定范围里。不同作用域之间可以是并列或无关的,也可以是嵌套或包含关系。一个作用域将明确开发者能用哪些名字访问哪些程序元素,具体规则是:
- 当前作用域中定义的程序元素与名字的绑定关系,在当前作用域和其内层作用域中是有效的,可以通过此名字直接访问对应的程序元素。
- 内层作用域中定义的程序元素与名字的绑定关系,在外层作用域中无效。
- 内层作用域可以使用外层作用域中的名字重新定义绑定关系,根据规则 1,此时内层作用域中的命名相当于遮盖了外层作用域中的同名定义,对此称内层作用域的级别比外层作用域的级别高。
表达式
if 表达式
if 表达式基本形式为:
1 | if (条件) { |
while 表达式
while 表达式的基本形式为:
1 | while (条件) { |
do-while 表达式
do-while 表达式的基本形式为:
1 | do { |
for-in 表达式
for-in 表达式可以遍历那些扩展了迭代器接口 Iterable
1 | for (迭代变量 in 序列) { |
如果一个序列的元素是元组类型,则使用 for-in 表达式遍历时,“迭代变量”可以写成元组形式,以此实现对序列元素的解构,例如:
1 | main() { |
在 for-in 表达式的循环体中,不能修改迭代变量。
在一些应用场景中,只需要循环执行某些操作,但并不使用迭代变量,这时可以使用通配符 _ 代替迭代变量,例如:
1 | main() { |
在部分循环遍历场景中,对于特定取值的迭代变量,可能需要直接跳过,进入下一轮循环。虽然可以使用 if 表达式和 continue 表达式在循环体中实现这一逻辑,但仓颉为此提供了更便捷的表达方式——可以在所遍历的“序列”之后用 where 关键字引导一个布尔表达式,这样在每次将进入循环体执行前,会先计算此表达式。如果值为 true 则执行循环体,反之直接进入下一轮循环。例如:
1 | main() { |
break 与 continue 表达式
在循环结构的程序中,有时需要根据特定条件提前结束循环或跳过本轮循环,为此仓颉引入了 break 与 continue 表达式,它们可以出现在循环表达式的循环体中,break 用于终止当前循环表达式的执行、转去执行循环表达式之后的代码,continue 用于提前结束本轮循环、进入下一轮循环。break 与 continue 表达式的类型都是 Nothing。
例如,以下程序使用 for-in 表达式和 break 表达式,在给定的整数数组中,找到第一个能被 5 整除的数字:
1 | main() { |
函数
仓颉使用关键字 func 来表示函数定义的开始,func 之后依次是函数名、参数列表、可选的函数返回值类型、函数体。其中,函数名可以是任意的合法标识符,参数列表定义在一对圆括号内(多个参数间使用逗号分隔),参数列表和函数返回值类型(如果存在)之间使用冒号分隔,函数体定义在一对花括号内。
函数定义举例:
1 | func add(a: Int64, b: Int64): Int64 { |