这里写自定义目录标题
花了半天时间,对华为新出的仓颉编程语言做了简单的了解,整体观感如下:
- 仓颉语言看起来是一门大而全的语言,吸纳了现存的很多中编程语言的范式和语法。
- 语法非常像Swift,有些语法又有rust的影子;
- 静态类型语言,但编译为二进制可执行文件,无虚拟机。并发、垃圾回收与内存管理模块与java类似;
- 支持声明式UI语法,类似于现在ArkUI使用的ArkTS语法,估计以后HarmonyOS的开发语言会从ArkTS转化为仓颉。
相似点(主要与Swift进行对比)
-
类型扩展
-
添加函数 (swift包含)
swift仓颉: extend String { func printSize() { print(this.size) } } "123".printSize() // 3
swiftSwift: extension String { func printSize() { print(self.size) } } "123".printSize() // 3
-
添加属性 (swift不包含)
-
添加操作符重载 (swift包含)
swift仓颉: struct Point { let x: Int let y: Int init(x: Int, y: Int) {...} operator func +(rhs: Point): Point { return Point( this.x + rhs.x, this.y + rhs.y ) } } let a: Point = ... let b: Point = ... let c = a + b
swiftSwift: struct Point { let x: Int let y: Int init(x: Int, y: Int) { self.x = x self.y = y } static func +(lhs:Point, rhs: Point) -> Point { return Point(x: lhs.x + rhs.x, y: lhs.y + rhs.y) } } let c: Point = Point(x: 1, y: 1) let d: Point = Point(x: 2, y: 2) let e = c + d
-
实现接口 (swift包含)
swift仓颉: sealed interface Integer {} extend Int8 <: Integer {} extend Int16 <: Integer {} extend Int32 <: Integer {} extend Int64 <: Integer {} let a: Integer = 123 // ok
swiftSwift: protocol Integer {} extension Int8 : Integer {} let a :Integer = Int8(123)
-
-
代数数据类型和模式匹配
swift仓颉中的枚举定义与使用: enum BinaryTree { | Node(value: Int, left: BinaryTree, right: BinaryTree) | Empty } func sumBinaryTree(bt: BinaryTree) { match (bt) { //match关键字实际是rust语言中的模式匹配关键字。 case Node(v, l, r) => v + sumBinaryTree(l) + sumBinaryTree(r) case Empty => 0 } }
swiftSwift中的枚举定义与使用: indirect enum BinaryTree { case Node(value: Int, left: BinaryTree, right: BinaryTree) case Empty } func sumBinaryTree(bt: BinaryTree) -> Int { switch bt { case .Node(let value, let left, let right): return value + sumBinaryTree(bt: left) + sumBinaryTree(bt: right) case .Empty: return 0 } }
-
泛型
泛型函数的声明方式几乎一样,尤其是针对泛型类型T的限制,两者都使用where关键字。
swift仓颉: func lookup<T>(element: T, arr: Array<T>): Bool where T <: Equatable<T> { for (e in arr){ if (element == e){ return true } } return false }
swiftSwift: func lookup<T>(element: T, arr: Array<T>) -> Bool where T : Equatable { for e in arr { if (element == e){ return true } } return false }
-
命名参数&参数默认值
swift仓颉: func dateOf(year!: Int64, month!: Int64, dayOfMonth!: Int64, timeZone!: TimeZone = TimeZone.Local) { } dateOf(year: 2024, month: 6, dayOfMonth: 21) // ok dateOf(year: 2024, month: 6, dayOfMonth: 21, timeZone: TimeZone.UTC) // ok
swiftSwift: func dateOf(year: Int64, month: Int64, dayOfMonth: Int64, timeZone: TimeZone = TimeZone.current) { } dateOf(year: 2024, month: 6, dayOfMonth: 21) // ok dateOf(year: 2024, month: 6, dayOfMonth: 21, timeZone: TimeZone.gmt) // ok
-
尾随lambda(trailing lambda)
swift仓颉: func unless(condition: Bool, f: ()->Unit) { if(!condition) { f() } } int a = f(...) unless(a > 0) { print("no greater than 0") }
swiftSwift: func unless(condition: Bool, f: () -> Void) { if !condition { f() } } unless(condition: true) { print("no greater than 0") }
-
属性
属性的get/set配置。
swift仓颉: x和y是只读的,只有get实现,而color则是可变的,用mut prop修饰,同时具有get和set实现。 class Point { private let _x: Int private let _y: Int private var _color: String init(x: Int, y: Int, color: String) {...} prop x: Int { get() { Logger.log(level: Debug, "access x") return _x } } prop y: Int { get() { Logger.log(level: Debug, "access y") return _y } } mut prop color: String { get() { Logger.log(level: Debug, "access color") return _color } set(c) { Logger.log(level: Debug, "reset color to ${c}") color = c } } } main() { let p = Point(0, 0, "red") let x = p.x // "access x" let y = p.y // "access y" p.color = "green" // "reset color to green" }
swiftSwift: x和y是只读的,只有get实现,而color则是可变的,同时具有get和set实现。 class Point2 { private let _x: Int private let _y: Int private var _color: String init(_ x: Int, _ y: Int,_ color: String) { self._x = x self._y = y self._color = color } var x: Int { get { return _x } } var y: Int { get { return _y } } var color: String { get { return _color } set(c) { _color = c } } } let p = Point2(0, 0, "red") p.x = 100 //error let x = p.x // "access x" let y = p.y // "access y" p.color = "green" // "reset color to green"
-
空引用安全
在仓颉中,对于任意类型T,都可以有对应的可选类型Option。具有Option类型的变量要么对应一个实际的具有T类型的值v,因此取值为Some(v),要么具有空值,取值为None。
可选类型(Option)是一种 enum 类型,是一个经典的代数数据类型,表示有值或空值两种状态。
在Swift,用来表示变量可空的关键字为Optional.
swift仓颉: var a: ?Int = None a?.toString() // None a ?? 123 // 123 a = Some(321) a?.toString() // Some("321") a ?? 123 // 321
swiftSwift: var f: Int? = nil print(f) //nil print(f ?? 123) // 123 var g = Optional(321) print(g) //Optional(321) print(g ?? 123) // 321
-
值类型
仓颉和Swift都使用struct来实现用户自定义的值类型。
swift仓颉: struct Point { var x: Int var y: Int init(x: Int, y: Int) { ... } ... } var a = Point(0, 0) var b = a a.x = 1 print(b.x) // 0
swiftSwift: struct Point { var x: Int var y: Int init(x: Int, y: Int) { self.x = x self.y = y } } var a1 = Point3(x:0,y: 0) var b1 = a1 a1.x = 1 print(b1.x) // 0
-
宏
swift仓颉: 定义一个名为 DebugLog 的宏: public macro DebugLog(input: Tokens) { if (globalConfig.mode == Mode.development) { return quote( println( ${input} ) ) } else { return quote() } } 使用 DebugLog 宏: @DebugLog( expensiveComputation() )
rustRust: use proc_macro; #[some_attribute] pub fn some_name(input: TokenStream) -> TokenStream { }
-
Actor
使用更简洁的语法来实现异步编程、并发编程中的数据竞争问题。
swift仓颉: actor Account { instance var balance: Int64 init (x: Int64) { this.balance = f1() } instance func performWithdraw(amount: Int64): Unit { balance -= amount } receiver func withdraw(amount: Int64): Bool { if (this.balance < amount) { return false } else { this.performWithdraw(amount); return true } } }
swiftSwift: 注意:这段代码是来自于Swift的官方文档。仓颉的文档示例与swift的文档示例代码基本是一致的,看来仓颉语言应该是参考了Swift语言不少的东西。 actor Account { var balance: Int = 20// current user balance is 20 // ... func withdraw(amount: Int) { guard balance >= amount else {return} self.balance = balance - amount } }
-
可变性修饰符
可变性修饰符:let 与 var,分别对应不可变和可变属性,
不同点
-
垃圾收集方案
仓颉使用追踪式垃圾回收,类似于java中的基于可达性分析的垃圾回收算法;Swift使用引用计数法。(Swift有weak关键字)
亮点
-
管道(Pipeline)操作符
swiftfunc double(a: Int) { a * 2 } func increment(a: Int) { a + 1 } double(increment(double(double(5)))) // 42 5 |> double |> double |> increment |> double // 42
-
类型扩展可添加属性
-
try-with-resources
该特性应该借鉴自java.
swifttry (input = MyResource(), output = MyResource()) { while (input.hasNextLine()) { let lineString = input.readLine() output.writeLine(lineString) } }
-
溢出检查
这个机制使得大多数时候,整数溢出都会及时被感知,避免造成业务隐患。
swift@OverflowWrapping func test(x: Int8, y: Int8) { // if x equals to 127 and y equals to 3 let z = x + y // z equals to -126 }
-
并发编程
-
线程创建简单且占用内存量小。使用Spawn关键字来创建新线程。
swiftfunc fetch_data(url: String) { let response = http_get(url) process(response) } main() { let urls = ["https://example.com/data1", "https://example.com/data2", ...] let futures = ArrayList<Future<Unit>>() for (url in urls) { let fut = spawn { fetch_data(url) } // 创建仓颉线程进行网络请求 futures.append(fut) } for (fut in futures) { // 等待所有仓颉线程完成 fut.get() } }
-
无锁并发对象。
运行时库提供了一系列的原子操作对象,尽量让开发者少使用互斥量或者锁来实现线程安全。同时提供的这些原子操作对象,针对多线程操作做了优化,其效率比单纯使用互斥量要高得多。
-