华为仓颉编程语言的表达式及其特点

仓颉(Cangjie)语言的表达式有一个明显的特点,范围不再局限于传统算术运算,而是扩展到条件表达式、循环表达式等多种类型,每种表达式均有确定的类型和值。

传统基本表达式,由一个或多个操作数(operand)通过零个或多个操作符(operator)组合而成如 a + 10(假设a和b为已定义的数值变量)。字面量是直接表示值的表达式如 42、"Hello"。

表达式总是隐含着一个计算过程,因此每个表达式都会有一个计算结果。对于只有操作数而没有操作符的表达式,其计算结果就是操作数自身。

本文不多介绍传统基本表达式,下面重点介绍控制流表达式。

仓颉(Cangjie)作为一门融合了现代编程语言设计理念的语言,弱化了传统 “语句” 与 “表达式” 的界限:

• 条件分支 → if-else 表达式

• 循环 → while、for 表达式

• 异常处理 → try 表达式

• 控制转移 → break、continue 也是表达式,类型为 Nothing

这体现了该语言将传统控制结构表达式化的设计理念。但需要特别注意在这方面的差异化处置:

【仅就目前( 2025 年 7 月推出首个长期支持版本(LTS 1.0.0)),华为仓颉编程语言,在传统控制结构表达式化这方面的差异化处置的总结】

if-else 表达式的类型(返回值类型)由分支类型推断(可能是任意类型,包括 Unit 或非 Unit——指的是它们通常用于返回一个有意义的值(如 StringInt 等)

while、do-while、for 表达式类型(返回值类型)都是 Unit,强调副作用而非返回值。和if-else 表达式不同,仓颉编程语言的while、do-while、for 表达式类型都是 Unit(表示 “无实际值” 的空类型),强调副作用而非返回值。

Unit:表示“有操作但无值”,类型安全且可显式使用。

【唯一值:Unit 类型只有一个实例,即 ()(空元组)。它不携带任何数据,仅表示“操作已完成,但无有意义的结果”。

类型安全:与直接忽略返回值不同,仓颉强制要求显式处理 Unit 类型,避免隐式丢弃值导致的潜在错误。】

异常处理 try 表达式‌返回值可能为非 Unit 类型。

break 和 continue 表达式的类型(返回值类型)为 Nothing,表示它们不返回任何值且不会改变程序的控制流之外的状态。

Nothing:表示“无可能返回”(如 break/continue/抛出异常),是所有类型的子类型,用于控制流转移。

刚开始不太好懂,先总体了解之,看完下面展开介绍及例子,就会逐渐明了。

如何运行下面代码,可参见

华为仓颉编程语言简介与快速实验上手图解_仓颉1.0.0示例-CSDN博客

华为仓颉编程语言实践体验-CSDN博客

if-else 表达式

基本形式:

if (条件) {

  分支 1

} else {

  分支 2

}

也可写为:

if (条件) { 分支1 } else { 分支2 }。

例如:

import std.convert.*main() {print("请输入score的值: ")var str: String = readln()var score =  Int8.parse(str)// if-else 示例if (score >= 60) {println("及格")} else {println("不及格")}}

测试运行:

特别说明

if-else 表达式的类型由分支类型推断(可能是任意类型,包括 Unit 或非 Unit)。求值规则:

计算“条件”表达式的值,若为 true,则执行“分支1”;若为 false 且存在 else 分支,则执行“分支2”。例如:

import std.convert.*main() {print("请输入a的值: ")var str: String = readln()var a =  Int64.parse(str)print("请输入b的值: ")var str2: String = readln()var b =  Int64.parse(str2)println("max = ${if (a >= b) { a } else { b }}")  //注意这一句,相当于下面两句let max = if (a >= b) { a } else { b }  //注意这一句println("max = ${max}")}

测试运行

循环:while、do-while、for 表达式

while、do-while、for 表达式的类型都是 Unit,强调副作用而非返回值。后面以for 表达式为例特别说明。

while 表达式

基本形式

while (条件) {

  循环体

}

例如:

main() {var i = 0  var sum = 0  while (i < 10) {  // 调整条件,确保累加1~10i += 1sum += i       }println("输出: sum = ${sum}") //输出: sum = 55return 0
}

do-while 表达式

基本形式:

do {

  循环体

} while (条件)

例如:

main() {var i = 1do {println("Current value: ${i}") i += 1                     } while (i <= 3)               
}

输出:

Current value: 1
Current value: 2
Current value: 3

for-in 表达式

基本形式:

for (迭代变量 in 序列) {

  循环体

}

例如

main() {var sum = 0for (i in 1..=100) {sum += i}println("sum = ${sum}")  //sum = 5050
}

前面提到while、do-while、for 表达式类型都是 Unit,强调副作用而非返回值。什么意思?for 循环表达式为例说明,请看下面例子:

main() {var sum = 0println("sum = ${for (i in 1..=100) { sum += i }}")
}

你可能想,预期通过 for 循环表达式计算 1 + 2 + ... + 100 的和(5050),然后通过字符串模板 ${...} 输出 sum = 5050。

但是实际输出sum = (),而不是sum = 5050 ,问什么?

解释

for循环作为表达式,其默认返回值类型是Unit(表示 “无实际值” 的空类型),无论循环体内做了什么操作。

代码中for (i in 1..=100) { sum += i }的作用是修改外部变量sum(这是一种 “副作用”),但循环本身的返回值始终是Unit。

当你在字符串模板中使用${for (...) {}}时,实际插入的是Unit类型的默认表示形式(),因此输出sum = ()。

你打印的是循环表达式的返回值(Unit),而不是sum变量的值。要打印sum变量的值,可参见前面的示例。

异常处理:try 表达式

基本形式:

try {

    // 可能出现异常的代码

} catch (e: ExceptionType) {

    // 处理异常的代码

} finally {

    // 资源释放的代码(可选)

}

try 块:执行可能抛出异常的代码。

catch 块:捕获异常并返回一个备用值(确保表达式始终有返回值)。

finally 块(可选):执行清理操作,但不影响 try 表达式的返回值。

、判断用户给出的整数的奇偶性,用try异常处理,防止用户输入非数字将出错中断运行,源码如下:

import std.convert.*
import std.io.*main(){print("请输入一个整数:")while (true) {var str: String = readln()if (str.isEmpty()) {print("输入为空,请重新输入一个整数:")continue}// 使用 try-catch 捕获 parse 可能抛出的异常try {var n =  Int64.parse(str)if( n % 2 == 0) {println("${n} 是偶数")} else {println("${n} 是奇数")}break} catch(e:IllegalArgumentException){print("输入非法,请输入一个有效的整数:")}}}

特别提示

异常处理 try 表达式‌返回值可能为非 Unit 类型

在华为仓颉编程语言中,try 表达式的返回值类型由 try 块或 catch 块中的最后一行表达式决定。若这些分支返回非 Unit 类型的值,则整个 try 表达式的类型会推断为该具体类型。

例如:

main() {// 示例1:try和catch都返回Int类型let result1 = try {let x = 10let y = 2x / y  // 返回Int} catch (e: Exception) {println("发生错误: ${e.message}")0  // 返回Int}println("结果1: ${result1}")  // 输出: 结果1: 5// 示例2:try返回String,catch返回Stringlet result2 = try {"成功执行"  // 返回String} catch (e: Exception) {"执行失败"  // 返回String}println("结果2: ${result2}")  // 输出: 结果2: 成功执行// 示例3:try抛出异常,catch返回非Unit类型let result3 = try {throw Exception("故意抛出异常")//println("不会执行到这里")} catch (e: Exception) {"捕获到故意抛出异常"  // 返回String}println("结果3: ${result3}")  // 输出: 结果3: 捕获到异常
}

测试运行:

这个示例展示了try表达式在不同情况下的返回值类型推断。当try或catch块最后一行是非Unit类型表达式时,整个try表达式就会采用该类型。

控制转移:break、continue 表达式

break 和 continue 表达式的类型为 Nothing,表示它们不返回任何值且不会改变程序的控制流之外的状态。

【Nothing 是一种特殊的类型,它不包含任何值,并且 Nothing 类型是所有类型的子类型(这当中也包括 Unit 类型)

break、continue、return 和 throw 表达式的类型是 Nothing,程序执行到这些表达式时,它们之后的代码将不会被执行。return 只能在函数体中使用,break、continue 只能在循环体中使用。】

例、以下程序使用 for-in 表达式和 break 表达式,在给定的整数数组中,找到第一个能被 5 整除的数字,源码如下:

main() {let numbers = [12, 18, 25, 36, 49, 55]for (number in numbers) {if (number % 5 == 0) {println(number)break}}
}

、以下程序使用 for-in 表达式和 continue 表达式,将给定整数数组中的奇数打印出来,源码如下:

main() {let numbers = [12, 18, 25, 36, 49, 55]for (number in numbers) {if (number % 2 == 0) {continue}println(number)}
}
输出:

输出:

25
49
55

赋值表达式

a= 2

b = a + 3

这些是是赋值表达式(包含赋值操作符的表达式),赋值表达式的类型是 Unit,值是 ()即空元组。例如:

main(){var a = 1var b = 2println("${a}, ${b}")/*a = (b = 0) // 编译错误,赋值表达式的类型是 Unit,值是 ()if (a = 5) { // 编译错误,赋值表达式的类型是 Unit,值是 ()}a = b = 0 // 语法错误,不支持链式使用赋值*/
}

其中,// 符号之后写单行注释;一对 /* 和 */ 符号之间写多行注释。注释内容不影响程序的编译和运行。

、官网介绍

https://cangjie-lang.cn/docs?url=%2F1.0.0%2Fuser_manual%2Fsource_zh_cn%2Fbasic_programming_concepts%2Fexpression.html

https://cangjie-lang.cn/docs?url=%2F0.53.18%2FSpec%2Fsource_zh_cn%2FChapter_12_Exceptions%28zh%29.html 中的“Try 表达式的类型”部分

https://cangjie-lang.cn/docs?url=%2F1.0.0%2Fuser_manual%2Fsource_zh_cn%2Fbasic_data_type%2Fbasic_operators.html 见开头几段有相关赋值表达式的介绍

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

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

相关文章

【linux】keepalived

一.高可用集群1.1 集群类型LB&#xff1a;Load Balance 负载均衡 LVS/HAProxy/nginx&#xff08;http/upstream, stream/upstream&#xff09; HA&#xff1a;High Availability 高可用集群 数据库、Redis SPoF: Single Point of Failure&#xff0c;解决单点故障 HPC&#xff…

Webpack配置原理

一、Loader&#xff1a; 1、定义&#xff1a;将不同类型的文件转换为 webpack 可识别的模块2、分类&#xff1a; ① pre&#xff1a; 前置 loader &#xff08;1&#xff09;配置&#xff1a;在 webpack 配置文件中通过enforce进行指定 loader的优先级配置&#xff08;2&#x…

对比JS“上下文”与“作用域”

下面从定义、特性、示例&#xff0c;以及在代码分析中何时侧重“上下文”&#xff08;Execution Context/this&#xff09;和何时侧重“作用域”&#xff08;Scope/变量查找&#xff09;&#xff0c;以及二者结合的场景来做对比和指导。一、概念对比 | 维度 | 上下文&#xff0…

如何做数据增强?

目录 1、为什么要做数据增强&#xff1f; 2、图像数据增强&#xff1f; 3、文本与音频数据增强&#xff1f; 4、高级数据增强&#xff1f; 数据增强技术就像是一种“造数据”的魔法&#xff0c;通过对原始数据进行各种变换&#xff0c;生成新的样本&#xff0c;从而提高模型…

Go by Example

网页地址Go by Example 中文版 Github仓库地址mmcgrana/gobyexample&#xff1a;按示例进行 HelloWorld package mainimport ("fmt" )func main() {fmt.Println("Hello World") } Hello World 值 package mainimport ("fmt" )func main() {…

ClickHouse高性能实时分析数据库-消费实时数据流(消费kafka)

告别等待&#xff0c;秒级响应&#xff01;这不只是教程&#xff0c;这是你驾驭PB级数据的超能力&#xff01;我的ClickHouse视频课&#xff0c;凝练十年实战精华&#xff0c;从入门到精通&#xff0c;从单机到集群。点开它&#xff0c;让数据处理速度快到飞起&#xff0c;让你…

电子电气架构 --- 车载软件与样件产品交付的方法

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

C++:STL中vector的使用和模拟实现

在上一篇中讲到了string类&#xff0c;string并不属于STL中因为string出现的比STL早&#xff0c;但是在使用方法上两者有相似之处&#xff0c;学习完string后再来看vector会容易的多&#xff0c;接着往下阅读&#xff0c;一定会有收获滴&#xff01; 目录 vector的介绍 vect…

仓库管理的流程、绩效和解决方案?

什么是仓库管理&#xff1f; 仓库管理涉及对所有仓库运营的日常监督。一个全面、集成的仓库管理解决方案采用行业最佳实践&#xff0c;并涵盖使高效运营得以实现的所有基本要素。这些要素包括分销和库存管理、仓库劳动力管理以及业务支持服务。此外&#xff0c;由内部提供或与服…

TIM 实现定时中断【STM32L4】【实操】

使用定时器实现定时中断的功能&#xff1a;比如每1ms进入中断处理函数使用STM32CubeMX配置TIM初始化先了解每个参数的含义&#xff0c;在进行配置Counter Settings: 计数器基本设置Prescaler(PSC): 预分频器&#xff0c;设置预分频器系数Counter Mode: 技术模式&#xff0c;…

Elasticsearch 的聚合(Aggregations)操作详解

目录 1. 概述 2. 聚合类型分类详解 2.1 桶聚合&#xff08;Bucket Aggregations&#xff09; 2.1.1 基础桶聚合 2.1.2 特殊桶聚合 2.1.3 高级桶聚合 2.2 指标聚合&#xff08;Metric Aggregations&#xff09; 2.2.1 单值指标聚合&#xff08;Single-value Metrics&am…

电子电气架构 --- 高阶智能驾驶对E/E架构的新要求

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

0.深度学习环境配置步骤

0.深度学习环境配置步骤 这里介绍深度学习环境配置详细步骤&#xff0c;包括安装软件&#xff0c;每一步都有安装时的截图&#xff08;后续持续更新&#xff0c;敬请关注&#xff09; 目录如下&#xff1a; 1.安装anaconda 2.安装CUDA 3.安装CU_DNN 4.安装pytorch

在 Azure 中配置 SMS 与 OTP

1. Azure Active Directory B2C (AAD B2C) 中的 SMS/OTP 身份验证 1.1. 现状与原理&#xff1a;电话注册与登录 Azure Active Directory B2C (AAD B2C) 提供了将电话号码作为用户身份标识进行注册和登录的功能&#xff0c;旨在为用户提供一种便捷的替代传统电子邮件或用户名登录…

简单实现支付密码的页面及输入效果

干我们这行&#xff0c;风吹日晒不到&#xff0c;就怕甲方突发奇想。 今天客户要做一个安全密码前置校验&#xff0c;还要做成支付宝那种效果。ps:android端 心理吐槽了一万遍以后&#xff0c;还是得面对现实。 先用通义问一遍&#xff0c;给了两个方案&#xff0c;要么自己写&…

proxmox 解决docker容器MongoDB创建报错MongoDB 5.0+ requires a CPU with AVX support

目录 最简单直接的方式 测试MongoDB docker compose的安装shell脚本 验证访问 最简单直接的方式 让虚拟机直接使用宿主机的物理 CPU 功能标志。 打开 Proxmox Web UI。 选择你的 VM → 硬件 (Hardware) → CPU → 点击 编辑 (Edit)。 将 CPU 类型改为 host。 确认并重启…

向前滚动累加SQL 实现思路

一、业务背景在经营分析场景里&#xff0c;我们经常需要回答&#xff1a;“截至今天&#xff0c;过去 N 天/月/周累计发生了多少&#xff1f;”“把维度切到省、市、房型、项目经理、代理商等&#xff0c;结果又是什么&#xff1f;”本文用两个真实需求做演示&#xff1a;以天为…

Spring AI(14)——文本分块优化

RAG时&#xff0c;检索效果的优劣&#xff0c;和文本的分块的情况有很大关系。SpringAI中通过TokenTextSplitter对文本分块。本文对SpringAI提供的TokenTextSplitter源码进行了分析&#xff0c;并给出一些自己的想法&#xff0c;欢迎大家互相探讨。查看了TokenTextSplitter的源…

Python----大模型(RAG 的智能评估-LangSmith)

一、LangSmith LangSmith是LangChain的一个子产品&#xff0c;是一个大模型应用开发平台。它提供了从原 型到生产的全流程工具和服务&#xff0c;帮助开发者构建、测试、评估和监控基于LangChain 或其他 LLM 框架的应用程序。 安装 LangSmith pip install langsmith0.1.137 官网…

磁悬浮轴承转子不平衡质量控制策略设计:原理、分析与智能实现

磁悬浮轴承(Active Magnetic Bearing, AMB)以其无接触、无摩擦、高转速、无需润滑等革命性优势,在高端旋转机械领域(如高速电机、离心压缩机、飞轮储能、航空航天动力系统)展现出巨大潜力。然而,转子固有的质量不平衡是AMB系统面临的核心挑战之一,它诱发强同步振动,威胁…