《仓颉语言入门指南:开启编程新征程》
一、引言

仓颉语言作为华为推出的新一代编程语言,具有诸多强大的特性。本文将带你快速入门仓颉语言,了解其基本概念、语法和应用。
仓颉语言是华为历经五年研发沉淀推出的编程语言,于 2024 年华为开发者大会上正式官宣。它主打原生智能化、天生全场景、高性能、强安全等特点,为开发者打造友好开发体验和卓越程序性能。
仓颉语言的名字来自 “仓颉造字”,寄托了团队希望该语言被广大开发者喜爱并广为流传的期望。其文件后缀名为.cj,以下是第一个入门代码输出:“你好,仓颉。”
仓颉语言具有高效的数据处理能力、强大的 AI 支持、高度可读的语法和广泛的跨平台支持等特性。在大数据分析和处理任务中,其独特的数据流模型允许开发者以声明式的方式编写数据处理逻辑,简化了代码的复杂度。同时,仓颉语言集成了先进的机器学习和深度学习框架,支持包括 TensorFlow 和 PyTorch 在内的主流 AI 工具,开发者可以通过简洁的语法定义和训练模型,快速实现智能应用。
仓颉语言采用了类似于自然语言的语法结构,使得代码更加直观和易读。无论是经验丰富的开发者还是初学者,都可以轻松上手,提高开发效率。此外,仓颉语言支持多种操作系统和硬件平台,包括 Windows、Linux、macOS 以及华为的自研操作系统 HarmonyOS,开发者可以在不同平台之间无缝迁移代码,实现真正的跨平台开发。
二、仓颉语言简介

仓颉语言是华为推出的面向全场景应用开发的现代编程语言。它有着深厚的背景,华为于 2019 年启动仓颉编程语言项目,历经五年精心研发,在 2024 年华为开发者大会上正式亮相。
其特点鲜明:
- 原生智能化:内嵌 AgentDSL 的编程框架,实现自然语言与编程语言的有机融合。多 Agent 协同工作,简化符号表达,支持各类智能应用开发,模式可自由组合。
- 天生全场景:采用轻量化可缩放运行时和模块化分层设计,即使在资源受限的设备上也能流畅运行。支持全场景领域扩展,通过元编程和 eDSL 技术,助力面向领域声明式开发。
- 高性能:采用全并发 GC,应用线程运行更加流畅,响应速度更快。轻量化线程设计进一步提升了并发性能,降低了开发成本。
- 强安全:将安全理念融入语言设计,帮助开发者专注于业务逻辑,减少安全漏洞的产生,实现 “编码即安全”。
仓颉语言的应用场景广泛,在大数据分析和处理任务中,其独特的数据流模型允许开发者以声明式的方式编写数据处理逻辑,简化代码复杂度。同时,集成了先进的机器学习和深度学习框架,支持包括 TensorFlow 和 PyTorch 在内的主流 AI 工具,开发者可以通过简洁的语法定义和训练模型,快速实现智能应用。此外,仓颉语言支持多种操作系统和硬件平台,包括 Windows、Linux、macOS 以及华为的自研操作系统 HarmonyOS,开发者可以在不同平台之间无缝迁移代码,实现真正的跨平台开发。
三、安装与环境配置

1. 获取 SDK
要获取仓颉编程语言通用版本 SDK,可以按照以下步骤进行:
- 首先关注仓颉编程语言官方微信公众号,会收到自动推送消息,按照提示回复 SDK。
- 然后填写试用问卷,等待仓颉编程语言官方邮箱回复邮件,官方会在 1 - 2 个工作日内回复。需要注意的是,仓颉编程语言 SDK 及开发工具存储在 GitCode Cangjie 社区上,Cangjie 社区会根据用户手机号通过审核,因此填写问卷时手机号需要与 GitCode 注册手机号保持一致,否则社区无法通过审核。
- 根据仓颉编程语言官方邮件提示完成承诺函签署并回复邮件。
- 最后仓颉编程语言官方邮箱会再次回复邮件。此时,仓颉编程语言社区运营在 GitCode Cangjie 社区上,点击链接才能申请加入社区。
2. 安装插件
以 Windows 平台为例,在 GitCode Cangjie 社区下载仓颉 VScode 插件后,进行以下操作:
- 找到下载的插件文件,如果是压缩包则进行解压操作。
- 在解压后的文件中找到.vsix 文件。
- 打开 VSCode,点击左侧 “Extensions -> Views and More Actions -> Install from VSIX”,找到刚才解压出来的.vsix 文件进行安装。安装成功后,可在左侧 “Extensions -> Cangjie -> 齿轮图标 -> settings” 中进行配置。在 “Cangjie Sdk Path: CJNative Backend” 中填入步骤 1 中安装的仓颉 SDK 路径(如 “D:\Code\cangjiesdk\cangjie”,根据实际情况填写)。
3. 创建项目
在 VScode 中创建仓颉项目的步骤如下:
- 按 Ctrl + Shift + P 打开 VScode 功能搜索框,输入 “Create Cangjie Project” 就可以找到创建仓颉项目的选项。
- 下一步选择 “Create CJNative Cangjie Project”。
- 再下一步选择 “Create Executable Output Cangjie Project”。
- 弹出窗里选择工程存放的目录文件夹。
- 回到之前界面,在上方输入框中输入工程的名称,并回车。
- 在左侧目录结构中找到 “src -> main.cj”,可以看到默认创建的一段 “helloworld” 代码。
- 编辑器右上方三角按钮编译并输出代码,自动弹出 TERMINAL 显示打印结果。
四、基本概念

1.Hello World
展示如何编写第一个仓颉程序,输出 “你好,仓颉!”。
以下是一个简单的仓颉程序,输出 “你好,仓颉!”:
main() {
println("你好,仓颉!")
}
2. 标识符
包括普通变量、原始表示符等的使用方法。
在仓颉编程语言中,标识符分为普通标识符和原始标识符两类。普通标识符不能和仓颉关键字相同,可以取自以下两类字符序列:
- 由英文字母开头,后接零至多个英文字母、数字或下划线 “_”。例如:abc_abc、abc_a1b2c3、a_b_c、a1_b2_c3。
- 由一至多个下划线 “” 开头,后接一个英文字母,最后可接零至多个英文字母、数字或下划线 “”。
原始标识符是在普通标识符或仓颉关键字的外面加上一对反引号,主要用于将仓颉关键字作为标识符的场景。例如:abc、_abc、a1b2c3、if、while。
以下是一个示例程序:
main() {
// 普通变量
let num = 10
let ___x = "___Str"
println(num)
println(___x)
// 原始表示符
// 用于将关键字作为标识符
let `for` = "这是一个将for关键字用作原始标识符"
println(`for`)
}
3. 内置类型
介绍各种字面量后缀、字符类型、字符串、数组、元组、区间类型等。
在仓颉编程语言中,有以下内置类型:
- 字面量后缀:
-
- 整形:Int8 -> i8、Uint8 -> u8 等。
-
- 浮点型:Float16 -> f16。
- 字符类型:表示一个 unicode 字符,可以用单引号括起来。例如:let e: Rune = ' 仓 ';let f: Rune = '\u {9889}'。
- 字符串:
-
- 单行字符串:let g: String = "Cang" + "jie"。
-
- 多行字符串:let h: String = """ 第 1 行,这是多行字符串
第 2 行 """。
-
- 插值字符串:要求表达式类型实现了 ToString 接口。例如:let i: String = "Cangjie${a}"。
- 数组:
-
- 引用类型数组:let j: Array<UInt8> = [1u8, 2u8]。
-
- 值类型数组:let k: VArray<Rune, $2> = [e, f]。
- 元组类型:let l: (Int64, Float64) = (2024, 9.6)。
- 区间类型:主要用于 for in 表达式中。let m: Range<Int64> = 2019..2024。
4.if 表达式
通过示例讲解类似 gcc 中的大括号表达式的 if 表达式的用法。
仓颉语言中的 if 表达式用于根据条件的值来决定是否执行相关代码逻辑。if 表达式有三种形式:单分支的 if 表达式、双分支的 if 表达式和嵌套的 if 表达式。
单分支的 if 表达式
单分支的 if 表达式只有一个分支,其语法如下:
if (条件) {
代码块
}
其中的条件必须是一个布尔类型的表达式,由一对匹配的花括号包围代码块。执行时,首先测试条件的值,如果条件为 true,就执行括号内的代码块;否则,不执行任何代码。例如:
// isScorePassed 表示分数是否合格,true 表示合格,false 表示不合格
if (isScorePassed) {
println("合格")
}
println("执行完毕")
在上述代码中,isScorePassed 为 true 时,将输出:合格执行完毕。如果 isScorePassed 为 false,则只会输出:执行完毕。这表明,单分支的 if 表达式是否会执行代码,完全取决于条件的取值。值得注意的是,if 表达式的类型为 Unit,其值为 0。
双分支的 if 表达式
双分支的 if 表达式包含两个分支,语法如下:
if (条件) {
代码块1
} else {
代码块2
}
在执行时,如果条件为 true,执行代码块 1;如果条件为 false,则执行代码块 2。例如:
if (isScorePassed) {
println("合格")
} else {
println("不合格")
}
println("执行完毕")
如果 isScorePassed 为 true,输出结果为:合格执行完毕。如果 isScorePassed 为 false,输出结果为:不合格执行完毕。这里,else 分支必须在 if 表达式之后的代码中运行。
双分支 if 表达式的类型
当 if 表达式的值被使用时,双分支的 if 表达式的类型是 if 分支和 else 分支类型的最小公共父类。例如:
main() {
var creditScore: UInt16 = 800
var interestRate: Float64 = if (creditScore >= 600) {
0.06
} else {
0.08
}
println(interestRate)
}
在这个例子中,interestRate 的值是根据 creditScore 的值决定的。如果 creditScore 大于或等于 600,则利率为 0.06;否则,利率为 0.08。最终输出利率的结果。
嵌套的 if 表达式
当希望匹配更多的条件时,可以使用嵌套的 if 表达式。嵌套 if 表达式可以包含多个分支。其语法结构如下:
if (条件1) {
代码块1
} else if (条件2) {
代码块2
}...else {
代码块n
}
其中每个条件都必须是布尔类型的表达式。整个 if 表达式的执行流程如下:测试条件 1 的值,如果为 true,执行代码块 1,整个 if 表达式结束;如果条件 1 为 false,测试条件 2 的值,以此类推,直到找到为 true 的条件;如果所有条件都为 false,则执行 else 分支中的代码块。例如:
if (creditScore < 600) {
interestRate = 0.08
} else if (creditScore < 800) {
interestRate = 0.06
} else {
interestRate = 0.05
}
println(interestRate)
根据 creditScore 的值,选择执行不同的分支,最终输出相应的利率。
if 表达式中的类型推断
在某些情况下,if 表达式不仅用于条件分支选择,还可以返回值。此时,if 表达式的返回值类型由 if 和 else 分支的类型决定。例如,以下代码会根据 creditScore 的值,推断出 interestRate 的类型:
main() {
var creditScore: UInt16 = 800
var interestRate: Float64 = if (creditScore >= 600) {
0.06
} else {
0.08
}
println(interestRate)
}
在这个例子中,interestRate 的类型被推断为 Float64,因为 if 和 else 分支中的返回值都是浮点数。这种情况适用于条件表达式需要返回一个值的场景。
嵌套 if 表达式中的执行顺序
嵌套的 if 表达式可以根据多个条件执行不同的逻辑。例如,以下代码展示了如何根据不同的 creditScore 值调整利率:
if (creditScore < 600) {
interestRate = 0.08
} else if (creditScore < 800) {
interestRate = 0.06
} else if (creditScore < 1000) {
interestRate = 0.05
} else {
interestRate = 0.04
}
在这个例子中,程序将依次测试 creditScore 是否满足每个条件,直到找到符合条件的分支。如果 creditScore 小于 600,利率设置为 0.08;如果小于 800,但大于等于 600,利率为 0.06,以此类推。最终的输出结果取决于条件的匹配情况。
条件表达式的最佳实践
对于 if 表达式的使用,编写整洁的代码并避免重复是非常重要的。例如,如果条件非常复杂,可以通过添加额外的条件块减少不必要的代码重复,确保代码逻辑清晰。例如:
if (creditScore <= 1000) {
if (creditScore < 600) {
interestRate = 0.08
} else if (creditScore < 800) {
interestRate = 0.06
} else if (creditScore < 900) {
interestRate = 0.05
} else {
interestRate = 0.04
}
} else {
println("数据错误!")
}
这种写法将不同的条件组合在一起,确保只有在 creditScore 小于等于 1000 时才会进入利率设置的逻辑,如果超出此范围,将输出错误信息。这是一种防止数据错误的良好实践。
5.for 表达式
分别介绍不同形式的 for 循环,如范围循环、元组解构循环、占位符循环和条件循环。
在仓颉编程语言中,for 表达式有多种形式:
- 范围循环:
var sum = 0
for (i in 1..99 : 2) {
sum += i
}
println(sum)
- 元组解构循环:
let arr = [(1,2), (3, 4)]
for ((x, y) in arr) {
println("x=${x} y=${y}")
}
- 占位符循环:
var num = 2
for (_ in 0..5) {
num *= num
}
- 条件循环:
for (i in 0..10 where i % 2 == 1) {
println(i)
}
6.while 表达式
展示如何使用 while 循环进行数值计算。
while 表达式的基本形式为:
while (条件) {
循环体
}
例如,以下程序使用 while 表达式,基于二分法,近似计算数字 2 的平方根:
main() {
var root = 0.0
var min = 1.0
var max = 2.0
var error = 1.0
let tolerance = 0.1**10
while (error**2 > tolerance) {
root = (min + max) / 2.0
error = root**2 - 2.0
if (error > 0.0) {
max = root
} else {
min = root
}
}
println("2 的平方根约等于:${root}")
}
7.demo 手动计算 Π
讲解如何在正方形中随机投点手动计算圆周率,但可能在在线编译器中运行失败。
以下是手动计算圆周率的示例程序:
import std.random.*
import std.math.*
main() {
/**
* 手动计算圆周率
* 在一个正方形中随机投点
*/
const N = 10000
var n: UInt32 = 0
let random = Random()
for (_ in 0..N) {
let x = random.nextFloat64()
let y = random.nextFloat64()
if ((x - 0.5)**2 + (y - 0.5)**2 < 0.25) {
n++
}
}
let pi = Float64(n) / Float64(N) * 4.0
println("Π = ${pi}")
println("deviation: ${abs(Float64.PI - pi)}")
}
五、函数

1. 普通函数
在仓颉语言中,普通函数可以用于实现各种复杂的逻辑。以二叉树的中序遍历为例,我们可以定义一个函数来遍历二叉树的节点。
首先,定义一个节点函数,接受一个值和左右子节点的函数:
func node(value: Int32, left!: () -> Unit = void, right!: () -> Unit = void) {
// 二叉树的中序遍历
func show() {
left()
print(value)
right()
}
return show
}
在主函数中,可以使用这个节点函数来构建一个二叉树并进行遍历:
main() {
let tree = node(0, left: node(1, left: node(2, right: node(3))), right: node(4, left: node(5), right: node(6)))
tree()
}
通过这种方式,我们可以方便地定义和使用普通函数来处理二叉树等数据结构。
2.lambda
在仓颉语言中,lambda 表达式是一种简洁的函数定义方式。它可以用于定义匿名函数,并且可以作为参数传递给其他函数或者赋值给变量。
lambda 表达式的语法为 { p1: T1,..., pn: Tn => expressions | declarations }。其中,=> 之前为参数列表,多个参数之间使用 , 分隔,每个参数名和参数类型之间使用 : 分隔。=> 之后为 lambda 表达式体,是一组表达式或声明序列。
例如,定义一个接受两个参数并返回它们和的 lambda 表达式:
let f1 = { a: Int64, b: Int64 => a + b }
无参数的 lambda 表达式也可以定义,如下:
var display = { => println("Hello") }
lambda 表达式可以直接调用,也可以赋值给变量再调用。例如:
let r1 = { a: Int64, b: Int64 => a + b }(1,2) // r1=3
let r2 = { => 123 }() // r2=123
lambda 表达式作为参数使用时,其参数类型根据使用处所在的函数调用的形参类型推断。例如:
func f(a1: (Int64) -> Int64): Int64 {
a1(1)
}
main() {
f({ a2 => a2 + 10 })
}
lambda 表达式作为返回值使用时,其返回类型根据使用处所在函数的返回类型推断。例如:
func f(): (Int64) -> Int64 {
{ a: Int64 => a }
}
lambda 表达式中不支持声明返回类型,其返回类型总是从上下文中推断出来,若无法推断则报错。若上下文明确指定了 lambda 表达式的返回类型,则其返回类型为上下文指定的类型。
六、结语

仓颉语言作为华为推出的新一代编程语言,为编程之路开启了新的篇章。通过本文的介绍,我们了解了仓颉语言的基本概念、语法和应用,包括安装与环境配置、基本概念、函数等方面的内容。
仓颉语言的入门要点总结如下:首先,要了解仓颉语言的背景和特点,认识到其在原生智能化、天生全场景、高性能、强安全等方面的优势。其次,掌握安装与环境配置的方法,包括获取 SDK、安装插件和创建项目。在学习基本概念时,要熟悉 Hello World 程序、标识符、内置类型、if 表达式、for 表达式、while 表达式和手动计算圆周率等内容。函数部分则包括普通函数和 lambda 的使用方法。
对于想要深入学习仓颉语言的读者,建议多实践、多探索。可以通过参与实际项目、阅读官方文档和参与社区讨论等方式,不断提升自己的编程技能。同时,也可以关注仓颉语言的发展动态,了解其新特性和优化,为自己的编程之路增添更多的可能性。
总之,仓颉语言为开发者提供了一个强大而灵活的编程工具,鼓励读者勇敢地迈出第一步,深入学习和探索仓颉语言,开启编程之旅的新篇章。
更多推荐



所有评论(0)