前言
在刚刚召开的华为开发者大会(HDC 2024)上,华为内部研发已久的国产自主编程语言仓颉终于正式对外官宣!
当前在鸿蒙原生应用的开发中,支持声明式 UI 和一次开发、多端部署的 ArkTS 语言已经被广泛使用。仓颉语言作为面向未来的下一代编程语言,当前已经完成设计与实现并启动了开发者预览,未来将与 ArkTS 共同发展,为鸿蒙原生应用开发者提供极致高效的开发体验。
仓颉的优势
仓颉的定位同样如此,据官方介绍,它是一款面向“全场景”智能的新一代编程语言,主打原生智能化、天生全场景、高性能、强安全。
- 原生智能化:仓颉编程语言内嵌了 AgentDSL 的编程框架,实现了自然语言与编程语言有机融合。多 Agent 协同,简化符号表达,模式可以自由组合,支持各类智能应用开发。
- 天生全场景:仓颉编程语言采用轻量化可缩放运行时和模块化分层设计,即使在资源受限的设备上也能流畅运行。同时,它支持全场景领域扩展,元编程和 eDSL 技术,可助力面向领域声明式开发。
- 高性能:仓颉编程语言采用全并发 GC,应用线程运行更加流畅,响应速度更快。轻量化线程设计进一步提升了并发性能,降低了开发成本。
- 强安全:仓颉编程语言将安全理念融入语言设计,帮助开发者专注于业务逻辑,减少安全漏洞的产生,实现“编码即安全”的愿景。
当然好像每个新的语言都会这么说,而对于观望的开发者来说,我们首先还是需要来了解一下仓颉的语法。
环境配置
可以直接使用HarmonyOS DevEco Studio或者VsCode进行开发,但需要安装仓颉插件,目前来看,需要报名仓颉语言开发者预览版Beta招募,才能获得对应的Studio版本。在获得对应的Studio版本后,就可以体验仓颉的语法特性了。
HelloWorld
和所有语言一样,我们先来实现仓颉的HelloWorld程序。
新建脚本文件Hello,后缀名是.cj没错就是仓颉的中文😂
main() {
println("你好,仓颉")
}
> cjc hello.cj -o hello
> ./hello你好,仓颉
通过cjc命令运行,打印输出“你好,仓颉”。emm... 只看main这个方法谁也不知道这是kotlin还是啥。
变量声明
变量定义的具体形式为:
修饰符 变量名: 变量类型 = 初始值
其中修饰符用于设置变量的各类属性,可以有一个或多个,常用的修饰符包括:
- 可变性修饰符:let 与 var,分别对应不可变和可变属性,可变性决定了变量被初始化后其值还能否改变,仓颉变量也由此分为不可变变量和可变变量两类。
- 可见性修饰符:private 与 public 等,影响全局变量和成员变量的可引用范围,详见后续章节的相关介绍。
- 静态性修饰符:static,影响成员变量的存储和引用方式,详见后续章节的相关介绍。
如下程序所示,定义了两个 Int64 类型的不可变变量 a 和可变变量 b,随后修改了变量 b 的值。
main() {
let a: Int64 = 20
var b: Int64 = 12
b = 23
println("${a}${b}")
}
从这里来看,相当于把Kotlin中的“val”替换成了“let”。接着我们来看它的struct 类型。
Struct类型
基础结构
struct Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
如上述代码所示,通过struct关键字定义了一个Rectangle结构,声明了变量width、height并提供了init、area两个方法。我们完全把它当成一个class 即可,通过下列方法我们可以创建struct的实例并调用相关方法。
let r = Rectangle(10, 20)
let width = r.width
let height = r.height
let a = r.area()
let r = Rectangle(10, 20)
let width = r.width
let height = r.height
let a = r.area()
但是仓颉也是有自己的class的,主要区别在于:class 是引用类型,struct 是值类型,class 之间可以继承,但 struct 之间不能继承。
struct Test {
var i = 0
public func add() {
i += 1
}
}
我们是无法在add函数中修改成员变量i的值的,如果想要修改我们就需要借助mute函数。
mute函数
修改代码如下所示:
struct Test {
var i = 0
public mute func add() {
i += 1
}
}
在add函数前新增一个mute关键字,就可以在函数内修改i的值了。需要注意的是mute关键字不能修改静态函数,如下列代码无法正常编译:
public mut static func g(): Unit {}
public mut static func g(): Unit {}
其他的语法如模式匹配、网络编程等几乎与Kotlin无异,我们可以在手机操作过程中了解。
跨语言操作
和大多数语言一样,仓颉是支持跨语言调用的,当前支持仓颉-C语言与仓颉-Artks语言的互操作。这里我们以仓颉调用C语言为例。
在仓颉中要调用 C 的函数,需要在仓颉语言中用 @C 和 foreign 关键字声明这个函数,但 @C 在修饰 foreign 声明的时候,可以省略。举个例子,假设我们要调用 C 的 rand 和 printf 函数,它的函数签名是这样的:
// stdlib.h
int rand();
// stdio.h
int printf (const char *fmt, ...);
那么在仓颉中调用这两个函数的方式如下:
foreign func rand(): Int32
foreign func printf(fmt: CString, ...): Int32
main() {
let r = unsafe { rand() }
println("random number ${r}")
unsafe {
var fmt = LibC.mallocCString("Hello, No.%d\n")
printf(fmt, 1)
LibC.free(fmt)
}
}
foreign func rand(): Int32
foreign func printf(fmt: CString, ...): Int32
main() {
let r = unsafe { rand() }
println("random number ${r}")
unsafe {
var fmt = LibC.mallocCString("Hello, No.%d\n")
printf(fmt, 1)
LibC.free(fmt)
}
}
在引入与 C 语言的互操作过程中,同时也引入了 C 的许多不安全因素,因此在仓颉中使用 unsafe 关键字,用于对跨 C 调用的不安全行为进行标识。
最后
同时,仓颉当前在尝试支持AI Native原生智能应用开发、DSL KIT、Actor和分布式编程等。不过,就目前来看感觉仓颉是一个所有语言的组合,不管你之前使用的是什么语言可能都会感觉得到很熟悉。但我觉得,开发者的脑子马上就不够用了。
现在又多了一个选择,你会学吗?