华为仓颉编程语言观感

这里写自定义目录标题

  • 相似点(主要与Swift进行对比)
  • 不同点
  • 亮点

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

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

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

  • 类型扩展

    1. 添加函数 (swift包含)

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

    3. 添加操作符重载 (swift包含)

      仓颉:
      struct Point {let x: Intlet y: Intinit(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
      
      Swiftstruct Point {let x: Intlet y: Intinit(x: Int, y: Int) {self.x = xself.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包含)

      仓颉:
      sealed interface Integer {}extend Int8 <: Integer {}
      extend Int16 <: Integer {}
      extend Int32 <: Integer {}
      extend Int64 <: Integer {}let a: Integer = 123 // ok
      
      Swift:
      protocol Integer {}extension Int8 : Integer {}let a :Integer = Int8(123)
  • 代数数据类型和模式匹配

    仓颉中的枚举定义与使用: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中的枚举定义与使用: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关键字。

    仓颉:
    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:
    func lookup<T>(element: T, arr: Array<T>) -> Bool where T : Equatable {for e in arr {if (element == e){return true}}return false
    }
    
  • 命名参数&参数默认值

    仓颉:
    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:
    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)

    仓颉:
    func unless(condition: Bool, f: ()->Unit) {if(!condition) {f()}
    }int a = f(...)
    unless(a > 0) {print("no greater than 0")
    }
    
    Swift:
    func unless(condition: Bool, f: () -> Void) {if !condition {f()}
    }unless(condition: true) {print("no greater than 0")
    }
  • 属性
    属性的get/set配置。

    仓颉:
    x和y是只读的,只有get实现,而color则是可变的,用mut prop修饰,同时具有getset实现。
    class Point {private let _x: Intprivate let _y: Intprivate var _color: Stringinit(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:
    x和y是只读的,只有get实现,而color则是可变的,同时具有getset实现。
    class Point2 {private let _x: Intprivate let _y: Intprivate var _color: Stringinit(_ x: Int, _ y: Int,_ color: String) {self._x = xself._y = yself._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 //errorlet 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.

    仓颉:
    var a: ?Int = None
    a?.toString() // None
    a ?? 123 // 123
    a = Some(321)
    a?.toString() // Some("321")
    a ?? 123 // 321
    
    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来实现用户自定义的值类型。

    仓颉:
    struct Point {var x: Intvar y: Intinit(x: Int, y: Int) { ... }...
    }var a = Point(0, 0)
    var b = a
    a.x = 1
    print(b.x) // 0
    
    Swift:
    struct Point {var x: Intvar y: Intinit(x: Int, y: Int) { self.x  = xself.y = y}}var a1 = Point3(x:0,y: 0)
    var b1 = a1
    a1.x = 1
    print(b1.x) // 0
    
  • 仓颉:
    定义一个名为 DebugLog 的宏:
    public macro DebugLog(input: Tokens) {if (globalConfig.mode == Mode.development) {return quote( println( ${input} ) )}else {return quote()}
    }
    使用 DebugLog 宏:
    @DebugLog( expensiveComputation() )
    
    Rust:
    use proc_macro;#[some_attribute]
    pub fn some_name(input: TokenStream) -> TokenStream {
    }
    
  • Actor

    使用更简洁的语法来实现异步编程、并发编程中的数据竞争问题。

    仓颉:
    actor Account {instance var balance: Int64init (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语言不少的东西。
    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)操作符

    func double(a: Int) {a * 2
    }func increment(a: Int) {a + 1
    }double(increment(double(double(5)))) // 425 |> double |> double |> increment |> double // 42
    
  • 类型扩展可添加属性

  • try-with-resources
    该特性应该借鉴自java.

    try (input = MyResource(),output = MyResource()) {while (input.hasNextLine()) {let lineString = input.readLine()output.writeLine(lineString)}
    }
    
  • 溢出检查
    这个机制使得大多数时候,整数溢出都会及时被感知,避免造成业务隐患。

    @OverflowWrapping
    func test(x: Int8, y: Int8) { // if x equals to 127 and y equals to 3let z = x + y // z equals to -126
    }
    
  • 并发编程

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/860347.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图书管理系统(详解版 附源码)

目录 项目分析 实现页面 功能描述 页面预览 准备工作 数据准备 创建数据库 用户表 创建项目 导入前端页面 测试前端页面 后端代码实现 项目公共模块 实体类 公共层 统一结果返回 统一异常处理 业务实现 持久层 用户登录 用户注册 密码加密验证 添加图书…

Cesium默认bing地图数据,还支持哪些地图的数据源呢?

传统的前端开发增长乏力了&#xff0c;新兴的web3D方向前端开发需求旺盛&#xff0c;这一块在国外很成熟&#xff0c;在国内兴起不久&#xff0c; 甚至很多前端老铁都没听过&#xff0c;没见过&#xff0c;没有意识到&#xff0c;前端除了框架、vue、uniapp这些烂大街的&#x…

黑马苍穹外卖7 用户下单+订单支付(微信小程序支付流程图)

地址簿 数据库表设计 就是基本增删改查&#xff0c;与前面的类似。 用户下单 用户点餐业务流程&#xff1a; 购物车-订单提交-订单支付-下单成功 展示购物车数据&#xff0c;不需要提交到后端 数据库设计&#xff1a;两个表【订单表orders&#xff0c;订单明细表order_d…

cnpm run dev 报错 Error: Cannot find module ‘fs/promises’

主要原因是babel版本冲突 卸载以下依赖可以解决问题&#xff1a; 之后重新安装babel-loader依赖 可能会报以下错误&#xff1a; 接着安装babel-core依赖 项目顺利启动

【启明智显分享】低成本RISC-V工业级HMI方案推荐

伴随着工业4.0的迅猛发展&#xff0c;工业HMI以方便、快捷的特点逐渐成为工业的日常应用&#xff0c;成为备受追捧的全新多媒体交互设备。 什么是工业HMI&#xff1f;工业HMI是用于工业自动化系统中的人机交互界面&#xff0c;通常由触摸屏、按钮、指示灯、显示器等组成&#…

如何正确使用C#短信接口发送招生短信

群发短信对教育机构来讲虽然是个不错的招生工具,但怎么使用决定着生源转化效率,如果是为了单纯的发短信而发短信效率当然不好,那么如何正确使用招生群发短信呢?技巧才是关键! 教育短信发送较多的就是招生群发短信内容,而运营商对教育行业内容审核一般比较严格,需要短信公司特殊…

新媒体矩阵系统是什么?怎么搭建矩阵系统?

目录 前言&#xff1a; 一、新媒体矩阵分别是什么&#xff1f; 1、横向矩阵 2、 纵向矩阵 二、新媒体矩阵的作用&#xff1f; 1、多元化发展&#xff0c;吸引目标 2、多平台协同&#xff0c;放大宣传效果 3、多平台运营&#xff0c;分散风险 三、怎么做矩阵系统&…

【摄像头标定】双目摄像头标定及矫正-opencv(python)

双目摄像头标定及矫正 棋盘格标定板标定矫正 棋盘格标定板 本文使用棋盘格标定板&#xff0c;可以到这篇博客中下载&#xff1a;https://blog.csdn.net/qq_39330520/article/details/107864568 标定 要进行标定首先需要双目拍的棋盘格图片&#xff0c;20张左右&#xff0c;…

企业微信内嵌H5项目接入聊天功能

产品需求是,在列表中把符合条件的列表接入聊天功能,以下是详细步骤: 1.引入企业微信 <script src"https://res.wx.qq.com/wwopen/js/jsapi/jweixin-1.0.0.js"></script> 2.获取wx签名(必须要) /*** 获取wx签名**/ export function getWxJsApi(data) {r…

RKmedia进行vi-vo模块

一、简介 分析一下rkmedia的代码&#xff0c;给自己加深一下印象 二、代码 2.1 头文件以及定义 首先包含了必要的头文件&#xff0c;以及rkmedia底层的库 static bool quit 是定义了布尔类型的变量来表示这个程序的运行状态 false表示没停止 true表示停止 sigterm_handle…

pdf压缩,pdf压缩在线,pdf文件太大怎么变小

在数字化时代&#xff0c;PDF文档因其跨平台、保持原样、易于阅读和打印等特点&#xff0c;成为了我们日常工作和生活中不可或缺的一部分。然而&#xff0c;随着PDF文件的不断累积&#xff0c;存储空间逐渐变得紧张&#xff0c;特别是在处理大量大型PDF文件时&#xff0c;如何有…

【Python】在 VS Code 里面绘制动图不显示动画的解决办法

在 VS Code 中&#xff0c;可以通过以下步骤来确保动画正确显示&#xff1a; 配置 VS Code 使用适当的绘图后端&#xff1a; VS Code 中使用 matplotlib 的动画功能&#xff0c;需要配置适当的绘图后端。推荐使用 TkAgg 或者 Qt5Agg 后端。你可以在代码中显式指定&#xff1a;…

若依前后端分离项目整合shardingjdbc分表(详细,分片字段订单id)

文章目录 1. 引入Maven依赖2.引入配置文件3.兼容之前的数据库源,使用现在的sharding数据库源&#xff08;shardingjdbc默认的数据源&#xff09;&#xff0c;但是配置好文件之后是没有生效的&#xff0c;需要加配置文件覆盖4. 检测是否成功5. 如何使用&#xff0c;在需要使用的…

qt开发-14_QListwidget 仿qq好友列表制作

QListWidget 继承 QListView。QListWidget 类提供了一个基于项的列表小部件。QListWidg et 是一个便捷的类&#xff0c;它提供了一个类似于 QListView&#xff08;下一小节将讲到&#xff09;提供的列表视图&#xff0c;但 是提供了一个用于添加和删除项目的基于项目的经典接口…

第10章 启动过程组 (启动过程组的重点工作)

第10章 启动过程组 10.3启动过程组的重点工作&#xff0c;在第三版教材第362~364页&#xff1b; 文字图片音频方式 第一个知识点&#xff1a;项目启动会议 1、作用 标志着对项目经理责权的定义结果的正式公布&#xff0c;通常由项目经理负责组织和召开。2、目的 使项目各…

数据库常用操作命令

数据库基本操作 #查看数据库 show databases#创建数据库 create database db DEFAULT CHARSET utf8 COLLATE utf8_general_ci;#使用数据库 use db;用户操作 #创建用户 create user 用户名IP地址 identified by 密码;#删除用户 drop user 用户名IP地址;#修改用户 rename user …

分享:Wordpress插件-AI Image Pro v2.6.0中文版语言包

AI Image Pro是一个wordpress插件,可将您的 WordPress 网站直接与最佳图像生成 A模型(DALL.E和稳定扩散)集成&#xff0c;并允许您利用 AI 生成图像、编辑(内画)图像和创建图像变体。最重要的是&#xff0c;它配备了许多一键式滤镜和许多微调选项,您可以使用它们来增强和创建令…

【算法介绍】开集识别算法 OpenMax

OpenMax算法简介 OpenMax是一种用于深度学习模型的开集识别算法&#xff0c;它能够在模型的输出中区分已知类别和未知类别。该算法的核心思想是利用深度神经网络的倒数第二层&#xff08;全连接层&#xff09;的激活向量&#xff0c;通过构建每个类别的平均激活向量&#xff0…

黑匣子问题:大语言模型的内部工作原理

像 GPT-3 这样的大型语言模型 (LLM) 已经展示了令人印象深刻的自然语言能力&#xff0c;但它们的内部工作原理仍然知之甚少。这种“黑匣子”性质使得ChatGPT在敏感的现实应用程序中部署时可能会出现问题。 什么是LLM黑匣子问题&#xff1f; 语言学习模型 (LLM) 是强大的工具&…

Postman 接口测试工具使用方法

Postman 是一个强大的 API 测试工具,广泛用于开发和测试 API。以下是对 Postman 的详细介绍,包括其主要功能、使用方法和一些高级功能。 一、Postman 简介 Postman 是一个用于 API 开发的协作平台,提供了丰富的功能来进行 API 请求、测试和文档编写。它可以用来测试 RESTfu…