- 文档
- 编程语言
【免费下载链接】cangjie_docs
仓颉编程语言开发者文档。
布尔类型(Bool)是仓颉编程语言中表示逻辑"真"与"假"的基础数据类型,也是if、while、do-while等所有条件控制结构的判断依据。本篇基于仓颉开发者文档中的 布尔类型 章节,系统讲解Bool的字面量、支持的全部运算符(逻辑操作符、关系操作符与复合赋值操作符)、短路求值语义与操作符优先级,并结合文档中if/while条件表达式、for-in的where条件、Range构造函数与 C 互操作类型映射等实际场景,给出可直接运行的代码示例。读完本篇,你将能准确使用Bool组合复杂判断条件、编写无副作用的短路求值逻辑,并理解仓颉强类型设计下布尔表达式的类型约束。
Bool 类型与布尔字面量
布尔类型使用Bool表示,用来表示逻辑中的真(true)和假(false)。作为仓颉语言的基础数据类型之一,Bool与整数(Int8/Int16/Int32/Int64等)、浮点数、Rune、String等类型并列,是类型系统中使用频率最高的"开关"类型。
布尔类型只有两个字面量:true和false。在仓颉中,true与false是语言保留的关键字,不能作为标识符使用。下面的例子展示了布尔字面量的基本用法:
let a: Bool = true let b: Bool = false与部分弱类型语言不同,仓颉是强类型语言,布尔值不会与数值隐式互相转换:你不能用1或0代替true/false,也不能把Bool直接当数值参与算术运算。这一点在if条件中体现得尤为明显(见下文"Bool 在条件表达式中的应用")。
从编译器的词法层面看,布尔类型对应TokenKind枚举中的BOOLEAN分类(对应字符串"Bool"),与INT64、FLOAT64、RUNE等基础类型 Token 并列,可参见 TokenKind 类型:
public enum TokenKind <: ToString { ... | BOOLEAN // "Bool" ... }Bool 支持的操作符总览
布尔类型支持的操作符包括三类:
| 类别 | 操作符 | 说明 |
|---|---|---|
| 逻辑操作符 | ! | 逻辑非(一元前缀操作符) |
| 逻辑操作符 | && | 逻辑与(二元中缀操作符) |
| 逻辑操作符 | \|\| | 逻辑或(二元中缀操作符) |
| 关系操作符 | ==、!= | 判等与判不等("部分关系操作符",结果类型为Bool) |
| 复合赋值操作符 | &&=、\|\|= | 逻辑与赋值、逻辑或赋值 |
其中"部分关系操作符"的说法意味着:Bool自身不参与<、<=、>、>=这类大小比较(布尔值之间没有大小次序),但支持==与!=判等操作。所有关系操作符(包括作用于其他类型的六种操作符)的表达式结果类型都是Bool,即值只可能是true或false,详见 基本操作符 中"关系操作符"一节的说明。
逻辑操作符:!、&&、||
仓颉编程语言支持三种逻辑操作符:逻辑非(!)、逻辑与(&&)、逻辑或(||),相关完整说明可参考 基本操作符 中的"逻辑操作符"小节。
逻辑非(!)
逻辑非(!)是一元前缀操作符,作用是对其操作数的布尔值取反:!false的值等于true,!true的值等于false。
var a: Bool = true // a = true var b: Bool = !a // b = false var c: Bool = !false // c = true注意:一元
!同时承担"按位求反"职责,作用于整数类型时为按位取反(如!10结果为-11)。当操作数为Bool时,!表示逻辑非。
逻辑与(&&)与逻辑或(||)
逻辑与(&&)和逻辑或(||)都是二元中缀操作符,两个操作数必须同为布尔类型:
- 对于表达式
expr1 && expr2,只有当expr1和expr2的值均等于true时,整个表达式的值才等于true; - 对于表达式
expr1 || expr2,只有当expr1和expr2的值均等于false时,整个表达式的值才等于false。
真值表如下:
| expr1 | expr2 | expr1 && expr2 | expr1 || expr2 |
|---|---|---|---|
| true | true | true | true |
| true | false | false | true |
| false | true | false | true |
| false | false | false | false |
对应的可编译示例:
var a: Bool = true && true // a = true var b: Bool = true && false // b = false var c: Bool = false && false // c = false var d: Bool = false && true // d = false a = true || true // a = true b = true || false // b = true c = false || false // c = false d = false || true // d = true短路求值语义
逻辑与(&&)和逻辑或(||)采用短路求值(short-circuit evaluation)策略:
- 计算
expr1 && expr2时,当expr1 = false则无需对expr2求值,整个表达式的值为false; - 计算
expr1 || expr2时,当expr1 = true则无需对expr2求值,整个表达式的值为true。
短路求值不仅是性能优化,更直接影响程序行为:右侧表达式未被求值时,其可能产生的副作用(函数调用、输出、变量修改等)也不会发生。下面的示例用带输出的函数验证这一点:
func isEven(a: Int64): Bool { if ((a % 2) == 0) { println("${a} is an even number") true } else { println("${a} is not an even number") false } } main() { var a: Bool = isEven(2) && isEven(20) var b: Bool = isEven(3) && isEven(30) // isEven(3)返回值是false,b值为false,无需对isEven(30)求值 a = isEven(4) || isEven(40) // isEven(4)返回值是true,a值为true,无需对isEven(40)求值 b = isEven(5) || isEven(50) }该示例中,isEven(3) && isEven(30)只打印一行 "3 is not an even number";isEven(4) || isEven(40)只打印一行 "4 is an even number"。短路求值让"先做前置检查、再执行后续操作"的判断模式既安全又高效,例如if (index >= 0 && arr[index] > 0)这样的写法可以避免越界访问。
结合短路求值的实际应用
仓颉的if表达式条件中,多个布尔表达式通过&&/||直接连接即构成复合条件,例如"数值同时满足两个区间判断":
let i = 5 if (i > 0 && i < 10) { println("i 在区间 (0, 10) 内") }而在for-in表达式中,可以用where关键字引导一个布尔表达式作为循环过滤条件,每次进入循环体前先计算该表达式,值为true才执行循环体。例如只遍历奇数:
main() { for (i in 0..8 where i % 2 == 1) { // i 为奇数才会执行循环体 println(i) } }运行以上程序,将输出:
1 3 5 7关系操作符:== 与 !=
关系操作符包括六种:相等(==)、不等(!=)、小于(<)、小于等于(<=)、大于(>)、大于等于(>=)。它们都是二元操作符,要求两个操作数的类型相同,而关系表达式的类型一律是Bool类型。
对于Bool类型本身,适用的关系操作符是==与!=。判等与判不等可用于布尔值的比较,其真值表为:true == true为true,true == false为false,false != true为true。典型用法:
main(): Int64 { var flag: Bool = true var isTrue: Bool = flag == true // true var isFalse: Bool = flag != false // true return 0 }关系表达式同样可以与其他布尔表达式组合。例如,元组类型支持==判等与!=判不等,当且仅当其所有元素均支持==和!=运算;两个同类型元组实例相等,当且仅当它们长度相同且对应索引位置的所有元素均相等,其结果就是Bool:
var isTrue: Bool = (1, 3) == (0, 2) // false此外,is类型检查操作符(expr is Type)与as类型转换等表达式也以布尔结果参与条件判断,完整的操作符优先级与结合性表参见 操作符附录。
复合赋值操作符:&&= 与 ||=
仓颉编程语言提供&&=和||=两个逻辑复合赋值操作符。它们与+=、-=等复合赋值操作符一样,本质上是赋值表达式的一种:
expr1 &&= expr2等价于把expr1 && expr2的布尔结果重新赋给左操作数对应的变量;expr1 ||= expr2等价于把expr1 || expr2的布尔结果重新赋给左操作数对应的变量。
复合赋值表达式的求值顺序遵循统一规则:总是先计算=左边的表达式的左值,然后根据这个左值取右值,再将此右值与=右边的表达式做计算,最后赋值。因为复合赋值表达式也是赋值表达式,所以复合赋值操作符是非结合的,且复合赋值表达式要求两个操作数的类型相同,详见 基本操作符 中"复合赋值操作符"小节。
特别地,文档明确指出:复合赋值若涉及短路规则,会继续遵循短路规则。也就是说&&=与||=同样具备短路求值特性。示例:
main() { var a: Bool = true var b: Bool = false a &&= (b == false) // 等价于 a = a && (b == false),结果为 true println(a) // true b ||= (a == false) // 等价于 b = b || (a == false),a == false 为 false,结果仍为 false println(b) // false var flag: Bool = true flag &&= false // flag = false flag ||= true // flag = true }在实际编码中,flag &&= cond常用来实现"逐条件收紧的开关":只有所有条件都成立时flag才保持为true;而flag ||= cond常用来实现"任一条件成立即置位"。由于短路求值的存在,a &&= expr在a为false时不会对expr求值,a ||= expr在a为true时不会对expr求值,这在需要避免不必要的函数调用或空指针判断的场景中非常实用。
操作符优先级与结合性
正确书写布尔表达式离不开对优先级的把握。根据 操作符附录 中的完整优先级表(数值越小优先级越高),与Bool相关的操作符优先级如下:
| 操作符 | 优先级 | 结合方向 |
|---|---|---|
!(逻辑非) | 3 | 右结合 |
==、!= | 10 | 无(不可链式结合) |
&& | 14 | 左结合 |
\|\| | 15 | 左结合 |
&&=、\|\|=(及其余复合赋值) | 18 | 无 |
=(赋值) | 18 | 无 |
由此可以推导几个关键结论:
!的优先级高于所有二元逻辑与关系操作符,因此!a && b解析为(!a) && b;==/!=的优先级高于&&,高于||,因此a == b && c != d解析为(a == b) && (c != d),无需额外加括号;&&的优先级高于||,因此a || b && c解析为a || (b && c);- 赋值与复合赋值操作符优先级最低,且不结合,因此
a &&= b == c解析为a &&= (b == c)。
仓颉还支持自定义类型的操作符重载(包括逻辑与关系操作符),相关机制参见 操作符重载。
Bool 在条件表达式中的应用:强类型约束
仓颉是强类型语言,if、while、do-while等控制表达式的"条件"必须是布尔类型的表达式,这与 C 语言"以非 0 值作为真值"的约定完全不同。仓颉不会把整数或浮点数隐式当作布尔值使用,if (number)这类写法会直接编译报错,参见 表达式:
main() { let number = 1 if (number) { // 编译错误,类型不匹配 println("非零数") } }这种设计从根本上杜绝了"判等==误写成赋值="这类常见错误:赋值表达式(包含赋值操作符的表达式)的类型是Unit、值是(),而不是Bool,因此if (a = 5)同样会编译报错,无法通过编译。相关讨论可参见 基本操作符 开头的说明,以及 Unit 类型(Unit只有一个值(),除赋值、判等和判不等外不支持其他操作)。
典型的条件判断写法如下(完整示例见 表达式):
main() { let number: Int8 = 10 if (number % 2 == 0) { println("偶数") } else { println("奇数") } }while与do-while的条件同样必须是Bool:
var i = 0 while (i < 10) { i++ }提示:
if/while的条件除了布尔表达式,还允许 "let pattern"(let pattern <- expression语法糖)以及多个 "let pattern" 与布尔表达式通过&&/||组合的形式,例如if (let Some(b) <- a)。这类模式匹配成功的值为true,匹配失败为false,本质上仍是布尔判定,详见 表达式 与 Option 类型。
Bool 在库与互操作场景中的体现
Bool不仅是语法层面的基础类型,也广泛出现在仓颉标准库类型与 C 互操作接口中:
区间类型的构造参数:
Range<T>的构造函数签名为Range<T>(start: T, end: T, step: Int64, hasStart: Bool, hasEnd: Bool, isClosed: Bool),其中hasStart、hasEnd、isClosed三个Bool参数分别控制区间是否含起始值、终止值以及是否闭区间,参见 区间类型:// Range<T>(start: T, end: T, step: Int64, hasStart: Bool, hasEnd: Bool, isClosed: Bool) let r1 = Range<Int64>(0, 10, 1, true, true, true) // r1 contains 0, 1, ..., 9, 10 let r2 = Range<Int64>(0, 10, 1, true, true, false) // r2 contains 0, 1, ..., 9C 互操作类型映射:在仓颉与 C 语言互操作(FFI)中,
Bool与 C 的bool类型对应,占用 1 字节,见 Cangjie-C 互操作 中的基础类型映射表:Cangjie Type C Type Size (byte) Boolbool1 标准库 API 返回值:仓颉字符串等类型的接口大量以
Bool作为返回值,例如isEmpty()判断字符串长度是否为 0、isNull()判断指针是否为null、startsWith(str)判断字符串是否以str开头、equals(rhs)判断相等(忽略大小写版本为equalsLower)等,见 Cangjie-C 互操作 中 CString 相关接口列表:let t2: Bool = s2.isEmpty() let t3: Bool = s1.equals(s2) let t4: Bool = s1.startsWith(s2)
小结
Bool是仓颉编程语言中最基础也最常用的类型之一,其要点可以概括为:
- 字面量:仅有
true和false两个保留关键字值,无其他构造方式; - 逻辑操作符:
!(非)、&&(与)、||(或),其中&&与||遵循短路求值,右侧表达式在可提前确定结果时不求值; - 关系操作符:
Bool支持==与!=,所有关系表达式的类型均为Bool; - 复合赋值:
&&=与||=是赋值表达式,左值先求、保留短路语义、非结合; - 优先级:
!>==/!=>&&>||> 赋值类操作符,可通过括号显式控制; - 强类型约束:
if/while/do-while条件必须为Bool,数值不能隐式充当布尔值,这也从语言层面规避了==误写成=的经典错误。
想进一步了解其他基础类型(整数、浮点数、字符、字符串、元组、区间、Unit、Nothing)与操作符全貌,可继续阅读 基本数据类型目录 下的对应章节,以及 基本操作符 与 操作符附录。
- 文档
- 编程语言
【免费下载链接】cangjie_docs
仓颉编程语言开发者文档。
相关推荐
仓颉编程语言布尔类型(Bool)完全指南:字面量、逻辑运算与短路求值实战
仓颉编程语言布尔类型(Bool)完全指南:字面量、逻辑运算与短路求值实战 仓颉编程语言使用 Bool 类型表示逻辑中的真( true )与假( false ),
文档编程语言Gopeed 完整指南:多协议下载器一个任务列表装下 5 种协议,AI 也能直接管
Gopeed 完整指南:多协议下载器一个任务列表装下 5 种协议,AI 也能直接管 Gopeed 是一个用 Go 和 Flutter 写的免费开源多协议下载器,
网络CLI后端Move 语言布尔类型 bool 完全指南:字面量、逻辑运算与控制流
Move 语言布尔类型 bool 完全指南:字面量、逻辑运算与控制流 本篇技术指南系统讲解 Diem 项目中 Move 语言的内建布尔类型 bool :从 tr
区块链金融科技
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考