华为仓颉编程语言观感

这里写自定义目录标题

花了半天时间,对华为新出的仓颉编程语言做了简单的了解,整体观感如下:

  • 仓颉语言看起来是一门大而全的语言,吸纳了现存的很多中编程语言的范式和语法。
  • 语法非常像Swift,有些语法又有rust的影子;
  • 静态类型语言,但编译为二进制可执行文件,无虚拟机。并发、垃圾回收与内存管理模块与java类似;
  • 支持声明式UI语法,类似于现在ArkUI使用的ArkTS语法,估计以后HarmonyOS的开发语言会从ArkTS转化为仓颉。

相似点(主要与Swift进行对比)

  • 类型扩展

    1. 添加函数 (swift包含)

      swift 复制代码
      仓颉:
      extend String { 
          func printSize() {
              print(this.size)
          }
      }
      
      "123".printSize() // 3
      swift 复制代码
      Swift:
      extension String {
          func printSize() {
              print(self.size)
          }
      }
      
      "123".printSize() // 3
    2. 添加属性 (swift不包含)

    3. 添加操作符重载 (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
      swift 复制代码
      Swift:
      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
    4. 实现接口 (swift包含)

      swift 复制代码
      仓颉:
      sealed interface Integer {}
      
      extend Int8 <: Integer {}
      extend Int16 <: Integer {}
      extend Int32 <: Integer {}
      extend Int64 <: Integer {}
      
      let a: Integer = 123 // ok
      swift 复制代码
      Swift:
      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
        }
    }
    swift 复制代码
    Swift中的枚举定义与使用:
    
    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
    }
    swift 复制代码
    Swift:
    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
    swift 复制代码
    Swift:
    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")
    }
    swift 复制代码
    Swift:
    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"
    }
    swift 复制代码
    Swift:
    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
    swift 复制代码
    Swift:
    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
    swift 复制代码
    Swift:
    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() )
    rust 复制代码
    Rust:
    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
            }
        }
    }
    swift 复制代码
    Swift:
    注意:这段代码是来自于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)操作符

    swift 复制代码
    func 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.

    swift 复制代码
    try (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
    }
  • 并发编程

    1. 线程创建简单且占用内存量小。使用Spawn关键字来创建新线程。

      swift 复制代码
      func 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()
          }
      }
    2. 无锁并发对象。

      运行时库提供了一系列的原子操作对象,尽量让开发者少使用互斥量或者锁来实现线程安全。同时提供的这些原子操作对象,针对多线程操作做了优化,其效率比单纯使用互斥量要高得多。

相关推荐
康康这名还挺多5 分钟前
鸿蒙HarmonyOS list优化一: list 结合 lazyforeach用法
数据结构·list·harmonyos·lazyforeach
晚秋大魔王3 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos
python算法(魔法师版)7 小时前
.NET 在鸿蒙系统上的适配现状
华为od·华为·华为云·.net·wpf·harmonyos
bestadc8 小时前
鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
harmonyos
枫叶丹49 小时前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十二)
华为·harmonyos·deveco studio·harmonyos next
ax一号街阿楠11 小时前
华为FAT AP配置 真机
网络·华为·智能路由器
吗喽对你问好11 小时前
华为5.7机考第一题充电桩问题Java代码实现
java·华为·排序
乱世刀疤13 小时前
深度 |国产操作系统“破茧而出”:鸿蒙电脑填补自主生态空白
华为·harmonyos
博睿谷IT99_18 小时前
华为HCIP-AI认证考试版本更新通知
人工智能·华为
连续讨伐19 小时前
ensp的华为小实验
华为