0. 版本介绍
本版本为Cangjie语言LTS 1.0.0版本的更新版本(LTS版本定义及维护周期详见仓颉社区版本生命周期管理规范,版本号为Cangjie 1.0.4,主要解决部分发现的Bug,以及对某些功能进行优化。版本包含了仓颉应用开发必须的能力,包括编译器,运行时,标准库,和工具链。欢迎各位开发者使用,如有任何问题,欢迎在Cangjie社区提出issue,我们会第一时间处理。以下介绍本版本相比LTS 1.0.3版本的更新。
1. 语言特性
无特性新增。
2. 编译器
本版本仅修复问题,无特性新增。修复问题如下:
- 【issue-105】let变量在lambda中被赋值了两次,未编译报错
- 【issue-2591】当同一个包不同文件中存在同名私有函数时,无法编译
- 【issue-2533】项目cjpm build -g编译失败,cjpm test --coverage编译崩溃,报错Error Code: 13
- 【issue-2565】【缺陷】Option
作为返回值时,当T为Array,ArrayList时,多层API调用时返回值不对
3. 运行时
本版本仅修复问题,无特性新增。修复问题如下:
- 【issue-2395】新项目MacOS26报SG_READ_ONLY缺失,修复MacOS26编译失败问题
- 【issue-2649】在运行GC场景中,长时间压测情况下,偶现cangjie进程卡死现象问题解决
4. 标准库
本版本仅修复问题,无特性新增。修复问题如下:
- 【issue-2242】修复在Timer的定时任务中调用cancel()时后不能以预期的方式取消的问题
- 【issue-2408】修复TreeMap和TreeSet中出现同一key值多次出现的问题
5. 工具链
1 IDE插件
本版本仅修复问题,无特性新增。修复问题如下:
- 【issue-1961】codeArts编译错误信息的中文内容显示为
- 【issue-6】codeArts编译错误信息的中文内容显示为乱码
2 cjpm
新增支持lto-combined功能,详情请参见工具指南。
本版本修复问题如下:
- 【issue-2373】优化cjpm init报错信息
- 【issue-2650】交叉编译场景下,cjpm宏包依赖出现错误
3 cjdb
无变化。
4 cjfmt
本版本仅修复问题,无特性新增:修复问题如下:
- 【issue-2385】cjfmt文档缺少cangjie-format.toml配置的介绍
5 cjlint
本版本仅修复问题,无特性新增:修复问题如下:
- 【issue-2433】cjlint的G.VAR.02规则误报,预期无警告
6 cjcov
无变化。
7 cjprof
无变化。
8 cjtrace-recover
无变化。
6. 遗留问题
在lambda body 体内修改lambda 参数,编译崩溃
【问题现象】在lambda body体内误修改lambda 参数,可能会导致 ICE,ErrorCode 为12。
【规避措施】不要错误的在lambda body体内修改lambda 参数
调用被扩展的接口函数的部分场景会导致运行时崩溃的问题
【问题现象】当存在一个泛型类 A 扩展了某个泛型接口 I,且存在另一个非泛型类 B 继承了实例化版本的类 A,将 B 的实例赋值给 I 类型变量且调用接口 I 函数时可能导致运行时崩溃。 样例:
interface I<T> {
func foo() {}
}
open class A<T> {}
extend<T> A<T> <: I<T> {}
class B <: A<Int64> {}
main() {
let i: I<Int64> = B()
i.foo() // 此处调用会发生运行阶段崩溃
return 0
}
【规避措施】 方案一:若类 A 定义在本包,可以不使用扩展,通过 A 直接继承接口 I 以规避该问题。 规避样例:
interface I<T> {
func foo() {}
}
open class A<T> <: I<T> {} // 使 A 继承 I
open class B <: A<Int64> {}
main() {
let i: I<Int64> = B()
i.foo()
return 0
}
方案二:若类 A 是导入自其它包,可以将类B定义为泛型类以规避该问题。 规避样例:
import pkgA.A
interface I<T> {
func foo() {}
}
extend<T> A<T> <: I<T> {}
open class B<T> <: A<T> {} // 将类 B 定义为泛型类
main() {
let i: I<Int64> = B<Int64>()
i.foo()
return 0
}
7. 文档变更说明
开发指南
- 程序结构章节新增说明:函数和lambda中的静态成员变量赋值,编译器无法判断函数或者lambda是否会被执行,因此采用保守策略,即编译报错。
- 普通try表达式中新增说明:当在try块中可能发生内存溢出错误时,应避免在catch或finally块中执行任何内存分配操作,以免再次触发溢出并导致未定义行为。一旦检测到内存溢出,建议在catch块中立即终止程序(例如调用exit函数),以确保系统稳定性并防止进一步错误。
- 新增编译选项--compile-as-exe相关内容。
标准库API
- 无变化。
工具指南
- 格式化工具cjfmt章节新增说明:CANGJIE_HOME环境下的默认格式化工具配置文件路径为CANGJIE_HOME/tools/config。
- cjpm工具中的模块配置文件说明增加支持工程级LTO相关说明。
初识仓颉语言
仓颉编程语言是一种面向全场景应用开发的通用编程语言,可以兼顾开发效率和运行性能,并提供良好的编程体验,主要具有如下特点:
- 多后端支持:仓颉编程语言支持 CJNative 和 CJVM 两种后端。其中 CJNative 后端将代码编译为原生二进制代码,直接在操作系统层面上运行;CJVM 后端将代码编译为字节码,基于 VM(虚拟机)进行运行。本次发布仅提供 CJNative 后端 SDK,CJVM 后端 SDK 敬请期待。
- 语法简明高效:仓颉编程语言提供了一系列简明高效的语法,旨在减少冗余书写、提升开发效率,例如插值字符串、主构造函数、Flow 表达式、
match和重导出等语法,让开发者可以用较少编码表达相关逻辑。 - 多范式编程:仓颉编程语言支持函数式、命令式和面向对象等多范式编程,融合了高阶函数、代数数据类型、模式匹配、泛型等函数式语言的先进特性,还有封装、接口、继承、子类型多态等支持模块化开发的面向对象语言特性,以及值类型、全局函数等简洁高效的命令式语言特性。开发者可以根据开发偏好或应用场景,选用不同的编程范式。
- 类型安全:仓颉编程语言是静态强类型语言,通过编译时类型检查尽早识别程序错误,降低运行时风险,也便于代码维护。同时,仓颉编译器提供了强大的类型推断能力,可以减少类型标注工作,提高开发效率。
- 内存安全:仓颉编程语言支持自动内存管理,并在运行时进行数组下标越界检查、溢出检查等操作,确保运行时内存安全。
- 高效并发:仓颉编程语言提供了用户态轻量化线程(原生协程),以及简单易用的并发编程机制,保证并发场景的高效开发和运行。
- 兼容语言生态:仓颉编程语言支持和 C 等编程语言的互操作,并采用便捷的声明式编程范式,可实现对其他语言库的高效复用和生态兼容。
- 领域易扩展:仓颉编程语言提供了基于词法宏的元编程能力,支持在编译时变换代码。此外,还提供了尾随
lambda、属性、操作符重载、部分关键字可省略等特性,开发者可由此深度定制程序的语法和语义,这有利于内嵌式领域专用语言(Embedded Domain Specific Languages,EDSL)的构建。 - 助力 UI 开发:UI 开发是构建端侧应用的重要环节,基于仓颉编程语言的元编程和尾随
lambda等特性,用户可以搭建声明式 UI 开发框架,提升 UI 开发效率和体验。 - 内置库功能丰富:仓颉编程语言提供了功能丰富的内置库,涉及数据结构、常用算法、数学计算、正则匹配、系统交互、文件操作、网络通信、数据库访问、日志打印、解压缩、编解码、加解密和序列化等功能。
安装仓颉工具链
在开发仓颉程序时,必用的工具之一是仓颉编译器,它可以将仓颉源代码编译为可运行的二进制文件,但现代编程语言的配套工具并不止于此,实际上,仓颉为开发者提供了编译器、调试器、包管理器、静态检查工具、格式化工具和覆盖率统计工具等一整套仓颉开发工具链,同时提供了友好的安装和使用方式,基本能做到“开箱即用”。
目前仓颉工具链已适配部分版本的 Linux、macOS 和 Windows 平台,但是仅针对部分 Linux 发行版做了完整功能测试,详情可参阅附录Linux 版本工具链的支持与安装章节,在暂未进行过完整功能测试的平台上,仓颉工具链的功能完整性不受到保证。此外,当前 Windows 平台上的仓颉编译器基于 MinGW 实现,相较于 Linux 版本的仓颉编译器,功能会有部分欠缺。
Linux / macOS
环境准备
Linux
Linux 版仓颉工具链的系统环境要求如下:
| 架构 | 环境要求 |
|---|---|
| x86_64 | glibc 2.22,Linux Kernel 4.12 或更高版本,系统安装 libstdc++ 6.0.24 或更高版本 |
| aarch64 | glibc 2.27,Linux Kernel 4.15 或更高版本,系统安装 libstdc++ 6.0.24 或更高版本 |
除此之外,对于 Ubuntu 18.04,还需要安装相应的依赖软件包:
$ apt-get install binutils libc-dev libc++-dev libgcc-7-dev
更多 Linux 发行版的依赖安装命令可以参见附录Linux 版本工具链的支持与安装章节。
此外,仓颉工具链还依赖 OpenSSL 3 组件,由于该组件可能无法从以上发行版的默认软件源直接安装,因此需要自行手动安装,安装方式请参见附录Linux 版本工具链的支持与安装章节。
macOS
macOS 版仓颉工具链支持在 macOS 12.0 及以上版本(aarch64 架构)运行。
使用 macOS 版本前需要安装相应的依赖软件包,可以通过执行以下命令安装:
$ brew install libffi
安装指导
首先请前往仓颉官网,下载适配平台架构的安装包:
cangjie-sdk-linux-x64-x.y.z.tar.gz:适用于 x86_64 架构 Linux 系统的仓颉工具链cangjie-sdk-linux-aarch64-x.y.z.tar.gz:适用于 aarch64 架构 Linux 系统的仓颉工具链cangjie-sdk-mac-aarch64-x.y.z.tar.gz:适用于 aarch64/arm64 架构 macOS 系统的仓颉工具链
假设这里选择了 cangjie-sdk-linux-x64-x.y.z.tar.gz,下载到本地后,请执行如下命令解压:
tar xvf cangjie-sdk-linux-x64-x.y.z.tar.gz
解压完成,可以在当前工作路径下看到一个名为 cangjie 的目录,其中存放了仓颉工具链的全部内容,请执行如下命令完成仓颉工具链的安装配置:
source cangjie/envsetup.sh
为了验证是否安装成功,可以执行如下命令:
cjc -v
其中 cjc 是仓颉编译器的可执行文件名,如果在命令行中看到了仓颉编译器版本信息,表示已经成功安装了仓颉工具链。值得说明的是,envsetup.sh 脚本只是在当前 shell 环境中配置了工具链相关的环境变量,所以仓颉工具链仅在当前 shell 环境中可用,在新的 shell 环境中,需要重新执行 envsetup.sh 脚本配置环境。
若想使仓颉工具链的环境变量配置在 shell 启动时自动生效,可以在 $HOME/.bashrc 或 $HOME/.zshrc(依 shell 种类而定)等 shell 初始化配置文件的最后加入以下命令:
# 假设仓颉安装包解压在 /home/user/cangjie 中
source /home/user/cangjie/envsetup.sh # 即 envsetup.sh 的绝对路径
配置完成后 shell 启动即可直接使用仓颉编译工具链。
卸载与更新
在 Linux 和 macOS 平台,删除上述仓颉工具链的安装包目录,同时移除上述环境变量(最简单的,可以新开一个 shell 环境),即可完成卸载。
$ rm -rf <path>/<to>/cangjie
若需要更新仓颉工具链,需要先卸载当前版本,然后按上述指导重新安装最新版本的仓颉工具链。
Windows
本节以 Windows 10 平台为例,介绍仓颉工具链的安装方式。
安装指导
在 Windows 平台上,仓颉为开发者提供了 exe 和 zip 两种格式的安装包,请前往仓颉官网,选择和下载适配平台架构的 Windows 版安装包。
-
如果选择
exe格式的安装包(例如cangjie-sdk-windows-x64-x.y.z.exe),请直接执行此文件,跟随安装向导点击操作,即可完成安装。 -
如果选择
zip格式的安装包(例如cangjie-sdk-windows-x64-x.y.z.zip),请将它解压到适当目录,在安装包中,仓颉为开发者提供了三种不同格式的安装脚本,分别是envsetup.bat,envsetup.ps1和envsetup.sh,可以根据使用习惯及环境配置,选择一种执行:-
若使用 Windows 命令提示符(CMD)环境,请执行:
path\to\cangjie\envsetup.bat -
若使用 PowerShell 环境,请执行:
. path\to\cangjie\envsetup.ps1 -
若使用 MSYS shell、bash 等环境,请执行:
source path/to/cangjie/envsetup.sh
为了验证是否安装成功,请在以上命令环境中继续执行
cjc -v命令,如果输出了仓颉编译器版本信息,表示已经成功安装了仓颉工具链。 -
值得注意的是,基于 zip 安装包和执行脚本的安装方式,类似于 Linux 平台,即 envsetup 脚本所配置的环境变量,只在当前命令行环境中有效,如果打开新的命令行窗口,需要重新执行 envsetup 脚本配置环境。此时,若想使仓颉工具链的环境变量配置在命令提示符或终端启动时自动生效,可以对系统进行如下配置:
-
若使用 bash 环境,可以根据如下步骤操作:
在
$HOME/.bashrc初始化配置文件的最后加入以下命令($HOME为当前用户目录的路径):# 假设仓颉安装包解压在 /home/user/cangjie 中 source /home/user/cangjie/envsetup.sh # 即 envsetup.sh 的绝对路径配置完成后 bash 启动即可直接使用仓颉编译工具链。
-
若使用 Windows 命令提示符(CMD)、PowerShell 或其他环境,可以根据如下步骤操作:
-
在 Windows 搜索框中,搜索 “查看高级系统设置” 并打开对应窗口;
-
单击 “环境变量” 按钮;
-
执行如下操作,配置 CANGJIE_HOME 变量:
-
在 “用户变量”(为当前用户进行配置)或 “系统变量”(为系统所有用户进行配置)区域中,查看是否已有 CANGJIE_HOME 环境变量。若没有,则单击 “新建” 按钮,并在 “变量名” 字段中输入
CANGJIE_HOME;若有,则说明该环境可能已经进行过仓颉配置,如果想要继续为当前的仓颉版本进行配置并覆盖原配置,请点击 “编辑” 按钮,进入 “编辑系统变量” 窗口。 -
在 “变量值” 字段中输入仓颉安装包的解压路径,若原先已经存在路径,则使用新的路径覆盖原有的路径,例如仓颉安装包解压在
D:\cangjie,则输入D:\cangjie。 -
配置完成后, “编辑用户变量” 或 “编辑系统变量” 窗口中显示的变量名为
CANGJIE_HOME、变量值为D:\cangjie。确认路径正确配置后单击 “确定” 。
-
-
执行如下操作,配置 Path 变量:
-
在 “用户变量”(为当前用户进行配置)或 “系统变量”(为系统所有用户进行配置)区域中,找到并选择 Path 变量,单击 “编辑” 按钮,进入 “编辑环境变量” 窗口。
-
分别单击 “新建” 按钮,并分别输入
%CANGJIE_HOME%\bin、%CANGJIE_HOME%\tools\bin、%CANGJIE_HOME%\tools\lib、%CANGJIE_HOME%\runtime\lib\windows_x86_64_llvm(%CANGJIE_HOME%为仓颉安装包的解压路径)。例如,仓库安装包解压在D:\cangjie,则新建的环境变量分别为:D:\cangjie\bin、D:\cangjie\tools\bin、D:\cangjie\tools\lib、D:\cangjie\runtime\lib\windows_x86_64_llvm。 -
(仅适用于为当前用户设置)单击 “新建” 按钮,并输入当前用户目录路径,并在路径后面添加
.cjpm\bin。例如用户路径在C:\Users\bob,则输入C:\Users\bob\.cjpm\bin。 -
配置完成后应能在 “编辑环境变量” 窗口中看到配置的路径如下所示。确认路径正确配置后单击 “确定” 。
D:\cangjie\bin D:\cangjie\tools\bin D:\cangjie\tools\lib D:\cangjie\runtime\lib\windows_x86_64_llvm C:\Users\bob\.cjpm\bin
-
-
单击 “确定” 按钮,退出 “环境变量” 窗口。
-
单击 “确定” 按钮,完成设置。
注意:
设置完成后可能需要重启命令行窗口或重启系统以让设置生效。
配置完成后 Windows 命令提示符(CMD)或 PowerShell 启动即可直接使用仓颉编译工具链。
-
卸载与更新
-
如果选择
exe格式的安装包进行的安装,运行仓颉安装目录下的unins000.exe可执行文件,跟随卸载向导点击操作,即可完成卸载。 -
如果选择
zip格式的安装包进行的安装,删除仓颉工具链的安装包目录,同时移除上述环境变量设置(若有),即可完成卸载。
若需要更新仓颉工具链,需要先卸载当前版本,然后按上述指导重新安装最新版本的仓颉工具链。
运行第一个仓颉程序
万事俱备,开始编写和运行第一个仓颉程序吧!
首先,请在适当目录下新建一个名为 hello.cj 的文本文件,并向文件中写入以下仓颉代码:
// hello.cj
main() {
println("你好,仓颉")
}
在这段代码中,使用了仓颉的注释语法,可以在 // 符号之后写单行注释,也可以在一对 /* 和 */ 符号之间写多行注释,这与 C/C++ 等语言的注释语法相同。注释内容不影响程序的编译和运行。
然后,请在此目录下执行如下命令:
cjc hello.cj -o hello
这里仓颉编译器会将 hello.cj 中的源代码编译为此平台上的可执行文件 hello,在命令行环境中运行此文件,将看到程序输出了如下内容:
你好,仓颉
注意:
以上编译命令是针对 Linux 和 macOS 平台的,如果使用 Windows 平台,只需要将编译命令改为
cjc hello.cj -o hello.exe即可。
标识符
在仓颉编程语言中,开发者可以给一些程序元素命名,这些名字被称为“标识符”。
学习标识符之前,需要了解一些 Unicode 字符集概念。在 Unicode 标准中,XID_Start 和 XID_Continue 属性用于标记可以作为 Unicode 标识符(Identifier)的起始字符和后续字符,其详细定义请参见 Unicode 标准文档。其中, XID_Start 包含中文和英文等字符,XID_Continue 包含中文、英文和阿拉伯数字等字符。仓颉语言使用 Unicode 标准 15.0.0 。
仓颉编程语言的标识符分为普通标识符和原始标识符两类,它们遵从不同的命名规则。
普通标识符不能和仓颉关键字相同,其取自以下两类字符序列:
- 由
XID_Start字符开头,后接任意长度的XID_Continue字符。 - 由一个
_开头,后接至少一个XID_Continue字符。
仓颉把所有标识符识别为 Normalization Form C (NFC) 后的形式。两个标识符如果在 NFC 后相等,则被认为是相同的标识符。
例如,以下每行字符串都是合法的普通标识符:
abc
_abc
abc_
a1b2c3
a_b_c
a1_b2_c3
仓颉
__こんにちは
以下每行字符串都是不合法的普通标识符:
ab&c // & 不是 XID_Continue 字符
3abc // 阿拉伯数字不是 XID_Start 字符,因此,数字不能作为起始字符
_ // _ 后至少需要有一个 XID_Continue 字符
while // while 是仓颉关键字,普通标识符不能使用仓颉关键字
原始标识符是在普通标识符或仓颉关键字的首尾加上一对反引号,主要用于将仓颉关键字作为标识符的场景。
例如,以下每行字符串都是合法的原始标识符:
`abc`
`_abc`
`a1b2c3`
`if`
`while`
`à֮̅̕b`
以下每行字符串,由于反引号内的部分是不合法的普通标识符,所以它们整体也是不合法的原始标识符:
`ab&c`
`3abc`
程序结构
通常,开发者会在扩展名为 .cj 的文本文件中编写仓颉程序,这些程序和文件也被称为源代码和源文件。在程序开发的最后阶段,这些源代码将被编译为特定格式的二进制文件。
在仓颉程序的顶层作用域中,可以定义一系列的变量、函数和自定义类型(如 struct、class、enum 和 interface 等),其中的变量和函数分别被称为全局变量和全局函数。如果要将仓颉程序编译为可执行文件,需要在顶层作用域中定义一个 main 函数作为程序入口,它可以有 Array<String> 类型的参数,也可以没有参数,它的返回值类型可以是整数类型或 Unit 类型。
注意:
定义
main函数时,不需要写func修饰符。此外,如果需要获取程序启动时的命令行参数,可以声明和使用Array<String>类型参数。
例如,在以下程序中,在顶层作用域定义了全局变量 a 和全局函数 b,还有自定义类型 C、D 和 E,以及作为程序入口的 main 函数。
// example.cj
let a = 2023
func b() {}
struct C {}
class D {}
enum E { F | G }
main() {
println(a)
}
在非顶层作用域中不能定义上述自定义类型,但可以定义变量和函数,称之为局部变量和局部函数。特别地,对于定义在自定义类型中的变量和函数,称之为成员变量和成员函数。
注意:
enum和interface中仅支持定义成员函数,不支持定义成员变量。
例如,在以下程序中,在顶层作用域定义了全局函数 a 和自定义类型 A,在函数 a 中定义了局部变量 b 和局部函数 c,在自定义类型 A 中定义了成员变量 b 和成员函数 c。
// example.cj
func a() {
let b = 2023
func c() {
println(b)
}
c()
}
class A {
let b = 2024
public func c() {
println(b)
}
}
main() {
a()
A().c()
}
运行以上程序,将输出:
2023
2024
变量
在仓颉编程语言中,一个变量由对应的变量名、数据(值)和若干属性构成,开发者通过变量名访问变量对应的数据,但访问操作需要遵从相关属性的约束(如数据类型、可变性和可见性等)。
变量定义的具体形式为:
修饰符 变量名: 变量类型 = 初始值
其中修饰符用于设置变量的各类属性,可以有一个或多个,常用的修饰符包括:
- 可变性修饰符:
let与var,分别对应不可变和可变属性,可变性决定了变量被初始化后其值还能否改变,仓颉变量也由此分为不可变变量和可变变量两类。 const修饰符:const是一种特殊的变量修饰符。它用于声明常量,要求在声明时必须初始化,一旦被赋值,其值就不能被改变。这与let修饰符类似,都具有不可变的特性,但const在使用上有更严格的限制。- 可见性修饰符:
private与public等,影响全局变量和成员变量的可引用范围,详见后续章节的相关介绍。 - 静态性修饰符:
static,影响成员变量的存储和引用方式,详见后续章节的相关介绍。
变量均支持赋值操作符(=),与类型无关。let 修饰的变量只能被赋值一次,即初始化;var 修饰的变量可以被多次赋值。
在定义仓颉变量时,可变性修饰符是必要的,在此基础上,还可以根据需要添加其他修饰符。
- 变量名应是一个合法的仓颉标识符。
- 变量类型指定了变量所持有数据的类型。当初始值具有明确类型时,可以省略变量类型标注,此时编译器可以自动推断出变量类型。
- 初始值是一个仓颉表达式,用于初始化变量,如果标注了变量类型,需要保证初始值类型和变量类型一致。在定义全局变量或静态成员变量时,必须指定初始值。在定义局部变量或实例成员变量时,可以省略初始值,但需要标注变量类型,同时要在此变量被引用前完成初始化,否则编译会报错。
例如,下列程序定义了三个 Int64 类型的变量(分别为不可变变量 a 、可变变量 b 和 const 变量 c )。随后修改了变量 b 的值,同时将 b 的值赋值给a,并调用 println 函数打印 a, b 和c 的值。
main() {
let a: Int64
var b: Int64 = 14
const c: Int64 = 13
b = 12
a = b // A variable modified by let can only be assigned once, that is, initialized
println("${a}, ${b}, ${c}")
}
编译运行此程序,将输出:
12, 12, 13
如果尝试修改不可变变量,编译时会报错,例如:
main() {
let pi: Float64 = 3.14159
pi = 2.71828 // Error, cannot assign to immutable value
}
当初始值具有明确类型时,可以省略变量类型标注,例如:
main() {
let a: Int64 = 2023
let b = a
println("a - b = ${a - b}")
}
其中变量 b 的类型可以由其初值 a 的类型自动推断为 Int64,所以此程序也可以被正常编译和运行,将输出:
a - b = 0
在定义局部变量时,可以不进行初始化,但一定要在变量被引用前赋予初值,例如:
main() {
let text: String
text = "仓颉造字"
println(text)
}
编译运行此程序,将输出:
仓颉造字
在定义全局变量和静态成员变量时必须初始化,否则编译会报错,例如:
let global: Int64 // Error, variable in top-level scope must be initialized
main(): Unit{
}
class Player {
static let score: Int32 // Error, static variable 'score' needs to be initialized when declaring
}
需要注意的是,当编译器无法判断某些场景是否一定会被初始化或无法判断是否重复初始化了不可变变量时,会倾向于保守策略进行编译报错,见如下示例:
func calc(a: Int32){
println(a)
return a * a
}
main() {
let a: String
if(calc(32) == 0){
a = "1"
}
a = "2" // Error, cannot assign to immutable value
}
对于函数和 lambda 中进行的静态成员变量赋值,编译器无法判断函数或者 lambda 是否会执行,会倾向于保守策略进行编译报错,见如下示例:
func foo(a: () -> Unit) {
// do something
}
class A {
public static var ctx: Int64 // error: the static member variable 'ctx' is not initialized
static init() {
let lambda1 = {=> ctx = 10}
foo(lambda1)
}
}
main() {}
此外,对于 try-catch 场景,编译器会假设 try 块总是全部被执行,且总是抛异常,从而进行相关报错,见如下示例:
main() {
let a: String
try {
a = "1"
} catch (_) {
a = "2" // Error, cannot assign to immutable value
}
}
const 变量
const 变量是一种特殊的变量,它以关键字 const 修饰,定义在编译时完成求值,并且在运行时不可改变的变量。例如,下面的例子定义了万有引力常数 G:
const G = 6.674e-11
const 变量可以省略类型标注,但是不可省略初始化表达式。const 变量可以是全局变量,局部变量,静态成员变量。但是 const 变量不能在扩展中定义。const 变量可以访问对应类型的所有实例成员,也可以调用对应类型的所有非 mut 实例成员函数。
下例定义了一个 struct,记录行星的质量和半径,同时定义了一个 const 成员函数 gravity 用来计算该行星对距离为 r 质量为 m 的物体的万有引力:
struct Planet {
const Planet(let mass: Float64, let radius: Float64) {}
const func gravity(m: Float64, r: Float64) {
G * mass * m / r**2
}
}
main() {
const myMass = 71.0
const earth = Planet(5.972e24, 6.378e6)
println(earth.gravity(myMass, earth.radius))
}
编译执行得到地球对地面上一个质量为 71 kg 的成年人的万有引力:
695.657257
const 变量初始化后该类型实例的所有成员都是 const 的(深度 const,包含成员的成员),因此不能被用于左值。
main() {
const myMass = 71.0
myMass = 70.0 // Error, cannot assign to immutable value
}
值类型和引用类型变量
从编译器实现层面看,任何变量总会关联一个值(一般是通过内存地址/寄存器关联),只是在使用时,对有些变量,将直接取用这个值本身,这被称为值类型变量;而对另一些变量,将这个值作为索引、取用这个索引指示的数据,这被称为引用类型变量。值类型变量通常在线程栈上分配,每个变量都有自己的数据副本;引用类型变量通常在进程堆中分配,多个变量可引用同一数据对象,对一个变量执行的操作可能会影响其他变量。
从语言层面看,值类型变量对它所绑定的数据/存储空间是独占的,而引用类型变量所绑定的数据/存储空间可以和其他引用类型变量共享。
基于上述原理,在使用值类型变量和引用类型变量时,会存在一些行为差异,以下几点值得注意:
- 在给值类型变量赋值时,一般会产生拷贝操作,且原来绑定的数据/存储空间会被覆盖。在给引用类型变量赋值时,只是改变了引用关系,原来绑定的数据/存储空间不会被覆盖。
- 用
let定义的变量,要求变量被初始化后都不能再赋值。对于引用类型,这只是限定了引用关系不可改变,但是所引用的数据是可以被修改的。
在仓颉编程语言中,class 和 Array 等类型属于引用类型,其他基础数据类型和 struct 等类型属于值类型。
例如,以下程序演示了 struct 和 class 类型变量的行为差异:
struct Copy {
var data = 2012
}
class Share {
var data = 2012
}
main() {
let c1 = Copy()
var c2 = c1
c2.data = 2023
println("${c1.data}, ${c2.data}")
let s1 = Share()
let s2 = s1
s2.data = 2023
println("${s1.data}, ${s2.data}")
}
运行以上程序,将输出:
2012, 2023
2023, 2023
由此可以看出,对于值类型的 Copy 类型变量,在赋值时总是获取 Copy 实例的拷贝,如 c2 = c1,随后对 c2 成员的修改并不影响 c1。对于引用类型的 Share 类型变量,在赋值时将建立变量和实例之间的引用关系,如 s2 = s1,随后对 s2 成员的修改会影响 s1。
如果将以上程序中的 var c2 = c1 改成 let c2 = c1,则编译会报错,例如:
struct Copy {
var data = 2012
}
main() {
let c1 = Copy()
let c2 = c1
c2.data = 2023 // Error, cannot assign to immutable value
}
作用域
在前文中,初步介绍了如何给仓颉程序元素命名,实际上,除了变量,还可以给函数和自定义类型等命名,在程序中将使用这些名字访问对应的程序元素。
但在实际应用中,需要考虑一些特殊情况:
- 当程序规模较大时,那些简短的名字很容易重复,即产生命名冲突。
- 结合运行时考虑,在有些代码片段中,另一些程序元素是无效的,对它们的引用会导致运行时错误。
- 在某些逻辑构造中,为了表达元素之间的包含关系,不应通过名字直接访问子元素,而是要通过其父元素名间接访问。
为了应对这些问题,现代编程语言引入了“作用域”的概念及设计,将名字和程序元素的绑定关系限制在一定范围里。不同作用域之间可以是并列或无关的,也可以是嵌套或包含关系。一个作用域将明确开发者能用哪些名字访问哪些程序元素,具体规则是:
- 当前作用域中定义的程序元素与名字的绑定关系,在当前作用域和其内层作用域中是有效的,可以通过此名字直接访问对应的程序元素。
- 内层作用域中定义的程序元素与名字的绑定关系,在外层作用域中无效。
- 内层作用域可以使用外层作用域中的名字重新定义绑定关系,根据规则 1,此时内层作用域中的命名相当于遮盖了外层作用域中的同名定义,对此称内层作用域的级别比外层作用域的级别高。
在仓颉编程语言中,用一对大括号“{}”包围一段仓颉代码,即构造了一个新的作用域,其中可以继续使用大括号“{}”包围仓颉代码,由此产生了嵌套作用域,这些作用域均服从上述规则。特别的,在一个仓颉源文件中,不被任何大括号“{}”包围的代码,它们所属的作用域被称为“顶层作用域”,即当前文件中“最外层”的作用域,按上述规则,其作用域级别最低。
注意:
仓颉不允许使用单独的大括号“{}”,大括号必须依赖 if、match、函数体、类体、结构体等其他语法结构存在。
例如在以下名为 test.cj 的仓颉源文件里,在顶层作用域中定义了名字 element,它和字符串“仓颉”绑定,而 main 和 if 引导的代码块中也定义了名字 element,分别对应整数 9 和整数 2023。由上述作用域规则,在第 4 行,element 的值为“仓颉”,在第 8 行,element 的值为 2023,在第 10 行,element 的值为 9。
// test.cj
let element = "仓颉"
main() {
println(element)
let element = 9
if (element > 0) {
let element = 2023
println(element)
}
println(element)
}
运行以上程序,将输出:
仓颉
2023
9
表达式
在一些传统编程语言中,一个表达式由一个或多个操作数(operand)通过零个或多个操作符(operator)组合而成。表达式总是隐含着一个计算过程,因此每个表达式都会有一个计算结果。对于只有操作数而没有操作符的表达式,其计算结果就是操作数自身。对于包含操作符的表达式,计算结果是对操作数执行操作符定义的计算而得到的值。在这种定义下的表达式也被称为算术运算表达式。操作符优先级请参见操作符章节。
在仓颉编程语言中,简化并延伸了表达式的传统定义——凡是可求值的语言元素都是表达式。因此,仓颉不仅有传统的算术运算表达式,还有条件表达式、循环表达式和 try 表达式等,它们都可以被求值,并作为值去使用,如作为变量定义的初值和函数实参等。此外,因为仓颉是强类型的编程语言,所以仓颉表达式不仅可求值,还有确定的类型。
注意:
为了清晰地划分不同的程序语句或表达式,仓颉采用分号(
;)进行分隔。如果一条语句独占一行,该分号可以省略,但一行存在多条语句,这些语句必须用分号进行分隔。
仓颉编程语言的各种表达式将在后续章节中逐一介绍,本节介绍最常用的条件表达式、循环表达式以及部分控制转移表达式(break、continue)。
任何一段程序的执行流程,只会涉及三种基本结构——顺序结构、分支结构和循环结构。实际上,分支结构和循环结构,是由某些指令控制当前顺序执行流产生跳转而得到的,它们让程序能够表达更复杂的逻辑。在仓颉中,这种用来控制执行流的语言元素就是条件表达式和循环表达式。
在仓颉编程语言中,条件表达式是 if 表达式,其值与类型需要根据使用场景来确定。循环表达式有三种:for-in 表达式、while 表达式和 do-while 表达式,它们的类型都是 Unit,值为 ()。
在仓颉程序中,由一对大括号“{}”包围起来的一组表达式,被称为“代码块”,它将作为程序的一个顺序执行流,其中的表达式将按编码顺序依次执行。如果代码块中有至少一个表达式,规定此代码块的值与类型等于其中最后一个表达式的值与类型,如果代码块中没有表达式,规定这种空代码块的类型为 Unit,值为 ()。
注意:
代码块本身不是一个表达式,不能被单独使用,它将依附于函数、条件表达式和循环表达式等执行和求值。
if 表达式
if 表达式的基本形式为:
if (条件) {
分支 1
} else {
分支 2
}
其中“条件”可以是一个布尔类型的表达式,或者一个 “let pattern” (语法糖),或者多个 “let pattern” 和布尔类型的表达式之间通过逻辑与或逻辑或直接连接形成的表达式,涉及 “let pattern” 的介绍和示例,参照涉及 “let pattern” 的“条件”示例。
当表达式和模式匹配成功时,该模式匹配的值为 true,此时执行 if 分支对应的代码块;反之,为 false,执行 else 分支代码块,else 分支可以不存在。
“分支 1”和“分支 2”是两个代码块。if 表达式将按如下规则执行:
- 计算“条件”表达式,如果值为
true则转到第 2 步,值为false则转到第 3 步。 - 执行“分支 1”,转到第 4 步。
- 执行“分支 2”,转到第 4 步。
- 继续执行
if表达式后面的代码。
在一些场景中,可能只关注条件成立时该做些什么,所以 else 和对应的代码块是允许省略的。
如下程序演示了 if 表达式的基本用法:
import std.random.*
main() {
let number: Int8 = Random().nextInt8()
println(number)
if (number % 2 == 0) {
println("偶数")
} else {
println("奇数")
}
}
在这段程序中,使用仓颉标准库的 random 包生成了一个随机整数,然后使用 if 表达式判断这个整数是否能被 2 整除,并在不同的条件分支中打印“偶数”或“奇数”。
仓颉编程语言是强类型的,if 表达式的条件只能是布尔类型,不能使用整数或浮点数等类型,和 C 语言等不同,仓颉不以条件取值是否为 0 作为分支选择依据,例如以下程序将编译报错(此外,后文的错误的表达式示例补充了更多错误的表达式用例场景,可对比参照):
main() {
let number = 1
if (number) { // 编译错误,类型不匹配
println("非零数")
}
}
在许多场景中,当一个条件不成立时,可能还要判断另一个或多个条件,再执行对应的动作。仓颉允许在 else 之后跟随新的 if 表达式,由此支持多级条件判断和分支执行,例如:
import std.random.*
main() {
let speed = Random().nextFloat64() * 20.0
println("${speed} km/s")
if (speed > 16.7) {
println("第三宇宙速度,鹊桥相会")
} else if (speed > 11.2) {
println("第二宇宙速度,嫦娥奔月")
} else if (speed > 7.9) {
println("第一宇宙速度,腾云驾雾")
} else {
println("脚踏实地,仰望星空")
}
}
if 表达式的值与类型,需要根据使用形式与场景来确定:
-
当含
else分支的if表达式被求值时,需要根据求值上下文确定if表达式的类型:- 如果上下文明确要求值类型为
T,则if表达式各分支代码块的类型必须是T的子类型,这时if表达式的类型被确定为T,如果不满足子类型约束,编译会报错。 - 如果上下文没有明确的类型要求,则
if表达式的类型是其各分支代码块类型的最小公共父类型,如果最小公共父类型不存在,编译会报错。
如果编译通过,则
if表达式的值就是所执行分支代码块的值。 - 如果上下文明确要求值类型为
-
如果含
else分支的if表达式没有被求值,在这种场景里,开发者一般只想在不同分支里做不同操作,不会关注各分支最后一个表达式的值与类型,为了不让上述类型检查规则影响这一思维习惯,仓颉规定这种场景下的if表达式类型为Unit、值为(),且各分支不参与上述类型检查。 -
对于不含
else分支的if表达式,由于if分支也可能不被执行,所以规定这类if表达式的类型为Unit、值为()。
例如,以下程序基于 if 表达式求值,模拟一次简单的模数转换过程:
main() {
let zero: Int8 = 0
let one: Int8 = 1
let voltage = 5.0
let bit = if (voltage < 2.5) {
zero
} else {
one
}
}
在以上程序中,if 表达式作为变量定义的初值使用,由于变量 bit 没有被标注类型、需要从初值中推导,所以 if 表达式的类型取为两个分支代码块类型的最小公共父类型。根据前文对“代码块”的介绍,可知两个分支代码块类型都是 Int8,所以 if 表达式的类型被确定为 Int8,其值为所执行分支即 else 分支代码块的值,所以变量 bit 的类型为 Int8、值为 1。
涉及 “let pattern” 的“条件”示例
“let pattern” 属于语法糖。一个 “let pattern” 的构成为 let pattern <- expression,其中各字段含义为:
pattern:模式,用于匹配expression的值类型和内容。<-:模式匹配操作符。expression:表达式,该表达式求值后,再和模式进行匹配。expression表达式的优先级不能低于..运算符,但是可以用()改变优先级。运算符优先级请参见操作符。
此处介绍“条件”是两个 “let pattern” 进行逻辑与或逻辑或操作以及 “let pattern” 与其他表达式进行逻辑与或逻辑或操作的示例。
main() {
let a = Some(3)
let c = if (let Some(b) <- a) {
1 // 模式匹配成功,c = 1
} else {
2
}
let d = Some(1)
if (let Some(e) <- a && let Some(f) <- d) { // 两种模式都匹配,条件的值为真
println("${e} ${f}") // print 3 1
}
if (let Some(f) <- d && f > 3) { // 模式匹配;f = 1,f > 3 检查失败,跳转到 else 分支
println("${f}")
} else {
println("d is None or value of d is less or equal to 3") // 打印该行
}
if (let Some(_) <- a || let Some(_) <- d) { // 枚举模式通过||连接,没有变量绑定,正确
println("at least one of a and d is Some") // 打印该行
} else {
println("both a and d are None")
}
let g = 3
if (let Some(_) <- a || g > 1) {
println("this") // 打印该行
} else {
println("that")
}
}
“let pattern” 中表达式部分运算符优先级不能低于 .. 运算符,此处介绍对应的错误和正确示例。其中, Option 类型的相关介绍在后文给出。
if (let Some(a) <- fun() as Option<Int64>) {} // 解析错误,`as` 的优先级低于 `..`
if (let Some(a) <- (fun() as Option<Int64>)) {} // 正确
if (let Some(a) <- b && a + b > 3) {} // 正确,解析为 (let Some(a) <- b) && (a + b > 3)
if (let m <- 0..generateSomeInt()) {} // 正确
错误的表达式示例
此处介绍错误的“条件”示例。
if (let Some(a) <- b || a > 1) {} // 由 `||` 连接的条件不能使用会绑定变量的 enum 模式
if (let Some(a) <- b && a + 1) {} // `&&` 右侧既不是 let pattern,也不是类型为 Bool 的普通表达式
if (a > 3 && let Some(a) <- b) {} // a 由 Some(a) pattern 绑定,不能在绑定它的 pattern 左侧使用
if (let Some(a) <- b && a > 3) {
println("${a} > 3")
} else {
println("${a} < 3") // a 只能在 if 分支使用,不能在 else 分支使用
}
if (let Some(a) <- b where a > 3) {} // 使用 `&&` 表示条件检查,而不是 `where`
while 表达式
while 表达式的基本形式为:
while (条件) {
循环体
}
其中“条件”同 if 表达式的“条件”,“循环体”是一个代码块。while 表达式将按如下规则执行:
- 计算“条件”表达式,如果值为
true则转第 2 步,值为false转第 3 步。 - 执行“循环体”,转第 1 步。
- 结束循环,继续执行
while表达式后面的代码。
例如,以下程序使用 while 表达式,基于二分法,近似计算数字 2 的平方根:
main() {
var root = 0.0
var min = 1.0
var max = 2.0
var error = 1.0
let tolerance = 0.1 ** 10
while (error ** 2 > tolerance) {
root = (min + max) / 2.0
error = root ** 2 - 2.0
if (error > 0.0) {
max = root
} else {
min = root
}
}
println("2 的平方根约等于:${root}")
}
运行以上程序,将输出:
2 的平方根约等于:1.414215
do-while 表达式
do-while 表达式的基本形式为:
do {
循环体
} while (条件)
其中“条件”是布尔类型表达式,“循环体”是一个代码块。do-while 表达式将按如下规则执行:
- 执行“循环体”,转第 2 步。
- 计算“条件”表达式,如果值为
true则转第 1 步,值为false转第 3 步。 - 结束循环,继续执行
do-while表达式后面的代码。
例如,以下程序使用 do-while 表达式,基于蒙特卡洛算法,近似计算圆周率的值:
import std.random.*
main() {
let random = Random()
var totalPoints = 0
var hitPoints = 0
do {
// 在 ((0, 0), (1, 1)) 这个正方形中随机取点
let x = random.nextFloat64()
let y = random.nextFloat64()
// 判断是否落在正方形内接圆里
if ((x - 0.5) ** 2 + (y - 0.5) ** 2 < 0.25) {
hitPoints++
}
totalPoints++
} while (totalPoints < 1000000)
let pi = 4.0 * Float64(hitPoints) / Float64(totalPoints)
println("圆周率近似值为:${pi}")
}
运行以上程序,将输出:
圆周率近似值为:3.141872
说明:
由于算法涉及随机数,所以每次运行程序输出的数值可能都不同,但都会约等于 3.14。
for-in 表达式
for-in 表达式可以遍历那些扩展了迭代器接口 Iterable<T> 的类型实例。for-in 表达式的基本形式为:
for (迭代变量 in 序列) {
循环体
}
其中“循环体”是一个代码块。“迭代变量”是单个标识符或由多个标识符构成的元组,用于绑定每轮遍历中由迭代器指向的数据,可以作为“循环体”中的局部变量使用。“序列”是一个表达式,它只会被计算一次,遍历是针对此表达式的值进行的,其类型必须扩展了迭代器接口 Iterable<T>。for-in 表达式将按如下规则执行:
- 计算“序列”表达式,将其值作为遍历对象,并初始化遍历对象的迭代器。
- 更新迭代器,如果迭代器终止,转第 4 步,否则转第 3 步。
- 将当前迭代器指向的数据与“迭代变量”绑定,并执行“循环体”,转第 2 步。
- 结束循环,继续执行
for-in表达式后面的代码。
说明:
仓颉内置的区间和数组等类型已经扩展了
Iterable<T>接口。
例如,以下程序使用 for-in 表达式,遍历中国地支字符构成的数组 noumenonArray,输出农历 2024 年各月的干支纪法:
main() {
let metaArray = [r'甲', r'乙', r'丙', r'丁', r'戊', r'己', r'庚', r'辛', r'壬', r'癸']
let noumenonArray = [r'寅', r'卯', r'辰', r'巳', r'午', r'未', r'申', r'酉', r'戌', r'亥', r'子', r'丑']
let year = 2024
// 年份对应的天干索引
let metaOfYear = ((year % 10) + 10 - 4) % 10
// 此年首月对应的天干索引
var index = (2 * metaOfYear + 3) % 10 - 1
println("农历 2024 年各月干支:")
for (noumenon in noumenonArray) {
print("${metaArray[index]}${noumenon} ")
index = (index + 1) % 10
}
}
其中 r 开头的字符表示字符类型字面量。运行以上程序,将输出:
农历 2024 年各月干支:
丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 甲戌 乙亥 丙子 丁丑
遍历区间
for-in 表达式可以遍历区间类型实例,例如:
main() {
var sum = 0
for (i in 1..=100) {
sum += i
}
println(sum)
}
运行以上程序,将输出:
5050
关于区间类型的详细内容,请参见基本数据类型区间类型。
遍历元组构成的序列
如果一个序列的元素是元组类型,则使用 for-in 表达式遍历时,“迭代变量”可以写成元组形式,以此实现对序列元素的解构,例如:
main() {
let array = [(1, 2), (3, 4), (5, 6)]
for ((x, y) in array) {
println("${x}, ${y}")
}
}
运行以上程序,将输出:
1, 2
3, 4
5, 6
迭代变量不可修改
在 for-in 表达式的循环体中,不能修改迭代变量,例如以下程序在编译时会报错:
main() {
for (i in 0..5) {
i = i * 10 // 错误,不能对已初始化的 `let` 常量赋值
println(i)
}
}
使用通配符 _ 代替迭代变量
在一些应用场景中,只需要循环执行某些操作,但并不使用迭代变量,这时可以使用通配符 _ 代替迭代变量,例如:
main() {
var number = 2
for (_ in 0..5) {
number *= number
}
println(number)
}
运行以上程序,将输出:
4294967296
注意:
在这种场景下,如果使用普通的标识符定义迭代变量,编译会输出“unused variable”告警,使用通配符
_则可以避免这一告警。
where 条件
在部分循环遍历场景中,对于特定取值的迭代变量,可能需要直接跳过,进入下一轮循环。虽然可以使用 if 表达式和 continue 表达式在循环体中实现这一逻辑,但仓颉为此提供了更便捷的表达方式——可以在所遍历的“序列”之后用 where 关键字引导一个布尔表达式,这样在每次将进入循环体执行前,会先计算此表达式。如果值为 true 则执行循环体,反之直接进入下一轮循环。例如:
main() {
for (i in 0..8 where i % 2 == 1) { // i 为奇数才会执行循环体
println(i)
}
}
运行以上程序,将输出:
1
3
5
7
break 与 continue 表达式
在循环结构的程序中,有时需要根据特定条件提前结束循环或跳过本轮循环,为此仓颉引入了 break 与 continue 表达式,它们可以出现在循环表达式的循环体中,break 用于终止当前循环表达式的执行、转去执行循环表达式之后的代码,continue 用于提前结束本轮循环、进入下一轮循环。break 与 continue 表达式的类型都是 Nothing。
例如,以下程序使用 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 迭代至 numbers 数组的第三个数 25 时,由于 25 可以被 5 整除,所以将执行 if 分支中的 println 和 break,break 将终止 for-in 循环,numbers中的后续数字不会被遍历到。因此运行以上程序,将输出:
25
以下程序使用 for-in 表达式和 continue 表达式,将给定整数数组中的奇数打印出来:
main() {
let numbers = [12, 18, 25, 36, 49, 55]
for (number in numbers) {
if (number % 2 == 0) {
continue
}
println(number)
}
}
在循环迭代中,当 number 是偶数时,continue 将被执行,这会提前结束本轮循环,进入下一轮循环,println 不会被执行。因此运行以上程序,将输出:
25
49
55
函数
仓颉使用关键字 func 来表示函数定义的开始,func 之后依次是函数名、参数列表、可选的函数返回值类型、函数体。其中,函数名可以是任意的合法标识符,参数列表定义在一对圆括号内(多个参数间使用逗号分隔),参数列表和函数返回值类型(如果存在)之间使用冒号分隔,函数体定义在一对花括号内。
函数定义举例:
func add(a: Int64, b: Int64): Int64 {
return a + b
}
上例中定义了一个名为 add 的函数,其参数列表由两个 Int64 类型的参数 a 和 b 组成,函数返回值类型为 Int64,函数体中将 a 和 b 相加并返回。
详细介绍可参见定义函数模块介绍。
基本操作符
操作符是执行特定的数学运算或逻辑操作的符号。例如,数学运算符号的加号(+)可将两个数相加(如:let i = 1 + 2),逻辑操作符号的逻辑与(&&)可用于组合并确保多个条件判断均满足(如:if (i > 0 && i < 10))。
仓颉编程语言不仅支持各种常用的操作符,同时为了减少常见编码错误对它们做了部分改进。如:赋值表达式(包含赋值操作符的表达式)的类型是 Unit,值是 (),如果将 if(a == 3) 写成 if(a = 3),赋值表达式的返回值不是布尔类型,因此会编译报错,这样可以避免将判等操作符(==)误写成赋值操作符(=)的问题。算术操作符(+、-、*、/、% 等)的结果会被检测并禁止值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。
仓颉编程语言还提供了区间操作符,例如 a..b 或 a..=b,这方便表达一个区间内的数值。
本章节只描述了仓颉编程语言中的基本操作符,其他操作符参见附录中的操作符。如何进行自定义类型的操作符重载参见操作符重载章节。
赋值操作符
用于将左操作数的值修改为右操作数的值,要求右操作数的类型是左操作数类型的子类型。对赋值表达式求值时,总是先计算 = 右边的表达式,再计算 = 左边的表达式,最后进行赋值。
main(): Int64 {
var a = 1
var b = 1
a = (b = 0) // 编译错误,赋值表达式的类型是 Unit,值是 ()
if (a = 5) { // 编译错误,赋值表达式的类型是 Unit,值是 ()
}
a = b = 0 // 语法错误,不支持链式使用赋值
return 0
}
多赋值表达式是一种特殊的赋值表达式,多赋值表达式等号左边必须是一个 tuple(元组) ,这个 tuple 里面的元素必须都是左值,等号右边的表达式也必须是 tuple 类型,右边 tuple 每个元素的类型必须是对应位置左值类型的子类型。值得注意的是当左侧 tuple 中出现 _ 时,表示忽略等号右侧 tuple 对应位置处的求值结果(意味着这个位置处的类型检查总是可以通过的)。多赋值表达式可以将右边的 tuple 类型的值,一次性赋值给左边 tuple 内的对应左值,省去逐个赋值的代码。
main(): Int64 {
var a: Int64
var b: Int64
(a, b) = (1, 2) // a = 1, b = 2
(a, b) = (b, a) // 交换, a = 2, b = 1
(a, _) = (3, 4) // a = 3
(_, _) = (5, 6) // 无赋值
return 0
}
算术操作符
仓颉编程语言支持的算术操作符包括:一元负号(-)、加(+)、减(-)、乘(*)、除(/)、取余(%)、求幂(**)。除了一元负号是一元前缀操作符,其他操作符均是二元中缀操作符。
一元负号(-)的操作数只能是数值类型的表达式。一元前缀负号表达式的值等于操作数取负的值,类型和操作数的类型相同:
let num1: Int64 = 8
let num2 = -num1 // num2 = -8, 其数据类型为“Int64”。
let num3 = -(-num1) // num3 = 8, 其数据类型为“Int64”。
对于二元操作符 *、/、%、+ 和 -,要求两个操作数的类型相同。其中 % 的操作数只支持整数类型;*、/、+ 和 - 的操作数可以是任意数值类型。
注意:
- 除法(
/)的操作数为整数时,将非整数值向 0 的方向舍入为整数。- 整数取余运算
a % b的值定义为a - b * (a / b)。- 加法操作符也可用于字符串的拼接。
let a = 2 + 3 // a = 5
let b = 3 - 1 // b = 2
let c = 3 * 4 // c = 12
let d = 7 / 3 // d = 2
let e = 7 / -3 // e = -2, 当遇到“-”时,它具有更高的优先级。
let f = -7 / 3 // f = -2
let g = -7 / -3 // g = 2, 当遇到“-”时,它具有更高的优先级。
let h = 4 % 3 // h = 1
let i = 4 % -3 // i = 1, 当遇到“-”时,它具有更高的优先级。
let j = -4 % 3 // j = -1
let k = -4 % -3 // k = -1, 当遇到“-”时,它具有更高的优先级。
let s1 = "abc"
var s2 = "ABC"
let r1 = s1 + s2 // r1 = "abcABC"
** 表示求幂运算(如 x**y 表示计算底数 x 的 y 次幂)。** 的左操作数只能为 Int64 类型或 Float64 类型。
注意:
当左操作类型为 Int64 时,右操作数只能为 UInt64 类型,表达式的类型为 Int64。 当左操作类型为 Float64 时,右操作数只能为 Int64 类型或 Float64 类型,表达式的类型为 Float64。
let p1 = 2 ** 3 // p1 = 8
let p2 = 2 ** UInt64(3 ** 2) // p2 = 512
let p3 = 2.0 ** 3 // p3 = 8.0
let p4 = 2.0 ** 3 ** 2 // p4 = 512.0
let p5 = 2.0 ** 3.0 // p5 = 8.0
let p6 = 2.0 ** 3.0 ** 2.0 // p6 = 512.0
复合赋值操作符
仓颉编程语言也提供 **=、*=、/=、%=、+=、-=、<<=、>>=、&=、^=、|=、&&= 和 ||= 复合赋值操作符。对于复合赋值表达式求值时,总是先计算 = 左边的表达式的左值,再根据这个左值取右值,然后将该右值与 = 右边的表达式做计算(若有短路规则会继续遵循短路规则),最后赋值。因为复合赋值表达式也是一个赋值表达式,所以复合赋值操作符也是非结合的。复合赋值表达式同样要求两个操作数的类型相同。
var a: Int64 = 10
a += 2 // a = 12
a -= 2 // a = 10
a **= 2 // a = 100
a *= 2 // a = 200
a /= 10 // a = 20
a %= 6 // a = 2
a <<= 2 // a = 8
关系操作符
关系操作符包括六种:相等(==)、不等(!=)、小于(<)、小于等于(<=)、大于(>)、大于等于(>=)。关系操作符都是二元操作符,并且要求两个操作数的类型是一样的。关系表达式的类型是 Bool 类型,即值只可能是 true 或 false。
关系表达式举例:
main(): Int64 {
3 < 4 // true
3 <= 3 // true
3 > 4 // false
3 >= 3 // true
3.14 == 3.15 // false
3.14 != 3.15 // true
return 0
}
对于元组类型,当且仅当所有元素均支持使用 == 进行值判等(使用 != 进行值判不等)时,此元组类型才支持使用 == 进行值判等(使用 != 进行值判不等);否则,此元组类型不支持 == 和 !=(如果使用 == 和 !=,编译报错)。两个同类型的元组实例相等,当且仅当相同位置(index)的元素全部相等(意味着它们的长度相等)。
var isTrue: Bool = (1, 3) == (0, 2) // false
isTrue = (1, "123") == (1.0, 2) // 编译错误,两个操作数的类型不一致
isTrue = (1, _) == (1.0, _) // 编译错误,通配符不可作为元组中元素进行匹配
coalescing 操作符
coalescing 操作符使用 ?? 表示,?? 是二元中缀操作符。coalescing 操作符用于 Option 类型的解构。
e1 ?? e2 表达式,在 e1 的值等于 Option<T>.Some(v) 时,e1 ?? e2 的值等于 v 的值(此时,不会再去对 e2 求值,即满足 “短路求值”);在 e1 的值等于 Option<T>.None 时,e1 ?? e2 的值等于 e2 的值。
coalescing 表达式使用举例:
main(): Int64 {
let v1 = Option<Int64>.Some(100)
let v2 = Option<Int64>.None
let r1 = v1 ?? 0
let r2 = v2 ?? 0
print("${r1}") // 100
print("${r2}") // 0
return 0
}
区间操作符
区间操作符有两种:.. 和 ..=,分别用于创建 “左闭右开” 和 “左闭右闭” 的区间实例。关于它们的介绍,请参见 区间类型。
逻辑操作符
仓颉编程语言支持三种逻辑操作符:逻辑非(!)、逻辑与(&&)、逻辑或(||)。
逻辑非(!)是一元操作符,它的作用是对其操作数的布尔值取反:!false 的值等于 true,!true 的值等于 false。
var a: Bool = true // a = true
var b: Bool = !a // b = false
var c: Bool = !false // c = true
逻辑与(&&)和逻辑或(||)均是二元操作符。对于表达式 expr1 && expr2,只有当 expr1 和 expr2 的值均等于 true 时,它的值才等于 true;对于表达式 expr1 || expr2,只有当 expr1 和 expr2 的值均等于 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
逻辑与(&&)和逻辑或(||)采用短路求值策略:计算 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)
}
位运算操作符
仓颉编程语言支持一种一元前缀位运算操作符:按位求反(!),以及五种二元中缀位运算操作符:左移(<<)、右移(>>)、按位与(&)、按位异或(^)和按位或(|)。位运算操作符的操作数只能为整数类型,通过将操作数视为二进制序列,然后在每一位上进行逻辑运算(0 视为 false,1 视为 true )或移位操作来实现位运算。
对于移位操作符,要求其操作数必须是整数类型(但两个操作数可以是不同的整数类型,例如:左操作数是 Int8,右操作数是 Int16),并且无论左移还是右移,右操作数都不允许为负数(对于编译时可检查出的此类错误,编译报错,如果运行时发生此错误,则抛出异常)。对于无符号数的移位操作,移位和补齐规则是:左移低位补 0 高位丢弃,右移高位补 0 低位丢弃。对于有符号数的移位操作,移位和补齐规则是:
- 正数和无符号数的移位补齐规则一致;
- 负数左移低位补 0 高位丢弃;
- 负数右移高位补 1 低位丢弃。
另外,如果右移或左移的位数(右操作数)等于或者大于操作数的宽度,则为移位越界,如果编译时可以检测到则报错,否则运行时抛出异常。
var a = !10 // -11,符合移位和补齐规则
a = !20 // -21,符合移位和补齐规则
a = 10 << 1 // 20,符合移位和补齐规则
// a = 1000 << -1 // 编译报错,移位操作溢出(右操作数都不允许为负数)
// a = 1000 << 100000000000 // 编译报错,移位操作溢出(移位越界)
a = 10 << 1 << 1 // 40,符合移位和补齐规则
a = 10 >> 1 // 5,符合移位和补齐规则
a = 10 & 15 // 10
a = 10 ^ 15 // 5
a = 10 | 15 // 15
a = (1 ^ (8 & 15)) | 24 // 25
自增自减操作符
自增(++)和自减(--)操作符实现对值的加 1 和减 1 操作,且只能作为后缀操作符使用。自增(++)和自减(--)操作符是非结合的。
对于表达式 expr++ (或 expr-- ),规定如下:
expr的类型必须是整数类型;- 因为
expr++(或expr--)是expr += 1(或expr -= 1)的语法糖,所以此 expr 同时必须也是可被赋值的; expr++(或expr--)的类型为 Unit。
自增(自减)表达式举例:
var i: Int32 = 5
i++ // i = 6
i-- // i = 5
i--++ // 语法错误
var j = 0
j = i-- // 语义错误
整数类型
整数类型分为有符号(signed)整数类型和无符号(unsigned)整数类型。
有符号整数类型包括 Int8、Int16、Int32、Int64 和 IntNative,分别用于表示编码长度为 8-bit、16-bit、32-bit、64-bit 和平台相关大小的有符号整数值的类型。
无符号整数类型包括 UInt8、UInt16、UInt32、UInt64 和 UIntNative,分别用于表示编码长度为 8-bit、16-bit、32-bit、64-bit 和平台相关大小的无符号整数值的类型。
对于编码长度为 N 的有符号整数类型,其表示范围为:$-2^{N-1} \sim 2^{N-1}-1$;对于编码长度为 N 的无符号整数类型,其表示范围为:$0 \sim 2^{N}-1$。下表列出了所有整数类型的表示范围:
| 类型 | 表示范围 |
|---|---|
| Int8 | $-2^7 \sim 2^7-1 (-128 \sim 127)$ |
| Int16 | $-2^{15} \sim 2^{15}-1 (-32,768 \sim 32,767)$ |
| Int32 | $-2^{31} \sim 2^{31}-1 (-2,147,483,648 \sim 2,147,483,647)$ |
| Int64 | $-2^{63} \sim 2^{63}-1 (-9,223,372,036,854,775,808 \sim 9,223,372,036,854,775,807)$ |
| IntNative | platform dependent |
| UInt8 | $0 \sim 2^8-1 (0 \sim 255)$ |
| UInt16 | $0 \sim 2^{16}-1 (0 \sim 65,535)$ |
| UInt32 | $0 \sim 2^{32}-1 (0 \sim 4,294,967,295)$ |
| UInt64 | $0 \sim 2^{64}-1 (0 \sim 18,446,744,073,709,551,615)$ |
| UIntNative | platform dependent |
程序具体使用哪种整数类型,取决于该程序中需要处理的整数的性质和范围。在 Int64 类型适合的情况下,首选 Int64 类型,因为 Int64 的表示范围足够大,并且整数类型字面量在没有类型上下文的情况下默认推断为 Int64 类型,可以避免不必要的类型转换。
整数类型字面量
整数类型字面量有 4 种进制表示形式:二进制(使用 0b 或 0B 前缀)、八进制(使用 0o 或 0O 前缀)、十进制(没有前缀)、十六进制(使用 0x 或 0X 前缀)。例如,对于十进制数 24,表示成二进制是 0b00011000(或 0B00011000),表示成八进制是 0o30(或 0O30),表示成十六进制是 0x18(或 0X18)。
在各进制表示中,可以使用下划线 _ 充当分隔符的作用,方便识别数值的位数,如 0b0001_1000。
对于整数类型字面量,如果它的值超出了上下文要求的整数类型的表示范围,编译器将会报错。
let x: Int8 = 128 // Error, 128 out of the range of Int8
let y: UInt8 = 256 // Error, 256 out of the range of UInt8
let z: Int32 = 0x8000_0000 // Error, 0x8000_0000 out of the range of Int32
在使用整数类型字面量时,可以通过加入后缀来明确整数字面量的类型,后缀与类型的对应为:
| 后缀 | 类型 | 后缀 | 类型 |
|---|---|---|---|
| i8 | Int8 | u8 | UInt8 |
| i16 | Int16 | u16 | UInt16 |
| i32 | Int32 | u32 | UInt32 |
| i64 | Int64 | u64 | UInt64 |
加入了后缀的整数字面量可以通过以下方式使用:
var x = 100i8 // x is 100 with type Int8
var y = 0x10u64 // y is 16 with type UInt64
var z = 0o432i32 // z is 282 with type Int32
字符字节字面量
仓颉编程语言支持字符字节字面量,以方便使用 ASCII 码表示 UInt8 类型的值。字符字节字面量由字符 b、一对标识首尾的单引号、以及一个 ASCII 字符组成,例如:
var a = b'x' // a is 120 with type UInt8
var b = b'\n' // b is 10 with type UInt8
var c = b'\u{78}' // c is 120 with type UInt8
c = b'\u{90}' - b'\u{66}' + c // c is 162 with type UInt8
b'x' 表示类型为 UInt8 大小是 120 的字面值。另外还可以通过 b'\u{78}' 这种转义形式表示类型为 UInt8,16 进制大小为 0x78 或 10 进制大小为 120 的字面值。需要注意的是,\u 内部最多有两位 16 进制数,并且值必须小于 256(十进制)。
整数类型支持的操作
整数类型默认支持的操作符包括:算术操作符、位操作符、关系操作符、自增和自减操作符、复合赋值操作符。各操作符的优先级参见附录中的操作符。
-
算术操作符包括:一元负号(
-)、加法(+)、减法(-)、乘法(*)、除法(/)、取模(%)、幂运算(**)。-
除了一元负号(
-)和幂运算(**),其他操作符要求左右操作数是相同的类型。 -
*,/,+和-的操作数可以是整数类型或浮点类型。 -
%的操作数只支持整数类型。 -
**的左操作数只能为Int64类型或Float64类型,并且:- 当左操作数类型为
Int64时,右操作数只能为UInt64类型,表达式的类型为Int64。 - 当左操作数类型为
Float64时,右操作数只能为Int64类型或Float64类型,表达式的类型为Float64。
- 当左操作数类型为
-
-
位操作符包括:按位求反(
!)、左移(<<)、右移(>>)、按位与(&)、按位异或(^)、按位或(|)。注意,按位与、按位异或和按位或操作符要求左右操作数是相同的整数类型。 -
关系操作符包括:小于(
<)、大于(>)、小于等于(<=)、大于等于(>=)、相等(==)、不等(!=)。要求关系操作符的左右操作数是相同的整数类型。 -
自增和自减操作符包括:自增(
++)和自减(--)。注意,仓颉中的自增和自减操作符只能作为一元后缀操作符使用。 -
复合赋值操作符包括:
+=、-=、*=、/=、%=、**=、<<=、>>=、&=、^=、|=。
整数类型之间、整数类型和浮点类型之间可以互相转换,整数类型可以转换为字符类型,具体的类型转换语法及规则请参见数值类型之间的转换。
注意:
本章所提及的某个类型支持的操作,均是指在没有操作符重载的前提下。
浮点类型
浮点类型包括 Float16、 Float32 和 Float64,分别用于表示编码长度为 16-bit、 32-bit 和 64-bit 的浮点数(带小数部分的数字,如 3.14159、8.24 和 0.1 等)的类型。Float16、 Float32 和 Float64 分别对应 IEEE 754 中的半精度格式(即 binary16)、单精度格式(即 binary32)和双精度格式(即 binary64)。
Float64 的精度(有效数字位)约为 15 位,Float32 的精度(有效数字位)约为 6 位,Float16 的精度(有效数字位)约为 3 位。使用哪种浮点类型,取决于代码中需要处理的浮点数的性质和范围。在多种浮点类型都适合的情况下,首选精度高的浮点类型,因为精度低的浮点类型的累计计算误差很容易扩散,并且它能精确表示的整数范围也很有限。
浮点类型字面量
浮点类型字面量有两种进制表示形式:十进制、十六进制。在十进制表示中,一个浮点字面量至少要包含一个整数部分或一个小数部分,没有小数部分时必须包含指数部分(以 e 或 E 为前缀,底数为 10)。在十六进制表示中,一个浮点字面量除了至少要包含一个整数部分或小数部分(以 0x 或 0X 为前缀),同时必须包含指数部分(以 p 或 P 为前缀,底数为 2)。
下面的例子展示了浮点字面量的使用:
let a: Float32 = 3.14 // a is 3.140000 with type Float32
let b: Float32 = 2e3 // b is 2000.000000 with type Float32
let c: Float32 = 2.4e-1 // c is 0.240000 with type Float32
let d: Float64 = .123e2 // d is 12.300000 with type Float64
let e: Float64 = 0x1.1p0 // e is 1.062500 with type Float64
let f: Float64 = 0x1p2 // f is 4.000000 with type Float64
let g: Float64 = 0x.2p4 // g is 2.000000 with type Float64
在使用十进制浮点数字面量时,可以通过加入后缀来明确浮点数字面量的类型,后缀与类型的对应为:
| 后缀 | 类型 |
|---|---|
| f16 | Float16 |
| f32 | Float32 |
| f64 | Float64 |
加入了后缀的浮点数字面量可以像下面的方式来使用:
let a = 3.14f32 // a is 3.140000 with type Float32
let b = 2e3f32 // b is 2000.000000 with type Float32
let c = 2.4e-1f64 // c is 0.240000 with type Float64
let d = .123e2f64 // d is 12.300000 with type Float64
浮点类型支持的操作
浮点类型默认支持的操作符包括:算术操作符、关系操作符、复合赋值操作符。浮点类型不支持自增和自减操作符。
浮点类型之间、浮点类型和整数类型之间可以互相转换,具体的类型转换语法及规则请参见数值类型之间的转换。
布尔类型
布尔类型使用 Bool 表示,用来表示逻辑中的真和假。
布尔类型字面量
布尔类型只有两个字面量:true 和 false。
下面的例子展示了布尔字面量的使用:
let a: Bool = true
let b: Bool = false
布尔类型支持的操作
布尔类型支持的操作符包括:逻辑操作符(逻辑非 !,逻辑与 &&,逻辑或 ||)、部分关系操作符(== 和 !=)、部分复合赋值操作符(&&= 和 ||=)。
字符类型
字符类型使用 Rune 表示,可以表示 Unicode 字符集中的所有字符。
字符类型字面量
字符类型字面量有三种形式:单个字符、转义字符和通用字符。一个 Rune 字面量由字符 r 开头,后跟一个由一对单引号或双引号包含的字符。
单个字符的字符字面量举例:
let a: Rune = r'a'
let b: Rune = r"b"
转义字符是指在一个字符序列中对后面的字符进行另一种解释的字符。转义字符使用转义符号 \ 开头,后面加需要转义的字符。举例如下:
let slash: Rune = r'\\'
let newLine: Rune = r'\n'
let tab: Rune = r'\t'
通用字符以 \u 开头,后面加上定义在一对花括号中的 1~8 个十六进制数,即可表示对应的 Unicode 值代表的字符。举例如下:
main() {
let he: Rune = r'\u{4f60}'
let llo: Rune = r'\u{597d}'
print(he)
print(llo)
}
编译并执行上述代码,输出结果为:
你好
字符类型支持的操作
字符类型支持的操作符包括:关系操作符,即小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、相等(==)、不等(!=)。比较的是字符的 Unicode 值。
Rune 可以转换为 UInt32,整数类型可以转换为 Rune,具体的类型转换语法及规则请参见Rune 到 UInt32 和整数类型到 Rune 的转换。
字符串类型
字符串类型使用 String 表示,用于表达文本数据,由一串 Unicode 字符组合而成。
字符串字面量
字符串字面量分为三类:单行字符串字面量,多行字符串字面量,多行原始字符串字面量。
单行字符串字面量的内容定义在一对单引号或一对双引号之内,引号中的内容可以是任意数量的(除了用于定义字符串字面量的非转义的引号和单独出现的 \ 之外的)任意字符。单行字符串字面量只能写在同一行,不能跨越多行。举例如下:
let s1: String = ""
let s2 = 'Hello Cangjie Lang'
let s3 = "\"Hello Cangjie Lang\""
let s4 = 'Hello Cangjie Lang\n'
多行字符串字面量开头结尾需各存在三个双引号(""")或三个单引号(''')。字面量的内容从开头的三个引号换行后的第一行开始,到遇到的第一个非转义的三个引号为止,之间的内容可以是任意数量的(除单独出现的 \ 之外的)任意字符。不同于单行字符串字面量,多行字符串字面量可以跨越多行。举例如下:
let s1: String = """
"""
let s2 = '''
Hello,
Cangjie Lang'''
多行原始字符串字面量以一个或多个井号(#)和一个单引号(')或双引号(")开头,后跟任意数量的合法字符,直到出现与字符串开头相同的引号和与字符串开头相同数量的井号为止。在当前文件结束之前,如果还没遇到匹配的双引号和相同个数的井号,则编译报错。与多行字符串字面量一样,原始多行字符串字面量可以跨越多行。不同之处在于,转义规则不适用于多行原始字符串字面量,字面量中的内容会维持原样(转义字符不会被转义,如下例中 s2 中的 \n 不是换行符,而是由 \ 和 n 组成的字符串 \n)。举例如下:
let s1: String = #""#
let s2 = ##'#'\n'## // 输出结果为:#'\n
let s3 = ###"
Hello,
Cangjie
Lang"### // 该变量当中的换行、缩进等也会被保留
对于形如 left = right 的赋值操作,如果左操作数的类型是 Byte(内置类型 UInt8 的别名),并且右操作数是一个表示 ASCII 字符的字符串字面量,那么右操作数的字符串将分别被强制转换为 Byte 类型,再进行赋值;如果左操作数的类型是 Rune,并且右操作数是一个单字符的字符串字面量,那么右操作数的字符串将分别被强制转换为 Rune 类型,再进行赋值。
main() {
var b: Byte = "0"
print(b)
b = "1"
print(b)
var r: Rune = "0"
print(r)
r = "1"
print(r)
}
编译并执行上述代码,输出结果为:
484901
插值字符串
插值字符串是一种包含一个或多个插值表达式的字符串字面量(不适用于多行原始字符串字面量),通过将表达式插入到字符串中,可以有效避免字符串拼接的问题。插值字符串经常出现在 println 函数中输出非字符串类型的变量值,例如 println("${x}")。
插值表达式必须用花括号 {} 包起来,并在 {} 之前加上 $ 前缀。{} 中可以包含一个或者多个声明或表达式。
当插值字符串求值时,每个插值表达式所在位置会被 {} 中的最后一项的值替换,整个插值字符串最终仍是一个字符串。
下面是插值字符串的简单示例:
main() {
let fruit = "apples"
let count = 10
let s = "There are ${count * count} ${fruit}"
println(s)
let r = 2.4
let area = "The area of a circle with radius ${r} is ${let PI = 3.141592; PI * r * r}"
println(area)
}
编译并执行上述代码,输出结果为:
There are 100 apples
The area of a circle with radius 2.400000 is 18.095570
字符串类型支持的操作
字符串类型支持使用关系操作符进行比较,支持使用 + 进行拼接。下面的例子展示了字符串类型的判等和拼接:
main() {
let s1 = "abc"
var s2 = "ABC"
let r1 = s1 == s2
println("The result of 'abc' == 'ABC' is: ${r1}")
let r2 = s1 + s2
println("The result of 'abc' + 'ABC' is: ${r2}")
}
编译并执行上述代码,输出结果为:
The result of 'abc' == 'ABC' is: false
The result of 'abc' + 'ABC' is: abcABC
字符串还支持其他常见操作,例如拆分、替换等。具体操作可以参考《仓颉编程语言标准库 API 》的 String 介绍,下面给出部分常见操作:
main() {
var s1 = "abc"
var s2 = "ABCabc"
var s3 = "abcyyabcqqabcbc"
let r1 = s2.contains(s1) // 判断s2中是否包含字符串s1
println(r1) // true
let r2 = s3.split(s1) //对原字符串 s3 按照字符串 s1 分隔符分割,指定是否删除空串
println(r2[1]) // yy
s1 = s2
println(s1) // ABCabc
}
元组类型
元组(Tuple)可以将多个不同的类型组合在一起,成为一个新的类型。元组类型使用 (T1, T2, ..., TN) 表示,其中 T1 到 TN 可以是任意类型,不同类型间使用逗号(,)连接。元组至少是二元,例如,(Int64, Float64) 表示一个二元组类型,(Int64, Float64, String) 表示一个三元组类型。
元组的长度是固定的,即一旦定义了一个元组类型的实例,它的长度不能再被更改。
元组类型是不可变类型,即一旦定义了一个元组类型的实例,它的内容(即单个元素)不能再被更新。但整个元组可被覆盖替换,例如:
let tuple1 = (8, false)
var tuple2 = (true, 9, 20)
tuple2 = tuple1 // Error, mismatched types
tuple2[0] = false // Error, 'tuple element' can not be assigned
var tuple3 = (9, true)
tuple3 = tuple1
println(tuple3[0]) // 8
println(tuple3[1]) // false
元组类型的字面量
元组类型的字面量使用 (e1, e2, ..., eN) 表示,其中 e1 到 eN 是表达式,多个表达式之间使用逗号分隔。下面的例子中,分别定义了一个 (Int64, Float64) 类型的变量 x,以及一个 (Int64, Float64, String) 类型的变量 y,并且使用元组类型的字面量为它们定义了初值:
let x: (Int64, Float64) = (3, 3.141592)
let y: (Int64, Float64, String) = (3, 3.141592, "PI")
元组支持通过 t[index] 的方式访问某个具体位置的元素,其中 t 是一个元组,index 是下标,并且 index 只能是从 0 开始且小于元组元素个数的整数类型字面量,否则编译报错。下面的例子中,使用 pi[0] 和 pi[1] 可以分别访问二元组 pi 的第一个元素和第二个元素。
main() {
var pi = (3.14, "PI")
println(pi[0])
println(pi[1])
}
编译并执行上述代码,输出结果为:
3.140000
PI
在赋值表达式中,可使用元组进行多赋值,参见赋值操作符章节。
元组类型的类型参数
可以为元组类型标记显式的类型参数名,下面例子中的 name 和 price 就是 类型参数名。
func getFruitPrice (): (name: String, price: Int64) {
return ("banana", 10)
}
对于一个元组类型,只允许统一写类型参数名,或者统一不写类型参数名,不允许交替存在,并且参数名本身不能作为变量使用或用于访问元组中元素。
let a: (name: String, Int64) = ("banana", 5) // Error
let b: (name: String, price: Int64) = ("banana", 5) // OK
b.name // Error
数组类型
Array
可以使用 Array 类型来构造单一元素类型,有序序列的数据。
仓颉使用 Array<T> 来表示 Array 类型。T 表示 Array 的元素类型,T 可以是任意类型。
var a: Array<Int64> = [0, 0, 0, 0] // Array whose element type is Int64
var b: Array<String> = ["a1", "a2", "a3"] // Array whose element type is String
元素类型不相同的 Array 是不相同的类型,所以它们之间不可以互相赋值。
因此以下例子是不合法的。
b = a // Type mismatch
可以轻松使用字面量来初始化一个 Array,只需要使用方括号将逗号分隔的值列表括起来即可。
编译器会根据上下文自动推断 Array 字面量的类型。
let a: Array<String> = [] // Created an empty Array whose element type is String
let b = [1, 2, 3, 3, 2, 1] // Created a Array whose element type is Int64, containing elements 1, 2, 3, 3, 2, 1
也可以使用构造函数的方式构造一个指定元素类型的 Array。其中,repeat 属于 Array 构造函数中的一个命名参数。
需要注意的是,当通过 repeat 指定的初始值初始化 Array 时,该构造函数不会拷贝 repeat,如果 repeat 是一个引用类型,构造后数组的每一个元素都将指向相同的引用。
let a = Array<Int64>() // Created an empty Array whose element type is Int64
let c = Array<Int64>(3, repeat: 0) // Created an Array whose element type is Int64, length is 3 and all elements are initialized as 0
let d = Array<Int64>(3, {i => i + 1}) // Created an Array whose element type is Int64, length is 3 and all elements are initialized by the initialization function
示例中 let d = Array<Int64>(3, {i => i + 1}) 使用了 lambda 表达式作为初始化函数来初始化数组中的每一个元素,即 {i => i + 1}。
访问 Array 成员
当需要对 Array 的所有元素进行访问时,可以使用 for-in 循环遍历 Array 的所有元素。
Array 是按元素插入顺序排列的,因此对 Array 遍历的顺序总是恒定的。
main() {
let arr = [0, 1, 2]
for (i in arr) {
println("The element is ${i}")
}
}
编译并执行上面的代码,会输出:
The element is 0
The element is 1
The element is 2
当需要知道某个 Array 包含的元素个数时,可以使用 size 属性获得对应信息。
main() {
let arr = [0, 1, 2]
if (arr.size == 0) {
println("This is an empty array")
} else {
println("The size of array is ${arr.size}")
}
}
编译并执行上面的代码,会输出:
The size of array is 3
当想访问单个指定位置的元素时,可以使用下标语法访问(下标的类型必须是 Int64)。非空 Array 的第一个元素总是从位置 0 开始的。可以从 0 开始访问 Array 的任意一个元素,直到最后一个位置(Array 的 size - 1)。索引值不能使用负数或者大于等于 size,当编译器能检查出索引值非法时,会在编译时报错,否则会在运行时抛异常。
main() {
let arr = [0, 1, 2]
let a = arr[0] // a == 0
let b = arr[1] // b == 1
let c = arr[-1] // array size is '3', but access index is '-1', which would overflow
}
如果想获取某一段 Array 的元素,可以在下标中传入 Range 类型的值,就可以一次性取得 Range 对应范围的一段 Array。
let arr1 = [0, 1, 2, 3, 4, 5, 6]
let arr2 = arr1[0..5] // arr2 contains the elements 0, 1, 2, 3, 4
当 Range 字面量在下标语法中使用时,可以省略 start 或 end。
当省略 start 时,Range 会从 0 开始;当省略 end 时,Range 的 end 会延续到最后一位。
let arr1 = [0, 1, 2, 3, 4, 5, 6]
let arr2 = arr1[..3] // arr2 contains elements 0, 1, 2
let arr3 = arr1[2..] // arr3 contains elements 2, 3, 4, 5, 6
修改 Array
Array 是一种长度不变的 Collection 类型,因此 Array 没有提供添加和删除元素的成员函数。
但是 Array 允许对其中的元素进行修改,同样使用下标语法。
main() {
let arr = [0, 1, 2, 3, 4, 5]
arr[0] = 3
println("The first element is ${arr[0]}")
}
编译并执行上面的代码,会输出:
The first element is 3
Array 虽然是 struct 类型,但其内部持有的只是元素的引用,因此在作为表达式使用时不会拷贝副本,同一个 Array 实例的所有引用都会共享同样的元素数据。
因此对 Array 元素的修改会影响到该实例的所有引用。
let arr1 = [0, 1, 2]
let arr2 = arr1
arr2[0] = 3
// arr1 contains elements 3, 1, 2
// arr2 contains elements 3, 1, 2
VArray
除了引用类型的数组 Array,仓颉还引入了值类型数组 VArray<T, $N> ,其中 T 表示该值类型数组的元素类型,$N 是一个固定的语法。通过 $ 加上一个 Int64 类型的数值字面量表示这个值类型数组的长度。需要注意的是,VArray<T, $N> 不能省略 <T, $N>,且使用类型别名时,不允许拆分 VArray 关键字与其泛型参数。
与频繁使用引用类型 Array 相比,使用值类型 VArray 可以减少堆上内存分配和垃圾回收的压力。但是需要注意的是,由于值类型本身在传递和赋值时的拷贝,会产生额外的性能开销,因此建议不要在性能敏感场景使用较大长度的 VArray。值类型和引用类型的特点请参见值类型和引用类型变量。
type varr1 = VArray<Int64, $3> // Ok
type varr2 = VArray // Error
注意:
由于运行时后端限制,当前
VArray<T, $N>的元素类型T或T的成员不能包含引用类型、枚举类型、Lambda 表达式(CFunc除外)以及未实例化的泛型类型。
VArray 可以由一个数组的字面量来进行初始化,左值 a 必须标识出 VArray 的实例化类型:
var a: VArray<Int64, $3> = [1, 2, 3]
同时,它拥有两个构造函数:
// VArray<T, $N>(initElement: (Int64) -> T)
let b = VArray<Int64, $5>({ i => i }) // [0, 1, 2, 3, 4]
// VArray<T, $N>(repeat!: T)
let c = VArray<Int64, $5>(repeat: 0) // [0, 0, 0, 0, 0]
除此之外,VArray<T, $N> 类型提供了两个成员方法:
-
用于下标访问和修改的
[]操作符方法:var a: VArray<Int64, $3> = [1, 2, 3] let i = a[1] // i is 2 a[2] = 4 // a is [1, 2, 4]下标访问的下标类型必须为
Int64。 -
用于获取
VArray长度的size成员:var a: VArray<Int64, $3> = [1, 2, 3] let s = a.size // s is 3size 属性的类型为
Int64。
此外,VArray 还支持仓颉与 C 语言互操作场景使用,相关内容请参见数组。
区间类型
区间类型用于表示拥有固定步长的序列,区间类型是一个泛型,使用 Range<T> 表示。当 T 被实例化不同的类型时(要求此类型必须支持关系操作符,并且可以和 Int64 类型的值做加法),会得到不同的区间类型,如最常用的 Range<Int64> 用于表示整数区间。
每个区间类型的实例都会包含 start、end 和 step 三个值。其中,start 和 end 分别表示序列的起始值和终止值,step 表示序列中前后两个元素之间的差值(即步长);start 和 end 的类型相同(即 T 被实例化的类型),step 类型是 Int64,并且它的值不能等于 0。
下面的例子给出了区间类型的实例化方式(关于区间类型定义和其中的属性,详见《仓颉编程语言库 API》):
// 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, 2, 3, 4, 5, 6, 7, 8, 9, 10
let r2 = Range<Int64>(0, 10, 1, true, true, false) // r2 contains 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
let r3 = Range<Int64>(10, 0, -2, true, true, false) // r3 contains 10, 8, 6, 4, 2
区间类型字面量
区间字面量有两种形式:“左闭右开”区间和“左闭右闭”区间。
- “左闭右开”区间的格式是
start..end : step,它表示一个从start开始,以step为步长,到end(不包含end)为止的区间; - “左闭右闭”区间的格式是
start..=end : step,它表示一个从start开始,以step为步长,到end(包含end)为止的区间。
下面的例子定义了若干区间类型的变量:
let n = 10
let r1 = 0..10 : 1 // r1 contains 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
let r2 = 0..=n : 1 // r2 contains 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
let r3 = n..0 : -2 // r3 contains 10, 8, 6, 4, 2
let r4 = 10..=0 : -2 // r4 contains 10, 8, 6, 4, 2, 0
区间字面量中,可以不写 step,此时 step 默认等于 1,但是step 的值不能等于 0。另外,区间也有可能是空的(即不包含任何元素的空序列),举例如下:
let r5 = 0..10 // the step of r5 is 1, and r5 contains 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
let r6 = 0..10 : 0 // Error, step cannot be 0
let r7 = 10..0 : 1 // r7 to r10 are empty ranges
let r8 = 0..10 : -1
let r9 = 10..=0 : 1
let r10 = 0..=10 : -1
注意:
- 表达式
start..end : step中,当step > 0且start >= end,或者step < 0且start <= end时,start..end : step是一个空区间;- 表达式
start..=end : step中,当step > 0且start > end,或者step < 0且start < end时,start..=end : step是一个空区间。
Unit 类型
对于那些只关心副作用而不关心值的表达式,它们的类型是 Unit。例如,print 函数、赋值表达式、复合赋值表达式、自增和自减表达式、循环表达式,它们的类型都是 Unit。
Unit 类型只有一个值,也是它的字面量:()。除了赋值、判等和判不等外,Unit 类型不支持其他操作。
Nothing 类型
Nothing 是一种特殊的类型,它不包含任何值,并且 Nothing 类型是所有类型的子类型(这当中也包括 Unit 类型)。
break、continue、return 和 throw 表达式的类型是 Nothing,程序执行到这些表达式时,它们之后的代码将不会被执行。return 只能在函数体中使用,break、continue 只能在循环体中使用,参考如下示例:
while (true) {
func f() {
break // Error, break must be used directly inside a loop
}
let g = { =>
continue // Error, continue must be used directly inside a loop
}
}
由于函数的形参和其默认值不属于该函数的函数体,所以下面例子中的 return 表达式缺少包围它的函数体——它既不属于外层函数 f(因为内层函数定义 g 已经开始),也不在内层函数 g 的函数体中(该用例相关内容,请参考嵌套函数):
func f() {
func g(x!: Int64 = return) { // Error, return must be used inside a function body
0
}
1
}
注意:
目前编译器还不允许在使用类型的地方显式地使用 Nothing 类型。
定义函数
仓颉使用关键字 func 来表示函数定义的开始,func 之后依次是函数名、参数列表、可选的函数返回值类型、函数体。其中,函数名可以是任意的合法标识符,参数列表定义在一对圆括号内(多个参数间使用逗号分隔),参数列表和函数返回值类型(如果存在)之间使用冒号分隔,函数体定义在一对花括号内。
函数定义举例:
func add(a: Int64, b: Int64): Int64 {
return a + b
}
上例中定义了一个名为 add 的函数,其参数列表由两个 Int64 类型的参数 a 和 b 组成,函数返回值类型为 Int64,函数体中将 a 和 b 相加并返回。
下面依次对函数定义中的参数列表、函数返回值类型和函数体作进一步介绍。
参数列表
一个函数可以拥有 0 个或多个参数,这些参数均定义在函数的参数列表中。根据函数调用时是否需要给定参数名,可以将参数列表中的参数分为两类:非命名参数和命名参数。
非命名参数的定义方式是 p: T,其中 p 表示参数名,T 表示参数 p 的类型,参数名和其类型间使用冒号连接。例如,上例中 add 函数的两个参数 a 和 b 均为非命名参数。
命名参数的定义方式是 p!: T,与非命名参数的不同是在参数名 p 之后多了一个 !。可以将上例中 add 函数的两个非命名参数修改为命名参数,如下所示:
func add(a!: Int64, b!: Int64): Int64 {
return a + b
}
命名参数还可以设置默认值,通过 p!: T = e 方式将参数 p 的默认值设置为表达式 e 的值。例如,可以将上述 add 函数的两个参数的默认值都设置为 1:
func add(a!: Int64 = 1, b!: Int64 = 1): Int64 {
return a + b
}
注意:
只能为命名参数设置默认值,不能为非命名参数设置默认值。
参数列表中可以同时定义非命名参数和命名参数,但是需要注意的是,非命名参数只能定义在命名参数之前,也就意味着命名参数之后不能再出现非命名参数。例如,下例中 add 函数的参数列表定义是不合法的:
func add(a!: Int64, b: Int64): Int64 { // Error, named parameter 'a' must be defined after non-named parameter 'b'
return a + b
}
非命名参数和命名参数的主要差异在于调用时的不同,具体可参见下文调用函数中的介绍。
函数参数均为不可变变量,在函数定义内不能对其赋值。
func add(a: Int64, b: Int64): Int64 {
a = a + b // Error
return a
}
函数参数作用域从定义处起至函数体结束:
func add(a: Int64, b: Int64): Int64 {
var a_ = a // OK
var b = b // Error, redefinition of declaration 'b'
return a
}
函数返回值类型
函数返回值类型是函数被调用后得到的值的类型。函数定义时,返回值类型是可选的:可以显式地定义返回值类型(返回值类型定义在参数列表和函数体之间),也可以不定义返回值类型,交由编译器推导确定。
当显式地定义了函数返回值类型时,就要求函数体的类型(关于如何确定函数体的类型可参见下节函数体)、函数体中所有 return e 表达式中 e 的类型是返回值类型的子类型。例如,对于上述 add 函数,显式地定义了它的返回值类型为 Int64;如果将函数体中的 return a + b 修改为 return (a, b),则会因为类型不匹配而报错:
// Error, the type of the expression after return does not match the return type of the function
func add(a: Int64, b: Int64): Int64 {
return (a, b)
}
在函数定义时如果未显式定义返回值类型,编译器将根据函数体的类型以及函数体中所有的 return 表达式来共同推导出函数的返回值类型。例如,下例中 add 函数的返回值类型虽然被省略,但编译器可以根据 return a + b 推导出 add 函数的返回值类型是 Int64:
func add(a: Int64, b: Int64) {
return a + b
}
注意:
函数的返回值类型并不是任何情况下都可以被推导出来的,如果返回值类型推导失败,编译器会报错。
指定返回类型为 Unit 时,编译器会在函数体中所有可能返回的地方自动插入表达式 return (),使得函数的返回类型总是为 Unit。
函数体
函数体中定义了函数被调用时执行的操作,通常包含一系列的变量定义和表达式,也可以包含新的函数定义(即嵌套函数)。如下 add 函数的函数体中首先定义了 Int64 类型的变量 r(初始值为 0),接着将 a + b 的值赋值给 r,最后将 r 的值返回:
func add(a: Int64, b: Int64) {
var r = 0
r = a + b
return r
}
在函数体的任意位置都可以使用 return 表达式来终止函数的执行并返回。return 表达式有两种形式:return 和 return expr(expr 是一个表达式)。
对于 return expr,要求 expr 的类型与函数定义中的返回值类型保持一致。例如,下例中会因为 return 100 中 100 类型(Int64)和函数 foo 的返回值类型(String)不同而报错。
// Error, cannot convert an integer literal to type 'Struct-String'
func foo(): String {
return 100
}
对于 return,其等价于 return (),所以要求函数的返回值类型为 Unit。
func add(a: Int64, b: Int64) {
var r = 0
r = a + b
return r
}
func foo(): Unit {
add(1, 2)
return
}
注意:
return表达式作为一个整体,其类型并不由后面跟随的表达式决定,而是Nothing类型。
在函数体内定义的变量属于局部变量的一种(如上例中的 r 变量),它的作用域从其定义之后开始到函数体结束。
对于一个局部变量,允许在其外层作用域中定义同名变量,并且在此局部变量的作用域内,局部变量会“遮盖”外层作用域的同名变量。例如:
let r = 0
func add(a: Int64, b: Int64) {
var r = 0
r = a + b
return r
}
上例中,add 函数之前定义了 Int64 类型的全局变量 r,同时 add 函数体内定义了同名的局部变量 r,那么在函数体内,所有使用变量 r 的地方(如 r = a + b),用到的将是局部变量 r,即(在函数体内)局部变量 r “遮盖”了全局变量 r。
函数返回值类型中提到函数体也是有类型的,函数体的类型是函数体内最后一“项”的类型:若最后一项为表达式,则函数体的类型是此表达式的类型,若最后一项为变量定义或函数声明,或函数体为空,则函数体的类型为 Unit。例如:
func add(a: Int64, b: Int64): Int64 {
a + b
}
上例中,因为函数体的最后一“项”是 Int64 类型的表达式(即 a + b),所以函数体的类型也是 Int64,与函数定义的返回值类型相匹配。又如,下例中函数体的最后一项是 print 函数调用,所以函数体的类型是 Unit,同样与函数定义的返回值类型相匹配:
func foo(): Unit {
let s = "Hello"
print(s)
}
调用函数
函数调用的形式为 f(arg1, arg2, ..., argn)。其中,f 是要调用的函数的名字,arg1 到 argn 是 n 个调用时的参数(称为实参),要求每个实参的类型必须是对应参数类型的子类型。实参可以有 0 个或多个,当实参个数为 0 时,调用方式为 f()。
根据函数定义时参数是非命名参数还是命名参数的差异,函数调用时传实参的方式也有所不同:对于非命名参数,它对应的实参是一个表达式;对于命名参数,它对应的实参需要使用 p: e 的形式,其中 p 是命名参数的名字,e 是表达式(即传递给参数 p 的值)。
非命名参数调用举例:
func add(a: Int64, b: Int64) {
return a + b
}
main() {
let x = 1
let y = 2
let r = add(x, y)
println("The sum of x and y is ${r}")
}
执行结果为:
The sum of x and y is 3
命名参数调用举例:
func add(a: Int64, b!: Int64) {
return a + b
}
main() {
let x = 1
let y = 2
let r = add(x, b: y)
println("The sum of x and y is ${r}")
}
执行结果为:
The sum of x and y is 3
对于多个命名参数,调用时的传参顺序可以和定义时的参数顺序不同。例如,下例中调用 add 函数时 b 可以出现在 a 之前:
func add(a!: Int64, b!: Int64) {
return a + b
}
main() {
let x = 1
let y = 2
let r = add(b: y, a: x)
println("The sum of x and y is ${r}")
}
执行结果为:
The sum of x and y is 3
对于拥有默认值的命名参数,调用时如果没有传实参,那么此参数将使用默认值作为实参的值。例如,下例中调用 add 函数时没有为参数 b 传实参,那么参数 b 的值等于其定义时的默认值 2:
func add(a: Int64, b!: Int64 = 2) {
return a + b
}
main() {
let x = 1
let r = add(x)
println("The sum of x and y is ${r}")
}
执行结果为:
The sum of x and y is 3
对于拥有默认值的命名参数,调用时也可以为其传递新的实参,此时命名参数的值等于新的实参的值,即定义时的默认值将失效。例如,下例中调用 add 函数时为参数 b 传了新的实参值 20,那么参数 b 的值就等于 20:
func add(a: Int64, b!: Int64 = 2) {
return a + b
}
main() {
let x = 1
let r = add(x, b: 20)
println("The sum of x and y is ${r}")
}
执行结果为:
The sum of x and y is 21
函数类型
仓颉编程语言中,函数是一等公民(first-class citizens),可以作为函数的参数或返回值,也可以赋值给变量。因此函数本身也有类型,称之为函数类型。
函数类型由函数的参数类型和返回类型组成,参数类型和返回类型之间使用 -> 连接。参数类型使用圆括号 () 括起来,可以有 0 个或多个参数,如果参数超过一个,参数类型之间使用逗号(,)分隔。
例如:
func hello(): Unit {
println("Hello!")
}
上述示例定义了一个函数,函数名为 hello,其类型是 () -> Unit,表示该函数没有参数,返回类型为 Unit。
以下给出另一些示例:
-
示例:函数名为
display,其类型是(Int64) -> Unit,表示该函数有一个参数,参数类型为Int64,返回类型为Unit。func display(a: Int64): Unit { println(a) } -
示例:函数名为
add,其类型是(Int64, Int64) -> Int64,表示该函数有两个参数,两个参数类型均为Int64,返回类型为Int64。func add(a: Int64, b: Int64): Int64 { a + b } -
示例:函数名为
returnTuple,其类型是(Int64, Int64) -> (Int64, Int64),两个参数类型均为Int64, 返回类型为元组类型:(Int64, Int64)。func returnTuple(a: Int64, b: Int64): (Int64, Int64) { (a, b) }
函数类型的类型参数
可以为函数类型标记显式的类型参数名,下面例子中的 name 和 price 就是 类型参数名。
func showFruitPrice(name: String, price: Int64) {
println("fruit: ${name} price: ${price} yuan")
}
main() {
let fruitPriceHandler: (name: String, price: Int64) -> Unit
fruitPriceHandler = showFruitPrice
fruitPriceHandler("banana", 10)
}
另外对于一个函数类型,只允许统一写类型参数名,或者统一不写类型参数名,不能交替存在。
let handler: (name: String, Int64) -> Int64 // Error
函数类型作为参数类型
示例:函数名为 printAdd,其类型是 ((Int64, Int64) -> Int64, Int64, Int64) -> Unit,表示该函数有三个参数,参数类型分别为函数类型 (Int64, Int64) -> Int64 和两个 Int64,返回类型为 Unit。
func printAdd(add: (Int64, Int64) -> Int64, a: Int64, b: Int64): Unit {
println(add(a, b))
}
函数类型作为返回类型
函数类型可以作为另一个函数的返回类型。
如下示例中,函数名为 returnAdd,其类型是 () -> (Int64, Int64) -> Int64,表示该函数无参数,返回类型为函数类型 (Int64, Int64) -> Int64。注意,-> 是右结合的。
func add(a: Int64, b: Int64): Int64 {
a + b
}
func returnAdd(): (Int64, Int64) -> Int64 {
add
}
main() {
var a = returnAdd()
println(a(1,2))
}
函数类型作为变量类型
函数名本身也是表达式,它的类型为对应的函数类型。
func add(p1: Int64, p2: Int64): Int64 {
p1 + p2
}
let f: (Int64, Int64) -> Int64 = add
上述示例中,函数名是 add,其类型为 (Int64, Int64) -> Int64。变量 f 的类型与 add 类型相同,add 被用来初始化 f。
若一个函数在当前作用域中被重载(见函数重载)了,那么直接使用该函数名作为表达式可能产生歧义,如果产生歧义编译器会报错,例如:
func add(i: Int64, j: Int64) {
i + j
}
func add(i: Float64, j: Float64) {
i + j
}
main() {
var f = add // Error, ambiguous function 'add'
var plus: (Int64, Int64) -> Int64 = add // OK
}
嵌套函数
定义在源文件顶层的函数被称为全局函数。定义在函数体内的函数被称为嵌套函数。
示例,函数 foo 内定义了一个嵌套函数 nestAdd,可以在 foo 内调用该嵌套函数 nestAdd,也可以将嵌套函数 nestAdd 作为返回值返回,在 foo 外对其进行调用:
func foo() {
func nestAdd(a: Int64, b: Int64) {
a + b + 3
}
println(nestAdd(1, 2)) // 6
return nestAdd
}
main() {
let f = foo()
let x = f(1, 2)
println("result: ${x}")
}
程序会输出:
6
result: 6
Lambda 表达式
Lambda 表达式定义
Lambda 表达式是一种匿名函数(即没有函数名的函数),其核心设计目的是在程序中快速定义简短的函数逻辑,无需显式声明函数名称。这一概念起源于数学中的 λ 演算(lambda calculus),后被引入多种编程语言(如 C++、Python、C# 等),用于简化代码并提升灵活性。仓颉编程语言中也引入了 Lambda 表达式,具体使用介绍将在本小节展开介绍。
Lambda 表达式的语法为如下形式: { p1: T1, ..., pn: Tn => expressions | declarations }。
其中,=> 之前为参数列表,多个参数之间使用 , 分隔,每个参数名和参数类型之间使用 : 分隔。=> 之前也可以没有参数。=> 之后为 Lambda 表达式体,是一组表达式或声明序列。Lambda 表达式的参数名的作用域与函数的相同,为 Lambda 表达式的函数体部分,其作用域级别可视为与 Lambda 表达式的函数体内定义的变量等同。
let f1 = { a: Int64, b: Int64 => a + b }
var display = { => // Parameterless lambda expression.
println("Hello")
println("World")
}
Lambda 表达式不管有没有参数,都不可以省略 =>,除非其作为尾随 lambda。例如:
var display = { => println("Hello") }
func f2(lam: () -> Unit) {}
let f2Res = f2 { println("World") } // OK to omit the =>
Lambda 表达式中参数的类型标注可缺省。以下情形中,若参数类型省略,编译器会尝试进行类型推断,当编译器无法推断出类型时会编译报错:
- Lambda 表达式赋值给变量时,其参数类型根据变量类型推断;
- Lambda 表达式作为函数调用表达式的实参使用时,其参数类型根据函数的形参类型推断。
// The parameter types are inferred from the type of the variable sum1
var sum1: (Int64, Int64) -> Int64 = { a, b => a + b }
var sum2: (Int64, Int64) -> Int64 = { a: Int64, b => a + b }
func f(a1: (Int64) -> Int64): Int64 {
a1(1)
}
main(): Int64 {
// The parameter type of lambda is inferred from the type of function f
f({ a2 => a2 + 10 })
}
Lambda 表达式中不支持声明返回类型,其返回类型总是从上下文中推断出来,若无法推断则报错。
-
若上下文明确指定了 Lambda 表达式的返回类型,则其返回类型为上下文指定的类型。
-
Lambda 表达式赋值给变量时,其返回类型根据变量类型推断返回类型:
let f: () -> Unit = { ... } -
Lambda 表达式作为参数使用时,其返回类型根据使用处所在的函数调用的形参类型推断:
func f(a1: (Int64) -> Int64): Int64 { a1(1) } main(): Int64 { f({ a2: Int64 => a2 + 10 }) } -
Lambda 表达式作为返回值使用时,其返回类型根据使用处所在函数的返回类型推断:
func f(): (Int64) -> Int64 { { a: Int64 => a } }
-
-
若上下文中类型未明确,与推导函数的返回值类型类似,编译器会根据 Lambda 表达式体中所有 return 表达式
return xxx中 xxx 的类型,以及 Lambda 表达式体的类型,来共同推导出 Lambda 表达式的返回类型。-
=>右侧的内容与普通函数体的规则一样,返回类型为Int64:let sum1 = { a: Int64, b: Int64 => a + b } -
=>的右侧为空,返回类型为Unit:let f = { => }
-
Lambda 表达式调用
Lambda 表达式支持立即调用,例如:
let r1 = { a: Int64, b: Int64 => a + b }(1, 2) // r1 = 3
let r2 = { => 123 }() // r2 = 123
Lambda 表达式也可以赋值给一个变量,使用变量名进行调用,例如:
func f() {
var g = { x: Int64 => println("x = ${x}") }
g(2)
}
闭包
一个函数或 lambda 从定义它的静态作用域中捕获了变量,函数或 lambda 和捕获的变量一起被称为一个闭包,这样即使脱离了闭包定义所在的作用域,闭包也能正常运行。
函数或 lambda 的定义中对于以下几种变量的访问,称为变量捕获:
-
函数的参数缺省值中访问了本函数之外定义的局部变量;
-
函数或 lambda 内访问了本函数或本 lambda 之外定义的局部变量;
-
class/struct内定义的不是成员函数的函数或 lambda 访问了实例成员变量或this。
以下情形的变量访问不是变量捕获:
-
对定义在本函数或本 lambda 内的局部变量的访问;
-
对本函数或本 lambda 的形参的访问;
-
对全局变量和静态成员变量的访问;
-
对实例成员变量在实例成员函数或属性中的访问。由于实例成员函数或属性将
this作为参数传入,在实例成员函数或属性内通过this访问所有实例成员变量。
变量的捕获发生在闭包定义时,因此变量捕获有以下规则:
-
被捕获的变量必须在闭包定义时可见,否则编译报错;
-
被捕获的变量必须在闭包定义时已经完成初始化,否则编译报错。
示例 1:闭包 add,捕获了 let 声明的局部变量 num,之后通过返回值返回到 num 定义的作用域之外,调用 add 时仍可正常访问 num。
func returnAddNum(): (Int64) -> Int64 {
let num: Int64 = 10
func add(a: Int64) {
return a + num
}
add
}
main() {
let f = returnAddNum()
println(f(10))
}
程序输出的结果为:
20
示例 2:捕获的变量必须在闭包定义时可见。
func f() {
let x = 99
func f1() {
println(x)
}
let f2 = { =>
println(y) // Error, cannot capture 'y' which is not defined yet
}
let y = 88
f1() // Print 99
f2()
}
示例 3:捕获的变量必须在闭包定义前完成初始化。
func f() {
let x: Int64
func f1() {
println(x) // Error, x is not initialized yet
}
x = 99
f1()
}
如果捕获的变量是引用类型,可修改其可变实例成员变量的值。
class C {
public var num: Int64 = 0
}
func returnIncrementer(): () -> Unit {
let c: C = C()
func incrementer() {
c.num++
}
incrementer
}
main() {
let f = returnIncrementer()
f() // c.num increases by 1
}
为了防止捕获了 var 声明变量的闭包逃逸,这类闭包只能被调用,不能作为一等公民使用,包括不能赋值给变量,不能作为实参或返回值使用,不能直接将闭包的名字作为表达式使用。
func f() {
var x = 1
let y = 2
func g() {
println(x) // OK, captured a mutable variable
}
let b = g // Error, g cannot be assigned to a variable
g // Error, g cannot be used as an expression
g() // OK, g can be invoked
g // Error, g cannot be used as a return value
}
需要注意的是,捕获具有传递性。如果一个函数 f 调用了捕获 var 变量的函数 g,且 g 捕获的 var 变量不在函数 f 内定义,那么函数 f 同样捕获了 var 变量,此时,f 也不能作为一等公民使用。
以下示例中,g 捕获了 var 声明的变量 x,f 调用了 g,且 g 捕获的 x 不在 f 内定义,f 同样不能作为一等公民使用:
func h(){
var x = 1
func g() { x } // captured a mutable variable
func f() {
g() // invoked g
}
return f // Error
}
以下示例中,g 捕获了 var 声明的变量 x,f 调用了 g。但 g 捕获的 x 在 f 内定义,f 没有捕获其他 var 声明的变量。因此,f 仍作为一等公民使用:
func h(){
func f() {
var x = 1
func g() { x } // captured a mutable variable
g()
}
return f // Ok
}
静态成员变量和全局变量的访问,不属于变量捕获,因此访问了 var 修饰的全局变量、静态成员变量的函数或 lambda 仍可作为一等公民使用。
class C {
static public var a: Int32 = 0
static public func foo() {
a++ // OK
return a
}
}
var globalV1 = 0
func countGlobalV1() {
globalV1++
C.a = 99
let g = C.foo // OK
}
func g(){
let f = countGlobalV1 // OK
f()
}
函数调用语法糖
尾随 lambda
尾随 lambda 可以使函数的调用看起来像是语言内置的语法一样,增加语言的可扩展性。
当函数最后一个形参是函数类型,并且函数调用对应的实参是 lambda 时,可以使用尾随 lambda 语法,将 lambda 放在函数调用的尾部,圆括号外面。
例如,下例中定义了一个 myIf 函数,它的第一个参数是 Bool 类型,第二个参数是函数类型。当第一个参数的值为 true 时,返回第二个参数调用后的值,否则返回 0。调用 myIf 时可以像普通函数一样调用,也可以使用尾随 lambda 的方式调用。
func myIf(a: Bool, fn: () -> Int64) {
if(a) {
fn()
} else {
0
}
}
func test() {
myIf(true, { => 100 }) // General function call
myIf(true) { // Trailing closure call
100
}
}
当函数调用有且只有一个 lambda 实参时,还可以省略 (),只写 lambda。
示例:
func f(fn: (Int64) -> Int64) { fn(1) }
func test() {
f { i => i * i }
}
Flow 表达式
流操作符包括两种:表示数据流向的中缀操作符 |> (称为 pipeline)和表示函数组合的中缀操作符 ~> (称为 composition)。
Pipeline 表达式
当需要对输入数据做一系列的处理时,可以使用 pipeline 表达式来简化描述。pipeline 表达式的语法形式如下:e1 |> e2。等价于如下形式的语法糖:let v = e1; e2(v) 。
其中 e2 是函数类型的表达式,e1 的类型是 e2 的参数类型的子类型。
示例:
func inc(x: Array<Int64>): Array<Int64> { // Increasing the value of each element in the array by '1'
let s = x.size
var i = 0
for (e in x where i < s) {
x[i] = e + 1
i++
}
x
}
func sum(y: Array<Int64>): Int64 { // Get the sum of elements in the array
var s = 0
for (j in y) {
s += j
}
s
}
let arr: Array<Int64> = [1, 3, 5]
let res = arr |> inc |> sum // res = 12
Composition 表达式
composition 表达式表示两个单参函数的组合。composition 表达式语法为 f ~> g,等价于 { x => g(f(x)) }。
其中 f,g 均为只有一个参数的函数类型的表达式。
f 和 g 组合,则要求 f(x) 的返回类型是 g(...) 的参数类型的子类型。
示例 1:
func f(x: Int64): Float64 {
Float64(x)
}
func g(x: Float64): Float64 {
x
}
var fg = f ~> g // The same as { x: Int64 => g(f(x)) }
示例 2:
func f(x: Int64): Float64 {
Float64(x)
}
let lambdaComp = ({x: Int64 => x}) ~> f // The same as { x: Int64 => f({x: Int64 => x}(x)) }
示例 3:
func h1<T>(x: T): T { x }
func h2<T>(x: T): T { x }
var hh = h1<Int64> ~> h2<Int64> // The same as { x: Int64 => h2<Int64>(h1<Int64>(x)) }
注意:
表达式 f ~> g 中,会先对 f 求值,然后对 g 求值,最后才会进行函数的组合。
另外,流操作符不能与无默认值的命名形参函数直接一同使用,这是因为无默认值的命名形参函数必须给出命名实参才可以调用。例如:
func f(a!: Int64): Unit {}
var a = 1 |> f // Error
如果需要使用,开发者可以通过 lambda 表达式传入 f 函数的命名实参:
func f(a!: Int64): Unit {}
var x = 1 |> { x: Int64 => f(a: x) } // Ok
由于相同的原因,当 f 的参数有默认值时,直接与流运算符一起使用也是错误的,例如:
func f(a!: Int64 = 2): Unit {}
var a = 1 |> f // Error
但是当命名形参都存在默认值时,不需要给出命名实参也可以调用该函数,函数仅需要传入非命名形参,那么这种函数是可以同流运算符一起使用的,例如:
func f(a: Int64, b!: Int64 = 2): Unit {}
var a = 1 |> f // Ok
当然,如果想要在调用 f 时,为参数 b 传入其他参数,那么也需要借助 lambda 表达式:
func f(a: Int64, b!: Int64 = 2): Unit {}
var a = 1 |> {x: Int64 => f(x, b: 3)} // Ok
变长参数
变长参数是一种特殊的函数调用语法糖。当形参最后一个非命名参数是 Array 类型时,实参中对应位置可以直接传入参数序列代替 Array 字面量(参数个数可以是 0 个或多个)。示例如下:
func sum(arr: Array<Int64>) {
var total = 0
for (x in arr) {
total += x
}
return total
}
main() {
println(sum())
println(sum(1, 2, 3))
}
程序输出:
0
6
需要注意,只有最后一个非命名参数可以作为变长参数,命名参数不能使用这个语法糖。
func length(arr!: Array<Int64>) {
return arr.size
}
main() {
println(length()) // Error, expected 1 argument, found 0
println(length(1, 2, 3)) // Error, expected 1 argument, found 3
}
变长参数可以出现在全局函数、静态成员函数、实例成员函数、局部函数、构造函数、函数变量、lambda、函数调用操作符重载、索引操作符重载的调用处。不支持其他操作符重载、composition、pipeline 这几种调用方式。示例如下:
class Counter {
var total = 0
init(data: Array<Int64>) { total = data.size }
operator func ()(data: Array<Int64>) { total += data.size }
}
main() {
let counter = Counter(1, 2)
println(counter.total)
counter(3, 4, 5)
println(counter.total)
}
程序输出:
2
5
函数重载决议总是会优先考虑不使用变长参数就能匹配的函数,只有在所有函数都不能匹配,才尝试使用变长参数解析。示例如下:
func f<T>(x: T) where T <: ToString {
println("item: ${x}")
}
func f(arr: Array<Int64>) {
println("array: ${arr}")
}
main() {
f()
f(1)
f(1, 2)
}
程序输出:
array: []
item: 1
array: [1, 2]
当编译器无法决议时会报错:
func f(arr: Array<Int64>) { arr.size }
func f(first: Int64, arr: Array<Int64>) { first + arr.size }
main() {
println(f(1, 2, 3)) // Error
}
函数重载
函数重载定义
在仓颉编程语言中,如果一个作用域中,一个函数名对应多个函数定义,这种现象称为函数重载。
-
函数名相同,函数参数不同(是指参数个数不同,或者参数个数相同但参数类型不同)的两个函数构成重载。示例如下:
// Scenario 1 func f(a: Int64): Unit { } func f(a: Float64): Unit { } func f(a: Int64, b: Float64): Unit { } -
对于两个同名泛型函数 (详见泛型函数章节),如果重命名一个函数的泛型形参后(使泛型参数顺序相同),其非泛型部分与另一个函数的非泛型部分函数参数不同,则两个函数构成重载,否则这两个泛型函数构成重复定义错误(类型变元的约束不参与判断)。示例如下:
interface I1{} interface I2{} func f1<X, Y>(a: X, b: Y) {} func f1<Y, X>(a: X, b: Y) {} // Ok: after rename generic type parameter, it will be 'func f1<X, Y>(a: Y, b: X)' func f2<T>(a: T) where T <: I1 {} func f2<T>(a: T) where T <: I2 {} // Error, not overloading -
同一个类内的两个构造函数参数不同,构成重载。示例如下:
// Scenario 2 class C { var a: Int64 var b: Float64 public init(a: Int64, b: Float64) { this.a = a this.b = b } public init(a: Int64) { b = 0.0 this.a = a } } -
同一个类内的主构造函数和
init构造函数参数不同,构成重载(认为主构造函数和init函数具有相同的名字)。示例如下:// Scenario 3 class C { C(var a!: Int64, var b!: Float64) { this.a = a this.b = b } public init(a: Int64) { b = 0.0 this.a = a } } -
两个函数名相同,参数不同的函数定义在不同的作用域,在两个函数都可见的作用域中构成重载。示例如下:
// Scenario 4 func f(a: Int64): Unit { } func g() { func f(a: Float64): Unit { } } -
如果子类中存在与父类同名的函数,并且函数的参数类型不同,则构成函数重载。示例如下:
// Scenario 5 open class Base { public func f(a: Int64): Unit { } } class Sub <: Base { public func f(a: Float64): Unit { } }
只允许函数声明引入的函数重载,但是以下情形不构成重载,不构成重载的两个名字不能定义或声明在同一个作用域内:
- class、interface、struct 类型的静态成员函数和实例成员函数之间不能重载
- enum 类型的 constructor、静态成员函数和实例成员函数之间不能重载
如下示例,两个变量均为函数类型且函数参数类型不同,但由于它们不是函数声明所以不能重载,如下示例将编译报错(重定义错):
main() {
var f: (Int64) -> Unit
var f: (Float64) -> Unit
}
如下示例,虽然变量 f 为函数类型,但由于变量和函数之间不能同名,如下示例将编译报错(重定义错):
main() {
var f: (Int64) -> Unit
func f(a: Float64): Unit { // Error, functions and variables cannot have the same name
}
}
如下示例,静态成员函数 f 与实例成员函数 f 的参数类型不同,但由于类内静态成员函数和实例成员函数之间不能重载,如下示例将编译报错:
class C {
public static func f(a: Int64): Unit {
}
public func f(a: Float64): Unit {
}
}
函数重载决议
函数调用时,所有可被调用的函数(是指当前作用域可见且能通过类型检查的函数)构成候选集,候选集中有多个函数,究竟选择候选集中哪个函数,需要进行函数重载决议,有如下规则:
-
优先选择作用域级别高的作用域内的函数。在嵌套的表达式或函数中,越是内层作用域级别越高。
如下示例中在
inner函数体内调用g(Sub())时,候选集包括inner函数内定义的函数g和inner函数外定义的函数g,函数决议选择作用域级别更高的inner函数内定义的函数g。open class Base {} class Sub <: Base {} func outer() { func g(a: Sub) { print("1") } func inner() { func g(a: Base) { print("2") } g(Sub()) // Output: 2 } } -
如果作用域级别相对最高的仍有多个函数,则需要选择最匹配的函数(对于函数 f 和 g 以及给定的实参,如果 f 可以被调用时 g 也总是可以被调用的,但反之不然,则称 f 比 g 更匹配)。如果不存在唯一最匹配的函数,则报错。
如下示例中,两个函数
g定义在同一作用域,选择更匹配的函数g(a: Sub): Unit。open class Base {} class Sub <: Base {} func outer() { func g(a: Sub) { print("1") } func g(a: Base) { print("2") } g(Sub()) // Output: 1 } -
子类和父类认为是同一作用域。如下示例中,一个函数
g定义在父类中,另一个函数g定义在子类中,在调用s.g(Sub())时,两个函数g当成同一作用域级别决议,则选择更匹配的父类中定义的函数g(a: Sub): Unit。open class Base { public func g(a: Sub) { print("1") } } class Sub <: Base { public func g(a: Base) { print("2") } } func outer() { let s: Sub = Sub() s.g(Sub()) // Output: 1 }
操作符重载
如果希望在某个类型上支持此类型默认不支持的操作符,可以使用操作符重载实现。
如果需要在某个类型上重载某个操作符,可以通过为类型定义一个函数名为此操作符的函数的方式实现,这样,在该类型的实例使用该操作符时,就会自动调用此操作符函数。
操作符函数定义与普通函数定义相似,区别如下:
- 定义操作符函数时需要在
func关键字前面添加operator修饰符; - 操作符函数的参数个数需要匹配对应操作符的要求(详见附录操作符);
- 操作符函数只能定义在 class、interface、struct、enum 和 extend 中;
- 操作符函数具有实例成员函数的语义,所以禁止使用
static修饰符; - 操作符函数不能为泛型函数。
另外,需要注意的是,被重载后的操作符不改变它们固有的优先级和结合性(详见附录操作符)。
操作符重载函数定义和使用
定义操作符函数有两种方式:
- 对于可以直接包含函数定义的类型 (包括
struct、enum、class和interface),可以直接在其内部定义操作符函数的方式实现操作符的重载。 - 使用
extend的方式为其添加操作符函数,从而实现操作符在这些类型上的重载。对于无法直接包含函数定义的类型(是指除struct、class、enum和interface之外其他的类型)或无法改变其实现的类型,比如第三方定义的struct、class、enum和interface,只能采用这种方式(参见扩展)。
操作符函数对参数类型的约定如下:
-
对于一元操作符,操作符函数没有参数,对返回值的类型没有要求。
-
对于二元操作符,操作符函数只有一个参数,对返回值的类型没有要求。
如下示例中介绍了一元操作符和二元操作符的定义和使用:
-实现对一个Point实例中两个成员变量x和y取负值,然后返回一个新的Point对象,+实现对两个Point实例中两个成员变量x和y分别求和,然后返回一个新的Point对象。open class Point { var x: Int64 = 0 var y: Int64 = 0 public init (a: Int64, b: Int64) { x = a y = b } public operator func -(): Point { Point(-x, -y) } public operator func +(right: Point): Point { Point(this.x + right.x, this.y + right.y) } }接下来,就可以在
Point的实例上直接使用一元-操作符和二元+操作符:main() { let p1 = Point(8, 24) let p2 = -p1 // p2 = Point(-8, -24) let p3 = p1 + p2 // p3 = Point(0, 0) } -
索引操作符(
[])分为取值let a = arr[i]和赋值arr[i] = a两种形式,它们通过是否存在特殊的命名参数 value 来区分不同的重载。索引操作符重载不要求同时重载两种形式,可以只重载赋值不重载取值,反之亦可。索引操作符取值形式
[]内的参数序列对应操作符重载的非命名参数,可以是 1 个或多个,可以是任意类型。不可以有其他命名参数。返回类型可以是任意类型。class A { operator func [](arg1: Int64, arg2: String): Int64 { return 0 } } func f() { let a = A() let b: Int64 = a[1, "2"] // b == 0 }索引操作符赋值形式
[]内的参数序列对应操作符重载的非命名参数,可以是 1 个或多个,可以是任意类型。=右侧的表达式对应操作符重载的命名参数,有且只能有一个命名参数,该命名参数的名称必须是 value, 不能有默认值,value 可以是任意类型。返回类型必须是 Unit 类型。需要注意的是,value 只是一种特殊的标记,在索引操作符赋值时并不需要使用命名参数的形式调用。
class A { operator func [](arg1: Int64, arg2: String, value!: Int64): Unit { return } } func f() { let a = A() a[1, "2"] = 0 }特别的,除
enum外的不可变类型不支持重载索引操作符赋值形式。 -
函数调用操作符(
())重载函数,输入参数和返回值类型可以是任意类型。示例如下:open class A { public init() {} public operator func ()(): Unit {} } func test1() { let a = A() // Ok, A() is call the constructor of A a() // Ok, a() is to call the operator () overloading function }不能使用
this或super调用()操作符重载函数。示例如下:open class A { public init() {} public init(x: Int64) { this() // Ok, this() calls the constructor of A } public operator func ()(): Unit {} public func foo() { this() // Error, this() calls the constructor of A super() // Error } } class B <: A { public init() { super() // Ok, super() calls the constuctor of the super class } public func goo() { super() // Error } }对于枚举类型,当构造器形式和
()操作符重载函数形式都满足时,优先匹配构造器形式。示例如下:enum E { Y | X | X(Int64) public operator func ()(p: Int64) {} public operator func ()(p: Float64) {} } main() { let e = X(1) // Ok, X(1) is to call the constructor X(Int64) X(1.0) // Ok, X(1.0) is to call the operator () overloading function let e1 = X e1(1) // Ok, e1(1) is to call the operator () overloading function Y(1) // oK, Y(1) is to call the operator () overloading function }
可以被重载的操作符
下表列出了所有可以被重载的操作符(优先级从高到低):
| Operator | Description |
|---|---|
() | Function call |
[] | Indexing |
! | NOT |
- | Negative |
** | Power |
* | Multiply |
/ | Divide |
% | Remainder |
+ | Add |
- | Subtract |
<< | Bitwise left shift |
>> | Bitwise right shift |
< | Less than |
<= | Less than or equal |
> | Greater than |
>= | Greater than or equal |
== | Equal |
!= | Not equal |
& | Bitwise AND |
^ | Bitwise XOR |
| | Bitwise OR |
需要注意的是:
注意:
- 一旦在某个类型上重载了除关系操作符(
<、<=、>、>=、==和!=)之外的其他二元操作符,并且操作符函数的返回类型与左操作数的类型一致或是其子类型,那么此类型支持对应的复合赋值操作符。当操作符函数的返回类型与左操作数的类型不一致且不是其子类型时,在使用对应的复合赋值符号时将报类型不匹配错误。- 仓颉编程语言不支持自定义操作符,即不允许定义除上表中所列
operator之外的其他操作符函数。- 对于类型
T, 如果T已经默认支持了上述若干可重载操作符,那么通过扩展的方式再次为其实现同签名的操作符函数时将报重定义错误。例如,为数值类型重载其已支持的同签名算术操作符、位操作符或关系操作符等操作符时,为Rune重载同签名的关系操作符时,为Bool类型重载同签名的逻辑操作符、判等或不等操作符时,等等这些情况,均会报重定义错误。
const 函数和常量求值
常量求值允许某些特定形式的表达式在编译时求值,可以减少程序运行时需要的计算。本章主要介绍常量求值的使用方法与规则。
const 上下文与 const 表达式
const 上下文是指 const 变量初始化表达式,这些表达式始终在编译时求值。因此需要对 const 上下文中允许的表达式加以限制,避免修改全局状态、I/O 等副作用,确保其可以在编译时求值。
const 表达式具备了可以在编译时求值的能力。满足如下规则的表达式是 const 表达式:
- 数值类型、
Bool、Unit、Rune、String类型的字面量(不包含插值字符串)。 - 所有元素都是
const表达式的Array字面量(不能是Array类型,可以使用VArray类型),tuple字面量。 const变量,const函数形参,const函数中的局部变量。const函数,包含使用const声明的函数名、符合const函数要求的lambda、以及这些函数返回的函数表达式。const函数调用(包含const构造函数),该函数的表达式必须是const表达式,所有实参必须都是const表达式。- 所有参数都是
const表达式的enum构造器调用,和无参数的enum构造器。 - 数值类型、
Bool、Unit、Rune、String类型的算术表达式、关系表达式、位运算表达式,所有操作数都必须是const表达式。 if、match、try、throw、return、is、as。这些表达式内的表达式必须都是const表达式。const表达式的成员访问(不包含属性的访问),tuple的索引访问。const init和const函数中的this和super表达式。const表达式的const实例成员函数调用,且所有实参必须都是const表达式。
注意:
当前编译器实现暂不支持
throw作为const表达式使用。
const 函数
const 函数是一类特殊的函数,这些函数具备了可以在编译时求值的能力。在 const 上下文中调用这种函数时,这些函数会在编译时执行计算。而在其他非 const 上下文,const 函数会和普通函数一样在运行时执行。
下例是一个计算平面上两点距离的 const 函数,distance 中使用 let 定义了两个局部变量 dx 和 dy:
struct Point {
const Point(let x: Float64, let y: Float64) {}
}
const func distance(a: Point, b: Point) {
let dx = a.x - b.x
let dy = a.y - b.y
(dx**2 + dy**2)**0.5
}
main() {
const a = Point(3.0, 0.0)
const b = Point(0.0, 4.0)
const d = distance(a, b)
println(d)
}
编译运行输出:
5.000000
需要注意:
const函数声明必须使用const修饰。- 全局
const函数和static const函数中只能访问const声明的外部变量,包含const全局变量、const静态成员变量,其他外部变量都不可访问。const init函数和const实例成员函数除了能访问const声明的外部变量,还可以访问当前类型的实例成员变量。 const函数中的表达式都必须是const表达式,const init函数除外。const函数中可以使用let、const声明新的局部变量。但不支持var。const函数中的参数类型和返回类型没有特殊规定。如果该函数调用的实参不符合const表达式要求,那这个函数调用不能作为const表达式使用,但仍然可以作为普通表达式使用。const函数不一定都会在编译时执行,例如可以在非const函数中运行时调用。const函数与非const函数重载规则一致。- 数值类型、
Bool、Unit、Rune、String类型 和enum支持定义const实例成员函数。 - 对于
struct和class,只有定义了const init才能定义const实例成员函数。class中的const实例成员函数不能是open的。struct中的const实例成员函数不能是mut的。
另外,接口中也可以定义 const 函数,但会受到以下规则限制:
- 接口中的
const函数,实现类型必须也用const函数才算实现接口。 - 接口中的非
const函数,实现类型使用const或非const函数都算实现接口。 - 接口中的
const函数与接口的static函数一样,只有在该接口作为泛型约束的时候,受约束的泛型变元或变量才能使用这些const函数。
在下面的例子中,在接口 I 里定义了两个 const 函数,类 A 实现了接口 I,泛型函数 g 的形参类型上界是 I。
interface I {
const func f(): Int64
const static func f2(): Int64
}
class A <: I {
public const func f() { 0 }
public const static func f2() { 1 }
const init() {}
}
const func g<T>(i: T) where T <: I {
return i.f() + T.f2()
}
main() {
println(g(A()))
}
编译执行上述代码,输出结果为:
1
const init
如果一个 struct 或 class 定义了 const 构造器,那么这个 struct/class 实例可以用在 const 表达式中。
- 如果当前类型是
class,则不能具有var声明的实例成员变量,否则不允许定义const init。如果当前类型具有父类,当前的const init必须调用父类的const init(可以显式调用或者隐式调用无参const init),如果父类没有const init则报错。 - 当前类型的实例成员变量如果有初始值,初始值必须要是
const表达式,否则不允许定义const init。 const init内可以使用赋值表达式对实例成员变量赋值,除此以外不能有其他赋值表达式。
const init 与 const 函数的区别是 const init 内允许对实例成员变量进行赋值(需要使用赋值表达式)。
定义 struct 类型
struct 类型的定义以关键字 struct 开头,后跟 struct 的名字,接着是定义在一对花括号中的 struct 定义体。struct 定义体中可以定义一系列的成员变量、成员属性(参见属性)、静态初始化器、构造函数和成员函数。
struct Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
上例中定义了名为 Rectangle 的 struct 类型,它有两个 Int64 类型的成员变量 width 和 height,一个有两个 Int64 类型参数的构造函数(使用关键字 init 定义,函数体中通常是对成员变量的初始化),以及一个成员函数 area(返回 width 和 height 的乘积)。
注意:
struct只能定义在源文件的顶层作用域。
struct 成员变量
struct 成员变量分为实例成员变量和静态成员变量(使用 static 修饰符修饰),二者访问上的区别在于实例成员变量只能通过 struct 实例(说 a 是 T 类型的实例,指的是 a 是一个 T 类型的值)访问,静态成员变量只能通过 struct 类型名访问。
实例成员变量定义时可以不设置初值(但必须标注类型,如上例中的 width 和 height),也可以设置初值,例如:
struct Rectangle {
let width = 10
let height = 20
}
struct 静态初始化器
struct 支持定义静态初始化器,并在静态初始化器中通过赋值表达式来对静态成员变量进行初始化。
静态初始化器以关键字组合 static init 开头,后跟无参参数列表和函数体,且不能被访问修饰符修饰。函数体中必须完成对所有未初始化的静态成员变量的初始化,否则编译报错。
struct Rectangle {
static let degree: Int64
static init() {
degree = 180
}
}
一个 struct 中最多允许定义一个静态初始化器,否则报重定义错误。
struct Rectangle {
static let degree: Int64
static init() {
degree = 180
}
static init() { // Error, redefinition with the previous static init function
degree = 180
}
}
struct 构造函数
struct 支持两类构造函数:普通构造函数和主构造函数。
普通构造函数以关键字 init 开头,后跟参数列表和函数体,函数体中必须完成对所有未初始化的实例成员变量的初始化(如果参数名和成员变量名无法区分,可以在成员变量前使用 this 加以区分,this 表示 struct 的当前实例),否则编译报错。
struct Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) { // Error, 'height' is not initialized in the constructor
this.width = width
}
}
一个 struct 中可以定义多个普通构造函数,但它们必须构成重载(参见函数重载),否则报重定义错误。
struct Rectangle {
let width: Int64
let height: Int64
public init(width: Int64) {
this.width = width
this.height = width
}
public init(width: Int64, height: Int64) { // Ok: overloading with the first init function
this.width = width
this.height = height
}
public init(height: Int64) { // Error, redefinition with the first init function
this.width = height
this.height = height
}
}
除了可以定义若干普通的以 init 为名字的构造函数外,struct 内还可以定义(最多)一个主构造函数。主构造函数的名字和 struct 类型名相同,它的参数列表中可以有两种形式的形参:普通形参和成员变量形参(需要在参数名前加上 let 或 var),成员变量形参同时扮演定义成员变量和构造函数参数的功能。
使用主构造函数通常可以简化 struct 的定义,例如,上述包含一个 init 构造函数的 Rectangle 可以简化为如下定义:
struct Rectangle {
public Rectangle(let width: Int64, let height: Int64) {}
}
主构造函数的参数列表中也可以定义普通形参,例如:
struct Rectangle {
public Rectangle(name: String, let width: Int64, let height: Int64) {}
}
如果 struct 定义中不存在自定义构造函数(包括主构造函数),并且所有实例成员变量都有初始值,则会自动为其生成一个无参构造函数(调用此无参构造函数会创建一个所有实例成员变量的值均等于其初值的对象);否则,不会自动生成此无参构造函数。例如,对于如下 struct 定义,注释中给出了自动生成的无参构造函数:
struct Rectangle {
let width: Int64 = 10
let height: Int64 = 10
/* Auto-generated memberwise constructor:
public init() {
}
*/
}
struct 成员函数
struct 成员函数分为实例成员函数和静态成员函数(使用 static 修饰符修饰),二者的区别在于:实例成员函数只能通过 struct 实例访问,静态成员函数只能通过 struct 类型名访问;静态成员函数中不能访问实例成员变量,也不能调用实例成员函数,但在实例成员函数中可以访问静态成员变量以及静态成员函数。
下例中,area 是实例成员函数,typeName 是静态成员函数。
struct Rectangle {
let width: Int64 = 10
let height: Int64 = 20
public func area() {
this.width * this.height
}
public static func typeName(): String {
"Rectangle"
}
}
实例成员函数中可以通过 this 访问实例成员变量,例如:
struct Rectangle {
let width: Int64 = 1
let height: Int64 = 1
public func area() {
this.width * this.height
}
}
struct 成员的访问修饰符
struct 的成员(包括成员变量、成员属性、构造函数、成员函数、操作符函数(详见操作符重载章节))用 4 种访问修饰符修饰:private、internal、protected 和 public,缺省的修饰符是 internal。
private表示在struct定义内可见。internal表示仅当前包及子包(包括子包的子包,详见包章节)内可见。protected表示当前模块(详见包章节)可见。public表示模块内外均可见。
下面的例子中,width 是 public 修饰的成员,在类外可以访问,height 是缺省访问修饰符的成员,仅在当前包及子包可见,其他包无法访问。
package a
public struct Rectangle {
public var width: Int64
var height: Int64
private var area: Int64
...
}
func samePkgFunc() {
var r = Rectangle(10, 20)
r.width = 8 // Ok: public 'width' can be accessed here
r.height = 24 // Ok: 'height' has no modifier and can be accessed here
r.area = 30 // Error, private 'area' can't be accessed here
}
package b
import a.*
main() {
var r = Rectangle(10, 20)
r.width = 8 // Ok: public 'width' can be accessed here
r.height = 24 // Error, no modifier 'height' can't be accessed here
r.area = 30 // Error, private 'area' can't be accessed here
}
禁止递归 struct
递归和互递归定义的 struct 均是非法的。例如:
struct R1 { // Error, 'R1' recursively references itself
let other: R1
}
struct R2 { // Error, 'R2' and 'R3' are mutually recursive
let other: R3
}
struct R3 { // Error, 'R2' and 'R3' are mutually recursive
let other: R2
}
创建 struct 实例
定义了 struct 类型后,即可通过调用 struct 的构造函数来创建 struct 实例。在 struct 定义之外,通过 struct 类型名调用构造函数创建该类型实例,并可以通过实例访问满足可见性修饰符(如public )的实例成员变量和实例成员函数。例如,下例中定义了一个 Rectangle 类型的变量 r,通过 r.width 和 r.height 可分别访问 r 中 width 和 height 的值,通过 r.area() 可以调用 r 的成员函数 area。
struct Rectangle {
public var width: Int64
public var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
let r = Rectangle(10, 20)
let width = r.width // width = 10
let height = r.height // height = 20
let a = r.area() // a = 200
如果希望通过 struct 实例去修改成员变量的值,需要将 struct 类型的变量定义为可变变量,并且被修改的成员变量也必须是可变成员变量(使用 var 定义)。举例如下:
struct Rectangle {
public var width: Int64
public var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
main() {
var r = Rectangle(10, 20) // r.width = 10, r.height = 20
r.width = 8 // r.width = 8
r.height = 24 // r.height = 24
let a = r.area() // a = 192
}
在赋值或传参时,会对 struct 实例进行复制(成员变量为引用类型时,仅复制引用而不会复制引用的对象),生成新的实例,对其中一个实例的修改并不会影响另外一个实例。以赋值为例,下面的例子中,将 r1 赋值给 r2 之后,修改 r1 的 width 和 height 的值,并不会影响 r2 的 width 和 height 值。
struct Rectangle {
public var width: Int64
public var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
main() {
var r1 = Rectangle(10, 20) // r1.width = 10, r1.height = 20
var r2 = r1 // r2.width = 10, r2.height = 20
r1.width = 8 // r1.width = 8
r1.height = 24 // r1.height = 24
let a1 = r1.area() // a1 = 192
let a2 = r2.area() // a2 = 200
}
mut 函数
struct 类型是值类型,其实例成员函数无法修改实例本身。例如,下例中,成员函数 g 中不能修改成员变量 i 的值。
struct Foo {
var i = 0
public func g() {
i += 1 // Error, the value of a instance member variable cannot be modified in an instance member function
}
}
mut 函数是一种可以修改 struct 实例本身的特殊的实例成员函数。在 mut 函数内部,this 的语义是特殊的,这种 this 拥有原地修改字段的能力。
注意:
只允许在 interface、struct 和 struct 的扩展内定义
mut函数(class 是引用类型,实例成员函数不需要加mut也可以修改实例成员变量,所以禁止在 class 中定义mut函数)。
mut 函数定义
mut 函数与普通的实例成员函数相比,多一个 mut 关键字来修饰。
例如,下例中在函数 g 之前增加 mut 修饰符之后,即可在函数体内修改成员变量 i 的值。
struct Foo {
var i = 0
public mut func g() {
i += 1 // Ok
}
}
mut 只能修饰实例成员函数,不能修饰静态成员函数。
struct A {
public mut func f(): Unit {} // Ok
public mut operator func +(rhs: A): A { // Ok
A()
}
public mut static func g(): Unit {} // Error, static member functions cannot be modified with 'mut'
}
mut 函数中的 this 不能被捕获,也不能作为表达式。mut 函数中的 lambda 或嵌套函数不能对 struct 的实例成员变量进行捕获。
示例:
struct Foo {
var i = 0
public mut func f(): Foo {
let f1 = { => this } // Error, 'this' in mut functions cannot be captured
let f2 = { => this.i = 2 } // Error, instance member variables in mut functions cannot be captured
let f3 = { => this.i } // Error, instance member variables in mut functions cannot be captured
let f4 = { => i } // Error, instance member variables in mut functions cannot be captured
this // Error, 'this' in mut functions cannot be used as expressions
}
}
接口中的 mut 函数
接口中的实例成员函数,也可以使用 mut 修饰。
struct 类型在实现 interface 的函数时必须保持一样的 mut 修饰。struct 以外的类型实现 interface 的函数时不能使用 mut 修饰。
示例:
interface I {
mut func f1(): Unit
func f2(): Unit
}
struct A <: I {
public mut func f1(): Unit {} // Ok: as in the interface, the 'mut' modifier is used
public func f2(): Unit {} // Ok: as in the interface, the 'mut' modifier is not used
}
struct B <: I {
public func f1(): Unit {} // Error, 'f1' is modified with 'mut' in interface, but not in struct
public mut func f2(): Unit {} // Error, 'f2' is not modified with 'mut' in interface, but did in struct
}
class C <: I {
public func f1(): Unit {} // Ok
public func f2(): Unit {} // Ok
}
当 struct 的实例赋值给 interface 类型时是拷贝语义,因此 interface 的 mut 函数并不能修改 struct 实例的值。
示例:
interface I {
mut func f(): Unit
}
struct Foo <: I {
public var v = 0
public mut func f(): Unit {
v += 1
}
}
main() {
var a = Foo()
var b: I = a
b.f() // Calling 'f' via 'b' cannot modify the value of 'a'
println(a.v) // 0
}
程序输出结果为:
0
mut 函数的使用限制
因为 struct 是值类型,所以如果一个变量是 struct 类型且使用 let 声明,那么不能通过这个变量访问该类型的 mut 函数。
示例:
interface I {
mut func f(): Unit
}
struct Foo <: I {
public var i = 0
public mut func f(): Unit {
i += 1
}
}
main() {
let a = Foo()
a.f() // Error, 'a' is of type struct and is declared with 'let', the 'mut' function cannot be accessed via 'a'
var b = Foo()
b.f() // Ok
let c: I = Foo()
c.f() // Ok, 变量 c 为接口 I 类型,非 struct 类型,此处允许访问。
}
为避免逃逸,如果一个变量的类型是 struct 类型,那么这个变量不能将该类型使用 mut 修饰的函数作为一等公民来使用,只能调用这些 mut 函数。
示例:
interface I {
mut func f(): Unit
}
struct Foo <: I {
var i = 0
public mut func f(): Unit {
i += 1
}
}
main() {
var a = Foo()
var fn = a.f // Error, mut function 'f' of 'a' cannot be used as a first class citizen.
var b: I = Foo()
fn = b.f // Ok
}
为避免逃逸,非 mut 的实例成员函数(包括 lambda 表达式)不能直接访问所在类型的 mut 函数,反之可以。
示例:
struct Foo {
var i = 0
public mut func f(): Unit {
i += 1
g() // Ok
}
public func g(): Unit {
f() // Error, mut functions cannot be invoked in non-mut functions
}
}
interface I {
mut func f(): Unit {
g() // Ok
}
func g(): Unit {
f() // Error, mut functions cannot be invoked in non-mut functions
}
}
枚举类型
本节介绍仓颉中的 enum 类型。enum 类型提供了通过列举一个类型的所有可能取值来定义此类型的方式。
在很多语言中都有 enum 类型(或者称枚举类型),但是不同语言中的 enum 类型的使用方式和表达能力均有所差异,仓颉中的 enum 类型可以理解为函数式编程语言中的代数数据类型(Algebraic Data Types)。
enum 的定义
定义 enum 时需要把它所有可能的取值一一列出,称这些值为 enum 的构造器(或者 constructor)。
enum 类型的定义以关键字 enum 开头,接着是 enum 的名字,之后是定义在一对花括号中的 enum 体,enum 体中定义了若干构造器,多个构造器之间使用 | 进行分隔(第一个构造器之前的 | 是可选的)。构造器可以是有名字的,也可以是没有名字的 ...。
每个 enum 中至少存在一个有名字的构造器。有名字的构造器可以没有参数(即“无参构造器”),也可以携带若干个参数(即“有参构造器”)。如下示例代码定义了一个名为 RGBColor 的 enum 类型,它有 3 个构造器:Red、Green 和 Blue,分别表示 RGB 色彩模式中的红色、绿色和蓝色。每个构造器有一个 UInt8 类型的参数,用来表示每个颜色的亮度级别。
enum RGBColor {
| Red(UInt8) | Green(UInt8) | Blue(UInt8)
}
仓颉支持同一个 enum 中定义多个同名构造器,但是要求这些构造器的参数个数不同(认为没有参数的构造器的参数个数等于 0),例如:
enum RGBColor {
| Red | Green | Blue
| Red(UInt8) | Green(UInt8) | Blue(UInt8)
}
每个 enum 中最多只有一个没有名字的 ... 构造器,且 ... 只能是最后一个构造器。拥有 ... 构造器的 enum 称为 non-exhaustive enum。由于没有名字,这个构造器不能被直接匹配,在解构时,需要使用可匹配所有构造器的模式,如通配符模式 _ 或绑定模式,具体可参见match 表达式的定义 。例如:
enum T {
| Red | Green | Blue | ...
}
enum 支持递归定义,例如,下面的例子中使用 enum 定义了一种表达式(即 Expr),此表达式只能有 3 种形式:单独的一个数字 Num(携带一个 Int64 类型的参数)、加法表达式 Add(携带两个 Expr 类型的参数)、减法表达式 Sub(携带两个 Expr 类型的参数)。对于 Add 和 Sub 这两个构造器,其参数中递归地使用到了 Expr 自身。
enum Expr {
| Num(Int64)
| Add(Expr, Expr)
| Sub(Expr, Expr)
}
另外,在 enum 体中还可以定义一系列成员函数、操作符函数(详见操作符重载)和成员属性(详见属性),但是要求构造器、成员函数、成员属性之间不能重名。例如,下面的例子在 RGBColor 中定义了一个名为 printType 的函数,它会输出字符串 RGBColor:
enum RGBColor {
| Red | Green | Blue
public static func printType() {
print("RGBColor")
}
}
注意:
enum只能定义在源文件的顶层作用域。
enum 的使用
定义了 enum 类型之后,就可以创建此类型的实例(即 enum 值),enum 值只能取 enum 类型定义中的一个构造器。enum 没有构造函数,可以通过 类型名.构造器,或者直接使用构造器的方式来构造一个 enum 值(对于有参构造器,需要传实参)。
下例中,RGBColor 中定义了三个构造器,其中有两个无参构造器(Red 和 Green)和一个有参构造器(Blue(UInt8)),main 中定义了三个 RGBColor 类型的变量 r,g 和 b,其中,r 的值使用 RGBColor.Red 进行初始化,g 的值直接使用 Green 进行初始化,b 的值使用 Blue(100) 进行初始化:
enum RGBColor {
| Red | Green | Blue(UInt8)
}
main() {
let r = RGBColor.Red
let g = Green
let b = Blue(100)
}
当省略类型名时,enum 构造器的名字可能和类型名、变量名、函数名发生冲突。此时必须加上 enum 类型名来使用 enum 构造器,否则只会选择同名的类型、变量、函数定义。
下面的例子中,只有构造器 Blue(UInt8) 可以不带类型名使用,Red 和 Green(UInt8) 皆会因为名字冲突而不能直接使用,必须加上类型名 RGBColor。
let Red = 1
func Green(g: UInt8) {
return g
}
enum RGBColor {
| Red | Green(UInt8) | Blue(UInt8)
}
let r1 = Red // Will choose 'let Red'
let r2 = RGBColor.Red // Ok: constructed by enum type name
let g1 = Green(100) // Will choose 'func Green'
let g2 = RGBColor.Green(100) // Ok: constructed by enum type name
let b = Blue(100) // Ok: can be uniquely identified as an enum constructor
如下的例子中,只有构造器 Blue 会因为名称冲突而不能直接使用,必须加上类型名 RGBColor。
class Blue {}
enum RGBColor {
| Red | Green(UInt8) | Blue(UInt8)
}
let r = Red // Ok: constructed by enum type name
let g = Green(100) // Ok: constructed by enum type name
let b = Blue(100) // Will choose constructor of 'class Blue' and report an error
Option 类型
Option 类型使用 enum 定义,它包含两个构造器:Some 和 None。其中,Some 会携带一个参数,表示有值;None 不带参数,表示无值。当需要表示某个类型可能有值,也可能没有值时,可以选择使用 Option 类型。
Option 类型被定义为一个泛型 enum 类型,定义如下(这里仅需要知道尖括号中的 T 是一个类型形参,当 T 为不同类型时会得到不同的 Option 类型即可。关于泛型的详细介绍,可参见泛型):
enum Option<T> {
| Some(T)
| None
}
其中,Some 构造器的参数类型就是类型形参 T,当 T 被实例化为不同的类型时,会得到不同的 Option 类型,例如:Option<Int64>、Option<String>等。
Option 类型还有一种简单的写法:在类型名前加 ?。也就是说,对于任意类型 Ty,?Ty 等价于 Option<Ty>。例如,?Int64 等价于 Option<Int64>,?String 等价于 Option<String> 等等。
下面的例子展示了如何定义 Option 类型的变量:
let a: Option<Int64> = Some(100)
let b: ?Int64 = Some(100)
let c: Option<String> = Some("Hello")
let d: ?String = None
另外,虽然 T 和 Option<T> 是不同的类型,但是当明确知道某个位置需要的是 Option<T> 类型的值时,可以直接传一个 T 类型的值,编译器会用 Option<T> 类型的 Some 构造器将 T 类型的值封装成 Option<T> 类型的值(注意:这里并不是类型转换)。例如,下面的定义是合法的(等价于上例中变量 a,b 和 c 的定义):
let a: Option<Int64> = 100
let b: ?Int64 = 100
let c: Option<String> = "100"
在上下文没有明确的类型要求时,无法使用 None 直接构造出想要的类型,此时应使用 None<T> 这样的语法来构造 Option<T> 类型的数据,例如:
let a = None<Int64> // a: Option<Int64>
let b = None<Bool> // b: Option<Bool>
最后,关于 Option 的使用,请参见使用 Option。
模式概述
对于包含匹配值的 match 表达式,case 之后支持哪些模式决定了 match 表达式的表达能力。本节中将依次介绍仓颉支持的模式,包括:常量模式、通配符模式、绑定模式、tuple 模式、类型模式和 enum 模式。
常量模式
常量模式可以是整数字面量、浮点数字面量、字符字面量、布尔字面量、字符串字面量(不支持字符串插值)、Unit 字面量。
在包含匹配值的 match 表达式(参见match 表达式)中使用常量模式时,要求常量模式表示的值的类型与待匹配值的类型相同,匹配成功的条件是待匹配的值与常量模式表示的值相等。
下面的例子中,根据 score 的值(假设 score 只能取 0 到 100 间被 10 整除的值),输出考试成绩的等级:
main() {
let score = 90
let level = match (score) {
case 0 | 10 | 20 | 30 | 40 | 50 => "D"
case 60 => "C"
case 70 | 80 => "B"
case 90 | 100 => "A" // Matched.
case _ => "Not a valid score"
}
println(level)
}
编译执行上述代码,输出结果为:
A
-
在模式匹配的目标是静态类型为
Rune的值时,Rune字面量和单字符字符串字面量都可用于表示Rune类型字面量的常量 pattern。func translate(n: Rune) { match (n) { case "A" => 1 case "B" => 2 case "C" => 3 case _ => -1 } } main() { println(translate(r"C")) }编译执行上述代码,输出结果为:
3 -
在模式匹配的目标是静态类型为
Byte的值时,一个表示 ASCII 字符的字符串字面量可用于表示Byte类型字面量的常量 pattern。func translate(n: Byte) { match (n) { case "1" => 1 case "2" => 2 case "3" => 3 case _ => -1 } } main() { println(translate(51)) // UInt32(r'3') == 51 }编译执行上述代码,输出结果为:
3
通配符模式
通配符模式使用下划线 _ 表示,可以匹配任意值。通配符模式通常作为最后一个 case 中的模式,用来匹配其他 case 未覆盖到的情况,如常量模式中匹配 score 值的示例中,最后一个 case 中使用 _ 来匹配无效的 score 值。
绑定模式
绑定模式使用 id 表示,id 是一个合法的标识符。与通配符模式相比,绑定模式同样可以匹配任意值,但绑定模式会将匹配到的值与 id 进行绑定,在 => 之后可以通过 id 访问其绑定的值。
下面的例子中,最后一个 case 中使用了绑定模式,用于绑定非 0 值:
main() {
let x = -10
let y = match (x) {
case 0 => "zero"
case n => "x is not zero and x = ${n}" // Matched.
}
println(y)
}
编译执行上述代码,输出结果为:
x is not zero and x = -10
使用 | 连接多个模式时不能使用绑定模式,也不可嵌套出现在其他模式中,否则会报错:
main() {
let opt = Some(0)
match (opt) {
case x | x => {} // Error, variable cannot be introduced in patterns connected by '|'
case Some(x) | Some(x) => {} // Error, variable cannot be introduced in patterns connected by '|'
case x: Int64 | x: String => {} // Error, variable cannot be introduced in patterns connected by '|'
}
}
绑定模式 id 相当于新定义了一个名为 id 的不可变变量(其作用域从引入处开始到该 case 结尾处),因此在 => 之后无法对 id 进行修改。例如,下例中最后一个 case 中对 n 的修改是不允许的。
main() {
let x = -10
let y = match (x) {
case 0 => "zero"
case n => n = n + 0 // Error, 'n' cannot be modified.
"x is not zero"
}
println(y)
}
对于每个 case 分支,=> 之后变量作用域级别与 case 后 => 前引入的变量作用域级别相同,在 => 之后再次引入相同名字会触发重定义错误。例如:
main() {
let x = -10
let y = match (x) {
case 0 => "zero"
case n => let n = 0 // Error, redefinition
println(n)
"x is not zero"
}
println(y)
}
注意:
当模式的 identifier 为 enum 构造器时,该模式会被当成 enum 模式进行匹配,而不是绑定模式(关于 enum 模式,详见 enum 模式章节)。
enum RGBColor {
| Red | Green | Blue
}
main() {
let x = Red
let y = match (x) {
case Red => "red" // The 'Red' is enum mode here.
case _ => "not red"
}
println(y)
}
编译执行上述代码,输出结果为:
red
Tuple 模式
Tuple 模式用于 tuple 值的匹配,它的定义和 tuple 字面量类似:(p_1, p_2, ..., p_n),区别在于这里的 p_1 到 p_n(n 大于等于 2)是模式(可以是本章节中介绍的任何模式,多个模式间使用逗号分隔)而不是表达式。
例如,(1, 2, 3) 是一个包含三个常量模式的 tuple 模式,(x, y, _) 是一个包含两个绑定模式,一个通配符模式的 tuple 模式。
给定一个 tuple 值 tv 和一个 tuple 模式 tp,当且仅当 tv 每个位置处的值均能与 tp 中对应位置处的模式相匹配,才称 tp 能匹配 tv。例如,(1, 2, 3) 仅可以匹配 tuple 值 (1, 2, 3),(x, y, _) 可以匹配任何三元 tuple 值。
下面的例子中,展示了 tuple 模式的使用:
main() {
let tv = ("Alice", 24)
let s = match (tv) {
case ("Bob", age) => "Bob is ${age} years old"
case ("Alice", age) => "Alice is ${age} years old" // Matched, "Alice" is a constant pattern, and 'age' is a variable pattern.
case (name, 100) => "${name} is 100 years old"
case (_, _) => "someone"
}
println(s)
}
编译执行上述代码,输出结果为:
Alice is 24 years old
同一个 tuple 模式中不允许引入多个名称相同的绑定模式。例如,下例中最后一个 case 中的 case (x, x) 是不合法的。
main() {
let tv = ("Alice", 24)
let s = match (tv) {
case ("Bob", age) => "Bob is ${age} years old"
case ("Alice", age) => "Alice is ${age} years old"
case (name, 100) => "${name} is 100 years old"
case (x, x) => "someone" // Error, Cannot introduce a variable pattern with the same name, which will be a redefinition error.
}
println(s)
}
类型模式
类型模式用于判断一个值的运行时类型是否是某个类型的子类型。类型模式有两种形式:_: Type(嵌套一个通配符模式 _)和 id: Type(嵌套一个绑定模式 id),它们的区别是后者会发生变量绑定,而前者不会。
对于待匹配值 v 和类型模式 id: Type(或 _: Type),首先判断 v 的运行时类型是否是 Type 的子类型,若成立则视为匹配成功,否则视为匹配失败;如匹配成功,则将 v 的类型转换为 Type 并与 id 进行绑定(对于 _: Type,不存在绑定这一操作)。
假设有如下两个类,Base 和 Derived,并且 Derived 是 Base 的子类,Base 的无参构造函数中将 a 的值设置为 10,Derived 的无参构造函数中将 a 的值设置为 20:
open class Base {
var a: Int64
public init() {
a = 10
}
}
class Derived <: Base {
public init() {
a = 20
}
}
下面的代码展示了使用类型模式并匹配成功的例子:
main() {
var d = Derived()
var r = match (d) {
case b: Base => b.a // Matched.
case _ => 0
}
println("r = ${r}")
}
编译执行上述代码,输出结果为:
r = 20
下面的代码展示了使用类型模式但类型模式匹配失败的例子:
open class Base {
var a: Int64
public init() {
a = 10
}
}
class Derived <: Base {
public init() {
a = 20
}
}
main() {
var b = Base()
var r = match (b) {
case d: Derived => d.a // Type pattern match failed.
case _ => 0 // Matched.
}
println("r = ${r}")
}
编译执行上述代码,输出结果为:
r = 0
enum 模式
enum 模式用于匹配 enum 类型的实例,它的定义和 enum 的构造器类似:无参构造器 C 或有参构造器 C(p_1, p_2, ..., p_n),构造器的类型前缀可以省略,区别在于这里的 p_1 到 p_n(n 大于等于 1)是模式。例如,Some(1) 是一个包含一个常量模式的 enum 模式,Some(x) 是一个包含一个绑定模式的 enum 模式。
给定一个 enum 实例 ev 和一个 enum 模式 ep,当且仅当 ev 的构造器名字和 ep 的构造器名字相同,且 ev 参数列表中每个位置处的值均能与 ep 中对应位置处的模式相匹配,才称 ep 能匹配 ev。例如,Some("one") 仅可以匹配 Option<String> 类型的Some 构造器 Option<String>.Some("one"),Some(x) 可以匹配任何 Option 类型的 Some 构造器。
下面的例子中,展示了 enum 模式的使用,因为 x 的构造器是 Year,所以会和第一个 case 匹配:
enum TimeUnit {
| Year(UInt64)
| Month(UInt64)
}
main() {
let x = Year(2)
let s = match (x) {
case Year(n) => "x has ${n * 12} months" // Matched.
case TimeUnit.Month(n) => "x has ${n} months"
}
println(s)
}
编译执行上述代码,输出结果为:
x has 24 months
使用 | 连接多个 enum 模式:
enum TimeUnit {
| Year(UInt64)
| Month(UInt64)
}
main() {
let x = Year(2)
let s = match (x) {
case Year(0) | Year(1) | Month(_) => "Ok" // Ok
case Year(2) | Month(m) => "invalid" // Error, Variable cannot be introduced in patterns connected by '|'
case Year(n: UInt64) | Month(n: UInt64) => "invalid" // Error, Variable cannot be introduced in patterns connected by '|'
}
println(s)
}
使用 match 表达式匹配 enum 值时,要求 case 之后的模式要覆盖待匹配 enum 类型中的所有构造器,如果未做到完全覆盖,编译器将报错:
enum RGBColor {
| Red | Green | Blue
}
main() {
let c = Green
let cs = match (c) { // Error, Not all constructors of RGBColor are covered.
case Red => "Red"
case Green => "Green"
}
println(cs)
}
可以通过加上 case Blue 来实现完全覆盖,也可以在 match 表达式的最后通过使用 case _ 来覆盖其他 case 未覆盖的到的情况,如:
enum RGBColor {
| Red | Green | Blue
}
main() {
let c = Blue
let cs = match (c) {
case Red => "Red"
case Green => "Green"
case _ => "Other" // Matched.
}
println(cs)
}
上述代码的执行结果为:
Other
模式的嵌套组合
Tuple 模式和 enum 模式可以嵌套任意模式。下面的代码展示了不同模式嵌套组合使用:
enum TimeUnit {
| Year(UInt64)
| Month(UInt64)
}
enum Command {
| SetTimeUnit(TimeUnit)
| GetTimeUnit
| Quit
}
main() {
let command = (SetTimeUnit(Year(2022)), SetTimeUnit(Year(2024)))
match (command) {
case (SetTimeUnit(Year(year)), _) => println("Set year ${year}")
case (_, SetTimeUnit(Month(month))) => println("Set month ${month}")
case _ => ()
}
}
编译并执行上述代码,输出结果为:
Set year 2022
模式的 Refutability
模式可以分为两类:refutable 模式和 irrefutable 模式。在类型匹配的前提下,当一个模式有可能和待匹配值不匹配时,称此模式为 refutable 模式;反之,当一个模式总是可以和待匹配值匹配时,称此模式为 irrefutable 模式。
对于上述介绍的各种模式,规定如下:
常量模式是 refutable 模式。例如,下例中第一个 case 中的 1 和第二个 case 中的 2 都有可能和 x 的值不相等。
func constPat(x: Int64) {
match (x) {
case 1 => "one"
case 2 => "two"
case _ => "_"
}
}
通配符模式是 irrefutable 模式。例如,下例中无论 x 的值是多少,_ 总能和其匹配。
func wildcardPat(x: Int64) {
match (x) {
case _ => "_"
}
}
绑定模式是 irrefutable 模式。例如,下例中无论 x 的值是多少,绑定模式 a 总能和其匹配。
func varPat(x: Int64) {
match (x) {
case a => "x = ${a}"
}
}
Tuple 模式是 irrefutable 模式,当且仅当其包含的每个模式都是 irrefutable 模式。例如,下例中 (1, 2) 和 (a, 2) 都有可能和 x 的值不匹配,所以它们是 refutable 模式,而 (a, b) 可以匹配任何 x 的值,所以它是 irrefutable 模式。
func tuplePat(x: (Int64, Int64)) {
match (x) {
case (1, 2) => "(1, 2)"
case (a, 2) => "(${a}, 2)"
case (a, b) => "(${a}, ${b})"
}
}
类型模式是 refutable 模式。例如,下例中(假设 Base 是 Derived 的父类,并且 Base 实现了接口 I),x 的运行时类型有可能既不是 Base 也不是 Derived,所以 a: Derived 和 b: Base 均是 refutable 模式。
interface I {}
open class Base <: I {}
class Derived <: Base {}
func typePat(x: I) {
match (x) {
case a: Derived => "Derived"
case b: Base => "Base"
case _ => "Other"
}
}
enum 模式是 irrefutable 模式,当且仅当它对应的 enum 类型中只有一个有参构造器,且 enum 模式中包含的其他模式也是 irrefutable 模式。例如,对于下例中的 E1 和 E2 定义,函数 enumPat1 中的 A(1) 是 refutable 模式,A(a) 是 irrefutable 模式;而函数 enumPat2 中的 B(b) 和 C(c) 均是 refutable 模式。
enum E1 {
A(Int64)
}
enum E2 {
B(Int64) | C(Int64)
}
func enumPat1(x: E1) {
match (x) {
case A(1) => "A(1)"
case A(a) => "A(${a})"
}
}
func enumPat2(x: E2) {
match (x) {
case B(b) => "B(${b})"
case C(c) => "C(${c})"
}
}
match 表达式
match 表达式的定义
仓颉支持两种 match 表达式,第一种是包含待匹配值的 match 表达式,第二种是不含待匹配值的 match 表达式。
含匹配值的 match 表达式:
main() {
let x = 0
match (x) {
case 1 => let r1 = "x = 1"
print(r1)
case 0 => let r2 = "x = 0" // Matched.
print(r2)
case _ => let r3 = "x != 1 and x != 0"
print(r3)
}
}
match 表达式以关键字 match 开头,后跟要匹配的值(如上例中的 x,x 可以是任意表达式),接着是定义在一对花括号内的若干 case 分支。
每个 case 分支以关键字 case 开头,case 之后是一个模式或多个由 | 连接的相同种类的模式(如上例中的 1、0、_ 都是模式,详见模式概述章节);模式之后可以接一个可选的 pattern guard,表示本条 case 匹配成功后额外需要满足的条件,pattern guard 使用 where cond 表示,要求表达式 cond 的类型为 Bool;接着是一个 =>,=> 之后即本条 case 分支匹配成功后需要执行的操作,可以是一系列表达式、变量和函数定义(新定义的变量或函数的作用域从其定义处开始到下一个 case 之前结束),如上例中的变量定义和 print 函数调用。
match 表达式执行时依次将 match 之后的表达式与每个 case 中的模式进行匹配,一旦匹配成功(如果有 pattern guard,也需要 where 之后的表达式的值为 true;如果 case 中有多个由 | 连接的模式,只要待匹配值和其中一个模式匹配则认为匹配成功)则执行 => 之后的代码然后退出 match 表达式的执行(意味着不会再去匹配它之后的 case),如果匹配不成功则继续与它之后的 case 中的模式进行匹配,直到匹配成功(match 表达式可以保证一定存在匹配的 case 分支)。
上例中,因为 x 的值等于 0,所以会和第二条 case 分支匹配(此处使用的是常量模式,匹配的是值是否相等,详见常量模式章节),最后输出 x = 0。
编译并执行上述代码,输出结果为:
x = 0
match 表达式要求所有匹配必须是穷尽(exhaustive)的,意味着待匹配表达式的所有可能取值都应该被考虑到。当 match 表达式非穷尽,或者编译器判断不出是否穷尽时,均会编译报错,换言之,所有 case 分支(包含 pattern guard)所覆盖的取值范围的并集,应该包含待匹配表达式的所有可能取值。常用的确保 match 表达式穷尽的方式是在最后一个 case 分支中使用通配符模式 _,因为 _ 可以匹配任何值。
match 表达式的穷尽性保证了一定存在和待匹配值相匹配的 case 分支。下面的例子将编译报错,因为所有的 case 并没有覆盖 x 的所有可能取值:
func nonExhaustive(x: Int64) {
match (x) {
case 0 => print("x = 0")
case 1 => print("x = 1")
case 2 => print("x = 2")
}
}
如果被匹配值的类型包含 enum 类型且该 enum 为 non-exhaustive enum,则其在匹配时需要使用可匹配所有构造器的模式,如通配符模式 _ 和绑定模式。
enum T {
| Red | Green | Blue | ...
}
func foo(a: T) {
match (a) {
case Red => 0
case Green => 1
case Blue => 2
case _ => -1
}
}
func bar(a: T) {
match (a) {
case Red => 0
case k => -1 // simple binding pattern
}
}
func baz(a: T) {
match (a) {
case Red => 0
case k: T => -1 // binding pattern with nested type pattern
}
}
在 case 分支的模式之后,可以使用 pattern guard 进一步对匹配出来的结果进行判断。
在下面的例子中(使用到了 enum 模式,详见 enum 模式章节),当 RGBColor 的构造器的参数值大于等于 0 时,输出它们的值,当参数值小于 0 时,认为它们的值等于 0:
enum RGBColor {
| Red(Int16) | Green(Int16) | Blue(Int16)
}
main() {
let c = RGBColor.Green(-100)
let cs = match (c) {
case Red(r) where r < 0 => "Red = 0"
case Red(r) => "Red = ${r}"
case Green(g) where g < 0 => "Green = 0" // Matched.
case Green(g) => "Green = ${g}"
case Blue(b) where b < 0 => "Blue = 0"
case Blue(b) => "Blue = ${b}"
}
print(cs)
}
编译执行上述代码,输出结果为:
Green = 0
没有匹配值的 match 表达式:
main() {
let x = -1
match {
case x > 0 => print("x > 0")
case x < 0 => print("x < 0") // Matched.
case _ => print("x = 0")
}
}
与包含待匹配值的 match 表达式相比,关键字 match 之后并没有待匹配的表达式,并且 case 之后不再是 pattern,而是类型为 Bool 的表达式(上述代码中的 x > 0 和 x < 0)或者 _(表示 true),当然,case 中也不再有 pattern guard。
无匹配值的 match 表达式执行时依次判断 case 之后的表达式的值,直到遇到值为 true 的 case 分支;一旦某个 case 之后的表达式值等于 true,则执行此 case 中 => 之后的代码,然后退出 match 表达式的执行(意味着不会再去判断该 case 之后的其他 case)。
上例中,因为 x 的值等于 -1,所以第二条 case 分支中的表达式(即 x < 0)的值等于 true,执行 print("x < 0")。
编译并执行上述代码,输出结果为:
x < 0
match 表达式的类型
对于 match 表达式(无论是否有匹配值):
-
在上下文有明确的类型要求时,要求每个
case分支中=>之后的代码块的类型是上下文所要求的类型的子类型; -
在上下文没有明确的类型要求时,
match表达式的类型是每个case分支中=>之后的代码块的类型的最小公共父类型; -
当
match表达式的值没有被使用时,其类型为Unit,不要求各分支的类型有最小公共父类型。
下面分别举例说明。
let x = 2
let s: String = match (x) {
case 0 => "x = 0"
case 1 => "x = 1"
case _ => "x != 0 and x != 1" // Matched.
}
上面的例子中,定义变量 s 时,显式地标注了其类型为 String,属于上下文类型信息明确的情况,因此要求每个 case 的 => 之后的代码块的类型均是 String 的子类型,显然上例中 => 之后的字符串类型的字面量均满足要求。
再来看一个没有上下文类型信息的例子:
let x = 2
let s = match (x) {
case 0 => "x = 0"
case 1 => "x = 1"
case _ => "x != 0 and x != 1" // Matched.
}
上例中,定义变量 s 时,未显式标注其类型,因为每个 case 的 => 之后的代码块的类型均是 String,所以 match 表达式的类型是 String,进而可确定 s 的类型也是 String。
其他使用模式的地方
模式除了可以在 match 表达式中使用外,还可以使用在变量定义(等号左侧是一个模式)和 for in 表达式(for 关键字和 in 关键字之间是一个模式)中。
但是,并不是所有的模式都能使用在变量定义和 for in 表达式中,只有 irrefutable 的模式才能在这两处被使用,所以只有通配符模式、绑定模式、irrefutable tuple 模式和 irrefutable enum 模式是允许的。
-
变量定义和
for in表达式中使用通配符模式的例子如下:main() { let _ = 100 for (_ in 1..5) { println("0") } }上例中,变量定义时使用了通配符模式,表示定义了一个没有名字的变量(当然此后也就没办法对其进行访问),
for in表达式中使用了通配符模式,表示不会将1..5中的元素与某个变量绑定(当然循环体中就无法访问1..5中元素值)。编译执行上述代码,输出结果为:0 0 0 0 -
变量定义和
for in表达式中使用绑定模式的例子如下:main() { let x = 100 println("x = ${x}") for (i in 1..5) { println(i) } }上例中,变量定义中的
x以及for in表达式中的i都是绑定模式。编译执行上述代码,输出结果为:x = 100 1 2 3 4 -
变量定义和
for in表达式中使用irrefutabletuple 模式的例子如下:main() { let (x, y) = (100, 200) println("x = ${x}") println("y = ${y}") for ((i, j) in [(1, 2), (3, 4), (5, 6)]) { println("Sum = ${i + j}") } }上例中,变量定义时使用了 tuple 模式,表示对
(100, 200)进行解构并分别和x与y进行绑定,效果上相当于定义了两个变量x和y。for in表达式中使用了 tuple 模式,表示依次将[(1, 2), (3, 4), (5, 6)]中的 tuple 类型的元素取出,然后解构并分别和i与j进行绑定,循环体中输出i + j的值。编译执行上述代码,输出结果为:x = 100 y = 200 Sum = 3 Sum = 7 Sum = 11 -
变量定义和
for in表达式中使用irrefutableenum 模式的例子如下:enum RedColor { Red(Int64) } main() { let Red(red) = Red(0) println("red = ${red}") for (Red(r) in [Red(10), Red(20), Red(30)]) { println("r = ${r}") } }上例中,变量定义时使用了 enum 模式,表示对
Red(0)进行解构并将构造器的参数值(即0)与red进行绑定。for in表达式中使用了 enum 模式,表示依次将[Red(10), Red(20), Red(30)]中的元素取出,然后解构并将构造器的参数值与r进行绑定,循环体中输出r的值。编译执行上述代码,输出结果为:red = 0 r = 10 r = 20 r = 30
类
class 类型是面向对象编程中的经典概念,仓颉中同样支持使用 class 来实现面向对象编程。class 与 struct 的主要区别在于:class 是引用类型,struct 是值类型,它们在赋值或传参时行为是不同的;class 之间可以继承,但 struct 之间不能继承。
本节依次介绍如何定义 class 类型,如何创建对象,以及 class 的继承。
class 定义
class 类型的定义以关键字 class 开头,后跟 class 的名字,接着是定义在一对花括号中的 class 定义体。class 定义体中可以定义一系列的成员变量、成员属性(参见属性)、静态初始化器、构造函数、成员函数和操作符函数(详见操作符重载)。
class Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
上例中定义了名为 Rectangle 的 class 类型,它有两个 Int64 类型的成员变量 width 和 height,一个有两个 Int64 类型参数的构造函数,以及一个成员函数 area(返回 width 和 height 的乘积)。
注意:
class只能定义在源文件的顶层作用域。
使用 abstract 修饰的类为抽象类,与普通类不同的是,在抽象类中除了可以定义普通的函数,还允许声明抽象函数(没有函数体)。抽象类定义时的 open 修饰符是可选的,也可以使用 sealed 修饰符修饰抽象类,表示该抽象类只能在本包被继承。下例中在抽象类 AbRectangle 中定义了抽象函数 foo。
abstract class AbRectangle {
public func foo(): Unit
}
注意:
- 抽象类中禁止定义
private的抽象函数;- 不能为抽象类创建实例;
- 抽象类的非抽象子类必须实现父类中的所有抽象函数。
class 成员变量
class 成员变量分为实例成员变量和静态成员变量,静态成员变量使用 static 修饰符修饰,没有静态初始化器时必须有初值,只能通过类型名访问,参考如下示例:
class Rectangle {
let width = 10
static let height = 20
}
let l = Rectangle.height // l = 20
实例成员变量定义时可以不设置初值(但必须标注类型),也可以设置初值,只能通过对象(即类的实例)访问,参考如下示例:
class Rectangle {
let width = 10
let height: Int64
init(h: Int64){
height = h
}
}
let rec = Rectangle(20)
let l = rec.height // l = 20
class 静态初始化器
class 支持定义静态初始化器,并在静态初始化器中通过赋值表达式来对静态成员变量进行初始化。
静态初始化器以关键字组合 static init 开头,后跟无参参数列表和函数体,且不能被访问修饰符修饰。函数体中必须完成对所有未初始化的静态成员变量的初始化,否则编译报错。
class Rectangle {
static let degree: Int64
static init() {
degree = 180
}
}
一个 class 中最多允许定义一个静态初始化器,否则报重定义错误。
class Rectangle {
static let degree: Int64
static init() {
degree = 180
}
static init() { // Error, redefinition with the previous static init function
degree = 180
}
}
class 构造函数
和 struct 一样,class 中也支持定义普通构造函数和主构造函数。
普通构造函数以关键字 init 开头,后跟参数列表和函数体,函数体中必须完成所有未初始化实例成员变量的初始化,否则编译报错。
class Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) { // Error, 'height' is not initialized in the constructor
this.width = width
}
}
一个类中可以定义多个普通构造函数,但它们必须构成重载(参见函数重载),否则报重定义错误。
class Rectangle {
let width: Int64
let height: Int64
public init(width: Int64) {
this.width = width
this.height = width
}
public init(width: Int64, height: Int64) { // Ok: overloading with the first init function
this.width = width
this.height = height
}
public init(height: Int64) { // Error, redefinition with the first init function
this.width = height
this.height = height
}
}
除了可以定义若干普通的以 init 为名字的构造函数外,class 内还可以定义(最多)一个主构造函数。主构造函数的名字和 class 类型名相同,它的参数列表中可以有两种形式的形参:普通形参和成员变量形参(需要在参数名前加上 let 或 var),成员变量形参同时具有定义成员变量和构造函数参数的功能。
使用主构造函数通常可以简化 class 的定义,例如,上述包含一个 init 构造函数的 Rectangle 可以简化为如下定义:
class Rectangle {
public Rectangle(let width: Int64, let height: Int64) {}
}
主构造函数的参数列表中也可以定义普通形参,例如:
class Rectangle {
public Rectangle(name: String, let width: Int64, let height: Int64) {}
}
创建类的实例时调用的构造函数,将根据以下顺序执行类中的表达式:
- 先初始化主构造函数之外定义的有缺省值的变量;
- 如果构造函数体内未显式调用父类构造函数或本类其他构造函数,则调用父类的无参构造函数
super(),如果父类没有无参构造函数,则报错; - 执行构造函数体内的代码。
func foo(x: Int64): Int64 {
println("I'm foo, got ${x}")
x
}
open class A {
init() {
println("I'm A")
}
}
class B <: A {
var x = foo(0)
init() {
x = foo(1)
println("init B finished")
}
}
main() {
B()
0
}
上述例子中,调用 B 的构造函数时,首先初始化有缺省值的变量 x,此时 foo(0) 被调用;之后调用父类的无参构造函数,此时 A 的构造函数被调用;接下来执行构造函数体内的代码,此时 foo(1) 被调用,并打印字符串。因此上例的输出为:
I'm foo, got 0
I'm A
I'm foo, got 1
init B finished
如果 class 定义中不存在自定义构造函数(包括主构造函数),并且所有实例成员变量都有初始值,则会自动为其生成一个无参构造函数(调用此无参构造函数会创建一个所有实例成员变量的值均等于其初值的对象);否则,不会自动生成此无参构造函数。例如,对于如下 class 定义,编译器会为其自动生成一个无参构造函数:
class Rectangle {
let width = 10
let height = 20
/* Auto-generated parameterless constructor:
public init() {
}
*/
}
// Invoke the auto-generated parameterless constructor
let r = Rectangle() // r.width = 10,r.height = 20
class 终结器
class 支持定义终结器,这个函数在类的实例被垃圾回收的时候被调用。终结器的函数名固定为 ~init。终结器通常用于释放系统资源:
class C {
var p: CString
init(s: String) {
p = unsafe { LibC.mallocCString(s) }
println(s)
}
~init() {
unsafe { LibC.free(p) }
}
}
使用终结器有些限制条件,需要开发者注意:
-
终结器没有参数,没有返回类型,没有泛型类型参数,没有任何修饰符,也不可以被显式调用。
-
带有终结器的类不可被
open修饰,只有非open的类可以拥有终结器。 -
一个类最多只能定义一个终结器。
-
终结器不可以定义在扩展中。
-
终结器被触发的时机是不确定的。
-
终结器可能在任意一个线程上执行。
-
多个终结器的执行顺序是不确定的。
-
终结器向外抛出未捕获异常属于未定义行为。
-
终结器中创建线程或者使用线程同步功能属于未定义行为。
-
终结器执行结束之后,如果这个对象还可以被继续访问,则属于未定义行为。
-
如果对象在初始化过程中抛出异常,这样未完整初始化的对象的终结器不会执行。
-
依赖终结器的同步行为属于未定义行为。例如,下例中
main函数通过while (Test.t0 != 0)等待Test类中的终结器修改t0的值,属于未定义行为。import std.collection.* import std.runtime.* class Test { public static var t0 : Int32 = 0 public init () { t0++ } ~init () { t0-- } } var list: ArrayList<Test> = ArrayList<Test>() func foo() : Int32 { let o1 = Test() list.add(o1) if (Test.t0 != 1) { return 1 } list.remove(at: 0) return 0 } main() : Int64 { var i : Int64 = 0 while (i < 100) { if (foo() != 0) { print("fail: obj is freed before gc!") return 1 } gc(heavy: true) // blocking gc expected // wait ~init() to be executed while (Test.t0 != 0) { // error, this is undefined behavior continue } i++ } return 0 }
class 成员函数
class 成员函数同样分为实例成员函数和静态成员函数(使用 static 修饰符修饰),实例成员函数只能通过对象访问,静态成员函数只能通过 class 类型名访问;静态成员函数中不能访问实例成员变量,也不能调用实例成员函数,但在实例成员函数中可以访问静态成员变量以及静态成员函数。
下例中,area 是实例成员函数,typeName 是静态成员函数。
class Rectangle {
let width: Int64 = 10
let height: Int64 = 20
public func area() {
this.width * this.height
}
public static func typeName(): String {
"Rectangle"
}
}
根据是否有函数体,实例成员函数又可以分为抽象成员函数和非抽象成员函数。抽象成员函数没有函数体,只能定义在抽象类或接口(详见接口)中。需要注意的是,抽象实例成员函数默认具有 open 的语义,open 修饰符是可选的,且必须使用 public 或 protected 进行修饰。
非抽象函数必须有函数体,在函数体中可以通过 this 访问实例成员变量,例如:
class Rectangle {
let width: Int64 = 10
let height: Int64 = 20
public func area() {
this.width * this.height
}
}
class 成员的访问修饰符
对于 class 的成员(包括成员变量、成员属性、构造函数、成员函数),可以使用的访问修饰符有 4 种访问修饰符修饰:private、internal、protected 和 public,缺省的含义是 internal。
private表示在class定义内可见。internal表示仅当前包及子包(包括子包的子包,详见包)内可见。protected表示当前模块(详见包)及当前类的子类可见。public表示模块内外均可见。
package a
public open class Rectangle {
public var width: Int64
protected var height: Int64
private var area: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
this.area = this.width * this.height
}
init(width: Int64, height: Int64, multiple: Int64) {
this.width = width
this.height = height
this.area = width * height * multiple
}
}
func samePkgFunc() {
var r = Rectangle(10, 20) // Ok: constructor 'Rectangle' can be accessed here
r.width = 8 // Ok: public 'width' can be accessed here
r.height = 24 // Ok: protected 'height' can be accessed here
r.area = 30 // Error, private 'area' cannot be accessed here
}
package b
import a.*
public class Cuboid <: Rectangle {
private var length: Int64
public init(width: Int64, height: Int64, length: Int64) {
super(width, height)
this.length = length
}
public func volume() {
this.width * this.height * this.length // Ok: protected 'height' can be accessed here
}
}
main() {
var r = Rectangle(10, 20, 2) // Error, Rectangle has no `public` constructor with three parameters
var c = Cuboid(20, 20, 20)
c.width = 8 // Ok: public 'width' can be accessed here
c.height = 24 // Error, protected 'height' cannot be accessed here
c.area = 30 // Error, private 'area' cannot be accessed here
}
This 类型
在类内部,支持 This 类型占位符,代指当前类的类型。它只能被作为实例成员函数的返回类型来使用,当使用子类对象调用在父类中定义的返回 This 类型的函数时,该函数调用的类型会被识别为子类类型,而非定义所在的父类类型。
如果实例成员函数没有声明返回类型,并且只存在返回 This 类型表达式时,当前函数的返回类型会推断为 This。示例如下:
open class C1 {
func f(): This { // its type is `() -> C1`
return this
}
func f2() { // its type is `() -> C1`
return this
}
public open func f3(): C1 {
return this
}
}
class C2 <: C1 {
// member function f is inherited from C1, and its type is `() -> C2` now
public override func f3(): This { // Ok
return this
}
}
var obj1: C2 = C2()
var obj2: C1 = C2()
var x = obj1.f() // During compilation, the type of x is C2
var y = obj2.f() // During compilation, the type of y is C1
创建对象
定义了 class 类型后,即可通过调用其构造函数来创建对象(通过 class 类型名调用构造函数)。例如,下例中通过 Rectangle(10, 20) 创建 Rectangle 类型的对象并赋值给变量 r。创建对象之后,可以通过对象访问(public 修饰的)实例成员变量和实例成员函数。例如,下例中通过 r.width 和 r.height 可分别访问 r 中 width 和 height 的值,通过 r.area() 可以调用成员函数 area。
class Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
this.width * this.height
}
}
let r = Rectangle(10, 20) // r.width = 10, r.height = 20
let width = r.width // width = 10
let height = r.height // height = 20
let a = r.area() // a = 200
如果希望通过对象去修改成员变量的值(不鼓励这种方式,最好还是通过成员函数去修改),需要将 class 类型中的成员变量定义为可变成员变量(即使用 var 定义)。举例如下:
class Rectangle {
public var width: Int64
public var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
main() {
let r = Rectangle(10, 20) // r.width = 10, r.height = 20
r.width = 8 // r.width = 8
r.height = 24 // r.height = 24
let a = r.area() // a = 192
}
不同于 struct,对象在赋值或传参时,不会将对象进行复制,多个变量指向的是同一个对象,通过一个变量去修改对象中成员的值,其他变量中对应的成员变量也会被修改。以赋值为例,下面的例子中,将 r1 赋值给 r2 之后,修改 r1 的 width 和 height 的值,r2 的 width 和 height 值也同样会被修改。
class Rectangle {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
this.width * this.height
}
}
main() {
var r1 = Rectangle(10, 20) // r1.width = 10, r1.height = 20
var r2 = r1 // r2.width = 10, r2.height = 20
r1.width = 8 // r1.width = 8
r1.height = 24 // r1.height = 24
let a1 = r1.area() // a1 = 192
let a2 = r2.area() // a2 = 192
}
class 的继承
像大多数支持 class 的编程语言一样,仓颉中的 class 同样支持继承。如果类 B 继承类 A,则称 A 为父类,B 为子类。子类将继承父类中除 private 成员和构造函数以外的所有成员。
抽象类总是可被继承的,故抽象类定义时的 open 修饰符是可选的,也可以使用 sealed 修饰符修饰抽象类,表示该抽象类只能在本包被继承。但非抽象的类可被继承是有条件的:定义时必须使用修饰符 open 修饰。当带 open 修饰的实例成员被 class 继承时,该 open 的修饰符也会被继承。当非 open 修饰的类中存在 open 修饰的成员时,编译器会给出告警。
可以在子类定义处通过 <: 指定其继承的父类,但要求父类必须是可继承的。例如,下面的例子中,class A 使用 open 修饰,是可以被类 B 继承的,但是因为类 B 是不可继承的,所以 C 在继承 B 的时候会报错。
open class A {
let a: Int64 = 10
}
class B <: A { // Ok: 'B' Inheritance 'A'
let b: Int64 = 20
}
class C <: B { // Error, 'B' is not inheritable
let c: Int64 = 30
}
class 仅支持单继承,因此下面这样一个类继承两个类的代码是不合法的(& 是类实现多个接口时的语法,详见接口)。
open class A {
let a: Int64 = 10
}
open class B {
let b: Int64 = 20
}
class C <: A & B { // Error, 'C' can only inherit one class
let c: Int64 = 30
}
因为类是单继承的,所以任何类都最多只能有一个直接父类。对于定义时指定了父类的 class,它的直接父类就是定义时指定的类,对于定义时未指定父类的 class,它的直接父类是 Object 类型。Object 是所有类的父类(注意,Object 没有直接父类,并且 Object 中不包含任何成员)。
因为子类是继承自父类的,所以子类的对象天然可以当做父类的对象使用,但是反之不然。例如,下例中 B 是 A 的子类,那么 B 类型的对象可以赋值给 A 类型的变量,但是 A 类型的对象不能赋值给 B 类型的变量。
open class A {
let a: Int64 = 10
}
class B <: A {
let b: Int64 = 20
}
let a: A = B() // Ok: subclass objects can be assigned to superclass variables
open class A {
let a: Int64 = 10
}
class B <: A {
let b: Int64 = 20
}
let b: B = A() // Error, superclass objects can not be assigned to subclass variables
class 定义的类型不允许继承类型本身。
class A <: A {} // Error, 'A' inherits itself.
抽象类可以使用 sealed 修饰符,表示被修饰的类定义只能在本定义所在的包内被其他类继承。sealed 已经蕴含了 public/open 的语义,因此定义 sealed abstract class 时若提供 public/open 修饰符,编译器将会告警。sealed 的子类可以不是 sealed 类,仍可被 open/sealed 修饰,或不使用任何继承性修饰符。若 sealed 类的子类被 open 修饰,则其子类可在包外被继承。sealed 的子类可以不被 public 修饰。
package A
public sealed abstract class C1 {} // Warning, redundant modifier, 'sealed' implies 'public'
sealed open abstract class C2 {} // Warning, redundant modifier, 'sealed' implies 'open'
sealed abstract class C3 {} // OK, 'public' is optional when 'sealed' is used
class S1 <: C1 {} // OK
public open class S2 <: C1 {} // OK
public sealed abstract class S3 <: C1 {} // OK
open class S4 <: C1 {} // OK
package B
import A.*
class SS1 <: S2 {} // OK
class SS2 <: S3 {} // Error, S3 is sealed class, cannot be inherited here.
sealed class SS3 {} // Error, 'sealed' cannot be used on non-abstract class.
父类构造函数调用
子类的 init 构造函数可以使用 super(args) 的形式调用父类构造函数,或使用 this(args) 的形式调用本类其他构造函数,但两者之间只能调用一个。如果调用,必须在构造函数体内的第一个表达式处,在此之前不能有任何表达式或声明。
open class A {
A(let a: Int64) {}
}
class B <: A {
let b: Int64
init(b: Int64) {
super(30)
this.b = b
}
init() {
this(20)
}
}
子类的主构造函数中,可以使用 super(args) 的形式调用父类构造函数,但不能使用 this(args) 的形式调用本类其他构造函数。
如果子类的构造函数没有显式调用父类构造函数,也没有显式调用其他构造函数,编译器会在该构造函数体的开始处插入直接父类的无参构造函数的调用。如果此时父类没有无参构造函数,则会编译报错。
open class A {
let a: Int64
init() {
a = 100
}
}
open class B <: A {
let b: Int64
init(b: Int64) {
// OK, `super()` added by compiler
this.b = b
}
}
open class C <: B {
let c: Int64
init(c: Int64) { // Error, there is no non-parameter constructor in super class
this.c = c
}
}
覆盖和重定义
子类中可以覆盖(override)父类中的同名非抽象实例成员函数,即在子类中为父类中的某个实例成员函数定义新的实现。覆盖时,要求父类中的成员函数使用 open 修饰,子类中的同名函数使用 override 修饰,其中 override 是可选的。例如,下面的例子中,子类 B 中的函数 f 覆盖了父类 A 中的函数 f。
open class A {
public open func f(): Unit {
println("I am superclass")
}
}
class B <: A {
public override func f(): Unit {
println("I am subclass")
}
}
main() {
let a: A = A()
let b: A = B()
a.f()
b.f()
}
对于被覆盖的函数,调用时将根据变量的运行时类型(由实际赋给该变量的对象决定)确定调用的版本(即所谓的动态派发)。例如,上例中 a 的运行时类型是 A,因此 a.f() 调用的是父类 A 中的函数 f;b 的运行时类型是 B(编译时类型是 A),因此 b.f() 调用的是子类 B 中的函数 f。所以程序会输出:
I am superclass
I am subclass
对于静态函数,子类中可以重定义父类中的同名非抽象静态函数,即在子类中为父类中的某个静态函数定义新的实现。重定义时,要求子类中的同名静态函数使用 redef 修饰,其中 redef 是可选的。例如,下面的例子中,子类 D 中的函数 foo 重定义了父类 C 中的函数 foo。
open class C {
public static func foo(): Unit {
println("I am class C")
}
}
class D <: C {
public redef static func foo(): Unit {
println("I am class D")
}
}
main() {
C.foo()
D.foo()
}
对于被重定义的函数,调用时将根据 class 的类型决定调用的版本。例如,上例中 C.foo() 调用的是父类 C 中的函数 foo,D.foo() 调用的是子类 D 中的函数 foo。
I am class C
I am class D
如果抽象函数或 open 修饰的函数有命名形参,那么实现函数或 override 修饰的函数也需要保持同样的命名形参。
open class A {
public open func f(a!: Int32): Int32 {
a + 1
}
}
class B <: A {
public override func f(a!: Int32): Int32 { // Ok
a + 2
}
}
class C <: A {
public override func f(b!: Int32): Int32 { // Error
b + 3
}
}
main() {
B().f(a: 0)
C().f(b: 0)
}
还需要注意的是,当实现或重定义的函数为泛型函数时,子类型函数的类型变元约束需要比父类型中对应函数更宽松或相同。
open class A {}
open class B <: A {}
open class C <: B {}
open class Base {
public open func foo<T>(a: T): Unit where T <: B {}
public open func bar<T>(a: T): Unit where T <: B {}
public static func f<T>(a: T): Unit where T <: B {}
public static func g<T>(): Unit where T <: B {}
}
class D <: Base {
public override func foo<T>(a: T): Unit where T <: C {} // Error, stricter constraint
public override func bar<T>(a: T): Unit where T <: C {} // Error, stricter constraint
public redef static func f<T>(a: T): Unit where T <: C {} // Error, stricter constraint
public redef static func g<T>(): Unit where T <: C {} // Error, stricter constraint
}
class E <: Base {
public override func foo<T>(a: T): Unit where T <: A {} // OK: looser constraint
public override func bar<V>(a: V): Unit where V <: A {} // OK: looser constraint, names of generic parameters do not matter
public redef static func f<T>(a: T): Unit where T <: A {} // OK: looser constraint
public redef static func g<T>(): Unit where T <: A {} // OK: looser constraint
}
class F <: Base {
public override func foo<T>(a: T): Unit where T <: B {} // OK: same constraint
public override func bar<V>(a: V): Unit where V <: B {} // OK: same constraint
public redef static func f<T>(a: T): Unit where T <: B {} // OK: same constraint
public redef static func g<T>(): Unit where T <: B {} // OK: same constraint
}
接口
接口用来定义一个抽象类型,它不包含数据,但可以定义类型的行为。一个类型如果声明实现某接口,并且实现了该接口中所有的成员,就被称为实现了该接口。
接口的成员可以包含:
- 成员函数
- 操作符重载函数
- 成员属性
这些成员都是抽象的,要求实现类型必须拥有对应的成员实现。
接口定义
一个简单的接口定义如下:
interface I { // 'open' modifier is optional.
func f(): Unit
}
接口使用关键字 interface 声明,其后是接口的标识符 I 和接口的成员。接口成员可被 open 修饰符修饰,并且 open 修饰符是可选的。
当接口 I 声明了一个成员函数 f 之后,要为一个类型实现 I 时,就必须在该类型中实现一个对应的 f 函数。
因为 interface 默认具有 open 语义,所以 interface 定义时的 open 修饰符是可选的。
如下面的代码所示,定义了一个 class Foo,使用 Foo <: I 的形式声明了 Foo 实现 I 接口。
在 Foo 中必须包含 I 声明的所有成员的实现,即需要定义一个相同类型的 f,否则会由于没有实现接口而编译报错。
class Foo <: I {
public func f(): Unit {
println("Foo")
}
}
main() {
let a = Foo()
let b: I = a
b.f() // "Foo"
}
当某个类型实现了某个接口之后,该类型就会成为该接口的子类型。
对于上面的例子,Foo 是 I 的子类型,因此任何一个 Foo 类型的实例,都可以当作 I 类型的实例使用。
在 main 中将一个 Foo 类型的变量 a,赋值给一个 I 类型的变量 b。然后再调用 b 中的函数 f,就会打印出 Foo 实现的 f 版本。程序的输出结果为:
Foo
interface 也可以使用 sealed 修饰符表示只能在 interface 定义所在的包内继承、实现或扩展该 interface。sealed 已经蕴含了 public/open 的语义,因此定义 sealed interface 时若提供 public/open 修饰符,编译器将会告警。继承 sealed 接口的子接口或实现 sealed 接口的抽象类仍可被 sealed 修饰或不使用 sealed 修饰。若 sealed 接口的子接口被 public 修饰,且不被 sealed 修饰,则其子接口可在包外被继承、实现或扩展。继承、实现 sealed 接口的类型可以不被 public 修饰。
package A
public interface I1 {}
sealed interface I2 {} // OK
public sealed interface I3 {} // Warning, redundant modifier, 'sealed' implies 'public'
sealed open interface I4 {} // Warning, redundant modifier, 'sealed' implies 'open'
class C1 <: I1 {}
public open class C2 <: I1 {}
sealed abstract class C3 <: I2 {}
extend Int64 <: I2 {}
package B
import A.*
class S1 <: I1 {} // OK
class S2 <: I2 {} // Error, I2 is sealed interface, cannot be inherited here.
通过接口的这种约束能力,可以对一系列的类型约定共同的功能,达到对功能进行抽象的目的。
例如下面的代码,可以定义一个 Flyable 接口,并且让其他具有 Flyable 属性的类实现它。
interface Flyable {
func fly(): Unit
}
class Bird <: Flyable {
public func fly(): Unit {
println("Bird flying")
}
}
class Bat <: Flyable {
public func fly(): Unit {
println("Bat flying")
}
}
class Airplane <: Flyable {
public func fly(): Unit {
println("Airplane flying")
}
}
func fly(item: Flyable): Unit {
item.fly()
}
main() {
let bird = Bird()
let bat = Bat()
let airplane = Airplane()
fly(bird)
fly(bat)
fly(airplane)
}
编译并执行上面的代码,会看到如下输出:
Bird flying
Bat flying
Airplane flying
接口的成员可以是实例的或者静态的,以上的例子已经展示过实例成员函数的作用,接下来来看看静态成员函数的作用。
静态成员函数和实例成员函数类似,都要求实现类型提供实现。
例如下面的例子,定义了一个 NamedType 接口,这个接口含有一个静态成员函数 typename 用来获得每个类型的字符串名称。
这样其他类型在实现 NamedType 接口时就必须实现 typename 函数,之后就可以安全地在 NamedType 的子类型上获得类型的名称。
interface NamedType {
static func typename(): String
}
class A <: NamedType {
public static func typename(): String {
"A"
}
}
class B <: NamedType {
public static func typename(): String {
"B"
}
}
main() {
println("the type is ${ A.typename() }")
println("the type is ${ B.typename() }")
}
程序输出结果为:
the type is A
the type is B
接口中的静态成员函数(或属性)可以没有默认实现,也可以拥有默认实现。
当其没有默认实现时,将无法通过接口类型名对其进行访问。例如下面的代码,直接访问 NamedType 的 typename 函数会发生编译报错,因为 NamedType 不具有 typename 函数的实现。
interface NamedType {
static func typename(): String
}
main() {
NamedType.typename() // Error
}
接口中的静态成员函数(或属性)也可以拥有默认实现,当另一个类型继承拥有默认静态函数(或属性)实现的接口时,该类型可以不再实现这个静态成员函数(或属性),该函数(或属性)可以通过接口名和该类型名直接访问。如下用例,NamedType 的成员函数 typename 拥有默认实现,且在 A 中都可以不用再重新实现它,同时,也可以通过接口名和该类型名对其进行直接访问。
interface NamedType {
static func typename(): String {
"interface NamedType"
}
}
class A <: NamedType {}
main() {
println(NamedType.typename())
println(A.typename())
0
}
程序输出结果为:
interface NamedType
interface NamedType
通常会通过泛型约束,在泛型函数中使用这类静态成员。
例如下面的 printTypeName 函数,当约束泛型变元 T 是 NamedType 的子类型时,需要保证 T 的实例化类型中所有的静态成员函数(或属性)都必须拥有实现,以保证可以使用 T.typename 的方式访问泛型变元的实现,达到了对静态成员抽象的目的。详见泛型。
interface NamedType {
static func typename(): String
}
interface I <: NamedType {
static func typename(): String {
f()
}
static func f(): String
}
class A <: NamedType {
public static func typename(): String {
"A"
}
}
class B <: NamedType {
public static func typename(): String {
"B"
}
}
func printTypeName<T>() where T <: NamedType {
println("the type is ${ T.typename() }")
}
main() {
printTypeName<A>() // Ok
printTypeName<B>() // Ok
printTypeName<I>() // Error, 'I' must implement all static function. Otherwise, an unimplemented 'f' is called, causing problems.
}
接口中可以定义泛型实例成员函数或泛型静态成员函数,与非泛型函数一样具有 open 语义。
import std.collection.*
interface M {
func foo<T>(a: T): T
static func toString<T>(b: ArrayList<T>): String where T <: ToString
}
class C <: M {
public func foo<S>(a: S): S { // implements M::foo, names of generic parameters do not matter
a
}
public static func toString<T>(b: ArrayList<T>) where T <: ToString {
var res = ""
for (s in b) {
res += s.toString()
}
res
}
}
需要注意的是,接口的成员默认就被 public 修饰,不可以声明额外的访问控制修饰符,同时也要求实现类型必须使用 public 实现。
interface I {
func f(): Unit
}
open class C <: I {
protected func f() {} // Compiler Error, f needs to be public semantics
}
接口继承与接口实现
当想为一个类型实现多个接口,可以在声明处使用 & 分隔多个接口,实现的接口之间没有顺序要求。
例如下面的例子,可以让 MyInt 同时实现 Addable 和 Subtractable 两个接口。
interface Addable {
func add(other: Int64): Int64
}
interface Subtractable {
func sub(other: Int64): Int64
}
class MyInt <: Addable & Subtractable {
var value = 0
public func add(other: Int64): Int64 {
value + other
}
public func sub(other: Int64): Int64 {
value - other
}
}
接口可以继承一个或多个接口,但不能继承类。与此同时,接口继承的时候可以添加新的接口成员。
例如下面的例子,Calculable 接口继承了 Addable 和 Subtractable 两个接口,并且增加了乘除两种运算符重载。
interface Addable {
func add(other: Int64): Int64
}
interface Subtractable {
func sub(other: Int64): Int64
}
interface Calculable <: Addable & Subtractable {
func mul(other: Int64): Int64
func div(other: Int64): Int64
}
这样实现类型实现 Calculable 接口时就必须同时实现加减乘除四种运算符重载,不能缺少任何一个成员。
class MyInt <: Calculable {
var value = 0
public func add(other: Int64): Int64 {
value + other
}
public func sub(other: Int64): Int64 {
value - other
}
public func mul(other: Int64): Int64 {
value * other
}
public func div(other: Int64): Int64 {
value / other
}
}
MyInt 实现 Calculable 的同时,也同时实现了 Calculable 继承的所有接口,因此 MyInt 也实现了 Addable 和 Subtractable,即同时是它们的子类型。
main() {
let myInt = MyInt()
let add: Addable = myInt
let sub: Subtractable = myInt
let calc: Calculable = myInt
}
对于 interface 的继承,子接口如果继承了父接口中有默认实现的函数或属性,则在子接口中不允许仅写此函数或属性的声明(即没有默认实现),而是必须要给出新的默认实现,并且函数定义前的 override 修饰符(或 redef 修饰符)是可选的;子接口如果继承了父接口中没有默认实现的函数或属性,则在子接口中允许仅写此函数或属性的声明(当然也允许定义默认实现),并且函数声明或定义前的 override 修饰符(或 redef 修饰符)是可选的。
interface I1 {
func f(a: Int64) {
a
}
static func g(a: Int64) {
a
}
func f1(a: Int64): Unit
static func g1(a: Int64): Unit
}
interface I2 <: I1 {
/*'override' is optional*/ func f(a: Int64) {
a + 1
}
override func f(a: Int32) {} // Error, override function 'f' does not have an overridden function from its supertypes
static /*'redef' is optional*/ func g(a: Int64) {
a + 1
}
/*'override' is optional*/ func f1(a: Int64): Unit {}
static /*'redef' is optional*/ func g1(a: Int64): Unit {}
}
接口实现的要求
仓颉除 Tuple、VArray 和函数外的其他类型都可以实现接口。
一个类型实现接口有三种途径:
- 在定义类型时就声明实现接口,在以上的内容中已经见过相关例子。
- 通过扩展实现接口,这种方式详见扩展。
- 由语言内置实现,具体详见《仓颉编程语言库 API》相关文档。
实现类型声明实现接口时,需要实现接口中要求的所有成员,为此需要满足下面一些规则。
- 对于成员函数和操作符重载函数,要求实现类型提供的函数实现与接口对应的函数名称相同、参数列表相同、返回类型相同。
- 对于成员属性,要求是否被
mut修饰保持一致,并且属性的类型相同。
所以大部分情况都如同上面的例子,需要让实现类型中包含与接口要求的一样的成员的实现。
但有个地方是个例外,如果接口中的成员函数或操作符重载函数的返回值类型是 class 类型,那么允许实现函数的返回类型是其子类型。
例如下面这个例子,I 中的 f 返回类型是一个 class 类型 Base,因此 C 中实现的 f 返回类型可以是 Base 的子类型 Sub。
open class Base {}
class Sub <: Base {}
interface I {
func f(): Base
}
class C <: I {
public func f(): Sub {
Sub()
}
}
除此以外,接口的成员还可以提供默认实现。例如下面的代码中,SayHi 中的 say 拥有默认实现,因此 A 实现 SayHi 时可以继承 say 的实现,而 B 也可以选择提供自己的 say 实现。
interface SayHi {
func say() {
"hi"
}
}
class A <: SayHi {}
class B <: SayHi {
public func say() {
"hi, B"
}
}
特别地,如果一个类型在实现多个接口时,多个接口中包含同一个成员的默认实现,这时会发生多重继承的冲突,语言无法选择最适合的实现,因此这时接口中的默认实现也会失效,需要实现类型提供自己的实现。
例如下面的例子,SayHi 和 SayHello 中都包含了 say 的实现,Foo 在实现这两个接口时就必须提供自己的实现,否则会出现编译错误。
interface SayHi {
func say() {
"hi"
}
}
interface SayHello {
func say() {
"hello"
}
}
class Foo <: SayHi & SayHello {
public func say() {
"Foo"
}
}
struct、enum 和 class 在实现接口时,函数或属性定义前的 override 修饰符(或 redef 修饰符)是可选的,无论接口中的函数或属性是否存在默认实现。
interface I {
func foo(): Int64 {
return 0
}
}
enum E <: I{
elem
public override func foo(): Int64 {
return 1
}
}
struct S <: I {
public override func foo(): Int64 {
return 1
}
}
Any 类型
Any 类型是一个内置的接口,它的定义如下:
interface Any {}
仓颉中所有接口都默认继承它,所有非接口类型都默认实现它,因此所有类型都可以作为 Any 类型的子类型使用。
如下面的代码,可以将一系列不同类型的变量赋值给 Any 类型的变量。
main() {
var any: Any = 1
any = 2.0
any = "hello, world!"
}
属性
属性(Properties)提供了一个 getter 和一个可选的 setter 来间接获取和设置值。
使用属性的时候与普通变量无异,只需要对数据操作,对内部的实现无感知,可以更便利地实现访问控制、数据监控、跟踪调试、数据绑定等机制。
属性在使用时可以作为表达式或被赋值。此处以类和接口为例进行说明,但属性不仅限于类和接口。
以下是一个简单的例子,b 是一个典型的属性,封装了外部对 a 的访问:
class Foo {
private var a = 0
public mut prop b: Int64 {
get() {
println("get")
a
}
set(value) {
println("set")
a = value
}
}
}
main() {
var x = Foo()
let y = x.b + 1 // get
x.b = y // set
}
此处 Foo 提供了一个名为 b 的属性,针对 getter/setter 这两个功能,仓颉提供了 get 和 set 两种语法来定义。当一个类型为 Foo 的变量 x 在访问 b 时,会调用 b 的 get 操作返回类型为 Int64 的值,因此可以用来与 1 相加;而当 x 在对 b 进行赋值时,会调用 b 的 set 操作,将 y 的值传给 set 的 value,最终将 value 的值赋值给 a。
通过属性 b,外部对 Foo 的成员变量 a 完全不感知,但却可以通过 b 做到同样地访问和修改操作,实现了有效的封装性。所以程序的输出如下:
get
set
属性定义
属性可以在 interface、class、struct、enum、extend 中定义。
一个典型的属性语法结构如下:
class Foo {
public prop a: Int64 {
get() { 0 }
}
public mut prop b: Int64 {
get() { 0 }
set(v) {}
}
}
其中使用 prop 声明的 a 和 b 都是属性,a 和 b 的类型都是 Int64。a 是无 mut 修饰符的属性,这类属性有且仅有定义 getter(对应取值)实现。b 是使用 mut 修饰的属性,这类属性必须分别定义 getter(对应取值)和 setter(对应赋值)的实现。
注意:
对于数值、元组、函数、
Bool、Unit、Nothing、String、Range和enum类型,在它们的扩展和声明中不能声明 mut 修饰的属性,也不能实现有 mut 属性的接口。
属性的 getter 和 setter 分别对应两个不同的函数。
- getter 函数类型是
() -> T,T 是该属性的类型,当使用该属性作为表达式时会执行 getter 函数。 - setter 函数类型是
(T) -> Unit,T 是该属性的类型,形参名需要显式指定,当对该属性赋值时会执行 setter 函数。
getter 和 setter 的实现中可以和函数体一样包含声明和表达式,与函数体的规则一样,详见函数体章节。
setter 中的参数对应的是赋值时传入的值。
class Foo {
private var j = 0
public mut prop i: Int64 {
get() {
j
}
set(v) {
j = v
}
}
}
需要注意的是,在属性的 getter 和 setter 中访问属性自身属于递归调用,与函数调用一样可能会出现死循环的情况。
修饰符
可以在 prop 前面声明需要的修饰符。
class Foo {
public prop a: Int64 {
get() {
0
}
}
private prop b: Int64 {
get() {
0
}
}
}
和成员函数一样,成员属性也支持 open、override、redef 修饰,所以也可以在子类型中覆盖/重定义父类型属性的实现。
子类型覆盖父类型的属性时,如果父类型属性带有 mut 修饰符,则子类型属性也需要带有 mut 修饰符,同时也必须保持一样的类型。
如下代码所示,A 中定义了 x 和 y 两个属性,B 中可以分别对 x 和 y 进行 override/redef:
open class A {
private var valueX = 0
private static var valueY = 0
public open prop x: Int64 {
get() { valueX }
}
public static mut prop y: Int64 {
get() { valueY }
set(v) {
valueY = v
}
}
}
class B <: A {
private var valueX2 = 0
private static var valueY2 = 0
public override prop x: Int64 {
get() { valueX2 }
}
public redef static mut prop y: Int64 {
get() { valueY2 }
set(v) {
valueY2 = v
}
}
}
抽象属性
类似于抽象函数,在 interface 和抽象类中也可以声明抽象属性,这些抽象属性没有实现。
interface I {
prop a: Int64
}
abstract class C {
public prop a: Int64
}
当实现类型实现 interface 或者非抽象子类继承抽象类时,必须要实现这些抽象属性。
与覆盖的规则一样,实现类型或子类在实现这些属性时,如果父类型属性带有 mut 修饰符,则子类型属性也需要带有 mut 修饰符,同时也必须保持一样的类型。
interface I {
prop a: Int64
mut prop b: Int64
}
class C <: I {
private var value = 0
public prop a: Int64 {
get() { value }
}
public mut prop b: Int64 {
get() { value }
set(v) {
value = v
}
}
}
通过抽象属性,可以让接口和抽象类对一些数据操作能以更加易用的方式进行约定,相比函数的方式要更加直观。
如下代码所示,如果要对一个 size 值的获取和设置进行约定,使用属性的方式 (I1) 相比使用函数的方式 (I2) 代码更少,也更加符合对数据操作的意图。
interface I1 {
mut prop size: Int64
}
interface I2 {
func getSize(): Int64
func setSize(value: Int64): Unit
}
class C <: I1 & I2 {
private var mySize = 0
public mut prop size: Int64 {
get() {
mySize
}
set(value) {
mySize = value
}
}
public func getSize() {
mySize
}
public func setSize(value: Int64) {
mySize = value
}
}
main() {
let a: I1 = C()
a.size = 5
println(a.size)
let b: I2 = C()
b.setSize(5)
println(b.getSize())
}
5
5
属性使用
属性分为实例成员属性和静态成员属性。成员属性的使用和成员变量的使用方式一样,详见成员变量章节。
class A {
public prop x: Int64 {
get() {
123
}
}
public static prop y: Int64 {
get() {
321
}
}
}
main() {
var a = A()
println(a.x) // 123
println(A.y) // 321
}
结果为:
123
321
无 mut 修饰符的属性类似 let 声明的变量,不能被赋值。
class A {
private let value = 0
public prop i: Int64 {
get() {
value
}
}
}
main() {
var x = A()
println(x.i) // OK
x.i = 1 // Error
}
带有 mut 修饰符的属性类似 var 声明的变量,可以取值也可以被赋值。
class A {
private var value: Int64 = 0
public mut prop i: Int64 {
get() {
value
}
set(v) {
value = v
}
}
}
main() {
var x = A()
println(x.i) // OK
x.i = 1 // OK
}
0
子类型关系
与其他面向对象语言一样,仓颉语言提供子类型关系和子类型多态。举例说明(不限于下述用例):
- 假设函数的形参是类型
T,则函数调用时传入的参数的实际类型既可以是T也可以是T的子类型(严格地说,T的子类型已经包括T自身,下同)。 - 假设赋值表达式
=左侧的变量的类型是T,则=右侧的表达式的实际类型既可以是T也可以是T的子类型。 - 假设函数定义中用户标注的返回类型是
T,则函数体的类型(以及函数体内所有return表达式的类型)既可以是T也可以是T的子类型。
下文将说明两个类型为子类型关系的几种情况。
继承 class 带来的子类型关系
继承 class 后,子类即为父类的子类型。如下代码中, Sub 即为 Super 的子类型。
open class Super { }
class Sub <: Super { }
实现接口带来的子类型关系
实现接口(含扩展实现)后,实现接口的类型即为接口的子类型。如下代码中,I3 是 I1 和 I2 的子类型, C 是 I1 的子类型, Int64 是 I2 的子类型:
interface I1 { }
interface I2 { }
interface I3 <: I1 & I2 { }
class C <: I1 { }
extend Int64 <: I2 { }
元组类型的子类型关系
仓颉语言中的元组类型也有子类型关系。直观的,如果一个元组 t1 的每个元素的类型都是另一个元组 t2 的对应位置元素类型的子类型,那么元组 t1 的类型也是元组 t2 的类型的子类型。例如下面的代码中,由于 C2 <: C1 和 C4 <: C3,因此也有 (C2, C4) <: (C1, C3) 以及 (C4, C2) <: (C3, C1)。
open class C1 { }
class C2 <: C1 { }
open class C3 { }
class C4 <: C3 { }
let t1: (C1, C3) = (C2(), C4()) // OK
let t2: (C3, C1) = (C4(), C2()) // OK
函数类型的子类型关系
仓颉语言中,函数是一等公民,而函数类型亦有子类型关系:给定两个函数类型 (U1) -> S2 和 (U2) -> S1,如果存在 (U1) -> S2 是 (U2) -> S1的子类型,当且仅当 U2 是 U1 的子类型,且 S2 是 S1 的子类型(注意顺序)。例如下面的代码定义了两个函数 f : (U1) -> S2 和 g : (U2) -> S1,且 f 的类型是 g 的类型的子类型。由于 f 的类型是 g 的子类型,所以代码中使用到 g 的地方都可以换为 f。
open class U1 { }
class U2 <: U1 { }
open class S1 { }
class S2 <: S1 { }
func f(a: U1): S2 { S2() }
func g(a: U2): S1 { S1() }
func call1() {
g(U2()) // Ok.
f(U2()) // Ok.
}
func h(lam: (U2) -> S1): S1 {
lam(U2())
}
func call2() {
h(g) // Ok.
h(f) // Ok.
}
对于上面的规则,S2 <: S1 部分很好理解:函数调用产生的结果数据会被后续程序使用,函数 g 可以产生 S1 类型的结果数据,函数 f 可以产生 S2 类型的结果,而 g 产生的结果数据应当能被 f 产生的结果数据替代,因此要求 S2 <: S1。
对于 U2 <: U1 的部分,可以这样理解:在函数调用产生结果前,它本身应当能够被调用,函数调用的实参类型固定不变,同时形参类型要求更宽松时,依然可以被调用,而形参类型要求更严格时可能无法被调用——例如给定上述代码中的定义 g(U2()) 可以被换为 f(U2()),正是因为实参类型 U2 的要求更严格于形参类型 U1。
永远成立的子类型关系
仓颉语言中,有些预设的子类型关系是永远成立的:
- 一个类型
T永远是自身的子类型,即T <: T。 Nothing类型永远是其他任意类型T的子类型,即Nothing <: T。- 任意类型
T都是Any类型的子类型,即T <: Any。 - 任意
class定义的类型都是Object的子类型,即如果有class C {},则C <: Object。
传递性带来的子类型关系
子类型关系具有传递性。如下代码中,虽然只描述了 I2 <: I1、C <: I2 以及 Bool <: I2,但根据子类型的传递性,也隐式存在 C <: I1 以及 Bool <: I1 这两个子类型关系。
interface I1 { }
interface I2 <: I1 { }
class C <: I2 { }
extend Bool <: I2 { }
泛型类型的子类型关系
泛型类型间也有子类型关系,详见泛型类型的子类型关系。
类型转换
仓颉不支持不同类型之间的隐式转换(子类型天然是父类型,所以子类型到父类型的转换不是隐式类型转换),类型转换必须显式地进行。下面将依次介绍数值类型之间的转换,Rune 到 UInt32 和整数类型到 Rune 的转换,以及 is 和 as 操作符。
数值类型之间的转换
对于数值类型(包括:Int8,Int16,Int32,Int64,IntNative,UInt8,UInt16,UInt32,UInt64,UIntNative,Float16,Float32,Float64),仓颉支持使用 T(e) 的方式得到一个值等于 e,类型为 T 的值。其中,表达式 e 的类型和 T 可以是上述任意数值类型。
下面的例子展示了数值类型之间的类型转换:
main() {
let a: Int8 = 10
let b: Int16 = 20
let r1 = Int16(a)
println("The type of r1 is 'Int16', and r1 = ${r1}")
let r2 = Int8(b)
println("The type of r2 is 'Int8', and r2 = ${r2}")
let c: Float32 = 1.0
let d: Float64 = 1.123456789
let r3 = Float64(c)
println("The type of r3 is 'Float64', and r3 = ${r3}")
let r4 = Float32(d)
println("The type of r4 is 'Float32', and r4 = ${r4}")
let e: Int64 = 1024
let f: Float64 = 1024.1024
let r5 = Float64(e)
println("The type of r5 is 'Float64', and r5 = ${r5}")
let r6 = Int64(f)
println("The type of r6 is 'Int64', and r6 = ${r6}")
}
上述代码的执行结果为:
The type of r1 is 'Int16', and r1 = 10
The type of r2 is 'Int8', and r2 = 20
The type of r3 is 'Float64', and r3 = 1.000000
The type of r4 is 'Float32', and r4 = 1.123457
The type of r5 is 'Float64', and r5 = 1024.000000
The type of r6 is 'Int64', and r6 = 1024
注意:
类型转换时可能发生溢出,若溢出可提前在编译器检测出来,则编译器会直接给出报错,否则根据默认的溢出策略将抛出异常。
Rune 到 UInt32 和整数类型到 Rune 的转换
Rune 到 UInt32 的转换使用 UInt32(e) 的方式,其中 e 是一个 Rune 类型的表达式,UInt32(e) 的结果是 e 的 Unicode scalar value 对应的 UInt32 类型的整数值。
整数类型到 Rune 的转换使用 Rune(num) 的方式,其中 num 的类型可以是任意的整数类型,且仅当 num 的值落在 [0x0000, 0xD7FF] 或 [0xE000, 0x10FFFF] (即 Unicode scalar value)中时,返回对应的 Unicode scalar value 表示的字符,否则,编译报错(编译时可确定 num 的值)或运行时抛异常。
下面的例子展示了 Rune 和 UInt32 之间的类型转换:
main() {
let x: Rune = 'a'
let y: UInt32 = 65
let r1 = UInt32(x)
let r2 = Rune(y)
println("The type of r1 is 'UInt32', and r1 = ${r1}")
println("The type of r2 is 'Rune', and r2 = ${r2}")
}
上述代码的执行结果为:
The type of r1 is 'UInt32', and r1 = 97
The type of r2 is 'Rune', and r2 = A
is 和 as 操作符
仓颉支持使用 is 操作符来判断某个表达式的类型是否是指定的类型(或其子类型)。具体而言,对于表达式 e is T(e 可以是任意表达式,T 可以是任何类型),当 e 的运行时类型是 T 的子类型时,e is T 的值为 true,否则 e is T 的值为 false。
下面的例子展示了 is 操作符的使用:
open class Base {
var name: String = "Alice"
}
class Derived <: Base {
var age: UInt8 = 18
}
main() {
let a = 1 is Int64
println("Is the type of 1 'Int64'? ${a}")
let b = 1 is String
println("Is the type of 1 'String'? ${b}")
let b1: Base = Base()
let b2: Base = Derived()
var x = b1 is Base
println("Is the type of b1 'Base'? ${x}")
x = b1 is Derived
println("Is the type of b1 'Derived'? ${x}")
x = b2 is Base
println("Is the type of b2 'Base'? ${x}")
x = b2 is Derived
println("Is the type of b2 'Derived'? ${x}")
}
上述代码的执行结果为:
Is the type of 1 'Int64'? true
Is the type of 1 'String'? false
Is the type of b1 'Base'? true
Is the type of b1 'Derived'? false
Is the type of b2 'Base'? true
Is the type of b2 'Derived'? true
as 操作符可以用于将某个表达式的类型转换为指定的类型。因为类型转换有可能会失败,所以 as 操作返回的是一个 Option 类型。具体而言,对于表达式 e as T(e 可以是任意表达式,T 可以是任何类型),当 e 的运行时类型是 T 的子类型时,e as T 的值为 Option<T>.Some(e),否则 e as T 的值为 Option<T>.None。
下面的例子展示了 as 操作符的使用(注释中标明了 as 操作的结果):
open class Base {
var name: String = "Alice"
}
class Derived <: Base {
var age: UInt8 = 18
}
let a = 1 as Int64 // a = Option<Int64>.Some(1)
let b = 1 as String // b = Option<String>.None
let b1: Base = Base()
let b2: Base = Derived()
let d: Derived = Derived()
let r1 = b1 as Base // r1 = Option<Base>.Some(b1)
let r2 = b1 as Derived // r2 = Option<Derived>.None
let r3 = b2 as Base // r3 = Option<Base>.Some(b2)
let r4 = b2 as Derived // r4 = Option<Derived>.Some(b2)
let r5 = d as Base // r5 = Option<Base>.Some(d)
let r6 = d as Derived // r6 = Option<Derived>.Some(d)
泛型概述
在仓颉编程语言中,泛型指的是参数化类型,参数化类型是一个在声明时未知并且需要在使用时指定的类型。类型声明与函数声明可以是泛型的。最为常见的例子就是 Array<T>、Set<T> 等容器类型。
在仓颉中,function、class、interface、struct 与 enum 的声明都可以声明类型形参,也就是说它们都可以是泛型的。
为了方便讨论,定义如下几个常用的术语:
- 类型形参:一个类型或者函数声明可能有一个或者多个需要在使用处被指定的类型,这些类型就被称为类型形参。在声明形参时,需要给定一个标识符,以便在声明体中引用。
- 类型变元:在声明类型形参后,当通过标识符来引用这些类型时,这些标识符被称为类型变元。
- 类型实参:当在使用泛型声明的类型或函数时指定了泛型参数,这些参数被称为类型实参。
- 类型构造器:一个需要零个、一个或者多个类型作为实参的类型称为类型构造器。
类型形参在声明时一般在类型名称的声明或者函数名称的声明后,使用尖括号 <...> 括起来。例如一个泛型的列表可声明为:
class List<T> {
var elem: Option<T> = None
var tail: Option<List<T>> = None
}
func sumInt(a: List<Int64>) { }
其中 List<T> 中的 T 被称为类型形参。对于 elem: Option<T> 中对 T 的引用称为类型变元,同理 tail: Option<List<T>> 中的 T 也称为类型变元。函数 sumInt 的参数中 List<Int64> 的 Int64 被称为 List 的类型实参。 List 就是类型构造器,List<Int64> 通过 Int64 类型实参构造出了一个类型 Int64 的列表类型。
泛型函数
如果一个函数声明了一个或多个类型形参,则将其称为泛型函数。语法上,类型形参紧跟在函数名后,并用 <> 括起,如果有多个类型形参,则用 , 分离。
全局泛型函数
在声明全局泛型函数时,只需要在函数名后使用尖括号声明类型形参,然后就可以在函数形参、返回类型及函数体中对这一类型形参进行引用。例如 id 函数定义为:
func id<T>(a: T): T {
return a
}
其中 (a: T) 是函数声明的形参,其中使用到了 id 函数声明的类型形参 T,并且在 id 函数的返回类型使用。
再比如另一个复杂的例子,定义如下一个泛型函数 composition,该函数声明了 3 个类型形参,分别是 T1, T2, T3,其功能是把两个函数 f: (T1) -> T2, g: (T2) -> T3 复合成类型为 (T1) -> T3 的函数。
func composition<T1, T2, T3>(f: (T1) -> T2, g: (T2) -> T3): (T1) -> T3 {
return {x: T1 => g(f(x))}
}
因为可以被用来复合的函数是任意类型,例如可以是 (Int32) -> Bool, (Bool) -> Int64 的复合,也可以是 (Int64) -> Rune, (Rune) -> Int8 的复合,所以才需要使用泛型函数。
func times2(a: Int64): Int64 {
return a * 2
}
func plus10(a: Int64): Int64 {
return a + 10
}
func times2plus10(a: Int64) {
return composition<Int64, Int64, Int64>(times2, plus10)(a)
}
main() {
println(times2plus10(9))
return 0
}
这里,复合两个 (Int64) -> Int64 的函数,将 9 先乘以 2,再加 10,结果会是 28。
28
局部泛型函数
局部函数也可以是泛型函数。例如泛型函数 id 可以嵌套定义在其他函数中:
func foo(a: Int64) {
func id<T>(a: T): T { a }
func double(a: Int64): Int64 { a + a }
return (id<Int64> ~> double)(a) == (double ~> id<Int64>)(a)
}
main() {
println(foo(1))
return 0
}
这里由于 id 的单位元性质,函数 id<Int64> ~> double 和 double ~> id<Int64> 是等价的,结果是 true。
true
泛型成员函数
class、struct、enum 与 interface 的成员函数可以是泛型的。例如:
class A {
func foo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
struct B {
func bar<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
enum C {
| X | Y
func coo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
interface I {
func doo<T>(a: T): Unit where T <: ToString
}
class D <: I {
public func doo<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
abstract class E {
public func eoo1<T>(a: T): Unit where T <: ToString
public open func eoo2<T>(a: T): Unit where T <: ToString
}
class F <: E {
public func eoo1<T>(a: T): Unit where T <: ToString {
println("${a}")
}
public func eoo2<T>(a: T): Unit where T <: ToString {
println("${a}")
}
}
main() {
var a = A()
var b = B()
var c = C.X
var d = D()
var f = F()
a.foo<Int64>(10)
b.bar<String>("abc")
c.coo<Bool>(false)
d.doo<String>("doo")
f.eoo1<String>("eoo1")
f.eoo2<String>("eoo2")
return 0
}
程序输出的结果为:
10
abc
false
doo
eoo1
eoo2
在为类型使用 extend 声明进行扩展时,扩展中的函数也可以是泛型的,例如可以为 Int64 类型增加一个泛型成员函数:
extend Int64 {
func printIntAndArg<T>(a: T) where T <: ToString {
println(this)
println("${a}")
}
}
main() {
var a: Int64 = 12
a.printIntAndArg<String>("twelve")
}
程序输出的结果将为:
12
twelve
静态泛型函数
interface、class、struct、enum 与 extend 中可以定义静态泛型函数,例如下例 ToPair class 中从 ArrayList 中返回一个元组:
import std.collection.*
class ToPair {
public static func fromArray<T>(l: ArrayList<T>): (T, T) {
return (l[0], l[1])
}
}
main() {
var res: ArrayList<Int64> = ArrayList([1,2,3,4])
var a: (Int64, Int64) = ToPair.fromArray<Int64>(res)
return 0
}
泛型接口
泛型可以用来定义泛型接口,以标准库中定义的 Iterable 为例,它的成员函数 iterator 需要返回一个 Iterator 类型,这一类型是一个容器的遍历器。 Iterator 是一个泛型接口,Iterator 内部有一个从容器类型中返回下一个元素的 next 成员函数,next 成员函数返回的类型是一个需要在使用时指定的类型,所以 Iterator 需要声明泛型参数。
public interface Iterable<E> {
func iterator(): Iterator<E>
}
public interface Iterator<E> <: Iterable<E> {
func next(): Option<E>
}
public interface Collection<T> <: Iterable<T> {
prop size: Int64
func isEmpty(): Bool
}
泛型类
泛型接口中介绍了泛型接口的定义和使用,本节介绍泛型类的定义和使用。如 Map 的键值对就是使用泛型类来定义的。
Map 类型中的键值对 Node 类型就可以使用泛型类来定义:
public open class Node<K, V> where K <: Hashable & Equatable<K> {
public var key: Option<K> = Option<K>.None
public var value: Option<V> = Option<V>.None
public init() {}
public init(key: K, value: V) {
this.key = Option<K>.Some(key)
this.value = Option<V>.Some(value)
}
}
由于键与值的类型有可能不相同,且可以为任意满足条件的类型,所以 Node 需要两个类型形参 K 与 V ,K <: Hashable, K <: Equatable<K> 是对于键类型的约束,意为 K 要实现 Hashable 与 Equatable<K> 接口,也就是 K 需要满足的条件。对于泛型约束,详见泛型约束章节。
由于泛型类的静态成员变量的内存是共享的,因此,静态成员变量或属性的类型声明和表达式中不能引用类型参数或包含未实例化泛型类型表达式。另外,静态变量或属性初始化表达式中不能调用泛型类的静态成员函数或属性。
class A<T> {}
class B<T> {
static func foo() {1}
static var err1: A<T> = A<T>() // Error, static member cannot depend on generic parameter 'Generics-T'
static prop err2: A<T> { // Error, static member cannot depend on generic parameter 'Generics-T'
get() {
A<T>() // Error, static member cannot depend on generic parameter 'Generics-T'
}
}
static var vfoo = foo() // Error, it's equal to 'static var vfoo = B<T>.foo()', implicit reference to generic 'T'.
static var ok: Int64 = 1
}
main() {
B<Int32>.ok = 2
println(B<Int64>.ok) // 2
}
泛型结构体
struct 类型的泛型与 class 是类似的,下面可以使用 struct 定义一个类似于二元元组的类型:
struct Pair<T, U> {
let x: T
let y: U
public init(a: T, b: U) {
x = a
y = b
}
public func first(): T {
return x
}
public func second(): U {
return y
}
}
main() {
var a: Pair<String, Int64> = Pair<String, Int64>("hello", 0)
println(a.first())
println(a.second())
}
程序输出的结果为:
hello
0
在 Pair 中提供了 first 与 second 两个函数来取得元组的第一个与第二个元素。
泛型枚举
在仓颉编程语言的泛型 enum 类型设计中,Option 类型是一个典型的示例,关于 Option 详细描述请参见 Option 类型章节。 Option 类型用于表示在某一类型上的值可能是个空的值。这样,Option 就可以用来表示在某种类型上计算的失败。这里是何种类型上的失败是不确定的,所以很明显,Option 是一个泛型类型,需要声明类型形参。
package std.core // `Option` is defined in std.core.
public enum Option<T> {
Some(T)
| None
public func getOrThrow(): T {
match (this) {
case Some(v) => v
case None => throw NoneValueException()
}
}
...
}
可以看到,Option<T> 分成两种情况,一种是 Some(T),用来表示一个有值的返回结果,另一种是 None 用来表示一个空的结果。其中的 getOrThrow 函数会是将 Some(T) 内部的值返回出来的函数,返回的结果就是 T 类型,而如果参数是 None,那么直接抛出异常。
例如:如果想定义一个安全的除法,因为在除法上的计算是可能失败的。如果除数为 0,那么返回 None ,否则返回一个用 Some 包装过的结果:
func safeDiv(a: Int64, b: Int64): Option<Int64> {
var res: Option<Int64> = match (b) {
case 0 => None
case _ => Some(a/b)
}
return res
}
这样,在除数为 0 时,程序运行的过程中不会因除以 0 而抛出算术运算异常。
泛型类型的子类型关系
实例化后的泛型类型间也有子类型关系。例如:
interface I<X, Y> { }
class C<Z> <: I<Z, Z> { }
根据 class C<Z> <: I<Z, Z> { },便知 C<Bool> <: I<Bool, Bool> 以及 C<D> <: I<D, D> 等。可以解读为“于所有的(不含类型变元的) Z 类型,都有 C<Z> <: I<Z, Z> 成立”。
但是对于下列代码:
open class C { }
class D <: C { }
interface I<X> { }
I<D> <: I<C> 是不成立的(即使 D <: C 成立),这是因为在仓颉语言中,用户定义的类型构造器在其类型参数处是不型变的。
型变的具体定义为:如果 A 和 B 是(实例化后的)类型,T 是类型构造器,设有一个类型参数 X(例如 interface T<X>),那么
- 如果
T(A) <: T(B)当且仅当A = B,则T是不型变的。 - 如果
T(A) <: T(B)当且仅当A <: B,则T在X处是协变的。 - 如果
T(A) <: T(B)当且仅当B <: A,则T在X处是逆变的。
因为现阶段的仓颉中,所有用户自定义的泛型类型在其所有的类型变元处都是不变的,所以给定 interface I<X> 和类型 A、B,只有 A = B,才能得到 I<A> <: I<B>;反过来,如果知道了 I<A> <: I<B>,也可推出 A = B(内建类型除外:内建的元组类型对其每个元素类型来说,都是协变的;内建的函数类型在其入参类型处是逆变的,在其返回类型处是协变的。)
注意:
class以外的类型实现接口,该类型和该接口之间的子类型关系不能作为协变和逆变的依据。
不型变限制了一些语言的表达能力,但也避免了一些安全问题,例如“协变数组运行时抛异常”的问题。
类型别名
当某个类型的名字比较复杂或者在特定场景中不够直观时,可以选择使用类型别名的方式为此类型设置一个别名。
type I64 = Int64
类型别名的定义以关键字 type 开头,接着是类型的别名(如上例中的 I64),然后是等号 =,最后是原类型(即被取别名的类型,如上例中的 Int64)。
只能在源文件顶层定义类型别名,并且原类型必须在别名定义处可见。例如,下例中 Int64 的别名定义在 main 中将报错,LongNameClassB 类型在为其定义别名时不可见,同样报错。
main() {
type I64 = Int64 // Error, type aliases can only be defined at the top level of the source file
}
class LongNameClassA { }
type B = LongNameClassB // Error, type 'LongNameClassB' is not defined
一个(或多个)类型别名定义中禁止出现(直接或间接的)循环引用。
type A = (Int64, A) // Error, 'A' refered itself
type B = (Int64, C) // Error, 'B' and 'C' are circularly refered
type C = (B, Int64)
类型别名并不会定义一个新的类型,它仅仅是为原类型定义了另外一个名字,它有如下几种使用场景:
-
作为类型使用,例如:
type A = B class B {} var a: A = B() // Use typealias A as type B -
当类型别名实际指向的类型为 class、struct 时,可以作为构造器名称使用:
type A = B class B {} func foo() { A() } // Use type alias A as constructor of B -
当类型别名实际指向的类型为 class、interface、struct 时,可以作为访问内部静态成员变量或函数的类型名:
type A = B class B { static var b : Int32 = 0; static func foo() {} } func foo() { A.foo() // Use A to access static method in class B A.b } -
当类型别名实际指向的类型为 enum 时,可以作为 enum 声明的构造器的类型名:
enum TimeUnit { Day | Month | Year } type Time = TimeUnit var a = Time.Day var b = Time.Month // Use type alias Time to access constructors in TimeUnit
需要注意的是,当前用户自定义的类型别名暂不支持在类型转换表达式中使用,参考如下示例:
type MyInt = Int32
MyInt(0) // Error, no matching function for operator '()' function call
泛型别名
类型别名也是可以声明类型形参的,但是不能对其形参使用 where 声明约束,对于泛型变元的约束会在后面给出解释。
当一个泛型类型的名称过长时,可以使用类型别名来为其声明一个更短的别名。例如,有一个类型为 RecordData ,可以把他用类型别名简写为 RD :
struct RecordData<T> {
var a: T
public init(x: T){
a = x
}
}
type RD<T> = RecordData<T>
main(): Int64 {
var struct1: RD<Int32> = RecordData<Int32>(2)
return 1
}
在使用时就可以用 RD<Int32> 来代指 RecordData<Int32> 类型。
泛型约束
泛型约束的作用是在 function、class、interface、struct、enum 声明时明确泛型形参所具备的操作与能力。只有声明了这些约束才能调用相应的成员函数。在很多场景下泛型形参是需要加以约束的。以 id 函数为例:
func id<T>(a: T) {
return a
}
开发者唯一能做的事情就是将函数形参 a 这个值返回,而不能进行 a + 1,println("${a}") 等操作,因为它可能是一个任意的类型,比如 (Bool) -> Bool,这样就无法与整数相加,同样因为是函数类型,也不能通过 println 函数来输出在命令行上。而如果这一泛型形参上有了约束,那么就可以做更多操作了。
约束大致分为接口约束与 class 类型约束。语法为在函数、类型的声明体之前使用 where 关键字来声明,对于声明的泛型形参 T1, T2,可以使用 where T1 <: Interface, T2 <: Class 这样的方式来声明泛型约束,同一个类型变元的多个约束可以使用 & 连接。例如:where T1 <: Interface1 & Interface2。
仓颉中的 println 函数能接受类型为字符串的参数。如果需要把一个泛型类型的变量转为字符串后打印在命令行上,可以对这个泛型类型变元加以约束,这个约束是 core 中定义的 ToString 接口,显然它是一个接口约束:
package std.core // `ToString` is defined in core.
public interface ToString {
func toString(): String
}
这样就可以利用这个约束,定义一个名为 genericPrint 的函数:
func genericPrint<T>(a: T) where T <: ToString {
println(a)
}
main() {
genericPrint<Int64>(10)
return 0
}
结果为:
10
如果 genericPrint 函数的类型实参没有实现 ToString 接口,那么编译器会报错。例如传入一个函数做为参数时:
func genericPrint<T>(a: T) where T <: ToString {
println(a)
}
main() {
genericPrint<(Int64) -> Int64>({ i => 0 })
return 0
}
如果对上面的文件进行编译,那么编译器会抛出泛型类型参数不满足约束的错误。因为 genericPrint 函数的泛型的类型实参不满足约束 (Int64) -> Int64 <: ToString。
除了上述通过接口来表示约束,还可以使用 class 类型来约束一个泛型类型变元。例如:当要声明一个动物园类型 Zoo<T>,但是需要这里声明的类型形参 T 受到约束,这个约束就是 T 需要是动物类型 Animal 的子类型, Animal 类型中声明了 run 成员函数。这里声明两个子类型 Dog 与 Fox 都实现了 run 成员函数,这样在 Zoo<T> 的类型中,就可以对于 animals 数组列表中存放的动物实例调用 run 成员函数:
import std.collection.*
abstract class Animal {
public func run(): String
}
class Dog <: Animal {
public func run(): String {
return "dog run"
}
}
class Fox <: Animal {
public func run(): String {
return "fox run"
}
}
class Zoo<T> where T <: Animal {
var animals: ArrayList<Animal> = ArrayList<Animal>()
public func addAnimal(a: T) {
animals.add(a)
}
public func allAnimalRuns() {
for(a in animals) {
println(a.run())
}
}
}
main() {
var zoo: Zoo<Animal> = Zoo<Animal>()
zoo.addAnimal(Dog())
zoo.addAnimal(Fox())
zoo.allAnimalRuns()
return 0
}
程序的输出为:
dog run
fox run
注意:
泛型变元的约束只能是具体的 class 类型或 interface,且变元如果存在多个 class 类型的上界时,它们必须在同一继承链路上。
扩展概述
扩展可以为在当前 package 中可见的类型(除函数、元组、接口)添加新功能。
当不能破坏被扩展类型的封装性,但希望添加额外的功能时,可以使用扩展。
可以添加的功能包括:
- 添加成员函数
- 添加操作符重载函数
- 添加成员属性
- 实现接口
扩展虽然可以添加额外的功能,但不能变更被扩展类型的封装性,因此扩展不支持以下功能:
- 扩展不能增加成员变量。
- 扩展的函数和属性必须拥有实现。
- 扩展的函数和属性不能使用
open、override、redef修饰。 - 扩展不能访问被扩展类型中
private修饰的成员。
根据扩展有没有实现新的接口,扩展可以分为 直接扩展 和 接口扩展 两种用法。直接扩展即不包含额外接口的扩展;接口扩展即包含接口的扩展,接口扩展可以用来为现有的类型添加新功能并实现接口,增强抽象灵活性。
直接扩展
一个简单的扩展语法结构示例如下:
extend String {
public func printSize() {
println("the size is ${this.size}")
}
}
如上例所示,扩展使用 extend 关键字声明,其后跟着被扩展的类型 String 和扩展的功能。
当为 String 扩展了 printSize 函数之后,就能在当前 package 内对 String 的实例访问该函数,就像是 String 本身具备该函数。
main() {
let a = "123"
a.printSize() // the size is 3
}
编译执行上述代码,输出结果为:
the size is 3
被扩展类型是泛型类型时,有两种扩展语法可以对泛型类型扩展功能。
一种是针对特定泛型实例化类型进行扩展,关键字 extend 后允许带一个任意实例化完全的泛型类型。为这些类型增加的功能只有在类型完全匹配时才能使用,且泛型类型的类型实参必须符合泛型类型定义处的约束要求。
例如下面所示的 Foo<T>。
class Foo<T> where T <: ToString {}
extend Foo<Int64> {} // Ok
class Bar {}
extend Foo<Bar> {} // Error
另一种是在 extend 后面引入泛型形参的泛型扩展。泛型扩展可以用来扩展未实例化或未完全实例化的泛型类型。在 extend 后声明的泛型形参必须被直接或间接使用在被扩展的泛型类型上。为这些类型增加的功能只有在类型和约束完全匹配时才能使用。
例如下面所示的 MyList<T>。
class MyList<T> {
public let data: Array<T> = Array<T>()
}
extend<T> MyList<T> {} // OK
extend<R> MyList<R> {} // OK
extend<T, R> MyList<(T, R)> {} // OK
extend MyList {} // Error
extend<T, R> MyList<T> {} // Error
extend<T, R> MyList<T, R> {} // Error
对于泛型类型的扩展,可以在其中声明额外的泛型约束,来实现一些有限情况下才能使用的函数。
例如可以定义一个叫 Pair 的类型,这个类型可以方便地存储两个元素(类似于 Tuple)。
希望 Pair 类型可以容纳任何类型,因此两个泛型变元不应该有任何约束,这样才能保证 Pair 能容纳所有类型。
但同时又希望当两个元素可以判等的时候,让 Pair 也可以判等,这时就可以用扩展来实现这个功能。
如下面的代码所示,使用扩展语法,约束了 T1 和 T2 在支持 equals 的情况下,Pair 也可以实现 equals 函数。
class Pair<T1, T2> {
var first: T1
var second: T2
public init(a: T1, b: T2) {
first = a
second = b
}
}
interface Eq<T> {
func equals(other: T): Bool
}
extend<T1, T2> Pair<T1, T2> where T1 <: Eq<T1>, T2 <: Eq<T2> {
public func equals(other: Pair<T1, T2>) {
first.equals(other.first) && second.equals(other.second)
}
}
class Foo <: Eq<Foo> {
public func equals(other: Foo): Bool {
true
}
}
main() {
let a = Pair(Foo(), Foo())
let b = Pair(Foo(), Foo())
println(a.equals(b)) // true
}
编译执行上述代码,输出结果为:
true
接口扩展
例如下面的例子,类型 Array 本身没有实现接口 PrintSizeable,但可以通过扩展的方式为 Array 增加额外的成员函数 printSize,并实现 PrintSizeable。
interface PrintSizeable {
func printSize(): Unit
}
extend<T> Array<T> <: PrintSizeable {
public func printSize() {
println("The size is ${this.size}")
}
}
当使用扩展为 Array 实现 PrintSizeable 之后,就相当于在 Array 定义时实现接口 PrintSizeable。
因此可以将 Array 作为 PrintSizeable 的实现类型来使用,代码如下所示。
main() {
let a: PrintSizeable = Array<Int64>()
a.printSize() // 0
}
编译执行上述代码,输出结果为:
The size is 0
可以在同一个扩展内同时实现多个接口,多个接口之间使用 & 分开,接口的顺序没有先后关系。
如下面代码所示,可以在扩展中为 Foo 同时实现 I1、I2、I3。
interface I1 {
func f1(): Unit
}
interface I2 {
func f2(): Unit
}
interface I3 {
func f3(): Unit
}
class Foo {}
extend Foo <: I1 & I2 & I3 {
public func f1(): Unit {}
public func f2(): Unit {}
public func f3(): Unit {}
}
也可以在接口扩展中声明额外的泛型约束,来实现一些特定约束下才能满足的接口。
例如可以让上面的 Pair 类型实现 Eq 接口,这样 Pair 自己也能成为一个符合 Eq 约束的类型,如下代码所示。
class Pair<T1, T2> {
var first: T1
var second: T2
public init(a: T1, b: T2) {
first = a
second = b
}
}
interface Eq<T> {
func equals(other: T): Bool
}
extend<T1, T2> Pair<T1, T2> <: Eq<Pair<T1, T2>> where T1 <: Eq<T1>, T2 <: Eq<T2> {
public func equals(other: Pair<T1, T2>) {
first.equals(other.first) && second.equals(other.second)
}
}
class Foo <: Eq<Foo> {
public func equals(other: Foo): Bool {
true
}
}
main() {
let a = Pair(Foo(), Foo())
let b = Pair(Foo(), Foo())
println(a.equals(b)) // true
}
编译执行上述代码,输出结果为:
true
如果被扩展的类型已经包含接口要求的函数或属性,那么在扩展中不需要并且也不能重新实现这些函数或属性。
例如下面的例子,定义了一个新接口 Sizeable,目的是获取某个类型的 size,而已经知道 Array 中包含了这个函数,因此就可以通过扩展让 Array 实现 Sizeable,而不需要添加额外的函数。
interface Sizeable {
prop size: Int64
}
extend<T> Array<T> <: Sizeable {}
main() {
let a: Sizeable = Array<Int64>()
println(a.size)
}
编译执行上述代码,输出结果为:
0
当多个接口扩展实现的接口存在继承关系时,扩展将按照“先检查实现父接口的扩展,再检查子接口的扩展”的顺序进行检查。
例如,接口 I1 存在一个子接口 I2,且 I1 中包含一个默认实现,类型 A 的两个扩展分别实现了父子接口,根据以上检查顺序,实现 I1 的扩展将会优先检查,然后再检查实现 I2 的扩展。
interface I1 {
func foo(): Unit { println("I1 foo") }
}
interface I2 <: I1 {
func foo(): Unit { println("I2 foo") }
}
class A {}
extend A <: I1 {} // first check
extend A <: I2 {} // second check
main() {
A().foo()
}
编译执行上述代码,输出结果为:
I2 foo
以上例子中,当检查实现 I1 的扩展时,会从 I1 中继承 foo 函数。在检查实现 I2 的扩展时,由于 A 中已存在一个继承的,且签名相同的默认实现 foo ,此时 foo 将被覆盖。因此,调用 A 的 foo 函数时,最终指向 I2(子接口)中的实现。
如果同一类型的两个接口扩展实现的接口存在继承冲突,导致无法确定检查顺序时,将会报错。
interface I1 {}
interface I2 <: I1 {}
interface I3 {}
interface I4 <: I3 {}
class A {}
extend A <: I1 & I4 {} // error: unable to decide which extension happens first
extend A <: I2 & I3 {} // error: unable to decide which extension happens first
如果同一类型的两个接口扩展实现的接口不存在继承关系,将会被同时检查。
interface I1 {
func foo() {}
}
interface I2 {
func foo() {}
}
class A {}
extend A <: I1 {} // Error, multiple default implementations, need to re-implement 'foo' in 'A'
extend A <: I2 {} // Error, multiple default implementations, need to re-implement 'foo' in 'A'
注意:
当类 A 有个泛型基类
B<T1,...,Tn>,B<T1,...,Tn>扩展了一个接口I<R1,...,Rn>,I<R1,...,Rn>带有默认实现的实例或者静态函数(比如 foo),该函数没有在B<T1,...,Tn>及其扩展中被重写,且类 A 没有直接实现接口I<R1,...,Rn>时,通过类 A 的实例调用函数 foo 时会产生非预期行为。计划在后续版本修复该问题。
interface I<N> {
func foo(n: N): N {n}
}
open class B<T> {}
extend<T> B<T> <: I<T> {}
class A <: B<Int64>{}
main() {
A().foo(0) // this call triggers unexpected behaviour
}
访问规则
扩展的修饰符
扩展本身不能使用修饰符修饰。
例如,下面的例子中对 A 的直接扩展前使用了 public 修饰,将编译报错。
public class A {}
public extend A {} // Error, expected no modifier before extend
扩展成员可使用的修饰符有:static、public、protected、internal、private、mut。
- 使用
private修饰的成员只能在本扩展内使用,外部不可见。 - 使用
internal修饰的成员可以在当前包及子包(包括子包的子包)内使用,这是默认行为。 - 使用
protected修饰的成员在本模块内可以被访问(受导出规则限制)。当被扩展类型是 class 时,该 class 的子类定义体也能访问。 - 使用
static修饰的成员,只能通过类型名访问,不能通过实例对象访问。 - 对
struct类型的扩展可以定义mut函数。
package p1
public open class A {}
extend A {
public func f1() {}
protected func f2() {}
private func f3() {}
static func f4() {}
}
main() {
A.f4()
var a = A()
a.f1()
a.f2()
}
扩展内的成员定义不支持使用 open、override、redef 修饰。
class Foo {
public open func f() {}
static func h() {}
}
extend Foo {
public override func f() {} // Error
public open func g() {} // Error
redef static func h() {} // Error
}
扩展的孤儿规则
为一个其他 package 的类型实现另一个 package 的接口,可能造成理解上的困扰。
为了防止一个类型被意外实现不合适的接口,仓颉不允许定义孤儿扩展,即既不与接口(包含接口继承链上的所有接口)定义在同一个包中,也不与被扩展类型定义在同一个包中的接口扩展。
如下代码所示,不能在 package c 中,为 package a 里的 Foo 实现 package b 里的 Bar。
只能在 package a 或者在 package b 中为 Foo 实现 Bar。
// package a
public class Foo {}
// package b
public interface Bar {}
// package c
import a.Foo
import b.Bar
extend Foo <: Bar {} // Error
扩展的访问和遮盖
扩展的实例成员与类型定义处一样可以使用 this,this 的功能保持一致。同样也可以省略 this 访问成员。扩展的实例成员不能使用 super。
class A {
var v = 0
}
extend A {
func f() {
print(this.v) // Ok
print(v) // Ok
}
}
扩展不能访问被扩展类型中 private 修饰的成员。
class A {
private var v1 = 0
protected var v2 = 0
}
extend A {
func f() {
print(v1) // Error
print(v2) // Ok
}
}
扩展不能遮盖被扩展类型的任何成员。
class A {
func f() {}
}
extend A {
func f() {} // Error
}
扩展也不允许遮盖其他扩展增加的任何成员。
class A {}
extend A {
func f() {}
}
extend A {
func f() {} // Error
}
在同一个包内,对同一类型可以扩展多次,并且在扩展中可以直接调用被扩展类型的其他扩展中非 private 修饰的函数。
class Foo {}
extend Foo { // OK
private func f() {}
func g() {}
}
extend Foo { // OK
func h() {
g() // OK
f() // Error
}
}
扩展泛型类型时,可以使用额外的泛型约束。泛型类型的任意两个扩展之间的可见性规则如下:
- 如果两个扩展的约束相同,则两个扩展相互可见,即两个扩展内可以直接使用对方内的函数或属性;
- 如果两个扩展的约束不同,且两个扩展的约束有包含关系,约束更宽松的扩展对约束更严格的扩展可见,反之,不可见;
- 当两个扩展的约束不同时,且两个约束不存在包含关系,则两个扩展均互相不可见。
示例:假设对同一个类型 E<X> 的两个扩展分别为扩展 1 和扩展 2 ,X 的约束在扩展 1 中比扩展 2 中更严格,那么扩展 1 中的函数和属性对扩展 2 均不可见,反之,扩展 2 中的函数和属性对扩展 1 可见。
open class A {}
class B <: A {}
class E<X> {}
interface I1 {
func f1(): Unit
}
interface I2 {
func f2(): Unit
}
extend<X> E<X> <: I1 where X <: B { // extension 1
public func f1(): Unit {
f2() // OK
}
}
extend<X> E<X> <: I2 where X <: A { // extension 2
public func f2(): Unit {
f1() // Error
}
}
扩展的导入导出
扩展也是可以被导入和导出的,但是扩展本身不能使用可见性修饰符修饰,扩展的导出有一套特殊的规则。
对于直接扩展,当扩展与被扩展的类型在同一个包中,扩展是否导出,由被扩展类型与泛型约束(如果有)的访问修饰符同时决定,当所有的泛型约束都是导出类型(修饰符与导出规则,详见顶层声明的可见性章节)时,该扩展将被导出。当扩展与被扩展类型不在同一个包中时,该扩展不会导出。
如以下代码所示,Foo 是导出的,f1 函数所在的扩展由于不导出泛型约束,故该扩展不会被导出;f2 和 f3 函数所在的扩展的泛型约束均被导出,故该扩展被导出;f4 函数所在的扩展包含多个泛型约束,且泛型约束中 I1 未被导出,故该扩展不会被导出;f5 函数所在的扩展包含多个泛型约束,所有的泛型约束均是导出的,故该扩展会被导出。
// package a.b
package a.b
private interface I1 {}
internal interface I2 {}
protected interface I3 {}
extend Int64 <: I1 & I2 & I3 {}
public class Foo<T> {}
// The extension will not be exported
extend<T> Foo<T> where T <: I1 {
public func f1() {}
}
// The extension will be exported, and only packages that import both Foo and I2 will be able to access it.
extend<T> Foo<T> where T <: I2 {
public func f2() {}
}
// The extension will be exported, and only packages that import both Foo and I3 will be able to access it.
extend<T> Foo<T> where T <: I3 {
public func f3() {}
}
// The extension will not be exported. The I1 with the lowest access level determines the export.
extend<T> Foo<T> where T <: I1 & I2 & I3 {
public func f4() {}
}
// The extension is exported. Only the package that imports Foo, I2, and I3 can access the extension.
extend<T> Foo<T> where T <: I2 & I3 {
public func f5() {}
}
// package a.c
package a.c
import a.b.*
main() {
Foo<Int64>().f1() // Cannot access.
Foo<Int64>().f2() // Cannot access. Visible only for sub-pkg.
Foo<Int64>().f3() // Ok.
Foo<Int64>().f4() // Cannot access.
Foo<Int64>().f5() // Cannot access. Visible only for sub-pkg.
}
// package a.b.d
package a.b.d
import a.b.*
main() {
Foo<Int64>().f1() // Cannot access.
Foo<Int64>().f2() // Ok.
Foo<Int64>().f3() // Ok.
Foo<Int64>().f4() // Cannot access.
Foo<Int64>().f5() // Ok.
}
对于接口扩展则分为两种情况:
- 当接口扩展与被扩展类型在相同的
package时,扩展会与被扩展类型以及泛型约束(如果有)一起被导出,不受接口类型的访问级别影响,包外不需要导入接口类型也能访问该扩展的成员。 - 当接口扩展与被扩展类型在不同的
package时,接口扩展是否导出由接口类型以及泛型约束(如果有)里用到的类型中最小的访问级别决定。其他package必须导入被扩展类型、相应的接口以及约束用到的类型(如果有),才能访问对应接口包含的扩展成员。
如下代码所示,在包 a 中,虽然接口访问修饰符为 private,但 Foo 的扩展仍然会被导出。
// package a
package a
private interface I0 {}
public class Foo<T> {}
// The extension is exported.
extend<T> Foo<T> <: I0 {}
当在其他包中为 Foo 类型扩展时,扩展是否导出由实现接口和泛型约束的访问修饰符决定。实现接口至少存在一个导出的接口,且所有的泛型约束均可导出时,该扩展将被导出。
// package b
package b
import a.Foo
private interface I1 {}
internal interface I2 {}
protected interface I3 {}
public interface I4 {}
// The extension will not be exported because I1 is not visible outside the file.
extend<T> Foo<T> <: I1 {}
// The extension is exported.
extend<T> Foo<T> <: I2 {}
// The extension is exported.
extend<T> Foo<T> <: I3 {}
// The extension is exported
extend<T> Foo<T> <: I1 & I2 & I3 {}
// The extension will not be exported. The I1 with the lowest access level determines the export.
extend<T> Foo<T> <: I4 where T <: I1 & I2 & I3 {}
// The extension is exported.
extend<T> Foo<T> <: I4 where T <: I2 & I3 {}
// The extension is exported.
extend<T> Foo<T> <: I4 & I3 where T <: I2 {}
特别的,接口扩展导出的成员仅限于接口中包含的成员。
// package a
package a
public class Foo {}
// package b
package b
import a.Foo
public interface I1 {
func f1(): Unit
}
public interface I2 {
func f2(): Unit
}
extend Foo <: I1 & I2 {
public func f1(): Unit {}
public func f2(): Unit {}
public func f3(): Unit {} // f3 will not be exported
}
// package c
package c
import a.Foo
import b.I1
main() {
let x: Foo = Foo()
x.f1() // OK, because f1 is a member of I1.
x.f2() // error, I2 is not imported
x.f3() // error, f3 not found
}
与扩展的导出类似,扩展的导入也不需要显式地用 import 导入,扩展的导入只需要导入被扩展的类型、接口和泛型约束,就可以导入可访问的所有扩展。
如下面的代码所示,在 package b 中,只需要导入 Foo 就可以使用 Foo 对应的扩展中的函数 f。
而对于接口扩展,需要同时导入被扩展的类型、扩展的接口和泛型约束(如果有)才能使用。因此在 package c 中,需要同时导入 Foo 和 I 才能使用对应扩展中的函数 g。
// package a
package a
public class Foo {}
extend Foo {
public func f() {}
}
// package b
package b
import a.Foo
public interface I {
func g(): Unit
}
extend Foo <: I {
public func g() {
this.f() // OK
}
}
// package c
package c
import a.Foo
import b.I
func test() {
let a = Foo()
a.f() // OK
a.g() // OK
}
基础 Collection 类型概述
本章介绍仓颉语言中常用的几种基础 Collection 类型,包括 Array、ArrayList、HashSet 和 HashMap。
可以在不同的场景中选择适合对应业务的类型:
- Array:不需要增加和删除元素,但需要修改元素
- ArrayList:需要频繁对元素增删查改
- HashSet:希望每个元素都是唯一的
- HashMap:希望存储一系列的映射关系
下表是这些类型的基础特性:
| 类型名称 | 元素可变 | 增删元素 | 元素唯一性 | 有序序列 |
|---|---|---|---|---|
Array<T> | Y | N | N | Y |
ArrayList<T> | Y | Y | N | Y |
HashSet<T> | N | Y | Y | N |
HashMap<K, V> | K: N, V: Y | Y | K: Y, V: N | N |
ArrayList
使用 ArrayList 类型需要导入 collection 包:
import std.collection.*
仓颉使用 ArrayList<T> 表示 ArrayList 类型,T 表示 ArrayList 的元素类型,T 可以是任意类型。
ArrayList 具备非常好的扩容能力,适合于需要频繁增加和删除元素的场景。
相比 Array,ArrayList 既可以原地修改元素,也可以原地增加和删除元素。
ArrayList 的可变性是一个非常有用的特征,可以让同一个 ArrayList 实例的所有引用都共享同样的元素,并且对它们统一进行修改。
var a: ArrayList<Int64> = ... // ArrayList whose element type is Int64
var b: ArrayList<String> = ... // ArrayList whose element type is String
元素类型不相同的 ArrayList 是不相同的类型,所以它们之间不可以互相赋值。
因此以下例子是不合法的。
b = a // Type mismatch
仓颉中可以使用构造函数的方式构造一个指定的 ArrayList。
let a = ArrayList<String>() // Created an empty ArrayList whose element type is String
let b = ArrayList<String>(100) // Created an ArrayList whose element type is String, and allocate a space of 100
let c = ArrayList<Int64>([0, 1, 2]) // Created an ArrayList whose element type is Int64, containing elements 0, 1, 2
let d = ArrayList<Int64>(c) // Use another Collection to initialize an ArrayList
let e = ArrayList<String>(2, {x: Int64 => x.toString()}) // Created an ArrayList whose element type is String and size is 2. All elements are initialized by specified rule function
访问 ArrayList 成员
当需要对 ArrayList 的所有元素进行访问时,可以使用 for-in 循环遍历 ArrayList 的所有元素。
import std.collection.*
main() {
let list = ArrayList<Int64>([0, 1, 2])
for (i in list) {
println("The element is ${i}")
}
}
编译并执行上面的代码,会输出:
The element is 0
The element is 1
The element is 2
当需要知道某个 ArrayList 包含的元素个数时,可以使用 size 属性获得对应信息。
import std.collection.*
main() {
let list = ArrayList<Int64>([0, 1, 2])
if (list.size == 0) {
println("This is an empty arraylist")
} else {
println("The size of arraylist is ${list.size}")
}
}
编译并执行上面的代码,会输出:
The size of arraylist is 3
当想访问单个指定位置的元素时,可以使用下标语法访问(下标的类型必须是 Int64)。非空 ArrayList 的第一个元素总是从位置 0 开始的。可以从 0 开始访问 ArrayList 的任意一个元素,直到最后一个位置(ArrayList 的 size - 1)。使用负数或大于等于 size 的索引会触发运行时异常。
let a = list[0] // a == 0
let b = list[1] // b == 1
let c = list[-1] // Runtime exceptions
ArrayList 也支持下标中使用 Range 的语法,详见 Array 章节。
修改 ArrayList
可以使用下标语法对某个位置的元素进行修改。
let list = ArrayList<Int64>([0, 1, 2])
list[0] = 3
ArrayList 是引用类型,ArrayList 在作为表达式使用时不会拷贝副本,同一个 ArrayList 实例的所有引用都会共享同样的数据。
因此对 ArrayList 元素的修改会影响到该实例的所有引用。
let list1 = ArrayList<Int64>([0, 1, 2])
let list2 = list1
list2[0] = 3
// list1 contains elements 3, 1, 2
// list2 contains elements 3, 1, 2
如果需要将单个元素添加到 ArrayList 的末尾,请使用 add 函数。如果希望同时添加多个元素到末尾,可以使用 add(all!: Collection<T>) 函数,这个函数可以接受其他相同元素类型的 Collection 类型(例如 Array)。
import std.collection.*
main() {
let list = ArrayList<Int64>()
list.add(0) // list contains element 0
list.add(1) // list contains elements 0, 1
let li = [2, 3]
list.add(all: li) // list contains elements 0, 1, 2, 3
}
可以通过 add(T, at!: Int64) 和 add(all!: Collection<T>, at!: Int64) 函数将指定的单个元素或相同元素类型的 Collection 值插入到指定索引的位置。该索引处的元素和后面的元素会被挪后以腾出空间。
let list = ArrayList<Int64>([0, 1, 2]) // list contains elements 0, 1, 2
list.add(4, at: 1) // list contains elements 0, 4, 1, 2
从 ArrayList 中删除元素,可以使用 remove 函数,需要指定删除的索引。该索引处后面的元素会前移以填充空间。
let list = ArrayList<String>(["a", "b", "c", "d"]) // list contains the elements "a", "b", "c", "d"
list.remove(at: 1) // Delete the element at subscript 1, now the list contains elements "a", "c", "d"
增加 ArrayList 的大小
每个 ArrayList 都需要特定数量的内存来保存其内容。当向 ArrayList 添加元素并且该 ArrayList 开始超出其保留容量时,该 ArrayList 会分配更大的内存区域并将其所有元素复制到新内存中。这种增长策略意味着触发重新分配内存的添加操作具有性能成本,但随着 ArrayList 的保留内存变大,它们发生的频率会越来越低。
如果知道大约需要添加多少个元素,可以在添加之前预备足够的内存以避免中间重新分配,这样可以提升性能表现。
import std.collection.*
main() {
let list = ArrayList<Int64>(100) // Allocate space at once
for (i in 0..100) {
list.add(i) // Does not trigger reallocation of space
}
list.reserve(100) // Prepare more space
for (i in 0..100) {
list.add(i) // Does not trigger reallocation of space
}
}
HashSet
使用 HashSet 类型需要导入 collection 包:
import std.collection.*
可以使用 HashSet 类型来构造只拥有不重复元素的 Collection。
仓颉使用 HashSet<T> 表示 HashSet 类型,T 表示 HashSet 的元素类型,T 必须是实现了 Hashable 和 Equatable<T> 接口的类型,例如数值或 String。
var a: HashSet<Int64> = ... // HashSet whose element type is Int64
var b: HashSet<String> = ... // HashSet whose element type is String
元素类型不相同的 HashSet 是不相同的类型,所以它们之间不可以互相赋值。
因此以下例子是不合法的。
b = a // Type mismatch
仓颉中可以使用构造函数的方式构造一个指定的 HashSet。
let a = HashSet<String>() // Created an empty HashSet whose element type is String
let b = HashSet<String>(100) // Created a HashSet whose capacity is 100
let c = HashSet<Int64>([0, 1, 2]) // Created a HashSet whose element type is Int64, containing elements 0, 1, 2
let d = HashSet<Int64>(c) // Use another Collection to initialize a HashSet
let e = HashSet<Int64>(10, {x: Int64 => (x * x)}) // Created a HashSet whose element type is Int64 and size is 10. All elements are initialized by specified rule function
访问 HashSet 成员
当需要对 HashSet 的所有元素进行访问时,可以使用 for-in 循环遍历 HashSet 的所有元素。
需要注意的是,HashSet 并不保证按插入元素的顺序排列,因此遍历的顺序和插入的顺序可能不同。
import std.collection.*
main() {
let mySet = HashSet<Int64>([0, 1, 2])
for (i in mySet) {
println("The element is ${i}")
}
}
编译并执行上面的代码,有可能会输出:
The element is 0
The element is 1
The element is 2
当需要知道某个 HashSet 包含的元素个数时,可以使用 size 属性获得对应信息。
import std.collection.*
main() {
let mySet = HashSet<Int64>([0, 1, 2])
if (mySet.size == 0) {
println("This is an empty hashset")
} else {
println("The size of hashset is ${mySet.size}")
}
}
编译并执行上面的代码,会输出:
The size of hashset is 3
当想判断某个元素是否被包含在某个 HashSet 中时,可以使用 contains 函数。如果该元素存在会返回 true,否则返回 false。
let mySet = HashSet<Int64>([0, 1, 2])
let a = mySet.contains(0) // a == true
let b = mySet.contains(-1) // b == false
修改 HashSet
HashSet 是一种可变的引用类型,HashSet 类型提供了添加元素、删除元素的功能。
HashSet 的可变性是一个非常有用的特征,可以让同一个 HashSet 实例的所有引用都共享同样的元素,并且对它们统一进行修改。
如果需要将单个元素添加到 HashSet 里,请使用 add 函数。如果希望同时添加多个元素,可以使用 add(all!: Collection<T>) 函数,这个函数可以接受另一个相同元素类型的 Collection 类型(例如 Array)。当元素不存在时,add 函数会执行添加的操作,当 HashSet 中存在相同元素时,add 函数将不会有效果。
let mySet = HashSet<Int64>()
mySet.add(0) // mySet contains elements 0
mySet.add(0) // mySet contains elements 0
mySet.add(1) // mySet contains elements 0, 1
let li = [2, 3]
mySet.add(all: li) // mySet contains elements 0, 1, 2, 3
HashSet 是引用类型,HashSet 在作为表达式使用时不会拷贝副本,同一个 HashSet 实例的所有引用都会共享同样的数据。
因此对 HashSet 元素的修改会影响到该实例的所有引用。
let set1 = HashSet<Int64>([0, 1, 2])
let set2 = set1
set2.add(3)
// set1 contains elements 0, 1, 2, 3
// set2 contains elements 0, 1, 2, 3
从 HashSet 中删除元素,可以使用 remove 函数,需要指定删除的元素。
let mySet = HashSet<Int64>([0, 1, 2, 3])
mySet.remove(1) // mySet contains elements 0, 2, 3
HashMap
使用 HashMap 类型需要导入 collection 包:
import std.collection.*
可以使用 HashMap 类型来构造元素为键值对的 Collection。
HashMap 是一种哈希表,提供对其包含的元素的快速访问。表中的每个元素都使用其键作为标识,可以使用键来访问相应的值。
仓颉使用 HashMap<K, V> 表示 HashMap 类型,K 表示 HashMap 的键类型,K 必须是实现了 Hashable 和 Equatable<K> 接口的类型,例如数值或 String。V 表示 HashMap 的值类型,V 可以是任意类型。
var a: HashMap<Int64, Int64> = ... // HashMap whose key type is Int64 and value type is Int64
var b: HashMap<String, Int64> = ... // HashMap whose key type is String and value type is Int64
元素类型不相同的 HashMap 是不相同的类型,所以它们之间不可以互相赋值。
因此以下例子是不合法的。
b = a // Type mismatch
仓颉中可以使用构造函数的方式构造一个指定的 HashMap。
let a = HashMap<String, Int64>() // Created an empty HashMap whose key type is String and value type is Int64
let b = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)]) // whose key type is String and value type is Int64, containing elements ("a", 0), ("b", 1), ("c", 2)
let c = HashMap<String, Int64>(b) // Use another Collection to initialize a HashMap
let d = HashMap<String, Int64>(10) // Created a HashMap whose key type is String and value type is Int64 and capacity is 10
let e = HashMap<Int64, Int64>(10, {x: Int64 => (x, x * x)}) // Created a HashMap whose key and value type is Int64 and size is 10. All elements are initialized by specified rule function
访问 HashMap 成员
当需要对 HashMap 的所有元素进行访问时,可以使用 for-in 循环遍历 HashMap 的所有元素。
需要注意的是,HashMap 并不保证按插入元素的顺序排列,因此遍历的顺序和插入的顺序可能不同。
import std.collection.*
main() {
let map = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)])
for ((k, v) in map) {
println("The key is ${k}, the value is ${v}")
}
}
编译并执行上面的代码,有可能会输出:
The key is a, the value is 0
The key is b, the value is 1
The key is c, the value is 2
当需要知道某个 HashMap 包含的元素个数时,可以使用 size 属性获得对应信息。
import std.collection.*
main() {
let map = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)])
if (map.size == 0) {
println("This is an empty hashmap")
} else {
println("The size of hashmap is ${map.size}")
}
}
编译并执行上面的代码,会输出:
The size of hashmap is 3
当想判断 HashMap 中是否包含某个键时,可以使用 contains 函数。如果该键存在会返回 true,否则返回 false。
let map = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)])
let a = map.contains("a") // a == true
let b = map.contains("d") // b == false
当想访问指定键对应的元素时,可以使用下标语法访问(下标的类型必须是键类型)。使用不存在的键作为索引会触发运行时异常。
let map = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)])
let a = map["a"] // a == 0
let b = map["b"] // b == 1
let c = map["d"] // Runtime exceptions
修改 HashMap
HashMap 是一种可变的引用类型,HashMap 类型提供了修改元素、添加元素、删除元素的功能。
HashMap 的可变性是一个非常有用的特征,可以让同一个 HashMap 实例的所有引用都共享同样的元素,并且对它们统一进行修改。
可以使用下标语法对某个键对应的值进行修改。
let map = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)])
map["a"] = 3
HashMap 是引用类型,HashMap 在作为表达式使用时不会拷贝副本,同一个 HashMap 实例的所有引用都会共享同样的数据。
因此对 HashMap 元素的修改会影响到该实例的所有引用。
let map1 = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)])
let map2 = map1
map2["a"] = 3
// map1 contains the elements ("a", 3), ("b", 1), ("c", 2)
// map2 contains the elements ("a", 3), ("b", 1), ("c", 2)
如果需要将单个键值对添加到 HashMap 里,请使用 add 函数。如果希望同时添加多个键值对,可以使用 add(all!: Collection<(K, V)>) 函数。当键不存在时,add 函数会执行添加的操作,当键存在时,add 函数会将新的值覆盖旧的值。
let map = HashMap<String, Int64>()
map.add("a", 0) // map contains the element ("a", 0)
map.add("b", 1) // map contains the elements ("a", 0), ("b", 1)
let map2 = HashMap<String, Int64>([("c", 2), ("d", 3)])
map.add(all: map2) // map contains the elements ("a", 0), ("b", 1), ("c", 2), ("d", 3)
除了使用 add 函数以外,也可以使用赋值的方式直接将新的键值对添加到 HashMap。
let map = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2)])
map["d"] = 3 // map contains the elements ("a", 0), ("b", 1), ("c", 2), ("d", 3)
从 HashMap 中删除元素,可以使用 remove 函数,需要指定删除的键。
let map = HashMap<String, Int64>([("a", 0), ("b", 1), ("c", 2), ("d", 3)])
map.remove("d") // map contains the elements ("a", 0), ("b", 1), ("c", 2)
Iterable 和 Collections
前面已经了解过 Range、Array、ArrayList,它们都可以使用 for-in 进行遍历操作。对于开发者自定义的类型,也能实现类似的遍历操作。
Range、Array、ArrayList 都是通过 Iterable 来支持 for-in 语法的。
Iterable 是如下形式(只展示了核心代码)的一个内置 interface。
interface Iterable<T> {
func iterator(): Iterator<T>
...
}
iterator 函数要求返回的 Iterator 类型是如下形式(只展示了核心代码)的另一个内置 interface。
interface Iterator<T> <: Iterable<T> {
mut func next(): Option<T>
...
}
可以使用 for-in 语法来遍历任何一个实现了 Iterable 接口类型的实例。
假设有这样一段 for-in 代码,如下所示。
let list = [1, 2, 3]
for (i in list) {
println(i)
}
它等价于如下形式的 while 代码。
let list = [1, 2, 3]
var it = list.iterator()
while (true) {
match (it.next()) {
case Some(i) => println(i)
case None => break
}
}
另外一种常见的遍历 Iterable 类型的方法是在 while 表达式的条件中使用模式匹配,比如上面 while 代码的另一种等价写法是:
let list = [1, 2, 3]
var it = list.iterator()
while (let Some(i) <- it.next()) {
println(i)
}
Array、ArrayList、HashSet、HashMap 类型都实现了 Iterable,因此可以将其用在 for-in 或者 while 中。
包的概述
随着项目规模的不断扩大,仅在一个超大文件中管理源代码会变得十分困难。这时可以将源代码根据功能进行分组,并将不同功能的代码分开管理,每组独立管理的代码会生成一个输出文件。在使用时,通过导入对应的输出文件使用相应的功能,或者通过不同功能的交互与组合实现更加复杂的特性,使得项目管理更加高效。
在仓颉编程语言中,包是编译的最小单元,每个包可以单独输出 AST 文件、静态库文件、动态库文件等产物。每个包有自己的名字空间,在同一个包内不允许有同名的顶层定义或声明(函数重载除外)。一个包中可以包含多个源文件。
模块是若干包的集合,是第三方开发者发布的最小单元。一个模块的程序入口只能在其根目录下,它的顶层最多只能有一个作为程序入口的 main ,该 main 没有参数或参数类型为 Array<String>,返回类型为整数类型或 Unit 类型。
包和模块管理
在仓颉编程语言中,包由一个或多个源码文件组成,同一个包的源码文件必须在同一个目录,并且同一个目录里的源码文件只能属于同一个包。包可以定义子包从而构成树形结构。子包的目录是其父包目录的子目录。没有父包的包称为 root 包,root 包及其子包(包括子包的子包)构成的整棵树称为模块。
仓颉程序常见的组织结构如下:
demo
├── src
│ ├── main.cj
│ └── pkg0
│ ├── pkg0.cj
│ ├── aoo
│ │ └── aoo.cj
│ └── boo
│ └── boo.cj
└── cjpm.toml
cjpm.toml 是当前模块所在工作空间的配置文件,用于定义基础信息、依赖项、编译选项等内容。该文件由仓颉语言的官方包管理工具 cjpm 解析和执行。
注意:
对于同一个模块,如果需要为其配置一个有效的包,则该包所在目录必须直接包含至少一个仓颉代码文件,并且其上游目录都需要是有效包。
包的声明
在仓颉编程语言中,包声明以关键字 package 开头,后接 root 包至当前包由 . 分隔路径上所有包的包名。包名必须是合法的普通标识符(不含原始标识符)。例如:
package pkg1 // root 包 pkg1
package pkg1.sub1 // root 包 pkg1 的子包 sub1
注意:
当前 Windows 平台版本,包名暂不支持使用 Unicode 字符,包名必须是一个仅含 ASCII 字符的合法的普通标识符。
包声明必须在源文件的非空非注释的首行,且同一个包中的不同源文件的包声明必须保持一致。
// file 1
// Comments are accepted
package test
// declarations...
// file 2
let a = 1 // Error, package declaration must appear first in a file
package test
// declarations...
仓颉的包名需反映当前源文件相对于项目源码根目录 src 的路径,并将其中的路径分隔符替换为小数点。例如包的源代码位于 src/directory_0/directory_1 下,root 包名为 pkg 则其源代码中的包声明应为 package pkg.directory_0.directory_1。
需要注意的是:
- 包所在的文件夹名必须与包名一致。
- 源码根目录默认名为
src。 - 源码根目录下的包可以没有包声明,此时编译器将默认为其指定包名
default。
假设源代码目录结构如下:
// The directory structure is as follows:
src
`-- directory_0
|-- directory_1
| |-- a.cj
| `-- b.cj
`-- c.cj
`-- main.cj
则 a.cj、b.cj、c.cj、main.cj 中的包声明可以为:
// a.cj
// in file a.cj, the declared package name must correspond to relative path directory_0/directory_1.
package default.directory_0.directory_1
// b.cj
// in file b.cj, the declared package name must correspond to relative path directory_0/directory_1.
package default.directory_0.directory_1
// c.cj
// in file c.cj, the declared package name must correspond to relative path directory_0.
package default.directory_0
// main.cj
// file main.cj is in the module root directory and may omit package declaration.
main() {
return 0
}
另外,包声明不能引起命名冲突:子包不能和当前包的顶层声明同名。
以下是一些错误示例:
// a.cj
package a
public class B { // Error, 'B' is conflicted with sub-package 'a.B'
public static func f() {}
}
// b.cj
package a.B
public func f {}
// main.cj
import a.B // ambiguous use of 'a.B'
main() {
a.B.f()
return 0
}
顶层声明的可见性
仓颉编程语言中,可以使用访问修饰符来控制对类型、变量、函数等顶层声明的可见性。仓颉语言有 4 种访问修饰符:private、internal、protected、public,在修饰顶层元素时不同访问修饰符的语义如下:
private表示仅当前文件内可见。不同的文件无法访问这类成员。internal表示仅当前包及子包(包括子包的子包)内可见。同一个包内可以不导入就访问这类成员,当前包的子包(包括子包的子包)内可以通过导入来访问这类成员。protected表示仅当前模块内可见。同一个包的文件可以不导入就访问这类成员,不同包但是在同一个模块内的其他包可以通过导入访问这些成员,不同模块的包无法访问这些成员。public表示模块内外均可见。同一个包的文件可以不导入就访问这类成员,其他包可以通过导入访问这些成员。
| 修饰符 | 文件 | 包及子包 | 模块 | 所有包 |
|---|---|---|---|---|
private | Y | N | N | N |
internal | Y | Y | N | N |
protected | Y | Y | Y | N |
public | Y | Y | Y | Y |
不同顶层声明支持的访问修饰符和默认修饰符(默认修饰符是指在省略情况下的修饰符语义,这些默认修饰符也允许显式写出)规定如下:
package支持使用internal、protected、public,默认修饰符为public。import支持使用全部访问修饰符,默认修饰符为private。- 其他顶层声明支持使用全部访问修饰符,默认修饰符为
internal。
package a
private func f1() { 1 } // f1 仅在当前文件内可见
func f2() { 2 } // f2 仅当前包及子包内可见
protected func f3() { 3 } // f3 仅当前模块内可见
public func f4() { 4 } // f4 当前模块内外均可见
仓颉的访问级别排序为 public > protected > internal > private。一个声明的访问修饰符不得高于该声明中用到的类型的访问修饰符的级别,参考如下示例:
-
函数声明中的参数与返回值
// a.cj package a class C {} public func f1(a1: C) // Error, public declaration f1 cannot use internal type C. { return 0 } public func f2(a1: Int8): C // Error, public declaration f2 cannot use internal type C. { return C() } public func f3 (a1: Int8) // Error, public declaration f3 cannot use internal type C. { return C() } -
变量声明
// a.cj package a class C {} public let v1: C = C() // Error, public declaration v1 cannot use internal type C. public let v2 = C() // Error, public declaration v2 cannot use internal type C. -
泛型类型的类型实参
// a.cj package a public class C1<T> {} class C2 {} public let v1 = C1<C2>() // Error, public declaration v1 cannot use internal type C2. -
where约束中的类型上界// a.cj package a interface I {} public class B<T> where T <: I {} // Error, public declaration B cannot use internal type I.
值得注意的是:
-
public修饰的声明在其初始化表达式或者函数体里面可以使用本包可见的任意类型,包括被public修饰的类型和不被public修饰的类型。// a.cj package a class C1 {} func f1(a1: C1) { return 0 } public func f2(a1: Int8) // Ok. { var v1 = C1() return 0 } public let v1 = f1(C1()) // Ok. public class C2 // Ok. { var v2 = C1() } -
public修饰的顶层声明能使用匿名函数,或者任意顶层函数,包括被public修饰的类型和不被public修饰的顶层函数。public var t1: () -> Unit = { => } // Ok. func f1(): Unit {} public let t2 = f1 // Ok. public func f2() // Ok. { return f1 } -
内置类型诸如
Rune和Int64等默认的修饰符是public。var num = 5 public var t3 = num // Ok.
注意:
同一个包内,
private修饰的同名自定义类型(如struct、class、enum和interface等),在某些场景下不支持,不支持场景由编译器进行报错。
例如在以下程序中,example1.cj 与 example2.cj文件包名相同,在 example1.cj 文件中定义了 private 修饰的类 A, 在 example2.cj 文件中定义了 private 修饰的结构体 A。
// example1.cj
package test
private class A {}
public class D<T> {
private let a: A = A()
}
// example2.cj
package test
private struct A {}
public class C<T> {
private let a: A = A()
}
运行以上程序,将输出:
error: currently, it is not possible to export two private declarations with the same name
包的导入
使用 import 语句导入其他包中的声明或定义
在仓颉编程语言中,可以通过 import fullPackageName.itemName 的语法导入其他包中的一个顶层声明或定义,fullPackageName 为完整路径包名,itemName 为声明的名字。导入语句在源文件中的位置必须在包声明之后,其他声明或定义之前。例如:
package a
import std.math.*
import package1.foo
import {package1.foo, package2.bar}
如果要导入的多个 itemName 同属于一个 fullPackageName,可以使用 import fullPackageName.{itemName[, itemName]*} 语法,例如:
import package1.{foo, bar, fuzz}
这等价于:
import package1.foo
import package1.bar
import package1.fuzz
除了通过 import fullPackagename.itemName 语法导入一个特定的顶层声明或定义外,还可以使用 import packageName.* 语法将 packageName 包中所有可见的顶层声明或定义全部导入。例如:
import package1.*
import {package1.*, package2.*}
需要注意:
- 导入的成员的作用域级别低于当前包声明的成员。
- 当已导出的包的模块名或者包名被篡改,使其与导出时指定的模块名或包名不一致,在导入时会报错。
- 只允许导入当前文件可见的顶层声明或定义,导入不可见的声明或定义将会在导入处报错。
- 禁止通过
import导入当前源文件所在包的声明或定义。 - 禁止包间的循环依赖导入,如果包之间存在循环依赖,编译器会报错。
示例如下:
// pkga/a.cj
package pkga // Error, packages pkga pkgb are in circular dependencies.
import pkgb.*
class C {}
public struct R {}
// pkgb/b.cj
package pkgb
import pkga.*
// pkgc/c1.cj
package pkgc
import pkga.C // Error, 'C' is not accessible in package 'pkga'.
import pkga.R // OK, R is an external top-level declaration of package pkga.
import pkgc.f1 // Error, package 'pkgc' should not import itself.
public func f1() {}
// pkgc/c2.cj
package pkgc
func f2() {
/* OK, the imported declaration is visible to all source files of the same package
* and accessing import declaration by its name is supported.
*/
R()
// OK, accessing imported declaration by fully qualified name is supported.
pkga.R()
// OK, the declaration of current package can be accessed directly.
f1()
// OK, accessing declaration of current package by fully qualified name is supported.
pkgc.f1()
}
在仓颉编程语言中,导入的声明或定义如果和当前包中的顶层声明或定义重名且不构成函数重载,则导入的声明和定义会被遮盖;导入的声明或定义如果和当前包中的顶层声明或定义重名且构成函数重载,函数调用时将会根据函数重载的规则进行函数决议。
// pkga/a.cj
package pkga
public struct R {} // R1
public func f(a: Int32) {} // f1
public func f(a: Bool) {} // f2
// pkgb/b.cj
package pkgb
import pkga.*
func f(a: Int32) {} // f3
struct R {} // R2
func bar() {
R() // OK, R2 shadows R1.
f(1) // OK, invoke f3 in current package.
f(true) // OK, invoke f2 in the imported package
}
隐式导入 core 包
诸如 String、Range 等类型能直接使用,并不是因为这些类型是内置类型,而是因为编译器会自动为源码隐式的导入 core 包中所有的 public 修饰的声明。
使用 import as 对导入的名字重命名
不同包的名字空间是分隔的,因此在不同的包之间可能存在同名的顶层声明。在导入不同包的同名顶层声明时,支持使用 import packageName.name as newName 的方式进行重命名来避免冲突。没有名字冲突的情况下仍然可以通过 import as 来重命名导入的内容。import as 具有如下规则:
-
使用
import as对导入的声明进行重命名后,当前包只能使用重命名后的新名字,原名无法使用。 -
如果重命名后的名字与当前包顶层作用域的其他名字存在冲突,且这些名字对应的声明均为函数类型,则参与函数重载,否则报重定义的错误。
-
支持
import pkg as newPkgName的形式对包名进行重命名,以解决不同模块中同名包的命名冲突问题。// a.cj package p1 public func f1() {}// d.cj package p2 public func f3() {}// b.cj package p1 public func f2() {}// c.cj package pkgc public func f1() {}// main.cj import p1 as A import p1 as B import p2.f3 as f // OK import pkgc.f1 as a import pkgc.f1 as b // OK func f(a: Int32) {} main() { A.f1() // OK, package name conflict is resolved by renaming package name. B.f2() // OK, package name conflict is resolved by renaming package name. p1.f1() // Error, the original package name cannot be used. a() // Ok. b() // Ok. pkgc.f1() // Error, the original name cannot be used. } -
如果没有对导入的存在冲突的名字进行重命名,在
import语句处不报错;在使用处,会因为无法导入唯一的名字而报错。这种情况可以通过import as定义别名或者import fullPackageName导入包作为命名空间。// a.cj package p1 public class C {} // b.cj package p2 public class C {} // main1.cj package pkga import p1.C import p2.C main() { let _ = C() // Error } // main2.cj package pkgb import p1.C as C1 import p2.C as C2 main() { let _ = C1() // Ok let _ = C2() // Ok } // main3.cj package pkgc import p1 import p2 main() { let _ = p1.C() // Ok let _ = p2.C() // Ok }
重导出一个导入的名字
在功能繁多的大型项目的开发过程中,这样的场景是非常常见的:包 p2 大量地使用从包 p1 中导入的声明,当包 p3 导入包 p2 并使用其中的功能时,p1 中的声明同样需要对包 p3 可见。如果要求包 p3 自行导入 p2 中使用到的 p1 中的声明,这个过程将过于繁琐。因此希望能够在 p2 被导入时一并导入 p2 使用到的 p1 中的声明。
在仓颉编程语言中,import 可以被 private、internal、protected、public 访问修饰符修饰。其中,被 public、protected 或者 internal 修饰的 import 可以把导入的成员重导出(如果这些导入的成员没有因为名称冲突或者被遮盖导致在本包中不可用)。其他包可以根据可见性直接导入并使用本包中用重导出的内容,无需从原包中导入这些内容。
private import表示导入的内容仅当前文件内可访问,private是import的默认修饰符,不写访问修饰符的import等价于private import。internal import表示导入的内容在当前包及其子包(包括子包的子包)均可访问。非当前包访问需要显式import。protected import表示导入的内容在当前 module 内都可访问。非当前包访问需要显式import。public import表示导入的内容外部都可访问。非当前包访问需要显式import。
在下面的例子中,b 是 a 的子包,在 a 中通过 public import 重导出了 b 中定义的函数 f。
package a
public import a.b.f
public let x = 0
internal package a.b
public func f() { 0 }
import a.f // Ok
let _ = f() // Ok
需要注意的是,包不可以被重导出:如果被 import 导入的是包,那么该 import 不允许被 public、protected 或者 internal 修饰。
public import a.b // Error, cannot re-export package
程序入口
仓颉程序入口为 main,源文件根目录下的包的顶层最多只能有一个 main。
如果模块采用生成可执行文件的编译方式,编译器只在源文件根目录下的顶层查找 main。如果没有找到,编译器将会报错;如果找到 main,编译器会进一步对其参数和返回值类型进行检查。需要注意的是,main 不可被访问修饰符修饰,当一个包被导入时,包中定义的 main 不会被导入。
作为程序入口的 main 可以没有参数或参数类型为 Array<String>,返回值类型为 Unit 或整数类型。
没有参数的 main:
// main.cj
main(): Int64 { // Ok.
return 0
}
参数类型为 Array<String> 的 main:
// main.cj
main(args: Array<String>): Unit { // Ok.
for (arg in args) {
println(arg)
}
}
使用 cjc main.cj 编译完成后,通过命令行执行:./main Hello, World,将会得到如下输出:
Hello,
World
以下是一些错误示例:
// main.cj
main(): String { // Error, return type of 'main' is not 'Integer' or 'Unit'.
return ""
}
// main.cj
main(args: Array<Int8>): Int64 { // Error, 'main' cannot be defined with parameter whose type is not Array<String>.
return 0
}
// main.cj
// Error, multiple 'main's are found in source files.
main(args: Array<String>): Int32 {
return 0
}
main(): Int8 {
return 0
}
定义异常
异常是一类特殊的可以被程序员捕获并处理的错误,是程序执行时出现的一系列不正常行为的统称。例如,数组越界、除零错误、计算溢出、非法输入等。为了保证系统的正确性和健壮性,很多软件系统中都包含大量的代码用于错误检测和错误处理。
异常不属于程序的正常功能,一旦发生异常,要求程序必须立即处理,即将程序的控制权从正常功能的执行处转移至处理异常的部分。仓颉编程语言提供了异常处理机制,用于处理程序运行时可能出现的各种异常情况。
在仓颉语言中,异常类包括 Error 和 Exception:
Error类描述仓颉语言运行时,系统内部错误和资源耗尽错误。应用程序不应该抛出这种类型错误,如果出现内部错误,只能通知给用户,尽量安全终止程序。Exception类描述的是程序运行时的逻辑错误或者 IO 错误导致的异常,例如数组越界或者试图打开一个不存在的文件等,这类异常需要在程序中捕获处理。
开发者不可以通过继承仓颉语言内置的 Error 或其子类来自定义异常,但是可以继承内置的 Exception 或其子类来自定义异常,例如:
open class FatherException <: Exception {
public init() {
super("This is FatherException.")
}
public init(message: String) {
super(message)
}
public open override func getClassName(): String {
"FatherException"
}
}
class ChildException <: FatherException {
public init() {
super("This is ChildException.")
}
public open override func getClassName(): String {
"ChildException"
}
}
下表展示了 Exception 的主要函数及其说明:
| 函数种类 | 函数及说明 |
|---|---|
| 构造函数 | init() 默认构造函数。 |
| 构造函数 | init(message: String) 可以设置异常消息的构造函数。 |
| 成员属性 | open prop message: String 返回发生异常的详细信息。该消息在异常类构造函数中初始化,默认为空字符串。 |
| 成员函数 | open func toString(): String 返回异常类型名以及异常的详细信息,其中,异常的详细信息会默认调用 message。 |
| 成员函数 | func getClassName(): String 返回用户定义的类名,子类需要重写该方法以返回子类的名称。 |
| 成员函数 | func printStackTrace(): Unit 打印堆栈信息至标准错误流。 |
下表展示了 Error 的主要函数及其说明:
| 函数种类 | 函数及说明 |
|---|---|
| 成员属性 | open prop message: String 返回发生错误的详细信息。该消息在错误发生时,内部初始化,默认为空字符串。 |
| 成员函数 | open func toString(): String 返回错误类型名以及错误的详细信息,其中,错误的详细信息会默认调用 message。 |
| 成员函数 | func printStackTrace(): Unit 打印堆栈信息至标准错误流。 |
throw 和处理异常
上文介绍了如何自定义异常,接下来学习如何抛出和处理异常。
- 由于异常是
class类型,只需要按 class 对象的构建方式去创建异常即可。如表达式FatherException()即创建了一个类型为FatherException的异常。 - 仓颉语言提供
throw关键字,用于抛出异常。用throw来抛出异常时,throw之后的表达式必须是Exception的子类型(同为异常的Error不可以手动throw),如throw ArithmeticException("I am an Exception!")(被执行到时)会抛出一个算术运算异常。 throw关键字抛出的异常需要被捕获处理。若异常没有被捕获,则由系统调用默认的异常处理函数。
异常处理由 try 表达式完成,可分为:
- 不涉及资源自动管理的普通 try 表达式。
- 会进行资源自动管理 try-with-resources 表达式。
普通 try 表达式
普通 try 表达式包括三个部分:try 块,catch 块和 finally 块。
-
try 块,以关键字
try开始,后面紧跟一个由表达式与声明组成的块(用一对花括号括起来,定义了新的局部作用域,可以包含任意表达式和声明,后简称“块”),try 后面的块内可以抛出异常,并被紧随的 catch 块所捕获并处理(如果不存在 catch 块或未被捕获,则在执行完 finally 块后,该异常继续被抛出)。 -
catch 块,一个普通 try 表达式可以包含零个或多个 catch 块(当没有 catch 块时必须有 finally 块)。每个 catch 块以关键字
catch开头,后跟一条catchPattern和一个块,catchPattern通过模式匹配的方式匹配待捕获的异常。一旦匹配成功,则交由其后跟随的块进行处理,并且忽略它后面的其他 catch 块。当某个 catch 块可捕获的异常类型均可被定义在它前面的某个 catch 块所捕获时,会在此 catch 块处报“catch 块不可达”的 warning。 -
finally 块,以关键字
finally开始,后面紧跟一个块。原则上,finally 块中主要实现一些“善后”的工作,如释放资源等,且要尽量避免在 finally 块中再抛异常。并且无论异常是否发生(即无论 try 块中是否抛出异常),finally 块内的内容都会被执行(若异常未被处理,执行完 finally 块后,继续向外抛出异常)。一个 try 表达式在包含 catch 块时可以不包含 finally 块,否则必须包含 finally 块。
try 后面紧跟的块以及每个 catch 块的作用域互相独立。
注意:
当在 try 块中可能发生内存溢出错误时,应避免在 catch 或 finally 块中执行任何内存分配操作,以免再次触发溢出并导致未定义行为。一旦检测到内存溢出,建议在 catch 块中立即终止程序(例如调用
exit函数),以确保系统稳定性并防止进一步错误。
下面是一个只有 try 块和 catch 块的简单示例:
main() {
try {
throw NegativeArraySizeException("I am an Exception!")
} catch (e: NegativeArraySizeException) {
println(e)
println("NegativeArraySizeException is caught!")
}
println("This will also be printed!")
}
执行结果为:
NegativeArraySizeException: I am an Exception!
NegativeArraySizeException is caught!
This will also be printed!
catchPattern 中引入的变量作用域级别与 catch 后面的块中变量作用域级别相同,在 catch 块中再次引入相同名字会触发重定义错误。例如:
main() {
try {
throw NegativeArraySizeException("I am an Exception!")
} catch (e: NegativeArraySizeException) {
println(e)
let e = 0 // Error, redefinition
println(e)
println("NegativeArraySizeException is caught!")
}
println("This will also be printed!")
}
下面是带有 finally 块的 try 表达式的简单示例:
main() {
try {
throw NegativeArraySizeException("NegativeArraySizeException")
} catch (e: NegativeArraySizeException) {
println("Exception info: ${e}.")
} finally {
println("The finally block is executed.")
}
}
执行结果为:
Exception info: NegativeArraySizeException: NegativeArraySizeException.
The finally block is executed.
try 表达式可以出现在任何允许使用表达式的地方。try 表达式的类型的确定方式,与 if、match 表达式等多分支语法结构的类型的确定方式相似,为 finally 分支除外的所有分支的类型的最小公共父类型。例如下面代码中的 try 表达式和变量 x 的类型均为 E 和 D 的最小公共父类型 D;finally 分支中的 C() 并不参与公共父类型的计算(若参与,则最小公共父类型会变为 C)。
另外,当 try 表达式的值没有被使用时,其类型为 Unit,不要求各分支的类型有最小公共父类型。
open class C { }
open class D <: C { }
class E <: D { }
main () {
let x = try {
E()
} catch (e: Exception) {
D()
} finally {
C()
}
0
}
try-with-resources 表达式
try-with-resources 表达式主要是为了自动释放非内存资源。不同于普通 try 表达式,try-with-resources 表达式中的 catch 块和 finally 块均是可选的,并且 try 关键字其后的块之间可以插入一个或者多个 ResourceSpecification 用来申请一系列的资源(ResourceSpecification 并不会影响整个 try 表达式的类型)。这里所讲的资源对应到语言层面即指对象,因此 ResourceSpecification 其实就是实例化一系列的对象(多个实例化之间使用“,”分隔)。使用 try-with-resources 表达式的例子如下所示:
class Worker <: Resource {
var hasTools: Bool = false
let name: String
public init(name: String) {
this.name = name
}
public func getTools() {
println("${name} picks up tools from the warehouse.")
hasTools = true
}
public func work() {
if (hasTools) {
println("${name} does some work with tools.")
} else {
println("${name} doesn't have tools, does nothing.")
}
}
public func isClosed(): Bool {
if (hasTools) {
println("${name} hasn't returned the tool.")
false
} else {
println("${name} has no tools")
true
}
}
public func close(): Unit {
println("${name} returns the tools to the warehouse.")
hasTools = false
}
}
main() {
try (r = Worker("Tom")) {
r.getTools()
r.work()
}
try (r = Worker("Bob")) {
r.work()
}
try (r = Worker("Jack")) {
r.getTools()
throw Exception("Jack left, because of an emergency.")
}
}
程序输出结果为:
Tom picks up tools from the warehouse.
Tom does some work with tools.
Tom hasn't returned the tool.
Tom returns the tools to the warehouse.
Bob doesn't have tools, does nothing.
Bob has no tools
Jack picks up tools from the warehouse.
Jack hasn't returned the tool.
Jack returns the tools to the warehouse.
An exception has occurred:
Exception: Jack left, because of an emergency.
at test.main()(xxx/xx.cj:xx)
try 关键字和 {} 之间引入的名字,其作用域与 {} 中引入的变量作用域级别相同,在 {} 中再次引入相同名字会触发重定义错误。
class R <: Resource {
public func isClosed(): Bool {
true
}
public func close(): Unit {
print("R is closed")
}
}
main() {
try (r = R()) {
println("Get the resource")
let r = 0 // Error, redefinition
println(r)
}
}
try-with-resources 表达式中的 ResourceSpecification 的类型必须实现 Resource 接口:
interface Resource {
func isClosed(): Bool // 离开 try-with-resources 作用域时,判断是否需要调用 close 函数释放资源
func close(): Unit // 在 isClosed 返回 false 的场景下释放资源。
}
需要说明的是,try-with-resources 表达式中一般没有必要再包含 catch 块和 finally 块,也不建议开发者再手动释放资源(逻辑冗余)。但是,如果需要显式地捕获 try 块或资源申请和释放过程中可能抛出的异常并处理,仍可在 try-with-resources 表达式中包含 catch 块和 finally 块:
class R <: Resource {
public func isClosed(): Bool {
true
}
public func close(): Unit {
print("R is closed")
}
}
main() {
try (r = R()) {
println("Get the resource")
} catch (e: Exception) {
println("Exception happened when executing the try-with-resources expression")
} finally {
println("End of the try-with-resources expression")
}
}
程序输出结果如下:
Get the resource
End of the try-with-resources expression
try-with-resources 表达式的类型是 Unit。
CatchPattern 进阶介绍
大多数时候,只想捕获某一类型和其子类型的异常,这时候使用 CatchPattern 的类型模式来处理;但有时也需要所有异常做统一处理(如此处不该出现异常,出现了就统一报错),这时可以使用 CatchPattern 的通配符模式来处理。
类型模式在语法上有两种格式:
Identifier: ExceptionClass。此格式可以捕获类型为ExceptionClass及其子类的异常,并将捕获到的异常实例转换成ExceptionClass,然后与Identifier定义的变量进行绑定,接着就可以在 catch 块中通过 Identifier 定义的变量访问捕获到的异常实例。Identifier: ExceptionClass_1 | ExceptionClass_2 | ... | ExceptionClass_n。此格式可以通过连接符|将多个异常类进行拼接,连接符|表示“或”的关系:可以捕获类型为ExceptionClass_1及其子类的异常,或者捕获类型为ExceptionClass_2及其子类的异常,依次类推,或捕获类型为ExceptionClass_n及其子类的异常(假设 n 大于 1)。当待捕获异常的类型属于上述“或”关系中的任一类型或其子类型时,此异常将被捕获。但是由于无法静态地确定被捕获异常的类型,所以被捕获异常的类型会被转换成由|连接的所有类型的最小公共父类,并将异常实例与Identifier定义的变量进行绑定。因此在此类模式下,catch 块内只能通过Identifier定义的变量访问ExceptionClass_i(1 <= i <= n)的最小公共父类中的成员变量和成员函数。当然,也可以使用通配符代替类型模式中的Identifier,差别仅在于通配符不会进行绑定操作。
示例如下:
main(): Int64 {
try {
throw IllegalArgumentException("This is an Exception!")
} catch (e: OverflowException) {
println(e.message)
println("OverflowException is caught!")
} catch (e: IllegalArgumentException | NegativeArraySizeException) {
println(e.message)
println("IllegalArgumentException or NegativeArraySizeException is caught!")
} finally {
println("finally is executed!")
}
return 0
}
执行结果:
This is an Exception!
IllegalArgumentException or NegativeArraySizeException is caught!
finally is executed!
关于“被捕获异常的类型是由 | 连接的所有类型的最小公共父类”的示例:
open class Father <: Exception {
var father: Int32 = 0
}
class ChildOne <: Father {
var childOne: Int32 = 1
}
class ChildTwo <: Father {
var childTwo: Int32 = 2
}
main() {
try {
throw ChildOne()
} catch (e: ChildTwo | ChildOne) {
println("${e is Father}")
}
}
执行结果:
true
通配符模式的语法是 _,它可以捕获同级 try 块内抛出的任意类型的异常,等价于类型模式中的 e: Exception,即捕获 Exception 子类所定义的异常。示例如下:
// Catch with wildcardPattern.
try {
throw OverflowException()
} catch (_) {
println("catch an exception!")
}
常见运行时异常
在仓颉语言中内置了最常见的异常类,开发人员可以直接使用。
| 异常 | 描述 |
|---|---|
ConcurrentModificationException | 并发修改产生的异常 |
IllegalArgumentException | 传递不合法或不正确参数时抛出的异常 |
NegativeArraySizeException | 创建大小为负的数组时抛出的异常 |
NoneValueException | 值不存在时产生的异常,如 Map 中不存在要查找的 key |
OverflowException | 算术运算溢出异常 |
使用 Option
在 Option 类型中介绍了 Option 类型的定义,因为 Option 类型可以同时表示有值和无值两种状态,而无值在某些情况下也可以理解为一种错误,所以 Option 类型也可以用作错误处理。
例如,在下例中,如果函数 getOrThrow 的参数值等于 Some(v) 则将 v 的值返回,如果参数值等于 None 则抛出异常。
func getOrThrow(a: ?Int64) {
match (a) {
case Some(v) => v
case None => throw NoneValueException()
}
}
因为 Option 是一种非常常用的类型,所以仓颉为其提供了多种解构方式,以方便 Option 类型的使用,具体包括:模式匹配、getOrThrow 函数、coalescing 操作符(??),以及问号操作符(?)。下面将对这些方式逐一介绍。
-
模式匹配:因为 Option 类型是一种 enum 类型,所以可以使用上文提到的 enum 的模式匹配来实现对
Option值的解构。例如,下例中函数getString接受一个?Int64类型的参数,当参数是Some值时,返回其中数值的字符串表示,当参数是None值时,返回字符串"none"。func getString(p: ?Int64): String{ match (p) { case Some(x) => "${x}" case None => "none" } } main() { let a = Some(1) let b: ?Int64 = None let r1 = getString(a) let r2 = getString(b) println(r1) println(r2) }上述代码的执行结果为:
1 none -
coalescing操作符(??):对于?T类型的表达式e1,如果希望e1的值等于None时同样返回一个T类型的值e2,可以使用??操作符。对于表达式e1 ?? e2,当e1的值等于Some(v)时返回v的值,否则返回e2的值。举例如下:main() { let a = Some(1) let b: ?Int64 = None let r1: Int64 = a ?? 0 let r2: Int64 = b ?? 0 println(r1) println(r2) }上述代码的执行结果为:
1 0 -
问号操作符(
?):?需要和.或()或[]或{}(特指尾随 lambda 调用的场景)一起使用,用以实现Option类型对.,(),[]和{}的支持。以.为例((),[]和{}同理),对于?T1类型的表达式e,当e的值等于Some(v)时,e?.b的值等于Option<T2>.Some(v.b),否则e?.b的值等于Option<T2>.None,其中T2是v.b的类型。举例如下:struct R { public var a: Int64 public init(a: Int64) { this.a = a } } let r = R(100) let x = Some(r) let y = Option<R>.None let r1 = x?.a // r1 = Option<Int64>.Some(100) let r2 = y?.a // r2 = Option<Int64>.None class C { var item: Int64 = 100 } let c = C() let c1 = Option<C>.Some(c) let c2 = Option<C>.None func test1() { c1?.item = 200 // c.item = 200 c2?.item = 300 // no effect }问号操作符(
?)支持多层访问,以a?.b.c?.d为例((),[]和{}同理)。表达式a的类型需要是某个Option<T1>且T1包含实例成员b,b的类型中包含实例成员变量c且c的类型是某个Option<T2>,T2包含实例成员d;表达式a?.b.c?.d的类型为Option<T3>,其中T3是T2的实例成员d的类型;当a的值等于Some(va)且va.b.c的值等于Some(vc)时,a?.b.c?.d的值等于Option<T3>.Some(vc.d);当a的值等于Some(va)且va.b.c的值等于None时,a?.b.c?.d的值等于Option<T3>.None(d不会被求值);当a的值等于None时,a?.b.c?.d的值等于Option<T3>.None(b,c和d都不会被求值)。class A { public var b: B = B() } class B { public var c: Option<C> = C() public var c1: Option<C> = Option<C>.None } class C { public var d: Int64 = 100 } main(){ var a = Some(A()) let a1 = a?.b.c?.d // a1 = Option<Int64>.Some(100) let a2 = a?.b.c1?.d // a2 = Option<Int64>.None a?.b.c?.d = 200 // a.b.c.d = 200 a?.b.c1?.d = 200 // no effect } -
getOrThrow函数:对于?T类型的表达式e,可以通过调用getOrThrow函数实现解构。当e的值等于Some(v)时,getOrThrow()返回v的值,否则抛出异常。举例如下:main() { let a = Some(1) let b: ?Int64 = None let r1 = a.getOrThrow() println(r1) try { let r2 = b.getOrThrow() } catch (e: NoneValueException) { println("b is None") } }上述代码的执行结果为:
1 b is None
并发概述
并发编程是现代编程语言中不可或缺的特性,仓颉编程语言提供抢占式的线程模型作为并发编程机制。线程可以细分为两种不同概念,语言线程和 native 线程。
- 语言线程是编程语言中并发模型的基本执行单位。仓颉编程语言希望给开发者提供一个友好、高效、统一的并发编程界面,让开发者无需关心操作系统线程、用户态线程等差异,因此提供仓颉线程的概念。开发者在大多数情况下只需面向仓颉线程编写并发代码。
- native 线程指语言实现中所使用到的线程(一般是操作系统线程),它们作为语言线程的具体实现载体。不同编程语言会以不同的方式实现语言线程。例如,一些编程语言直接通过操作系统调用来创建线程,这意味着每个语言线程对应一个 native 线程,这种实现方案一般被称之为
1:1线程模型。此外,另有一些编程语言提供特殊的线程实现,它们允许多个语言线程在多个 native 线程上切换执行,这种也被称为M:N线程模型,即 M 个语言线程在 N 个 native 线程上调度执行,其中 M 和 N 不一定相等。当前,仓颉语言的实现同样采用M:N线程模型;因此,仓颉线程本质上是一种用户态的轻量级线程,支持抢占且相比操作系统线程更轻量化。
仓颉线程本质上是用户态的轻量级线程,每个仓颉线程都受到底层 native 线程的调度执行,并且多个仓颉线程可以由一个 native 线程执行。每个 native 线程会不断地选择一个就绪的仓颉线程完成执行,如果仓颉线程在执行过程中发生阻塞(例如等待互斥锁的释放),那么 native 线程会将当前的仓颉线程挂起,并继续选择下一个就绪的仓颉线程。发生阻塞的仓颉线程在重新就绪后会继续被 native 线程调度执行。
在大多数情况下,开发者只需要面向仓颉线程进行并发编程而不需要考虑这些细节。但在进行跨语言编程时,开发者需要谨慎调用可能发生阻塞的 foreign 函数,例如 IO 相关的操作系统调用等。例如,下列示例代码中的新线程会调用 foreign 函数 socket_read。在程序运行过程中,某一 native 线程将调度并执行该仓颉线程,在进入到 foreign 函数中后,系统调用会直接阻塞当前 native 线程直到函数执行完成。native 线程在阻塞期间将无法调度其他仓颉线程来执行,这会降低程序执行的吞吐量。
foreign socket_read(sock: Int64): CPointer<Int8>
let fut = spawn {
let sock: Int64 = ...
let ptr = socket_read(sock)
}
注意:
本文档在没有歧义的情况下将直接以线程简化对仓颉线程的指代。
创建线程
当开发者希望并发执行某一段代码时,只需创建一个仓颉线程即可。要创建一个新的仓颉线程,可以使用关键字 spawn 并传递一个无形参的 lambda 表达式,该 lambda 表达式即为在新线程中执行的代码。
下方示例代码中,主线程和新线程均会尝试打印一些文本:
main(): Int64 {
spawn { =>
println("New thread before sleeping")
sleep(100 * Duration.millisecond) // sleep for 100ms.
println("New thread after sleeping")
}
println("Main thread")
return 0
}
在上面的例子中,新线程会在主线程结束时一起停止,无论这个新线程是否已完成运行。上方示例的输出每次可能略有不同,有可能会输出类似如下的内容:
New thread before sleeping
Main thread
sleep() 函数会让当前线程睡眠指定的时长,之后再恢复执行,其时间由指定的 Duration 类型决定,详细介绍请参见线程睡眠指定时长章节。
访问线程
使用 Future<T> 等待线程结束并获取返回值
在上面的例子中,新创建的线程会由于主线程结束而提前结束,在缺乏顺序保证的情况下,甚至可能会出现新创建的线程还来不及得到执行就退出了。可以通过 spawn 表达式的返回值,来等待线程执行结束。
spawn 表达式的返回类型是 Future<T>,其中 T 是类型变元,其类型与 lambda 表达式的返回类型一致。当调用 Future<T> 的 get() 成员函数时,它将等待它的线程执行完成。
Future<T> 的原型声明如下:
public class Future<T> {
// Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.
// If an exception occurs in the corresponding thread, the method will throw the exception.
public func get(): T
// Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.
// If the corresponding thread has not completed execution within Duration, the method will throws TimeoutException.
// If `timeout` <= Duration.Zero, its behavior is the same as `get()`.
public func get(timeout: Duration): T
// Non-blocking method that immediately returns Option<T>.None if thread has not finished execution.
// Returns the computed result otherwise.
// If an exception occurs in the corresponding thread, the method will throw the exception.
public func tryGet(): Option<T>
}
下方示例代码演示了如何使用 Future<T> 在 main 中等待新创建的线程执行完成:
import std.sync.*
import std.time.*
main(): Int64 {
let fut: Future<Unit> = spawn { =>
println("New thread before sleeping")
sleep(100 * Duration.millisecond) // sleep for 100ms.
println("New thread after sleeping")
}
println("Main thread")
fut.get() // wait for the thread to finish.
return 0
}
调用 Future<T> 实例的 get() 会阻塞当前运行的线程,直到 Future<T> 实例所代表的线程运行结束。因此,上方示例有可能会输出类似如下内容:
New thread before sleeping
Main thread
New thread after sleeping
主线程在完成打印后会因为调用 get() 而等待新创建的线程执行结束。但主线程和新线程的打印顺序具有不确定性。
如果将 fut.get() 移动到主线程的打印之前,如下所示:
import std.sync.*
import std.time.*
main(): Int64 {
let fut: Future<Unit> = spawn { =>
println("New thread before sleeping")
sleep(100 * Duration.millisecond) // sleep for 100ms.
println("New thread after sleeping")
}
fut.get() // wait for the thread to finish.
println("Main thread")
return 0
}
主线程将等待新创建的线程执行完成,然后再执行打印,因此程序的输出将变得确定,如下所示:
New thread before sleeping
New thread after sleeping
Main thread
可见,get() 的调用位置会影响线程是否能同时运行。
Future<T> 除了可以用于阻塞等待线程执行结束以外,还可以获取线程执行的结果。如下是它提供的具体成员函数:
-
get(): T:阻塞等待线程执行结束,并返回执行结果,如果该线程已经结束,则直接返回执行结果。示例代码如下:
import std.sync.* import std.time.* main(): Int64 { let fut: Future<Int64> = spawn { sleep(Duration.second) // sleep for 1s. return 1 } try { // wait for the thread to finish, and get the result. let res: Int64 = fut.get() println("result = ${res}") } catch (_) { println("oops") } return 0 }输出结果如下:
result = 1 -
get(timeout: Duration): T:阻塞等待该Future<T>所代表的线程执行结束,并返回执行结果,当到达超时时间 timeout 时,如果该线程还没有执行结束,将会抛出异常 TimeoutException。如果timeout <= Duration.Zero, 其行为与get()相同。示例代码如下:
main(): Int64 { let fut = spawn { sleep(Duration.second) // sleep for 1s. return 1 } // wait for the thread to finish, but only for 1ms. try { let res = fut.get(Duration.millisecond * 1) println("result: ${res}") } catch (_: TimeoutException) { println("oops") } return 0 }输出结果如下:
oops
访问线程属性
每个 Future<T> 对象都有一个对应的仓颉线程,以 Thread 对象为表示。Thread 类主要被用于访问线程的属性信息,例如线程标识等。需要注意的是,Thread 无法直接被实例化构造对象,仅能从 Future<T> 的 thread 成员属性获取对应的 Thread 对象,或是通过 Thread 的静态成员属性 currentThread 得到当前正在执行线程对应的 Thread 对象。
Thread 类的部分方法定义如下(完整的方法描述可参考《仓颉编程语言库 API》)。
class Thread {
// Get the currently running thread
static prop currentThread: Thread
// Get the unique identifier (represented as an integer) of the thread object
prop id: Int64
// Check whether the thread has any cancellation request
prop hasPendingCancellation: Bool
}
下列示例代码在创建新线程后分别通过两种方式获取线程标识。由于主线程和新线程获取的是同一个 Thread 对象,所以他们能够打印出相同的线程标识。
main(): Unit {
let fut = spawn {
println("Current thread id: ${Thread.currentThread.id}")
}
println("New thread id: ${fut.thread.id}")
fut.get()
}
输出结果如下(其中线程 id 会变化,也可能为其他值):
New thread id: 1
Current thread id: 1
终止线程
可以通过 Future<T> 的 cancel() 方法向对应的线程发送终止请求,该方法不会停止线程执行。开发者需要使用 Thread 的 hasPendingCancellation 属性来检查线程是否存在终止请求。
一般而言,如果线程存在终止请求,那么开发者可以实施相应的线程终止逻辑。因此,如何终止线程都交由开发者自行处理,如果开发者忽略终止请求,那么线程继续执行直到正常结束。
示例代码如下:
import std.sync.SyncCounter
main(): Unit {
let syncCounter = SyncCounter(1)
let fut = spawn {
syncCounter.waitUntilZero() // block until the syncCounter becomes zero
if (Thread.currentThread.hasPendingCancellation) { // Check cancellation request
println("cancelled")
return
}
println("hello")
}
fut.cancel() // Send cancellation request
syncCounter.dec()
fut.get() // Join thread
}
输出结果如下:
cancelled
同步机制
在并发编程中,如果缺少同步机制来保护多个线程共享的变量,很容易会出现数据竞争问题(data race)。
仓颉编程语言提供三种常见的同步机制来确保数据的线程安全:原子操作、互斥锁和条件变量。
原子操作 Atomic
仓颉提供整数类型、Bool 类型和引用类型的原子操作。
其中整数类型包括: Int8、Int16、Int32、Int64、UInt8、UInt16、UInt32、UInt64。
整数类型的原子操作支持基本的读写、交换以及算术运算操作:
| 操作 | 功能 |
|---|---|
load | 读取 |
store | 写入 |
swap | 交换,返回交换前的值 |
compareAndSwap | 比较再交换,交换成功返回 true,否则返回 false |
fetchAdd | 加法,返回执行加操作之前的值 |
fetchSub | 减法,返回执行减操作之前的值 |
fetchAnd | 与,返回执行与操作之前的值 |
fetchOr | 或,返回执行或操作之前的值 |
fetchXor | 异或,返回执行异或操作之前的值 |
需要注意的是:
- 交换操作和算术操作的返回值是修改前的值。
- compareAndSwap 是判断当前原子变量的值是否等于 old 值,如果等于,则使用 new 值替换;否则不替换。
以 Int8 类型为例,对应的原子操作类型声明如下:
class AtomicInt8 {
public func load(): Int8
public func store(val: Int8): Unit
public func swap(val: Int8): Int8
public func compareAndSwap(old: Int8, new: Int8): Bool
public func fetchAdd(val: Int8): Int8
public func fetchSub(val: Int8): Int8
public func fetchAnd(val: Int8): Int8
public func fetchOr(val: Int8): Int8
public func fetchXor(val: Int8): Int8
}
上述每一种原子类型的方法都有一个对应的方法可以接收内存排序参数,目前内存排序参数仅支持顺序一致性。
类似的,其他整数类型对应的原子操作类型有:
class AtomicInt16 {...}
class AtomicInt32 {...}
class AtomicInt64 {...}
class AtomicUInt8 {...}
class AtomicUInt16 {...}
class AtomicUInt32 {...}
class AtomicUInt64 {...}
下方示例演示了如何在多线程程序中,使用原子操作实现计数:
import std.sync.*
import std.time.*
import std.collection.*
let count = AtomicInt64(0)
main(): Int64 {
let list = ArrayList<Future<Int64>>()
// create 1000 threads.
for (_ in 0..1000) {
let fut = spawn {
sleep(Duration.millisecond) // sleep for 1ms.
count.fetchAdd(1)
}
list.add(fut)
}
// Wait for all threads finished.
for (f in list) {
f.get()
}
let val = count.load()
println("count = ${val}")
return 0
}
输出结果应为:
count = 1000
以下是使用整数类型原子操作的一些其他正确示例:
var obj: AtomicInt32 = AtomicInt32(1)
var x = obj.load() // x: 1, the type is Int32
x = obj.swap(2) // x: 1
x = obj.load() // x: 2
var y = obj.compareAndSwap(2, 3) // y: true, the type is Bool.
y = obj.compareAndSwap(2, 3) // y: false, the value in obj is no longer 2 but 3. Therefore, the CAS operation fails.
x = obj.fetchAdd(1) // x: 3
x = obj.load() // x: 4
Bool 类型和引用类型的原子操作只提供读写和交换操作:
| 操作 | 功能 |
|---|---|
load | 读取 |
store | 写入 |
swap | 交换,返回交换前的值 |
compareAndSwap | 比较再交换,交换成功返回 true,否则返回 false |
注意:
引用类型原子操作只对引用类型有效。
原子引用类型是 AtomicReference,以下是使用 Bool 类型、引用类型原子操作的一些正确示例:
import std.sync.*
class A {}
main() {
var obj = AtomicBool(true)
var x1 = obj.load() // x1: true, the type is Bool
println(x1)
var t1 = A()
var obj2 = AtomicReference(t1)
var x2 = obj2.load() // x2 and t1 are the same object
var y1 = obj2.compareAndSwap(x2, t1) // x2 and t1 are the same object, y1: true
println(y1)
var t2 = A()
var y2 = obj2.compareAndSwap(t2, A()) // x and t1 are not the same object, CAS fails, y2: false
println(y2)
y2 = obj2.compareAndSwap(t1, A()) // CAS successes, y2: true
println(y2)
}
编译执行上述代码,输出结果为:
true
true
false
true
可重入互斥锁 Mutex
可重入互斥锁的作用是对临界区加以保护,使得任意时刻最多只有一个线程能够执行临界区的代码。当一个线程试图获取一个已被其他线程持有的锁时,该线程会被阻塞,直到锁被释放,该线程才会被唤醒,可重入是指线程获取该锁后可再次获得该锁。
使用可重入互斥锁时,必须牢记两条规则:
- 在访问共享数据之前,必须尝试获取锁;
- 处理完共享数据后,必须释放锁,以便其他线程可以获得锁。
Mutex 提供的主要成员函数如下:
public class Mutex <: UniqueLock {
// Create a Mutex.
public init()
// Locks the mutex, blocks if the mutex is not available.
public func lock(): Unit
// Unlocks the mutex. If there are other threads blocking on this
// lock, then wake up one of them.
public func unlock(): Unit
// Tries to lock the mutex, returns false if the mutex is not
// available, otherwise returns true.
public func tryLock(): Bool
// Generate a Condition instance for the mutex.
public func condition(): Condition
}
下方示例演示了如何使用 Mutex 来保护对全局共享变量 count 的访问,对 count 的操作即属于临界区:
import std.sync.*
import std.time.*
import std.collection.*
var count: Int64 = 0
let mtx = Mutex()
main(): Int64 {
let list = ArrayList<Future<Unit>>()
// create 1000 threads.
for (i in 0..1000) {
let fut = spawn {
sleep(Duration.millisecond) // sleep for 1ms.
mtx.lock()
count++
mtx.unlock()
}
list.add(fut)
}
// Wait for all threads finished.
for (f in list) {
f.get()
}
println("count = ${count}")
return 0
}
输出结果应为:
count = 1000
下方示例演示了如何使用 tryLock:
import std.sync.*
import std.time.*
main(): Int64 {
let mtx: Mutex = Mutex()
var future: Future<Unit> = spawn {
mtx.lock()
println("get the lock, do something")
sleep(Duration.millisecond * 10)
mtx.unlock()
}
try {
future.get(Duration.millisecond * 10)
} catch (e: TimeoutException) {
if (mtx.tryLock()) {
println("tryLock success, do something")
mtx.unlock()
return 0
}
println("tryLock failed, do nothing")
return 0
}
return 0
}
一种可能的输出结果如下:
get the lock, do something
以下是互斥锁的一些错误示例:
错误示例 1:线程操作临界区后没有解锁,导致其他线程无法获得锁而阻塞。
import std.sync.*
var sum: Int64 = 0
let mutex = Mutex()
main() {
let foo = spawn { =>
mutex.lock()
sum = sum + 1
}
let bar = spawn { =>
mutex.lock()
sum = sum + 1
}
foo.get()
println("${sum}")
bar.get() // Because the thread is not unlocked, other threads waiting to obtain the current mutex will be blocked.
}
错误示例 2:在本线程没有持有锁的情况下调用 unlock 将会抛出异常。
import std.sync.*
var sum: Int64 = 0
let mutex = Mutex()
main() {
let foo = spawn { =>
sum = sum + 1
mutex.unlock() // Error, Unlock without obtaining the lock and throw an exception: IllegalSynchronizationStateException.
}
foo.get()
0
}
错误示例 3:tryLock() 并不保证获取到锁,可能会造成不在锁的保护下操作临界区和在没有持有锁的情况下调用 unlock 抛出异常等行为。
import std.sync.*
var sum: Int64 = 0
let mutex = Mutex()
main() {
for (i in 0..100) {
spawn { =>
mutex.tryLock() // Error, `tryLock()` just trying to acquire a lock, there is no guarantee that the lock will be acquired, and this can lead to abnormal behavior.
sum = sum + 1
mutex.unlock()
}
}
}
另外,Mutex 在设计上是一个可重入锁,也就是说:在某个线程已经持有一个 Mutex 锁的情况下,再次尝试获取同一个 Mutex 锁,永远可以立即获得该 Mutex 锁。
注意:
虽然
Mutex是一个可重入锁,但是调用unlock()的次数必须和调用lock()的次数相同,才能成功释放该锁。
下方示例代码演示了 Mutex 可重入的特性:
import std.sync.*
import std.time.*
var count: Int64 = 0
let mtx = Mutex()
func foo() {
mtx.lock()
count += 10
bar()
mtx.unlock()
}
func bar() {
mtx.lock()
count += 100
mtx.unlock()
}
main(): Int64 {
let fut = spawn {
sleep(Duration.millisecond) // sleep for 1ms.
foo()
}
foo()
fut.get()
println("count = ${count}")
return 0
}
输出结果应为:
count = 220
在上方示例中,无论是主线程还是新创建的线程,如果在 foo() 中已经获得了锁,那么继续调用 bar() 的话,在 bar() 函数中由于是对同一个 Mutex 进行加锁,因此也是能立即获得该锁的,不会出现死锁。
Condition
Condition 是与某个互斥锁绑定的条件变量(也就是等待队列),Condition 实例由互斥锁创建,一个互斥锁可以创建多个 Condition 实例。Condition 可以使线程阻塞并等待来自另一个线程的信号以恢复执行。这是一种利用共享变量进行线程同步的机制,主要提供如下方法:
public class Mutex <: UniqueLock {
// ...
// Generate a Condition instance for the mutex.
public func condition(): Condition
}
public interface Condition {
// Wait for a signal, blocking the current thread.
func wait(): Unit
func wait(timeout!: Duration): Bool
// Wait for a signal and predicate, blocking the current thread.
func waitUntil(predicate: ()->Bool): Unit
func waitUntil(predicate: ()->Bool, timeout!: Duration): Bool
// Wake up one thread of those waiting on the monitor, if any.
func notify(): Unit
// Wake up all threads waiting on the monitor, if any.
func notifyAll(): Unit
}
调用 Condition 接口的 wait、notify 或 notifyAll 方法前,需要确保当前线程已经持有绑定的锁。wait 方法包含如下动作:
- 添加当前线程到对应锁的等待队列中;
- 阻塞当前线程,同时完全释放该锁,并记录锁的重入次数;
- 等待某个其他线程使用同一个
Condition实例的notify或notifyAll方法向该线程发出信号; - 当前线程被唤醒后,会自动尝试重新获取锁,且持有锁的重入状态与第 2 步记录的重入次数相同;但是如果尝试获取锁失败,则当前线程会阻塞在该锁上。
wait 方法接受一个可选参数 timeout。需要注意的是,业界很多常用的常规操作系统不保证调度的实时性,因此无法保证一个线程会被阻塞“精确的 N 纳秒”——可能会观察到与系统相关的不精确情况。此外,当前语言规范明确允许实现产生虚假唤醒——在这种情况下,wait 返回值是由实现决定的——可能为 true 或 false。因此鼓励开发者始终将 wait 包在一个循环中:
synchronized (obj) {
while (<condition is not true>) {
obj.wait()
}
}
以下是使用 Condition 的一个正确示例:
import std.sync.*
import std.time.*
let mtx = Mutex()
let condition = synchronized(mtx) {
mtx.condition()
}
var flag: Bool = true
main(): Int64 {
let fut = spawn {
mtx.lock()
while (flag) {
println("New thread: before wait")
condition.wait()
println("New thread: after wait")
}
mtx.unlock()
}
// Sleep for 10ms, to make sure the new thread can be executed.
sleep(10 * Duration.millisecond)
mtx.lock()
println("Main thread: set flag")
flag = false
mtx.unlock()
mtx.lock()
println("Main thread: notify")
condition.notifyAll()
mtx.unlock()
// wait for the new thread finished.
fut.get()
return 0
}
输出结果应为:
New thread: before wait
Main thread: set flag
Main thread: notify
New thread: after wait
Condition 对象执行 wait 时,必须在锁的保护下进行,否则 wait 中释放锁的操作会抛出异常。
以下是使用条件变量的一些错误示例:
import std.sync.*
let m1 = Mutex()
let c1 = synchronized(m1) {
m1.condition()
}
let m2 = Mutex()
var flag: Bool = true
var count: Int64 = 0
func foo1() {
spawn {
m2.lock()
while (flag) {
c1.wait() // Error:The lock used together with the condition variable must be the same lock and in the locked state. Otherwise, the unlock operation in `wait` throws an exception.
}
count = count + 1
m2.unlock()
}
m1.lock()
flag = false
c1.notifyAll()
m1.unlock()
}
func foo2() {
spawn {
while (flag) {
c1.wait() // Error:The `wait` of a conditional variable must be called with a lock held.
}
count = count + 1
}
m1.lock()
flag = false
c1.notifyAll()
m1.unlock()
}
main() {
foo1()
foo2()
c1.wait()
return 0
}
有时在复杂的线程间同步的场景下需要对同一个锁对象生成多个 Condition 实例,以下示例实现了一个长度固定的有界 FIFO 队列。当队列为空,get() 会被阻塞;当队列已满,put() 会被阻塞。
import std.sync.*
class BoundedQueue {
// Create a Mutex, two Conditions.
let m: Mutex = Mutex()
var notFull: Condition
var notEmpty: Condition
var count: Int64 // Object count in buffer.
var head: Int64 // Write index.
var tail: Int64 // Read index.
// Queue's length is 100.
let items: Array<Object> = Array<Object>(100, {i => Object()})
init() {
count = 0
head = 0
tail = 0
synchronized(m) {
notFull = m.condition()
notEmpty = m.condition()
}
}
// Insert an object, if the queue is full, block the current thread.
public func put(x: Object) {
// Acquire the mutex.
synchronized(m) {
while (count == 100) {
// If the queue is full, wait for the "queue notFull" event.
notFull.wait()
}
items[head] = x
head++
if (head == 100) {
head = 0
}
count++
// An object has been inserted and the current queue is no longer
// empty, so wake up the thread previously blocked on get()
// because the queue was empty.
notEmpty.notify()
} // Release the mutex.
}
// Pop an object, if the queue is empty, block the current thread.
public func get(): Object {
// Acquire the mutex.
synchronized(m) {
while (count == 0) {
// If the queue is empty, wait for the "queue notEmpty" event.
notEmpty.wait()
}
let x: Object = items[tail]
tail++
if (tail == 100) {
tail = 0
}
count--
// An object has been popped and the current queue is no longer
// full, so wake up the thread previously blocked on put()
// because the queue was full.
notFull.notify()
return x
} // Release the mutex.
}
}
synchronized 关键字
Lock 提供了一种便利灵活的加锁的方式,同时因为它的灵活性,也可能引起忘记解锁,或者在持有锁的情况下抛出异常不能自动释放持有的锁的问题。因此,仓颉编程语言提供一个 synchronized 关键字,搭配 Lock 一起使用,可以在其后跟随的作用域内自动进行加锁解锁操作,用来解决类似的问题。
下方示例代码演示了如何使用 synchronized 关键字来保护共享数据:
import std.sync.*
import std.time.*
import std.collection.*
var count: Int64 = 0
let mtx = Mutex()
main(): Int64 {
let list = ArrayList<Future<Unit>>()
// create 1000 threads.
for (i in 0..1000) {
let fut = spawn {
sleep(Duration.millisecond) // sleep for 1ms.
// Use synchronized(mtx), instead of mtx.lock() and mtx.unlock().
synchronized(mtx) {
count++
}
}
list.add(fut)
}
// Wait for all threads finished.
for (f in list) {
f.get()
}
println("count = ${count}")
return 0
}
输出结果应为:
count = 1000
通过在 synchronized 后面加上一个 Lock 实例,对其后面修饰的代码块进行保护,可以使得任意时刻最多只有一个线程可以执行被保护的代码:
- 一个线程在进入
synchronized修饰的代码块之前,会自动获取Lock实例对应的锁,如果无法获取锁,则当前线程被阻塞; - 一个线程在退出
synchronized修饰的代码块之前,会自动释放该Lock实例的锁。
对于控制转移表达式(如 break、continue、return、throw),在导致程序的执行跳出 synchronized 代码块时,也符合上面第 2 条的说明,也就说也会自动释放 synchronized 表达式对应的锁。
下方示例演示了在 synchronized 代码块中出现 break 语句的情况:
import std.sync.*
import std.collection.*
var count: Int64 = 0
var mtx: Mutex = Mutex()
main(): Int64 {
let list = ArrayList<Future<Unit>>()
for (i in 0..10) {
let fut = spawn {
while (true) {
synchronized(mtx) {
count = count + 1
break
println("in thread")
}
}
}
list.add(fut)
}
// Wait for all threads finished.
for (f in list) {
f.get()
}
synchronized(mtx) {
println("in main, count = ${count}")
}
return 0
}
输出结果应为:
in main, count = 10
实际上 in thread 这行不会被打印,因为 break 语句实际上会让程序执行跳出 while 循环(在跳出 while 循环之前,先跳出 synchronized 代码块)。
线程局部变量 ThreadLocal
使用 core 包中的 ThreadLocal 可以创建并使用线程局部变量,每一个线程都有它独立的一个存储空间来保存这些线程局部变量。因此,在每个线程可以安全地访问他们各自的线程局部变量,而不受其他线程的影响。
public class ThreadLocal<T> {
/* 构造一个携带空值的仓颉线程局部变量 */
public init()
/* 获得仓颉线程局部变量的值 */
public func get(): Option<T> // 如果值不存在,则返回 Option<T>.None。返回值 Option<T> - 仓颉线程局部变量的值
/* 通过 value 设置仓颉线程局部变量的值 */
public func set(value: Option<T>): Unit // 如果传入 Option<T>.None,该局部变量的值将被删除,在线程后续操作中将无法获取。参数 value - 需要设置的局部变量的值。
}
下方示例代码演示了如何通过 ThreadLocal类来创建并使用各自线程的局部变量:
main(): Int64 {
let tl = ThreadLocal<Int64>()
let fut1 = spawn {
tl.set(123)
println("tl in spawn1 = ${tl.get().getOrThrow()}")
}
let fut2 = spawn {
tl.set(456)
println("tl in spawn2 = ${tl.get().getOrThrow()}")
}
fut1.get()
fut2.get()
0
}
可能的输出结果如下:
tl in spawn1 = 123
tl in spawn2 = 456
或者
tl in spawn2 = 456
tl in spawn1 = 123
线程睡眠指定时长 sleep
sleep 函数会阻塞当前运行的线程,该线程会主动睡眠一段时间,之后再恢复执行,其参数类型为 Duration 类型。函数原型为:
func sleep(dur: Duration): Unit // Sleep for at least `dur`.
注意:
如果
dur<= Duration.Zero, 那么当前线程只会让出执行资源,并不会进入睡眠。
以下是使用 sleep 的示例:
import std.sync.*
import std.time.*
main(): Int64 {
println("Hello")
sleep(Duration.second) // sleep for 1s.
println("World")
return 0
}
输出结果如下:
Hello
World
I/O 流概述
本章介绍基本的 I/O 概念和文件操作。
仓颉编程语言将与应用程序外部载体交互的操作称为 I/O 操作。I 对应输入(Input),O 对应输出(Output)。
仓颉编程语言所有的 I/O 机制都是基于数据流进行输入输出,这些数据流表示了字节数据的序列。数据流是一串连续的数据集合,它就像承载数据的管道,在管道的一端输入数据,在管道的另一端就可以输出数据。
仓颉编程语言将输入输出抽象为流(Stream)。
- 将数据从外存中读取到内存中的称为输入流(InputStream),输入端可以一段一段地向管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。
- 将数据从内存写入外存中的称为输出流(OutputStream),输出端也可以一段一段地从管道中读出数据,每次可以读取其中的任意长度的数据(不需要跟输入端匹配),但只能读取先输入的数据,再读取后输入的数据。
有了这一层抽象,仓颉编程语言就可以使用统一的接口来实现与外部数据的交互。
仓颉编程语言将标准输入输出、文件操作、网络数据流、字符串流、加密流、压缩流等等形式的操作,统一用 Stream 描述。
Stream 主要面向处理原始二进制数据,Stream 中最小的数据单元是 Byte。
仓颉编程语言将 Stream 定义成了 interface,它让不同的 Stream 可以用装饰器模式进行组合,极大地提升了可扩展性。
输入流
程序从输入流读取数据源(数据源包括外界的键盘、文件、网络等),即输入流是将数据源读入到程序的通信通道。
仓颉编程语言用 InputStream 接口类型来表示输入流,它提供了 read 函数,这个函数会将可读的数据写入到 buffer 中,返回值表示了该次读取的字节总数。
InputStream 接口定义:
interface InputStream {
func read(buffer: Array<Byte>): Int64
}
当拥有一个输入流的时候,就可以像下面的代码那样去读取字节数据,读取的数据会被写到 read 的入参数组中。
输入流读取示例:
import std.io.InputStream
main() {
let input: InputStream = ...
let buf = Array<Byte>(256, repeat: 0)
while (input.read(buf) > 0) {
println(buf)
}
}
输出流
程序向输出流写入数据。输出流是将程序中的数据输出到外界(显示器、打印机、文件、网络等)的通信通道。
仓颉编程语言用 OutputStream 接口类型来表示输出流,它提供了 write 函数,这个函数会将 buffer 中的数据写入到绑定的流中。
特别的,有一些输出流的 write 不会立即写到外存中,而是有一定的缓冲策略,只有当符合条件或主动调用 flush 时才会真实写入,目的是提高性能。
为了统一处理这些 flush 操作,在 OutputStream 中有一个 flush 的默认实现,它有助于抹平 API 调用的差异性。
OutputStream 接口定义:
interface OutputStream {
func write(buffer: Array<Byte>): Unit
func flush(): Unit {
// 空实现
}
}
当拥有一个输出流时,可以写入字节数据。
输出流写入示例:
import std.io.OutputStream
main() {
let output: OutputStream = ...
let buf = Array<Byte>(256, repeat: 111)
output.write(buf)
output.flush()
}
数据流分类
按照数据流职责上的差异,可以将 Stream 简单分成两类:
- 节点流:直接提供数据源,节点流的构造方式通常是依赖某种直接的外部资源(如文件、网络等)。
- 处理流:只能代理其他数据流进行处理,处理流的构造方式通常是依赖其他的流。
I/O 节点流
节点流是指直接提供数据源的流,节点流的构造方式通常是依赖某种直接的外部资源(如文件、网络等)。
仓颉编程语言中常见的节点流包含标准流(ConsoleReader、ConsoleWriter)、文件流(File)、网络流(Socket)等。
本章介绍标准流和文件流。
标准流
标准流包含标准输入流、标准输出流和标准错误输出流。
标准流是程序与外部数据交互的标准接口。程序运行的时候从输入流读取数据,作为程序的输入,程序运行过程中输出的信息被传送到输出流,类似的,错误信息被传送到错误流。
在仓颉编程语言中可以使用 getStdIn、getStdOut、getStdErr 全局函数来分别获取这三个标准流。
使用上面的函数需要导入 env 包:
导入 env 包示例:
import std.env.*
env 包内的 ConsoleReader 和 ConsoleWriter 类型对这三个标准流都进行了易用性封装(标准错误输出流也是输出流,所以一共是两个类型),提供了更方便的基于 String 的扩展操作,并且对于很多常见类型都提供了丰富的重载来优化性能。
其中最重要的是 ConsoleReader 和 ConsoleWriter 类型提供了并发安全的保证,可以在任意线程中安全地通过该类型提供的接口来读写内容。
默认情况下标准输入流来源于键盘输入的信息,例如在命令行界面中输入的文本。
当需要从标准输入流中获取数据时,可以通过 getStdIn 全局函数获取 ConsoleReader 类型,再通过该类型的 readln 函数获取命令行的输入。
标准输入流读取示例:
import std.env.*
main() {
let consoleReader = getStdIn()
let txt = consoleReader.readln()
println(txt ?? "")
}
运行上面的代码,在命令行上输入一些文字,然后换行结束,即可看到输入的内容。
输出流分为标准输出流和标准错误流,默认情况下,它们都会输出到屏幕,例如在命令行界面中看到的文本。
当需要往标准输出流中写入数据时,可以通过 getStdOut/getStdErr 全局函数获取 ConsoleWriter 来写入,例如通过 write 函数来向控制台打印内容。
使用 ConsoleWriter 和直接使用 print 函数的差别是,ConsoleWriter 是并发安全的,并且由于 ConsoleWriter 使用了缓存技术,在输入内容较多时拥有更好的性能表现。
需要注意的是,写完数据后需要对 ConsoleWriter 调用 flush 才能保证内容被完整写到标准流中。
标准输出流写入示例:
import std.env.*
main() {
let consoleWriter = getStdOut()
for (_ in 0..1000) {
consoleWriter.writeln("hello, world!")
}
consoleWriter.flush()
}
文件流
仓颉编程语言提供了 fs 包来支持通用文件系统任务。不同的操作系统对于文件系统提供的接口有所不同。仓颉编程语言抽象出以下一些共通的功能,通过统一的功能接口,屏蔽不同操作系统之间的差异,来简化使用。
常规操作任务包括:创建文件/目录、读写文件、重命名或移动文件/目录、删除文件/目录、复制文件/目录、获取文件/目录元数据、检查文件/目录是否存在。具体 API 可以查阅库文档。
使用文件系统相关的功能需要导入 fs 包:
导入 fs 包示例:
import std.fs.*
本章会着重介绍 File 相关的使用,对于 Path 和 Directory 的使用可以查阅对应的 API 文档。
File 类型在仓颉编程语言中同时提供了常规文件操作和文件流两类功能。
常规文件操作
对于常规的文件操作,可以使用一系列静态函数来完成快捷的操作。
例如如果要检查某个路径对应的文件是否存在,可以使用 exists 函数。当 exists 函数返回 true 时表示文件存在,反之不存在。
exists 函数使用示例:
import std.fs.*
main() {
let exist = exists("./tempFile.txt")
println("exist: ${exist}")
}
移动文件、拷贝文件和删除文件也非常简单,File 同样提供了对应的静态函数 move、copy、delete。
move、copy、delete 函数使用示例:
import std.fs.*
main() {
copy("./tempFile.txt", to: "./tempFile2.txt", overwrite: false)
rename("./tempFile2.txt", to: "./tempFile3.txt", overwrite: false)
remove("./tempFile3.txt")
}
如果需要直接将文件的所有数据读出来,或者一次性将数据写入文件里,可以使用 File 提供的 readFrom、writeTo 函数直接读写文件。在数据量较少的情况下它们既简单易用又能提供较好的性能表现,无需手动处理数据流。
readFrom、writeTo 函数使用示例:
import std.fs.*
main() {
let bytes = File.readFrom("./tempFile.txt") // 一次性读取了所有的数据
File.writeTo("./otherFile.txt", bytes) // 把数据一次性写入另一个文件中
}
文件流操作
除了上述的常规文件操作之外,File 类型也被设计为一种数据流类型,因此 File 类型本身实现了 IOStream 接口。当创建了一个 File 的实例,可以把这个实例当成数据流来使用。
File 类定义:
public class File <: Resource & IOStream & Seekable {
...
}
File 提供了两种构造方式,一种是通过方便的静态函数 create 直接创建新文件的实例,另一种是通过构造函数传入完整的打开文件模式来构造新实例。
其中 create 创建的文件是只写的,不能对实例进行读操作,否则会抛出运行时异常。
File 构造示例:
// 创建
internal import std.fs.*
internal import std.io.*
main() {
let file = File.create("./tempFile.txt")
file.write("hello, world!".toArray())
// 打开
let file2 = File("./tempFile.txt", Read)
let bytes = readToEnd(file2) // 读取所有数据
println(bytes)
}
当需要更精细的打开模式时,可以使用构造函数传入一个 OpenMode 值。OpenMode 是一个 enum 类型,它提供了丰富的文件打开模式,包含 Read、Write、Append 和 ReadWrite 模式。
File 打开模式使用示例:
// 使用指定选项打开模式
let file = File("./tempFile.txt", Write)
因为打开 File 的实例会占用宝贵的系统资源,所以使用完 File 的实例之后需要注意及时关闭 File,以释放系统资源。
File 实现了 Resource 接口,在大多数时候都可以使用 try-with-resource 语法来简化使用。
try-with-resource 语法使用示例:
try (file2 = File("./tempFile.txt", Read)) {
...
// 结束使用后自动释放文件
}
I/O 处理流
处理流是指代理其他数据流进行处理的流。
仓颉编程语言中常见的处理流包含 BufferedInputStream、BufferedOutputStream、StringReader、StringWriter、ChainedInputStream 等。
本章介绍缓冲流和字符串流。
缓冲流
由于涉及磁盘的 I/O 操作相比内存的 I/O 操作要慢很多,所以对于高频次且小数据量的读写操作来说,不带缓冲的数据流效率很低,每次读取和写入数据都会带来大量的 I/O 耗时。而带缓冲的数据流,可以多次读写数据,但不触发磁盘 I/O 操作,只是先放到内存里。等凑够了缓冲区大小的时候再一次性操作磁盘,这种方式可以显著减少磁盘操作次数,从而提升性能表现。
仓颉编程语言标准库提供了 BufferedInputStream 和 BufferedOutputStream 这两个类型用来提供缓冲功能。
使用 BufferedInputStream 和 BufferedOutputStream 类型需要导入 io 包。
导入 io 包示例:
import std.io.*
BufferedInputStream 的作用是为另一个输入流添加缓冲的功能。本质上 BufferedInputStream 是通过一个内部缓冲数组实现的。
当通过 BufferedInputStream 来读取流的数据时,BufferedInputStream 会一次性读取整个缓冲区大小的数据,再使用 read 函数就可以分多次读取更小规模的数据;当缓冲区中的数据被读完之后,输入流就会再次填充缓冲区;如此反复,直到读完数据流的所有数据。
如果构造一个 BufferedInputStream,只需要在构造函数中传入另一个输入流。如果需要指定缓冲区的大小,也可以额外传入 capacity 参数进行指定。
BufferedInputStream 构造示例:
import std.io.{ByteBuffer, BufferedInputStream}
main(): Unit {
let arr1 = "0123456789".toArray()
let byteBuffer = ByteBuffer()
byteBuffer.write(arr1)
let bufferedInputStream = BufferedInputStream(byteBuffer)
let arr2 = Array<Byte>(20, repeat: 0)
/* 读取流中数据,返回读取到的数据的长度 */
let readLen = bufferedInputStream.read(arr2)
println(String.fromUtf8(arr2[..readLen])) // 0123456789
}
BufferedOutputStream 的作用是为另一个输出流添加缓冲的功能。BufferedOutputStream 也是通过一个内部缓冲数组实现的。
当通过 BufferedOutputStream 来向输出流写入数据时,write 的数据会先写入内部缓冲数组中;当缓冲区中的数据被填满之后,BufferedOutputStream 会将缓冲区的数据一次性写入输出流中,然后清空缓冲区再次被写入;如此反复,直到写完所有的数据。
需要注意的是,由于没写够缓冲区时不会触发输出流的写入操作,所以当往 BufferedOutputStream 写完所有的数据后,需要额外调用 flush 函数来最终完成写入。
如果构造一个 BufferedOutputStream,只需要在构造函数中传入另一个输出流。如果需要指定缓冲区的大小,也可以额外传入 capacity 参数指定。
BufferedOutputStream 构造示例:
import std.io.*
main(): Unit {
let arr1 = "01234".toArray()
let byteBuffer = ByteBuffer()
byteBuffer.write(arr1)
let bufferedOutputStream = BufferedOutputStream(byteBuffer)
let arr2 = "56789".toArray()
/* 向流中写入数据,此时数据在外部流的缓冲区中 */
bufferedOutputStream.write(arr2)
/* 调用 flush 函数,真正将数据写入内部流中 */
bufferedOutputStream.flush()
println(String.fromUtf8(readToEnd(byteBuffer))) // 0123456789
}
字符串流
由于仓颉编程语言的输入流和输出流是基于字节数据来抽象的(拥有更好的性能),在部分以字符串为主的场景中使用起来不太友好,例如往文件里写入大量的文本内容时,需要将文本内容转换成字节数据,再写入文件。
为了提供友好的字符串操作能力,仓颉编程语言提供了 StringReader 和 StringWriter 来添加字符串处理能力。
使用 StringReader 和 StringWriter 类型需要导入 io 包:
导入 io 包示例:
import std.io.*
StringReader 提供了按行读、按筛选条件读的能力,相比将字节数据读出来再手动转换成字符串,具有更好的性能表现和易用性。
如果构造 StringReader,传入另一个输入流即可。
StringReader 使用示例:
import std.io.*
main(): Unit {
let arr1 = "012\n346789".toArray()
let byteBuffer = ByteBuffer()
byteBuffer.write(arr1)
let stringReader = StringReader(byteBuffer)
/* 读取一行数据 */
let line = stringReader.readln()
println(line ?? "error") // 012
}
StringWriter 提供了直接写字符串、按行直接写字符串的能力,相比将字节数据手动转换成字符串再写入,具有更好的性能表现和易用性。
如果构造 StringWriter,传入另一个输出流即可。
StringWriter 使用示例:
import std.io.*
main(): Unit {
let byteBuffer = ByteBuffer()
let stringWriter = StringWriter(byteBuffer)
/* 写入字符串 */
stringWriter.write("number")
/* 写入字符串并自动转行 */
stringWriter.writeln(" is:")
/* 写入数字 */
stringWriter.write(100.0f32)
stringWriter.flush()
println(String.fromUtf8(readToEnd(byteBuffer))) // number is:\n100.000000
}
网络编程概述
网络通信是两个设备通过计算机网络进行数据交换的过程。通过编写软件达成网络通信的行为即为网络编程。
仓颉为开发者提供了基础的网络编程功能,在仓颉标准库中,开发者可使用 std 模块下的 socket 包来实现传输层网络通信。
在传输层协议中,分为不可靠传输和可靠传输两种,仓颉将其抽象为 DatagramSocket 和 StreamSocket。其中不可靠传输协议常见的是 UDP,可靠传输协议常见的是 TCP,仓颉分别将其抽象为 UdpSocket 和 TcpSocket。另外,仓颉也实现了对传输层 Unix Domain 协议的支持,并支持其通过可靠和不可靠传输两种方式进行通信。
而在应用层协议中,较为常见的是 HTTP 协议,常用于开发 Web 应用程序等。当前 HTTP 协议已有多个版本,仓颉目前支持 HTTP/1.0、HTTP/1.1、HTTP/2.0。
另外,WebSocket 作为一种提升 Web 服务端与客户端间的通信效率的应用层协议,仓颉将其抽象为 WebSocket 对象,并支持从 HTTP 协议升级至 WebSocket 协议。
需要注意的是,仓颉的网络编程是阻塞式的。但被阻塞的是仓颉线程,阻塞中的仓颉线程会将系统线程让渡出去,因此并不会真正阻塞一个系统线程。
Socket 编程
仓颉的 Socket 编程指的是基于传输层协议实现网络传输数据包的功能。
在可靠传输场景下,仓颉分别启动客户端套接字和服务端套接字。客户端套接字必须指定将要连接的远端地址,可选择性地绑定本端地址,在连接成功后,才可以收发报文。而服务端套接字必须绑定本端地址,在绑定成功后,才可以收发报文。
在不可靠传输场景下,套接字无需区分客户端和服务端,仓颉分别启动两个套接字进行数据传输。套接字必须绑定本端地址,绑定成功后,才可以收发报文。并且,套接字也可选择性地指定远端连接地址,指定后将仅接受指定的远端地址的报文,同时在 send 时无需指定远端地址,报文将发送至成功连接的地址。
TCP 编程
TCP 作为一种常见的可靠传输协议,以 TCP 类型套接字举例,仓颉在可靠传输场景下的可参考的编程模型如下:
- 创建服务端套接字,并指定本端绑定地址。
- 执行绑定。
- 执行 accept 动作,将阻塞等待,直到获取到一个客户端套接字连接。
- 同步创建客户端套接字,并指定远端的待连接的地址。
- 执行连接。
- 连接成功后,服务端会在 accept 接口返回一个新的套接字,此时服务端可以通过此套接字进行读写操作,即收发报文。客户端则可以直接进行读写操作。
TCP 服务端和客户端程序示例如下:
import std.time.*
import std.sync.*
import std.net.*
var SERVER_PORT: UInt16 = 0
func runTcpServer() {
try (serverSocket = TcpServerSocket(bindAt: SERVER_PORT)) {
serverSocket.bind()
SERVER_PORT = (serverSocket.localAddress as IPSocketAddress)?.port ?? 0
try (client = serverSocket.accept()) {
let buf = Array<Byte>(10, repeat: 0)
let count = client.read(buf)
// 服务端读取到的数据为: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
println("Server read ${count} bytes: ${buf}")
}
}
}
main(): Int64 {
let future = spawn {
runTcpServer()
}
sleep(Duration.millisecond * 500)
try (socket = TcpSocket("127.0.0.1", SERVER_PORT)) {
socket.connect()
socket.write([1, 2, 3])
}
future.get()
return 0
}
编译执行上述代码,将打印:
Server read 3 bytes: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
UDP 编程
UDP 作为一种常见的不可靠传输协议,以 UDP 类型套接字举例,仓颉在不可靠传输场景下的可参考的编程模型如下:
- 创建套接字,并指定本端绑定地址。
- 执行绑定。
- 指定远端地址进行报文发送。
- 不连接远端地址场景下,可以收取来自不同远端地址的报文,并返回远端地址信息。
UDP 收发报文程序示例如下:
import std.time.*
import std.sync.*
import std.net.*
let SERVER_PORT: UInt16 = 8080
func runUpdServer() {
try (serverSocket = UdpSocket(bindAt: SERVER_PORT)) {
serverSocket.bind()
let buf = Array<Byte>(3, repeat: 0)
let (clientAddr, count) = serverSocket.receiveFrom(buf)
let sender = (clientAddr as IPSocketAddress)?.address.toString() ?? ""
// Server receive 3 bytes: [1, 2, 3] from 127.0.0.1
println("Server receive ${count} bytes: ${buf} from ${sender}")
}
}
main(): Int64 {
let future = spawn {
runUpdServer()
}
sleep(Duration.second)
try (udpSocket = UdpSocket(bindAt: 0)) {
udpSocket.sendTimeout = Duration.second * 2
udpSocket.bind()
udpSocket.sendTo(
IPSocketAddress("127.0.0.1", SERVER_PORT),
[1, 2, 3]
)
}
future.get()
return 0
}
编译执行上述代码,将打印:
Server receive 3 bytes: [1, 2, 3] from 127.0.0.1
HTTP 编程
HTTP 作为一种通用的应用层协议,通过请求-响应的机制实现数据传输,客户端发送请求,服务端返回响应。请求和响应的格式是固定的,由报文头和报文体组成。
常用的请求类型为 GET 和 POST,GET 请求只有报文头,用于向服务器请求应用层数据,POST 请求带有报文体,以一个空行与报文头进行分隔,用于向服务器提供应用层数据。
请求-响应的报文头字段内容较多,此处不再一一赘述,仓颉支持 HTTP 1.0/1.1/2.0 等协议版本,开发者可以基于协议 RFC 9110、9112、9113、9218、7541 以及仓颉所提供的 HttpRequestBuilder 和 HttpResponseBuilder 类构造请求及响应报文。
以下示例展示了如何使用仓颉进行客户端和服务端编程,实现的功能是客户端发送请求头为 GET /hello 的请求,服务端返回响应,响应体为 "Hello Cangjie!",代码如下:
说明:
net、log 等库已从仓颉 SDK 移到 stdx 模块,使用前需要下载软件包,并在 cjpm.toml 中配置。
import stdx.net.http.*
import std.time.*
import std.sync.*
import stdx.log.*
// 1. 构建 Server 实例
let server = ServerBuilder()
.addr("127.0.0.1")
.port(0)
.build()
func startServer(): Unit {
// 2. 注册请求处理逻辑
server.distributor.register("/hello", {httpContext =>
httpContext.responseBuilder.body("Hello Cangjie!")
})
server.logger.level = LogLevel.OFF
// 3. 启动服务
server.serve()
}
func startClient(): Unit {
// 1. 构建 client 实例
let client = ClientBuilder().build()
// 2. 发送 request
let response = client.get("http://127.0.0.1:${server.port}/hello")
// 3. 读取response body
let buffer = Array<Byte>(32, repeat: 0)
let length = response.body.read(buffer)
println(String.fromUtf8(buffer[..length]))
// 4. 关闭连接
client.close()
}
main () {
spawn {
startServer()
}
sleep(Duration.second)
startClient()
}
编译执行上述代码,将打印:
Hello Cangjie!
WebSocket 编程
在网络编程中,WebSocket 是一种常用的应用层协议。与 HTTP 一样,它也基于 TCP 协议之上,并且常用于 web 服务端应用开发。
不同于 HTTP 的是, WebSocket 只需要客户端和服务端进行一次握手,即可创建长久的连接,并且进行双向的数据传输。即基于 WebSocket 实现的服务端可以主动传输数据给客户端,从而实现实时通讯。
WebSocket 是一个独立的协议,它与 HTTP 的关联在于,它的握手被 HTTP 服务端解释为一个升级请求。因此,仓颉将 WebSocket 包含在 http 包中。
仓颉将 WebSocket 协议通信机制抽象为 WebSocket 类,提供方法将一个 http/1.1 或 http/2.0 服务端句柄升级到 WebSocket 协议实例,通过返回的 WebSocket 实例进行 WebSocket 通信,例如数据报文的读写。
在仓颉中,WebSocket 所传输的数据基本单元称为帧,帧分为两类,一类为传输控制信息的帧,即 Close Frame 用于关闭连接, Ping Frame 用于实现 Keep-Alive , Pong Frame 是 Ping Frame 的响应类型,另一类是传输应用数据的帧,应用数据帧支持分段传输。
仓颉的帧由三个属性构成,其中 fin 和 frameType 共同说明了帧是否分段和帧的类型,payload 为帧的载荷,除此之外开发者无需关心其他属性即可进行报文传输。
如下示例展示了 WebSocket 的握手以及消息收发过程:创建 HTTP 客户端和服务端,分别发起 WebSocket 升级(或握手),握手成功后开始帧的读写。
说明:
net、encoding、log 等库已从仓颉 SDK 移到 stdx 模块,使用前需要下载软件包,并在 cjpm.toml 中配置。
import stdx.net.http.*
import stdx.encoding.url.*
import std.time.*
import std.sync.*
import std.collection.*
import stdx.log.*
let server = ServerBuilder()
.addr("127.0.0.1")
.port(0)
.build()
// client:
main() {
// 1 启动服务器
spawn { startServer() }
sleep(Duration.millisecond * 200)
let client = ClientBuilder().build()
let u = URL.parse("ws://127.0.0.1:${server.port}/webSocket")
let subProtocol = ArrayList<String>(["foo1", "bar1"])
let headers = HttpHeaders()
headers.add("test", "echo")
// 2 完成 WebSocket 握手,获取 WebSocket 实例
let websocket: WebSocket
let respHeaders: HttpHeaders
(websocket, respHeaders) = WebSocket.upgradeFromClient(client, u, subProtocols: subProtocol, headers: headers)
client.close()
println("subProtocol: ${websocket.subProtocol}") // fool1
println(respHeaders.getFirst("rsp") ?? "") // echo
// 3 消息收发
// 发送 hello
websocket.write(TextWebFrame, "hello".toArray())
// 收
let data = ArrayList<UInt8>()
var frame = websocket.read()
while(true) {
match(frame.frameType) {
case ContinuationWebFrame =>
data.add(all: frame.payload)
if (frame.fin) {
break
}
case TextWebFrame | BinaryWebFrame =>
if (!data.isEmpty()) {
throw Exception("invalid frame")
}
data.add(all: frame.payload)
if (frame.fin) {
break
}
case CloseWebFrame =>
websocket.write(CloseWebFrame, frame.payload)
break
case PingWebFrame =>
websocket.writePongFrame(frame.payload)
case _ => ()
}
frame = websocket.read()
}
println("data size: ${data.size}") // 4097
println("last item: ${String.fromUtf8(data.toArray()[4096])}") // a
// 4 关闭 websocket,
// 收发 CloseFrame
websocket.writeCloseFrame(status: 1000)
let websocketFrame = websocket.read()
println("close frame type: ${websocketFrame.frameType}") // CloseWebFrame
println("close frame payload: ${websocketFrame.payload}") // 3, 232
// 关闭底层连接
websocket.closeConn()
server.close()
}
func startServer() {
// 1 注册 handler
server.distributor.register("/webSocket", handler1)
server.logger.level = LogLevel.OFF
server.serve()
}
// server:
func handler1(ctx: HttpContext): Unit {
// 2 完成 websocket 握手,获取 websocket 实例
let websocketServer = WebSocket.upgradeFromServer(ctx, subProtocols: ArrayList<String>(["foo", "bar", "foo1"]),
userFunc: {request: HttpRequest =>
let value = request.headers.getFirst("test") ?? ""
let headers = HttpHeaders()
headers.add("rsp", value)
headers
})
// 3 消息收发
// 收 hello
let data = ArrayList<UInt8>()
var frame = websocketServer.read()
while(true) {
match(frame.frameType) {
case ContinuationWebFrame =>
data.add(all: frame.payload)
if (frame.fin) {
break
}
case TextWebFrame | BinaryWebFrame =>
if (!data.isEmpty()) {
throw Exception("invalid frame")
}
data.add(all: frame.payload)
if (frame.fin) {
break
}
case CloseWebFrame =>
websocketServer.write(CloseWebFrame, frame.payload)
break
case PingWebFrame =>
websocketServer.writePongFrame(frame.payload)
case _ => ()
}
frame = websocketServer.read()
}
println("data: ${String.fromUtf8(data.toArray())}") // hello
// 发 4097 个 a
websocketServer.write(TextWebFrame, Array<UInt8>(4097, repeat: 97))
// 4 关闭 websocket,
// 收发 CloseFrame
let websocketFrame = websocketServer.read()
println("close frame type: ${websocketFrame.frameType}") // CloseWebFrame
println("close frame payload: ${websocketFrame.payload}") // 3, 232
websocketServer.write(CloseWebFrame, websocketFrame.payload)
// 关闭底层连接
websocketServer.closeConn()
}
该示例运行结果如下:
subProtocol: foo1
echo
data: hello
data size: 4097
last item: a
close frame type: CloseWebFrame
close frame payload: [3, 232]
close frame type: CloseWebFrame
close frame payload: [3, 232]
宏的简介
宏可以理解为一种特殊的函数。一般的函数在输入的值上进行计算,然后输出一个新的值,而宏的输入和输出都是程序本身。在输入一段程序后,输出一段新的程序,这段输出的程序随后用于编译和执行。为了把宏的调用和函数调用区分开来,在调用宏时需使用 @ 加上宏的名称。
如下示例代码希望实现在调试过程中打印某个表达式的值,同时打印出表达式本身。
let x = 3
let y = 2
@dprint(x) // 打印 "x = 3"
@dprint(x + y) // 打印 "x + y = 5"
显然,dprint 不能被写为常规的函数,因为函数只能获得输入表达式的值,不能获得输入表达式本身。但是,可以将 dprint 实现为一个宏来获取输入表达式的程序片段。一个基本的实现如下:
macro package define
import std.ast.*
public macro dprint(input: Tokens): Tokens {
let inputStr = input.toString()
let result = quote(
print($(inputStr) + " = ")
println($(input)))
return result
}
在解释每行代码之前,先测试这个宏可以达到预期的效果。首先,在当前目录下创建一个 define 文件夹,并在 define 文件夹中创建 dprint.cj 文件,将以上内容复制到 dprint.cj 文件中。另外在当前目录下创建 main.cj,包含以下测试代码:
import define.*
main() {
let x = 3
let y = 2
@dprint(x)
@dprint(x + y)
}
请注意,得到的目录结构如下:
// Directory layout.
src
|-- define
| `-- dprint.cj
`-- main.cj
在当前目录(src)下,运行编译命令:
cjc define/*.cj --compile-macro
cjc main.cj -o main
然后运行 ./main,可以看到如下输出:
x = 3
x + y = 5
依次查看代码的每个部分:
-
第 1 行:
macro package define宏必须声明在独立的包中(不能和其他 public 函数一起),含有宏的包使用
macro package来声明。这里声明了一个名为define的宏包。 -
第 2 行:
import std.ast.*实现宏需要的数据类型,例如
Tokens和后面会讲到的语法节点类型,位于仓颉标准库的ast包中,因此任何宏的实现都需要首先引入ast包。 -
第 3 行:
public macro dprint(input: Tokens): Tokens在这里声明一个名为
dprint的宏。由于这个宏是一个非属性宏(之后会解释这个概念),它接受一个类型为Tokens的参数。该输入代表传给宏的程序片段。宏的返回值也是一个程序片段。 -
第 4 行:
let inputStr = input.toString()在宏的实现中,首先将输入的程序片段转化为字符串。在前面的测试案例中,
inputStr成为"x"或"x + y" -
第 5-7 行:
let result = quote(...)这里
quote表达式是用于构造Tokens的一种表达式,它将括号内的程序片段转换为Tokens。在quote的输入中,可以使用插值$(...)来将括号内的表达式转换为Tokens,然后插入到quote构建的Tokens中。对于以上代码,$(inputStr)中插入了inputStr字符串的值(包含字符串两端的引号),$(input)中插入了input,即输入的程序片段。因此,如果输入的表达式是x + y,那么形成的Tokens为:print("x + y" + " = ") println(x + y) -
第 8 行:
return result最后,将构造出来的代码片段返回,这两行代码片段将被编译,运行时将输出
x + y = 5。
回顾 dprint 宏的定义,dprint 使用 Tokens 作为入参,并使用 quote 和插值构造了另一个 Tokens 作为返回值。为了使用宏,需要详细了解 Tokens、quote 和插值的概念,下面将分别介绍它们。
Tokens 相关类型和 quote 表达式
Token 类型
宏操作的基本类型是 Tokens,代表一个程序片段。Tokens 由若干个 Token 组成,每个 Token 可以理解为用户可操作的词法单元。一个 Token 可能是一个标识符(例如变量名等)、字面量(例如整数、浮点数、字符串)、关键字或运算符。每个 Token 包含它的类型、内容和位置信息。
Token 的类型取值为 enum TokenKind 中的元素。TokenKind 的可用值详见《仓颉编程语言库 API》文档。通过提供 TokenKind 和 Token 的值(TokenKind 对应的标识符或字面量),可以直接构造任何 Token。具体的构造函数如下:
Token(k: TokenKind)
Token(k: TokenKind, v: String)
下面给出一些Token构造的例子:
import std.ast.*
let tk1 = Token(TokenKind.ADD) // '+' 运算符
let tk2 = Token(TokenKind.FUNC) // func 关键字
let tk3 = Token(TokenKind.IDENTIFIER, "x") // x 标识符
let tk4 = Token(TokenKind.INTEGER_LITERAL, "3") // 整数字面量
let tk5 = Token(TokenKind.STRING_LITERAL, "xyz") // 字符串字面量
Tokens 类型
一个 Tokens 代表由多个 Token 组成的序列。可以通过 Token 数组直接构造 Tokens。下面是 3 种基本的构造 Tokens 实例的方式:
Tokens() // 构造空列表
Tokens(tks: Array<Token>)
Tokens(tks: ArrayList<Token>)
此外,Tokens 类型支持以下功能:
size:返回Tokens中包含Token的数量get(index: Int64):获取指定下标的Token元素[]:获取指定下标的Token元素+:拼接两个Tokens,或者直接拼接Tokens和Tokendump():打印包含的所有Token,供调试使用toString():打印Tokens对应的程序片段
在下面的案例中,使用构造函数直接构造 Token 和 Tokens,然后打印详细的调试信息:
import std.ast.*
let tks = Tokens([
Token(TokenKind.INTEGER_LITERAL, "1"),
Token(TokenKind.ADD),
Token(TokenKind.INTEGER_LITERAL, "2")
])
main() {
println(tks)
tks.dump()
}
预期输出如下(具体的位置信息可能不同):
1 + 2
description: integer_literal, token_id: 140, token_literal_value: 1, fileID: 1, line: 4, column: 5
description: add, token_id: 12, token_literal_value: +, fileID: 1, line: 5, column: 5
description: integer_literal, token_id: 140, token_literal_value: 2, fileID: 1, line: 6, column: 5
在 dump 信息中,包含了每个 Token 的类型(description)和值(token_literal_value),最后打印每个 Token 的位置信息。
quote 表达式和插值
在大多数情况下,直接构造和拼接 Tokens 会比较繁琐。因此,仓颉语言提供了 quote 表达式来从代码模板构造 Tokens。之所以说是代码模板,因为在 quote 中可以使用 $(...) 来插入上下文中的表达式。插入的表达式的类型需要支持被转换为 Tokens(具体来说,实现了 ToTokens 接口)。在标准库中,以下类型实现了 ToTokens 接口:
- 所有的节点类型(节点将在语法节点中讨论)
Token和Tokens类型- 所有基础数据类型:整数、浮点数、
Bool、Rune和String Array<T>和ArrayList<T>,这里对T的类型有限制,并根据T的类型不同,输出不同的分隔符,详细请见《仓颉编程语言库 API》文档。
下面的例子展示 Array 和基础数据类型的插值:
import std.ast.*
let intList: Array<Int64> = [1, 2, 3, 4, 5]
let float: Float64 = 1.0
let str: String = "Hello"
let tokens = quote(
arr = $(intList)
x = $(float)
s = $(str)
)
main() {
println(tokens)
}
输出结果是:
arr =[1, 2, 3, 4, 5]
x = 1.0
s = "Hello"
更多插值的用法可以参考 使用 quote 插值语法节点。
特别地,当 quote 表达式包含某些特殊 Token 时,需要进行转义:
quote表达式中不允许出现不匹配的小括号,但是通过\转义的小括号,不计入小括号的匹配规则。- 当
$表示一个普通Token,而非用于代码插值时,需要通过\进行转义。 - 除以上情况外,
quote表达式中出现\会编译报错。
注意:
#符号仅能用于构造多行原始字符串字面量,不支持单独使用。
下面是一些 quote 表达式内包含这些特殊 Token 的例子:
import std.ast.*
let tks1 = quote((x)) // ok
let tks2 = quote(\() // ok
let tks3 = quote( ( \) ) ) // ok
let tks4 = quote()) // error: unmatched delimiter: ')'
let tks5 = quote( ( \) ) // error: unclosed delimiter: '('
let tks6 = quote(\$(1)) // ok
let tks7 = quote(\x) // error: unknown start of token: \
let tks8 = quote(#) // error: expected '#' or '"' in raw string
语法节点
在仓颉语言的编译过程中,首先通过词法分析将代码转换成 Tokens,然后对 Tokens 进行语法解析,得到一个语法树。每个语法树的节点可能是一个表达式、声明、类型、模式等。仓颉标准库 std.ast 包提供了每种节点对应的类,它们之间具有适当的继承关系。其中,主要的抽象类如下:
Node:所有语法节点的父类TypeNode:所有类型节点的父类Expr:所有表达式节点的父类Decl:所有声明节点的父类Pattern:所有模式节点的父类
具体节点的类型众多,具体细节请参见《仓颉编程语言库 API》。在下面的案例中,主要使用以下节点:
BinaryExpr:二元运算表达式FuncDecl:函数的声明
节点的解析
通过标准库 std.ast 包,基本上每种节点都可以从 Tokens 解析。有两种解析 Tokens 并构造语法节点的方法。
使用解析函数来解析 Tokens
以下函数用于从 Tokens 解析并构造任意的语法节点:
parseExpr(input: Tokens): Expr:将输入的Tokens解析为表达式节点。parseExprFragment(input: Tokens, startFrom!: Int64 = 0): (Expr, Int64):将输入Tokens的一个片段解析为表达式节点,片段从startFrom索引开始,解析可能只消耗从索引startFrom开始的片段的一部分,并返回第一个未被消耗的Token的索引(如果消耗了整个片段,返回值为input.size)。parseDecl(input: Tokens, astKind!: String = ""):将输入的Tokens解析为声明节点,astKind为额外的设置,具体请参见《仓颉编程语言库 API》文档。parseDeclFragment(input: Tokens, startFrom!: Int64 = 0): (Decl, Int64):将输入Tokens的一个片段解析为声明节点,startFrom参数和返回索引的含义和parseExpr相同。parseType(input: Tokens): TypeNode:将输入的Tokens解析为类型节点。parseTypeFragment(input: Tokens, startFrom!: Int64 = 0): (TypeNode, Int64):将输入Tokens的一个片段解析为类型节点,startFrom参数和返回索引的含义和parseExpr相同。parsePattern(input: Tokens): Pattern:将输入的Tokens解析为模式节点。parsePatternFragment(input: Tokens, startFrom!: Int64 = 0): (Pattern, Int64):将输入Tokens的一个片段解析为模式节点,startFrom参数和返回索引的含义和parseExpr相同。
如果解析失败将抛出异常。这种解析方式适用于类型未知的代码片段,如果需要获取具体的子类型节点,需要将解析结果手动转换成具体的子类型。
这些函数的使用如下例所示:
let tks1 = quote(a + b)
let tks2 = quote(u + v, x + y)
let tks3 = quote(
func f1(x: Int64) { return x + 1 }
)
let tks4 = quote(
func f2(x: Int64) { return x + 2 }
func f3(x: Int64) { return x + 3 }
)
let binExpr1 = parseExpr(tks1)
let (binExpr2, mid) = parseExprFragment(tks2)
let (binExpr3, _) = parseExprFragment(tks2, startFrom: mid + 1) // 跳过逗号
println("binExpr1 = ${binExpr1.toTokens()}")
println("binExpr2 = ${binExpr2.toTokens()}, binExpr3 = ${binExpr3.toTokens()}")
let funcDecl1 = parseDecl(tks3)
let (funcDecl2, mid2) = parseDeclFragment(tks4)
let (funcDecl3, _) = parseDeclFragment(tks4, startFrom: mid2)
println("${funcDecl1.toTokens()}")
println("${funcDecl2.toTokens()}")
println("${funcDecl3.toTokens()}")
输出结果是:
binExpr1 = a + b
binExpr2 = u + v, binExpr3 = x + y
func f1(x: Int64) {
return x + 1
}
func f2(x: Int64) {
return x + 2
}
func f3(x: Int64) {
return x + 3
}
使用语法节点的构造函数来解析 Tokens
大多数语法节点都支持 init(input: Tokens) 构造函数,将输入的 Tokens 解析为相应类型的节点,例如:
import std.ast.*
let binExpr = BinaryExpr(quote(a + b))
let funcDecl = FuncDecl(quote(func f1(x: Int64) { return x + 1 }))
如果解析失败将抛出异常。这种解析方式适用于类型已知的代码片段,解析后不需要再手动转换成具体的子类型。
节点的组成部分
从 Tokens 解析出节点之后,可以查看节点的组成部分。作为例子,仅列出 BinaryExpr 和 FuncDecl 的组成部分,关于其他节点的更详细的解释请参见《仓颉编程语言库 API》文档。
BinaryExpr节点:leftExpr: Expr:运算符左侧的表达式op: Token:运算符rightExpr: Expr:运算符右侧的表达式
FuncDecl节点(部分):identifier: Token:函数名funcParams: ArrayList<FuncParam>:参数列表declType: TypeNode:返回值类型block: Block:函数体
FuncParam节点(部分):identifier: Token:参数名paramType: TypeNode:参数类型
Block节点(部分):nodes: ArrayList<Node>:块中的表达式和声明
每个组成部分都是 public mut prop,因此可以被查看和更新。通过一些例子展示更新的结果。
BinaryExpr 案例
let binExpr = BinaryExpr(quote(x * y))
binExpr.leftExpr = BinaryExpr(quote(a + b))
println(binExpr.toTokens())
binExpr.op = Token(TokenKind.ADD)
println(binExpr.toTokens())
输出结果是:
(a + b) * y
a + b + y
首先,通过解析,获得 binExpr 为节点 x * y,图示如下:
*
/ \
x y
第二步,将左侧的节点(即 x)替换为 a + b,因此,获得的语法树如下:
*
/ \
+ y
/ \
a b
当输出这个语法树的时候,必须在 a + b 周围添加括号,得到 (a + b) * y(如果输出a + b * y,含义为先做乘法,再做加法,与语法树的含义不同)。ast 库具备在输出语法树时自动添加括号的功能。
第三步,将语法树根部的运算符从 * 替换为 +,因此得到语法树如下:
+
/ \
+ y
/ \
a b
这个语法树可以输出为 a + b + y,因为加法本身就是左结合的,不需要在左侧添加括号。
FuncDecl 案例
let funcDecl = FuncDecl(quote(func f1(x: Int64) { x + 1 }))
funcDecl.identifier = Token(TokenKind.IDENTIFIER, "foo")
println("Number of parameters: ${funcDecl.funcParams.size}")
funcDecl.funcParams[0].identifier = Token(TokenKind.IDENTIFIER, "a")
println("Number of nodes in body: ${funcDecl.block.nodes.size}")
let binExpr = (funcDecl.block.nodes[0] as BinaryExpr).getOrThrow()
binExpr.leftExpr = parseExpr(quote(a))
println(funcDecl.toTokens())
在这个案例中,首先通过解析构造出了一个 FuncDecl 节点,然后分别修改了该节点的函数名、参数名,以及函数体中表达式的一部分。输出结果是:
Number of parameters: 1
Number of nodes in body: 1
func foo(a: Int64) {
a + 1
}
使用 quote 插值语法节点
任何语法节点都可以在 quote 语句中插值,部分语法节点的 ArrayList 列表也可以被插值(主要对应实际情况中会出现这类节点列表的情况)。插值直接通过 $(node) 表达即可,其中 node 是任意节点类型的实例。
下面,通过一些案例展示节点的插值。
var binExpr = BinaryExpr(quote(1 + 2))
let a = quote($(binExpr))
let b = quote($binExpr)
let c = quote($(binExpr.leftExpr))
let d = quote($binExpr.leftExpr)
println("a: ${a.toTokens()}")
println("b: ${b.toTokens()}")
println("c: ${c.toTokens()}")
println("d: ${d.toTokens()}")
输出结果是:
a: 1 + 2
b: 1 + 2
c: 1
d: 1 + 2.leftExpr
一般来说,插值运算符后面的表达式使用小括号限定作用域,例如 $(binExpr)。但是当后面只跟单个标识符的时候,小括号可省略,即可写为 $binExpr。因此,在案例中 a 和 b 都在 quote 中插入了 binExpr节点,结果为 1 + 2。然而,如果插值运算符后面的表达式更复杂,不加小括号可能造成作用域出错。例如,表达式 binExpr.leftExpr 求值为 1 + 2 的左表达式,即 1,因此 c 正确赋值为 1。但 d 中的插值被解释为 ($binExpr).leftExpr,因此结果是 1 + 2.leftExpr。为了明确插值的作用域,推荐在插值运算符中使用小括号。
下面的案例展示节点列表(ArrayList)的插值。
var incrs = ArrayList<Node>()
for (i in 1..=5) {
incrs.add(parseExpr(quote(x += $(i))))
}
var foo = quote(
func foo(n: Int64) {
let x = n
$(incrs)
x
})
println(foo)
输出结果是:
func foo(n: Int64) {
let x = n
x += 1
x += 2
x += 3
x += 4
x += 5
x
}
在这个案例中,创建了一个节点列表 incrs,包含表达式 x += 1,...,x += 5。对 incrs 的插值将节点依次列出,在每个节点后换行。这适用于插入需要依次执行的表达式和声明的情况。
下面的案例展示在某些情况下,需要在插值周围添加括号,以保证正确性。
var binExpr1 = BinaryExpr(quote(x + y))
var binExpr2 = BinaryExpr(quote($(binExpr1) * z)) // 错误:得到 x + y * z
println("binExpr2: ${binExpr2.toTokens()}")
println("binExpr2.leftExpr: ${binExpr2.leftExpr.toTokens()}")
println("binExpr2.rightExpr: ${binExpr2.rightExpr.toTokens()}")
var binExpr3 = BinaryExpr(quote(($(binExpr1)) * z)) // 正确:得到 (x + y) * z
println("binExpr3: ${binExpr3.toTokens()}")
输出结果是:
binExpr2: x + y * z
binExpr2.leftExpr: x
binExpr2.rightExpr: y * z
binExpr3: (x + y) * z
首先,构建表达式 x + y,然后将该表达式插入到模板 $(binExpr1) * z 中。这里的意图是得到一个先计算 x + y 再乘 z 的表达式,但是,插值的结果是 x + y * z,即先计算 y * z 再加 x。这是因为插值不会自动添加括号以保证被插入的表达式的原子性(这和前一节介绍的 leftExpr 的替换不同)。因此,需要在 $(binExpr1) 周围添加小括号,保证得到正确的结果。
宏的实现
本章节介绍仓颉宏的定义和使用,仓颉宏可以分为非属性宏和属性宏。同时本章节还会介绍宏出现嵌套时的行为。
注意:
在宏的定义中使用 I/O 操作,如文件操作,网络通信等,可能产生不可预期的行为,请谨慎使用。
非属性宏
非属性宏只接受被转换的代码,不接受其他参数(属性),其定义格式如下:
import std.ast.*
public macro MacroName(args: Tokens): Tokens {
... // Macro body
}
宏的调用格式如下:
@MacroName(...)
宏调用使用 () 括起来。括号里面可以是任意合法 Tokens,也可以是空。
当宏作用于声明时,一般可以省略括号。参考如下示例:
@MacroName func name() {} // Before a FuncDecl
@MacroName struct name {} // Before a StructDecl
@MacroName class name {} // Before a ClassDecl
@MacroName var a = 1 // Before a VarDecl
@MacroName enum e {} // Before a Enum
@MacroName interface i {} // Before a InterfaceDecl
@MacroName extend e <: i {} // Before a ExtendDecl
@MacroName mut prop i: Int64 {} // Before a PropDecl
@MacroName @AnotherMacro(input) // Before a macro call
对于括号里 Tokens 的合法性有以下特殊说明:
-
输入的内容必须是由合法的
Token组成的序列,类似 "#"、" ` "、"\" 等符号单独使用都不是合法的仓颉Token,不支持其作为输入值。 -
输入的内容中,若存在不匹配的小括号则必须使用转义符号 "\" 对其进行转义。
-
输入的内容中,若希望 "@" 作为输入的
Token则必须使用转义符号 "\" 对其进行转义。
对于输入的特殊说明,可以参考如下示例:
// Illegal input Tokens
@MacroName(#) // Not a whole Token
@MacroName(`) // Not a whole Token
@MacroName(() // ( and ) not match
@MacroName(\[) // Escape for unsupported symbol
// Legal input Tokens
@MacroName(#"abc"#)
@MacroName(`class`)
@MacroName([)
@MacroName([])
@MacroName(\()
@MacroName(\@)
宏展开过程作用于仓颉语法树,宏展开后,编译器会继续进行后续的编译过程。因此,需要注意以下规则:
- 宏展开后的代码依然是合法的仓颉代码,并且宏展开后的代码不允许出现包的声明与导入语句,否则可能引发编译问题。
- 当宏用于声明时,如果省略括号,宏的输入必须是语法合法的声明。
下面是几个宏应用的典型示例。
-
示例 1
宏定义文件
macro_definition.cjmacro package macro_definition import std.ast.* public macro testDef(input: Tokens): Tokens { println("I'm in macro body") return input }宏调用文件
macro_call.cjpackage macro_calling import macro_definition.* main(): Int64 { println("I'm in function body") let a: Int64 = @testDef(1 + 2) println("a = ${a}") return 0 }上述代码的编译过程可以参考宏的编译和使用。
在用例中添加了打印信息,其中宏定义中的
I'm in macro body将在编译macro_call.cj的期间输出。同时,宏调用点被展开,如编译如下代码:let a: Int64 = @testDef(1 + 2)编译器将宏返回的
Tokens更新到调用点的语法树上,得到如下代码:let a: Int64 = 1 + 2也就是说,可执行程序中的代码实际变为了:
main(): Int64 { println("I'm in function body") let a: Int64 = 1 + 2 println("a = ${a}") return 0 }a经过计算得到的值为 3,在打印a的值时插值为 3。至此,上述程序的运行结果为:I'm in function body a = 3
下面看一个更有意义的用宏处理函数的例子,这个宏 ModifyFunc 宏的作用是给 myFunc 增加 id 参数,并在 counter++ 前后插入一段代码。
-
示例 2
宏定义文件
macro_definition.cj// file macro_definition.cj macro package macro_definition import std.ast.* public macro ModifyFunc(input: Tokens): Tokens { println("I'm in macro body") let funcDecl = FuncDecl(input) return quote( func $(funcDecl.identifier)(id: Int64) { println("start ${id}") $(funcDecl.block.nodes) println("end") }) }宏调用文件
macro_call.cjpackage macro_calling import macro_definition.* var counter = 0 @ModifyFunc func myFunc() { counter++ } func exModifyFunc() { println("I'm in function body") myFunc(123) println("myFunc called: ${counter} times") return 0 } main(): Int64 { exModifyFunc() }同样的,上述两段代码分别位于不同文件中,先编译宏定义文件
macro_definition.cj,再编译宏调用macro_call.cj生成可执行文件。这个例子中,ModifyFunc 宏的输入是一个函数声明,因此可以省略括号:
@ModifyFunc func myFunc() { counter++ }经过宏展开后,得到如下代码:
func myFunc(id: Int64) { println("start ${id}") counter++ println("end") }myFunc 会在 main 中调用,它接受的实参也是在 main 中定义的,从而形成了一段合法的仓颉程序。运行时打印如下:
I'm in function body start 123 end myFunc called: 1 times
属性宏
和非属性宏相比,属性宏的定义会增加一个 Tokens 类型的输入,这个增加的入参可以让开发者输入额外的信息。比如开发者可能希望在不同的调用场景下使用不同的宏展开策略,则可以通过这个属性入参进行标记位设置。同时,这个属性入参也可以传入任意 Tokens,这些 Tokens 可以与被宏修饰的代码进行组合拼接等。下面是一个简单的例子:
// Macro definition with attribute
public macro Foo(attrTokens: Tokens, inputTokens: Tokens): Tokens {
return attrTokens + inputTokens // Concatenate attrTokens and inputTokens.
}
如上面的宏定义,属性宏的入参数量为 2,入参类型为 Tokens,在宏定义内,可以对 attrTokens 和 inputTokens 进行一系列的组合、拼接等变换操作,最后返回新的 Tokens。
带属性的宏与不带属性的宏的调用类似,属性宏调用时新增的入参 attrTokens 通过 [] 传入,其调用形式为:
// attribute macro with parentheses
var a: Int64 = @Foo[1+](2+3)
// attribute macro without parentheses
@Foo[public]
struct Data {
var count: Int64 = 100
}
-
宏 Foo 调用,当参数是
2+3时,与[]内的属性1+进行拼接,经过宏展开后,得到var a: Int64 = 1+2+3。 -
宏 Foo 调用,当参数是 struct Data 时,与
[]内的属性public进行拼接,经过宏展开后,得到public struct Data { var count: Int64 = 100 }
关于属性宏,需要注意以下几点:
-
带属性的宏,与不带属性的宏相比,能修饰的 AST 是相同的,可以理解为带属性的宏对可传入参数做了增强。
-
属性宏小括号内的参数合法性规则与非属性宏的参数合法性规则一致。
-
属性宏中括号内的参数(属性)的合法性规则有如下特殊说明:
-
输入的内容必须是由合法的
Token组成的序列,类似 "#"、" ` "、"\" 等符号单独使用都不是合法的仓颉Token,不支持其作为输入值。 -
输入的内容中,若存在不匹配的中括号则必须使用转义符号 "\" 对其进行转义。
-
输入的内容中,若希望 "@" 作为输入的
Token则必须使用转义符号 "\" 对其进行转义。
// Illegal attribute Tokens @MacroName[#]() // Not a whole Token @MacroName[`]() // Not a whole Token @MacroName[@]() // Not escape for @ @MacroName[[]() // [ and ] not match @MacroName[\(]() // Escape for unsupported symbol // Legal attribute Tokens @MacroName[#"abc"#]() @MacroName[`class`]() @MacroName[(]() @MacroName[()]() @MacroName[\[]() @MacroName[\@]() -
-
宏的定义和调用的类型要保持一致:如果宏定义有两个入参,即为属性宏定义,调用时必须加上
[],且内容可以为空;如果宏定义有一个入参,即为非属性宏定义,调用时不能使用[]。
嵌套宏
仓颉语言不支持宏定义的嵌套;有条件地支持在宏定义和宏调用中嵌套宏调用。
宏定义中嵌套宏调用
下面是一个宏定义中包含其他宏调用的例子。
宏包 pkg1 中定义 getIdent 宏:
macro package pkg1
import std.ast.*
public macro getIdent(attr:Tokens, input:Tokens):Tokens {
return quote(
let decl = (parseDecl(input) as VarDecl).getOrThrow()
let name = decl.identifier.value
let size = name.size - 1
let $(attr) = Token(TokenKind.IDENTIFIER, name[0..size])
)
}
宏包 pkg2 中定义 Prop 宏,其中嵌套了 getIdent 宏的调用:
macro package pkg2
import std.ast.*
import pkg1.*
public macro Prop(input:Tokens):Tokens {
let v = parseDecl(input)
@getIdent[ident](input)
return quote(
$(input)
public prop $(ident): $(decl.declType) {
get() {
this.$(v.identifier)
}
}
)
}
宏调用包 pkg3 中调用 Prop 宏:
package pkg3
import pkg2.*
class A {
@Prop
private let a_: Int64 = 1
}
main() {
let b = A()
println("${b.a}")
}
注意,按照宏定义必须比宏调用点先编译的约束,上述 3 个文件的编译顺序必须是:pkg1 -> pkg2 -> pkg3。pkg2 中的 Prop 宏定义:
public macro Prop(input:Tokens):Tokens {
let v = parseDecl(input)
@getIdent[ident](input)
return quote(
$(input)
public prop $(ident): $(decl.declType) {
get() {
this.$(v.identifier)
}
}
)
}
会先被展开成如下代码,再进行编译。
public macro Prop(input: Tokens): Tokens {
let v = parseDecl(input)
let decl = (parseDecl(input) as VarDecl).getOrThrow()
let name = decl.identifier.value
let size = name.size - 1
let ident = Token(TokenKind.IDENTIFIER, name[0 .. size])
return quote(
$(input)
public prop $(ident): $(decl.declType) {
get() {
this.$(v.identifier)
}
}
)
}
宏调用中嵌套宏调用
嵌套宏的常见场景,是宏修饰的代码块中,出现了宏调用。一个具体的例子如下:
pkg1 包中定义 Foo 和 Bar 宏:
macro package pkg1
import std.ast.*
public macro Foo(input: Tokens): Tokens {
return input
}
public macro Bar(input: Tokens): Tokens {
return input
}
pkg2 包中定义 addToMul 宏:
macro package pkg2
import std.ast.*
public macro addToMul(inputTokens: Tokens): Tokens {
var expr: BinaryExpr = match (parseExpr(inputTokens) as BinaryExpr) {
case Some(v) => v
case None => throw Exception()
}
var op0: Expr = expr.leftExpr
var op1: Expr = expr.rightExpr
return quote(($(op0)) * ($(op1)))
}
pkg3 包中使用上面定义的三个宏:
package pkg3
import pkg1.*
import pkg2.*
@Foo
struct Data {
let a = 2
let b = @addToMul(2+3)
@Bar
public func getA() {
return a
}
public func getB() {
return b
}
}
main(): Int64 {
let data = Data()
var a = data.getA() // a = 2
var b = data.getB() // b = 6
println("a: ${a}, b: ${b}")
return 0
}
如上代码所示,宏 Foo 修饰了 struct Data,而在 struct Data 内,出现了宏调用 addToMul 和 Bar。这种嵌套场景下,代码变换的规则是:将嵌套内层的宏(addToMul 和 Bar)展开后,再去展开外层的宏(Foo)。允许出现多层宏嵌套,代码变换的规则总是由内向外去依次展开宏。
嵌套宏可以出现在带括号和不带括号的宏调用中,二者可以组合,但开发者需要保证没有歧义,且明确宏的展开顺序:
var a = @foo(@foo1(2 * 3)+@foo2(1 + 3)) // foo1, foo2 have to be defined.
@Foo1 // Foo2 expands first, then Foo1 expands.
@Foo2[attr: struct] // Attribute macro can be used in nested macro.
struct Data{
@Foo3 @Foo4[123] var a = @bar1(@bar2(2 + 3) + 3) // bar2, bar1, Foo4, Foo3 expands in order.
public func getA() {
return @foo(a + 2)
}
}
嵌套宏之间的消息传递
这里指的是宏调用的嵌套。
内层宏可以调用库函数 assertParentContext 来保证内层宏调用一定嵌套在特定的外层宏调用中。如果内层宏调用这个函数时没有嵌套在给定的外层宏调用中,该函数将抛出一个错误。库函数 InsideParentContext 同样用于检查内层宏调用是否嵌套在特定的外层宏调用中,该函数返回一个布尔值。下面是一个简单的例子。
宏定义如下:
public macro Outer(input: Tokens): Tokens {
return input
}
public macro Inner(input: Tokens): Tokens {
assertParentContext("Outer")
return input
}
宏调用如下:
@Outer var a = 0
@Inner var b = 0 // Error, The macro call 'Inner' should with the surround code contains a call 'Outer'.
如上代码所示,Inner 宏在定义时使用了 assertParentContext 函数用于检查其在调用阶段是否位于 Outer 宏中,在代码示例的宏调用场景下,由于 Outer 和 Inner 在调用时不存在这样的嵌套关系,因此编译器将报告一个错误。
内层宏也可以通过发送键/值对的方式与外层宏通信。当内层宏执行时,通过调用标准库函数 setItem 向外层宏发送信息;随后,当外层宏执行时,调用标准库函数 getChildMessages 接收每一个内层宏发送的信息(一组键/值对映射)。下面是一个简单的例子。
宏定义如下:
macro package define
import std.ast.*
public macro Outer(input: Tokens): Tokens {
let messages = getChildMessages("Inner")
let getTotalFunc = quote(public func getCnt() {
)
for (m in messages) {
let identName = m.getString("identifierName")
// let value = m.getString("key") // 接收多组消息
getTotalFunc.append(Token(TokenKind.IDENTIFIER, identName))
getTotalFunc.append(quote(+))
}
getTotalFunc.append(quote(0))
getTotalFunc.append(quote(}))
let funcDecl = parseDecl(getTotalFunc)
let decl = (parseDecl(input) as ClassDecl).getOrThrow()
decl.body.decls.add(funcDecl)
return decl.toTokens()
}
public macro Inner(input: Tokens): Tokens {
assertParentContext("Outer")
let decl = parseDecl(input)
setItem("identifierName", decl.identifier.value)
// setItem("key", "value") // 可以通过不同的key值传递多组消息
return input
}
宏调用如下:
import define.*
@Outer
class Demo {
@Inner var state = 1
@Inner var cnt = 42
}
main(): Int64 {
let d = Demo()
println("${d.getCnt()}")
return 0
}
在上面的代码中,Outer 接收两个 Inner 宏发送来的变量名,自动为类添加如下内容:
public func getCnt() {
state + cnt + 0
}
具体流程为:内层宏 Inner 通过 setItem 向外层宏发送信息;Outer 宏通过 getChildMessages 函数接收到 Inner 发送的一组信息对象(Outer 中可以调用多次 Inner);最后通过该信息对象的 getString 函数接收对应的值。
编译、报错与调试
宏的编译和使用
当前编译器约束宏的定义与宏的调用不允许在同一包里。宏包必须首先被编译,然后再编译宏调用的包。在宏调用的包中,不允许出现宏的定义。由于宏需在包中导出给另一个包使用,因此编译器约束宏定义必须使用 public 修饰。
下面介绍一个简单的例子。
源码目录结构如下:
// Directory layout.
root_path
├── macros
│ └── m.cj
├── src
│ └── demo.cj
└─ target
宏定义放在 macros 子目录下:
// macros/m.cj
// In this file, we define the macro Inner, Outer.
macro package define
import std.ast.*
public macro Inner(input: Tokens) {
return input
}
public macro Outer(input: Tokens) {
return input
}
宏调用放在 src 子目录下:
// src/demo.cj
import define.*
@Outer
class Demo {
@Inner var state = 1
@Inner var cnt = 42
}
main() {
println("test macro")
0
}
当宏定义文件的编译产物和使用宏的文件不在同一目录下时,需要通过添加 --import-path 编译选项来指定宏定义文件编译产物的路径。以下为 Linux 平台的编译命令(具体编译选项会随着 cjc 更新而演进,以最新 cjc 的编译选项为准):
# 先编译宏定义文件在指定目录产生默认的动态库文件(允许指定动态库的路径,但不能指定动态库的名字)
cjc macros/m.cj --compile-macro --output-dir ./target
# 编译使用宏的文件,宏替换完成,产生可执行文件
cjc src/demo.cj -o demo --import-path ./target --output-dir ./target
# 运行可执行文件
./target/demo
在 Linux 平台上,将生成用于包管理的 macro_define.cjo 和实际的动态库文件。
若在 Windows 平台:
# 当前目录: src
# 先编译宏定义文件在指定目录产生默认的动态库文件(允许指定动态库的路径,但不能指定动态库的名字)
cjc macros/m.cj --compile-macro --output-dir ./target
# 编译使用宏的文件,宏替换完成,产生可执行文件
cjc src/demo.cj -o demo.exe --import-path ./target --output-dir ./target
如果宏包还依赖其他动态库,则需要保证宏包在运行态(宏展开依赖宏包内方法的执行)下能够找到这些依赖。在 Linux 下可以通过设置 LD_LIBRAYR_PATH(Windows 下设置 PATH)环境变量添加所依赖动态库的路径。
说明:
宏替换过程依赖仓颉 runtime ,宏替换过程中仓颉 runtime 的初始化配置采用宏提供的默认配置,配置参数支持使用仓颉 runtime 运维日志进行查询,其中 cjHeapSize 与 cjStackSize 支持用户修改,其余暂不支持,仓颉 runtime 初始化配置可参见runtime 初始化可选配置章节。
并行宏展开
可以在编译宏调用文件时添加 --parallel-macro-expansion 选项,启用并行宏展开的能力。编译器会自动分析宏调用之间的依赖关系,无依赖关系的宏调用可以并行执行,如上述例子中的两个 @Inner 就可以并行展开,如此可以缩短整体编译时间。
注意:
如果宏函数依赖一些全局变量,使用并行宏展开会存在风险。
macro package define
import std.ast.*
import std.collection.*
var Counts = HashMap<String, Int64>()
public macro Inner(input: Tokens) {
for (t in input) {
if (t.value.size == 0) {
continue
}
// 统计所有有效token value的出现次数
if (!Counts.contains(t.value)) {
Counts[t.value] = 0
}
Counts[t.value] = Counts[t.value] + 1
}
return input
}
public macro B(input: Tokens) {
return input
}
参考上述代码,如果 @Inner 的宏调用出现在多处,并且启用了并行宏展开选项,则访问全局变量 Counts 就可能存在冲突,导致最后获取的结果不正确。
建议不要在宏函数中使用全局变量,如果必须使用,要么关闭并行宏展开选项,或者可以通过仓颉线程锁对全局变量进行保护。
diagReport 报错机制
仓颉标准库 std.ast 包提供了自定义报错接口 diagReport。方便定义宏的用户,在解析传入 Tokens 时,对错误 Tokens 内容进行自定义报错。
自定义报错接口提供同原生编译器报错一样的输出格式,允许用户报 warning 和 error 两类错误提示信息。
diagReport 的函数原型如下:
public func diagReport(level: DiagReportLevel, tokens: Tokens, message: String, hint: String): Unit
其参数含义如下:
- level: 报错信息等级
- tokens: 报错信息中所引用源码内容对应的 Tokens
- message: 报错的主信息
- hint: 辅助提示信息
参考如下使用示例。
宏定义文件:
// macro_definition.cj
macro package macro_definition
import std.ast.*
public macro testDef(input: Tokens): Tokens {
for (i in 0..input.size) {
if (input[i].kind == IDENTIFIER) {
diagReport(DiagReportLevel.ERROR, input[i..(i + 1)],
"This expression is not allowed to contain identifier",
"Here is the illegal identifier")
}
}
return input
}
宏调用文件:
// macro_call.cj
package macro_calling
import std.ast.*
import macro_definition.*
main(): Int64 {
let a = @testDef(1)
let b = @testDef(a)
let c = @testDef(1 + a)
return 0
}
编译宏调用文件过程中,会出现如下报错信息:
error: This expression is not allowed to contain identifier
==> call.cj:9:22:
|
9 | let b = @testDef(a)
| ^ Here is the illegal identifier
|
error: This expression is not allowed to contain identifier
==> call.cj:10:26:
|
10 | let c = @testDef(1 + a)
| ^ Here is the illegal identifier
|
2 errors generated, 2 errors printed.
使用 --debug-macro 输出宏展开结果
借助宏在编译期做代码生成时,如果发生错误,处理起来十分棘手,这是开发者经常遇到但一般很难定位的问题。这是因为,开发者写的源码,经过宏的变换后变成了不同的代码片段。编译器抛出的错误信息是基于宏最终生成的代码进行提示的,但这些代码在开发者的源码中没有体现。
为了解决这个问题,仓颉宏提供 debug 模式,在这个模式下,开发者可以从编译器为宏生成的 debug 文件中看到完整的宏展开后的代码,如下所示。
宏定义文件:
macro package define
import std.ast.*
public macro Outer(input: Tokens): Tokens {
let messages = getChildMessages("Inner")
let getTotalFunc = quote(public func getCnt() {
)
for (m in messages) {
let identName = m.getString("identifierName")
getTotalFunc.append(Token(TokenKind.IDENTIFIER, identName))
getTotalFunc.append(quote(+))
}
getTotalFunc.append(quote(0))
getTotalFunc.append(quote(}))
let funcDecl = parseDecl(getTotalFunc)
let decl = (parseDecl(input) as ClassDecl).getOrThrow()
decl.body.decls.add(funcDecl)
return decl.toTokens()
}
public macro Inner(input: Tokens): Tokens {
assertParentContext("Outer")
let decl = parseDecl(input)
setItem("identifierName", decl.identifier.value)
return input
}
宏调用文件 demo.cj:
import define.*
@Outer
class Demo {
@Inner var state = 1
@Inner var cnt = 42
}
main(): Int64 {
let d = Demo()
println("${d.getCnt()}")
return 0
}
在编译使用宏的文件时,在选项中,增加 --debug-macro,即使用仓颉宏的 debug 模式。
cjc --debug-macro demo.cj --import-path ./target
注意:
如果使用仓颉的
CJPM包管理工具进行编译,可在配置文件cjpm.toml中添加--debug-macro的编译选项来使用宏的 debug 模式。compile-option = "--debug-macro"
在 debug 模式下,会生成临时文件 demo.cj.macrocall,对应宏展开的部分如下:
// demo.cj.macrocall
/* ===== Emitted by MacroCall @Outer in demo.cj:3:1 ===== */
/* 3.1 */class Demo {
/* 3.2 */ var state = 1
/* 3.3 */ var cnt = 42
/* 3.4 */ public func getCnt() {
/* 3.5 */ state + cnt + 0
/* 3.6 */ }
/* 3.7 */}
/* 3.8 */
/* ===== End of the Emit ===== */
如果宏展开后的代码有语义错误,则编译器的错误信息会溯源到宏展开后代码的具体行列号。如果在编译时开启了 debug 模式,那么编译器的错误信息中不会打印完整的宏展开代码,仅打印实际错误位置和临时文件路径,开发者可以通过临时文件路径跳转至对应的错误位置;非 debug 模式下,报错信息中会打印出完整的宏展开代码。仓颉宏的 debug 模式有以下注意事项:
-
宏的 debug 模式会重排源码的行列号信息,不适用于某些特殊的换行场景。例如:
// before expansion @M{} - 2 // macro M return 2 // after expansion // ===== Emmitted my Macro M at line 1 === 2 // ===== End of the Emit ===== - 2这些因换行符导致语义改变的情形,不应使用 debug 模式。
-
不支持宏调用在宏定义内的调试,会编译报错。
public macro M(input: Tokens) { let a = @M2(1+2) // M2 is in macro M, not suitable for debug mode. return input + quote($a) } -
不支持带括号宏的调试。
// main.cj main() { // For macro with parenthesis, newline introduced by debug will change the semantics // of the expression, so it is not suitable for debug mode. let t = @M(1+2) 0 }
宏包定义和导入
仓颉语言中宏的定义需要放在由 macro package 声明的包中,被 macro package 限定的包仅允许宏定义对外可见,其他声明包内可见。
说明:
重导出的声明也允许对外可见,关于包管理和重导出的相关概念,请参见包的导入章节。
// file define.cj
macro package define // 编译 define.cjo 携带 macro 属性
import std.ast.*
public func A() {} // Error, 宏包不允许定义外部可见的非宏定义,此处会报错
public macro M(input: Tokens): Tokens { // macro M 外部可见
return input
}
需要特殊说明的是,在宏包中,允许其他宏包和非宏包的声明被重导出。在非宏包中仅允许非宏包的声明被重导出。
参考如下示例:
-
在宏包 A 中定义宏
M1macro package A import std.ast.* public macro M1(input: Tokens): Tokens { return input }编译命令如下:
cjc A.cj --compile-macro -
在非宏包 B 中定义一个 public 函数
f1。注意在非macro package中无法重导出macro package的符号package B // public import A.* // Error, it is not allowed to re-export a macro package in a package. public func f1(input: Int64): Int64 { return input }编译命令如下,这里选择使用
--output-type选项将 B 包编译成动态库,关于 cjc 编译选项,详情请参见 "附录 > cjc 编译选项"。cjc B.cj --output-type=dylib -o libB.so -
在宏包 C 中定义宏
M2,依赖了 A 包和 B 包的内容。可以看到macro package中可以重导出macro package和非macro package的符号macro package C public import A.* // correct: macro package is allowed to re-export in a macro package. public import B.* // correct: non-macro package is also allowed to re-export in a macro package. import std.ast.* public macro M2(input: Tokens): Tokens { return @M1(input) + Token(TokenKind.NL) + quote(f1(1)) }编译命令如下,注意这里需要显式链接 B 包动态库:
cjc C.cj --compile-macro -L. -lB -
在
main.cj中使用M2宏import C.* main() { @M2(let a = 1) }编译命令如下:
cjc main.cj -o main -L. -lBmain.cj中M2宏展开后的结果如下:import C.* main() { let a = 1 f1(1) }
可以看到 main.cj 中出现了来自于 B 包的符号 f1。宏的编写者可以在 C 包中重导出 B 包里的符号,这样宏的使用者仅需导入宏包,就可以正确地编译宏展开后的代码。如果在 main.cj 中仅使用 import C.M2 导入宏符号,则会报 undeclared identifier 'f1' 的错误信息。
内置编译标记
仓颉语言提供了一些预定义的编译标记,可以通过这些编译标记控制仓颉编译器的编译行为。
源码位置
仓颉提供了几个内置编译标记,用于在编译时获取源码的位置。
@sourcePackage()展开后是一个String类型的字面量,内容为该标记所在的源码的包名。@sourceFile()展开后是一个String类型的字面量,内容为该标记所在的源码的文件名。@sourceLine()展开后是一个Int64类型的字面量,内容为该标记所在的源码的代码行。
这几个编译标记可以在任意表达式内部使用,只要能符合类型检查规则即可。示例如下:
func test1() {
let s: String = @sourceFile() // The value of `s` is the current source file name
}
func test2(n!: Int64 = @sourceLine()) { /* at line 5 */
// The default value of `n` is the source file line number of the definition of `test2`
println(n) // print 5
}
条件编译
条件编译使用 @When 标记,是一种在程序代码中根据特定条件选择性地编译不同代码段的技术。条件编译的作用主要体现在以下几个方面:
- 平台适应:支持根据当前的编译环境选择性地编译代码,用于实现跨平台的兼容性。
- 功能选择:支持根据不同的需求选择性地编译代码,用于实现功能的灵活配置。
- 调试支持:支持调试模式下编译相关代码,用于提高程序的性能和安全性。例如,在调试模式下编译调试信息或记录日志相关的代码,而在发布版本中将其排除。
- 性能优化:支持根据预定义的条件选择性地编译代码,用于提高程序的性能。
关于条件编译的具体内容,请参见条件编译章节,这里不再额外展开。
@FastNative
为了提升与 C 语言互操作的性能,仓颉提供 @FastNative 标记用于优化对 C 函数的调用。值得注意的是 @FastNative 只能用于 foreign 声明的函数。
使用示例如下:
@FastNative
foreign func strlen(str: CPointer<UInt8>): UIntNative
开发者在使用 @FastNative 修饰 foreign 函数时,应确保对应的 C 函数满足以下两点要求:
- 函数的整体执行时间不宜太长。例如:不允许函数内部存在很大的循环;不允许函数内部产生阻塞行为,例如:调用
sleep、wait等函数。 - 函数内部不能调用仓颉方法。
@Frozen
@Frozen 标记可用于修饰函数和属性。如果确定某个函数、属性在将来的版本更新中不会去修改它的内部实现,那么可以使用 @Frozen 对其进行标记,该标记代表开发者对该函数/属性在未来版本演进的一种承诺。被 @Frozen 修饰的函数和属性,在后续的升级版本中,签名和函数体都不能发生任何变化。这意味着,前后两个代码版本,在相同编译器、相同编译选项的情况下,该函数或属性的生成产物完全一致。
@Frozen 标记可被用于修饰:
- 全局函数
- 类、结构、接口、扩展、枚举中的函数
- 类、接口、扩展中的属性
@Frozen 标记不可被用于修饰:
- 除了函数和属性以外的其他类型声明
- 嵌套函数
- 表达式
使用示例如下:
@Frozen
public func test(): Unit {}
public class testClass {
@Frozen
public func testFunc(): Unit {}
@Frozen
public prop testProp: Unit {
get() {}
}
}
@Attribute
仓颉语言内部提供 @Attribute 标记,开发者通过内置的 @Attribute 来对某个声明设置属性值,从而达到标记声明的目的。属性值可以是 identifier 或者 string,下面是一个简单的例子,这段示例代码为变量 cnt 添加了一个 identifier 类型的属性 State,为变量 bcnt 添加了一个 string 类型的属性 "Binding"。
@Attribute[State] var cnt = 0 // identifier
@Attribute["Binding"] var bcnt = 0 // string
同时,标准库 std.ast 包提供了 getAttrs() 方法用于获取节点的属性,以及 hasAttr(attrs: String) 方法用于判断当前节点是否具有某个属性,下面是一个具体的例子。
宏定义如下:
public macro Component(input: Tokens): Tokens {
var varDecl = parseDecl(input)
if (varDecl.hasAttr("State")) { // 如果该节点被标记了属性且值为 “State” 返回 true, 否则返回 false
var attrs = varDecl.getAttrs() // 返回一组 Tokens
println(attrs[0].value)
}
return input
}
宏调用如下:
@Component(
@Attribute[State] var cnt = 0
)
@Deprecated
@Deprecated 表示此 API 已废弃,虽然暂时可用,但未来将被移除或更改,建议其他开发者不要调用此 API。例如:
@Deprecated["用boo代替", since: "1.3.4"]
func foo() {}
main() {
foo()
}
编译器编译时将提供告警信息:
warning: function 'foo' is deprecated since 1.3.4. 用boo代替
==> file.cj:5:5:
|
5 | foo()
| ^^^ deprecated
|
# note: this warning can be suppressed by setting the compiler option `-Woff deprecated`
1 warning generated, 1 warning printed.
@Deprecated 自定义宏可以应用于以下声明:
- 类、接口、结构体、枚举、枚举构造器
- 顶级(全局)函数或变量
- 静态或非静态的成员函数、成员变量、属性、属性设置器
- 运算符函数
- 扩展的成员函数、静态函数、属性或属性设置器
- foreign 函数或声明在 foreign 块内的函数
- 构造函数和主构造函数
- 抽象的函数和属性
- 类型别名(包括关联类型)
- 函数具有默认参数的命名参数
- const 变量和函数
- 宏定义
- 注解类
@Deprecated 参数
message: String- 描述声明为何废弃、如何迁移等。since!: ?String- 废弃版本。strict!: Bool- 默认值为false,在被该标记修饰的 API 的调用处会触发警告。如果设置为true,则会触发编译错误。
@Deprecated["Use Macro2", since: "1990", strict: true]
public macro Macro(input: Tokens): Tokens {
return input
}
实用案例
快速幂的计算
通过一个简单的例子展示使用宏进行编译期求值,生成优化代码的应用。在计算幂 n ^ e 时,如果 e 是一个(比较大的)整数,可以通过重复取平方(而不是迭代相乘)的方式加速计算。这个算法可以直接使用 while 循环实现,例如:
func power(n: Int64, e: Int64) {
var result = 1
var vn = n
var ve = e
while (ve > 0) {
if (ve % 2 == 1) {
result *= vn
}
ve /= 2
if (ve > 0) {
vn *= vn
}
}
result
}
然而,这个实现需要每次对 e 的值进行分析,在循环和条件判断中多次对 ve 进行判断和更新。此外,实现只支持 n 的类型为Int64的情况,如果要支持其他类型的 n,还要处理如何表达 result = 1 的问题。如果预先知道 e 的具体值,可以将这个代码写的更简单。例如,如果知道 e 的值为 10,可以展开整个循环如下:
func power_10(n: Int64) {
var vn = n
vn *= vn // vn = n ^ 2
var result = vn // result = n ^ 2
vn *= vn // vn = n ^ 4
vn *= vn // vn = n ^ 8
result *= vn // result = n ^ 10
result
}
当然,手动编写这些代码非常繁琐,希望在给定 e 的值之后,自动将这些代码生成出来。宏可以做到这一点。使用案例如下:
public func power_10(n: Int64) {
@power[10](n)
}
这个宏展开的代码是(根据 .macrocall 文件):
public func power_10(n: Int64) {
/* ===== Emitted by MacroCall @power in main.cj:20:5 ===== */
/* 20.1 */var _power_vn = n
/* 20.2 */_power_vn *= _power_vn
/* 20.3 */var _power_result = _power_vn
/* 20.4 */_power_vn *= _power_vn
/* 20.5 */_power_vn *= _power_vn
/* 20.6 */_power_result *= _power_vn
/* 20.7 */_power_result
/* ===== End of the Emit ===== */
}
下面是宏 @power 的实现。
macro package define
import std.ast.*
import std.convert.*
public macro power(attrib: Tokens, input: Tokens) {
let attribExpr = parseExpr(attrib)
if (let Some(litExpr) <- (attribExpr as LitConstExpr)) {
let lit = litExpr.literal
if (lit.kind != TokenKind.INTEGER_LITERAL) {
diagReport(DiagReportLevel.ERROR, attrib,
"Attribute must be integer literal",
"Expected integer literal")
}
var n = Int64.parse(lit.value)
var result = quote(var _power_vn = $(input)
)
var flag = false
while (n > 0) {
if (n % 2 == 1) {
if (!flag) {
result += quote(var _power_result = _power_vn
)
flag = true
} else {
result += quote(_power_result *= _power_vn
)
}
}
n /= 2
if (n > 0) {
result += quote(_power_vn *= _power_vn
)
}
}
result += quote(_power_result)
return result
} else {
diagReport(DiagReportLevel.ERROR, attrib,
"Attribute must be integer literal",
"Expected integer literal")
}
return input
}
这段代码的解释如下:
- 首先,确认输入的属性
attrib是一个整数字面量,否则通过diagReport报错。将这个字面量解析为整数n。 - 设
result为当前积累的输出代码,首先添加var _power_vn的声明。这里为了避免变量名冲突,使用不易造成冲突的名字_power_vn。 - 下面进入 while 循环,布尔变量
flag表示var _power_result是否已经被初始化。其余的代码结构和之前展示的power函数的实现类似,但区别是使用 while 循环和 if 判断在编译时决定生成的代码是什么,而不是在运行时做这些判断。然后生成由_power_result *= _power_vn和_power_vn *= _power_vn适当组合的代码。 - 最后添加返回
_power_result的代码,并将这段代码作为宏的输出值返回。
将这段代码放到 macros/power.cj 文件中,并在 main.cj 添加如下测试:
import define.*
public func power_10(n: Int64) {
@power[10](n)
}
main() {
let a = 3
println(power_10(a))
}
输出结果为:
59049
Memoize 宏
Memoize(记忆化)是动态规划算法的常用手段。它将已经计算过的子问题的结果存储起来,当同一个子问题再次出现时,可以直接查询表来获取结果,从而避免重复的计算,提高算法的效率。
通常 Memoize 的使用需要开发者手动实现存储和提取的功能。通过宏,可以自动化这一过程。宏的效果如下:
@Memoize[true]
func fib(n: Int64): Int64 {
if (n == 0 || n == 1) {
return n
}
return fib(n - 1) + fib(n - 2)
}
main() {
let start = DateTime.now()
let f35 = fib(35)
let end = DateTime.now()
println("fib(35): ${f35}")
println("execution time: ${(end - start).toMicroseconds()} us")
}
在以上代码中,fib 函数采用简单的递归方式实现。如果没有 @Memoize[true] 标注,这个函数的运行时间将随着 n 指数增长。例如,如果在前面的代码中去掉 @Memoize[true] 这一行,或者把 true 改为 false,则 main 函数的运行结果为:
fib(35): 9227465
execution time: 199500 us
恢复 @Memoize[true],运行结果为:
fib(35): 9227465
execution time: 78 us
相同的答案和大幅缩短的计算时间表明,@Memoize 的使用确实实现了记忆化。
为了理解 @Memoize 的原理,展示对以上 fib 函数进行宏展开的结果(来自 .macrocall 文件,但是为了提高可读性整理了格式)。
import std.collection.*
var memoizeFibMap = HashMap<Int64, Int64>()
func fib(n: Int64): Int64 {
if (memoizeFibMap.contains(n)) {
return memoizeFibMap.get(n).getOrThrow()
}
let memoizeEvalResult = { =>
if (n == 0 || n == 1) {
return n
}
return fib(n - 1) + fib(n - 2)
}()
memoizeFibMap.add(n, memoizeEvalResult)
return memoizeEvalResult
}
上述代码的执行流程如下:
- 首先,定义
memoizeFibMap为一个从Int64到Int64的哈希表,这里第一个Int64对应fib的唯一参数的类型,第二个Int64对应fib返回值的类型。 - 其次,在函数体中,检查入参是否在
memoizeFibMap中,如果是则立即反馈哈希表中存储的值。否则,使用fib原来的函数体得到计算结果。这里使用了(不带参数的)匿名函数使fib的函数体不需要任何改变,并且能够处理任何从fib函数退出的方式(包括中间的 return,返回最后一个表达式等)。 - 最后,把计算结果存储到
memoizeFibMap中,然后将计算结果返回。
有了这样一个“模板”之后,下面宏的实现就不难理解了。完整的代码如下。
public macro Memoize(attrib: Tokens, input: Tokens) {
if (attrib.size != 1 || attrib[0].kind != TokenKind.BOOL_LITERAL) {
diagReport(DiagReportLevel.ERROR, attrib,
"Attribute must be a boolean literal (true or false)",
"Expected boolean literal (true or false) here")
}
let memoized = (attrib[0].value == "true")
if (!memoized) {
return input
}
let fd = FuncDecl(input)
if (fd.funcParams.size != 1) {
diagReport(DiagReportLevel.ERROR, fd.lParen + fd.funcParams.toTokens() + fd.rParen,
"Input function to memoize should take exactly one argument",
"Expect only one argument here")
}
let memoMap = Token(TokenKind.IDENTIFIER, "_memoize_" + fd.identifier.value + "_map")
let arg1 = fd.funcParams[0]
return quote(
var $(memoMap) = HashMap<$(arg1.paramType), $(fd.declType)>()
func $(fd.identifier)($(arg1)): $(fd.declType) {
if ($(memoMap).contains($(arg1.identifier))) {
return $(memoMap).get($(arg1.identifier)).getOrThrow()
}
let memoizeEvalResult = { => $(fd.block.nodes) }()
$(memoMap).add($(arg1.identifier), memoizeEvalResult)
return memoizeEvalResult
}
)
}
首先,对属性和输入做合法性检查。属性必须是布尔字面量,如果为 false 则直接返回输入。否则,检查输入必须能够解析为函数声明(FuncDecl),并且必须包含正好一个参数。下面,产生哈希表的变量,取不容易造成冲突的变量名。最后,通过 quote模板生成返回的代码,其中用到哈希表的变量名,以及唯一参数的名称、类型和输入函数的返回类型。
一个 dprint 宏的扩展
本节一开始使用了一个打印表达式的宏作为案例,但这个宏一次只能接受一个表达式。希望扩展这个宏,使其能够接受多个表达式,由逗号分开。下面展示如何使用 parseExprFragment 来实现这个功能。
宏的实现如下:
public macro dprint2(input: Tokens) {
let exprs = ArrayList<Expr>()
var index: Int64 = 0
while (true) {
let (expr, nextIndex) = parseExprFragment(input, startFrom: index)
exprs.add(expr)
if (nextIndex == input.size) {
break
}
if (input[nextIndex].kind != TokenKind.COMMA) {
diagReport(DiagReportLevel.ERROR, input[nextIndex..nextIndex+1],
"Input must be a comma-separated list of expressions",
"Expected comma")
}
index = nextIndex + 1 // 跳过逗号
}
let result = quote()
for (expr in exprs) {
result.append(quote(
print($(expr.toTokens().toString()) + " = ")
println($(expr))
))
}
return result
}
使用案例:
let x = 3
let y = 2
@dprint2(x, y, x + y)
输出结果为:
x = 3
y = 2
x + y = 5
在宏的实现中,使用 while 循环从索引 0 开始依次解析每个表达式。变量 index 保存当前解析的位置。每次调用 parseExprFragment 时,从当前位置开始,并返回解析后的位置(以及解析得到的表达式)。如果解析后的位置到达了输入的结尾,则退出循环。否则检查到达的位置是否是一个逗号,如果不是逗号,报错并退出,如果是逗号,跳过这个逗号并开始下一轮的解析。在得到表达式的列表后,依次输出每个表达式。
一个简单的 DSL
这个案例展示了如何使用宏实现一个简单的 DSL(Domain Specific Language,领域特定语言)。LINQ(Language Integrated Query,语言集成查询)是微软 .NET 框架的一个组成部分,它提供了一种统一的数据查询语法,允许开发者使用类似 SQL 的查询语句来操作各种数据源。在这里,仅展示一个最简单的 LINQ 语法的支持。
希望支持的语法为:
from <variable> in <list> where <condition> select <expression>
其中,variable 是一个标识符,list、condition 和 expression 都是表达式。因此,实现宏的策略是先后提取标识符和表达式,同时检查中间的关键字是正确的。最后,生成由提取部分组成的查询结果。
宏的实现如下:
public macro linq(input: Tokens) {
let syntaxMsg = "Syntax is \"from <attrib> in <table> where <cond> select <expr>\""
if (input.size == 0 || input[0].value != "from") {
diagReport(DiagReportLevel.ERROR, input[0..1], syntaxMsg,
"Expected keyword \"from\" here.")
}
if (input.size <= 1 || input[1].kind != TokenKind.IDENTIFIER) {
diagReport(DiagReportLevel.ERROR, input[1..2], syntaxMsg,
"Expected identifier here.")
}
let attribute = input[1]
if (input.size <= 2 || input[2].value != "in") {
diagReport(DiagReportLevel.ERROR, input[2..3], syntaxMsg,
"Expected keyword \"in\" here.")
}
var index: Int64 = 3
let (table, nextIndex) = parseExprFragment(input, startFrom: index)
if (nextIndex == input.size || input[nextIndex].value != "where") {
diagReport(DiagReportLevel.ERROR, input[nextIndex..nextIndex+1], syntaxMsg,
"Expected keyword \"where\" here.")
}
index = nextIndex + 1 // 跳过where
let (cond, nextIndex2) = parseExprFragment(input, startFrom: index)
if (nextIndex2 == input.size || input[nextIndex2].value != "select") {
diagReport(DiagReportLevel.ERROR, input[nextIndex2..nextIndex2+1], syntaxMsg,
"Expected keyword \"select\" here.")
}
index = nextIndex2 + 1 // 跳过select
let (expr, nextIndex3) = parseExprFragment(input, startFrom: index)
return quote(
for ($(attribute) in $(table)) {
if ($(cond)) {
println($(expr))
}
}
)
}
使用案例:
@linq(from x in 1..=10 where x % 2 == 1 select x * x)
这个例子从 1, 2, ... 10 列表中筛选出奇数,然后返回所有奇数的平方。输出结果为:
1
9
25
49
81
可以看到,宏的实现的很大部分用于解析并校验输入的 Tokens,这对宏的可用性至关重要。实际的 LINQ 语言(以及大多数 DSL)的语法更加复杂,需要一整套解析的机制,通过识别不同的关键字或连接符来决定下一步解析的内容。
动态特性
本章介绍 Cangjie 的动态特性,应用动态特性开发者能够更为优雅的实现一些功能。仓颉的动态特性主要包含反射。
仓颉反射基本介绍
反射指程序可以访问、检测和修改它本身状态或行为的一种机制。
反射这一动态特性有以下的优点:
-
提高了程序的灵活性和扩展性。
-
程序能够在运行时获悉各种对象的类型,对其成员进行枚举、调用等操作。
-
允许在运行时创建新类型,无需提前硬编码。
但使用反射调用,其性能通常低于直接调用,因此反射机制主要应用于对灵活性和拓展性要求很高的系统框架上。
如何获得 TypeInfo
对于仓颉的反射特性,需要知道 TypeInfo 这一类型,这个核心类型中记录任意类型的类型信息,并且定义了方法用于获取类型信息、设置值等。当然为了便于用户操作仓颉还提供了 ClassTypeInfo、PrimitiveTypeInfo、ParameterInfo 等一系列的信息类型。
可以使用三种静态的 of 方法来生成 TypeInfo 信息类。
public class TypeInfo {
public static func of(a: Any): TypeInfo
public static func of(a: Object): ClassTypeInfo
public static func of<T>(): TypeInfo
}
当采用入参为 Any 和 Object 类型的 of 函数,输出为该实例的运行时类型信息,采用泛型参数的 of 函数则会返回传入参数的静态类型信息。两种方法产生的信息完全相同,但不保证一定对应同一对象。
例如可以用反射来获取一个自定义类型的类型信息。
import std.reflect.*
class Foo {}
main() {
let a: Foo = Foo()
let info: TypeInfo = TypeInfo.of(a)
let info2: TypeInfo = TypeInfo.of<Foo>()
println(info)
println(info2)
}
编译并执行上面的代码,会输出:
default.Foo
default.Foo
此外 TypeInfo 还提供了静态函数 get,该接口可通过传入的类型名称获取 TypeInfo。
public class TypeInfo {
public static func get(qualifiedName: String): TypeInfo
}
请注意,传入参数需要符合 module.package.type 的完全限定模式规则。对于编译器预导入的类型,包含 core 包中的类型和编译器内置类型,例如 primitive type、Option、Iterable 等,查找的字符串需要直接使用其类型名,不能带包名和模块名前缀。当运行时无法查询到对应类型的实例,则会抛出 InfoNotFoundException。
let t1: TypeInfo = TypeInfo.get("Int64")
let t1: TypeInfo = TypeInfo.get("default.Foo")
let t2: TypeInfo = TypeInfo.get("std.socket.TcpSocket")
let t3: TypeInfo = TypeInfo.get("net.http.ServerBuilder")
采用这种方式时无法获取一个未实例化的泛型类型。
import std.collection.*
import std.reflect.*
class A<T> {
A(public let t: T) {}
}
class B<T> {
B(public let t: T) {}
}
main() {
let aInfo: TypeInfo = TypeInfo.get("default.A<Int64>")// Error,`default.A<Int64>` is not instantiated,will throw InfoNotFoundException
let b: B<Int64> = B<Int64>(1)
let bInfo: TypeInfo = TypeInfo.get("default.B<Int64>")// Ok `default.B<Int64>` has been instantiated.
}
如何使用反射访问成员
在获取到对应的类型信息类即 TypeInfo 后,便可以通过其相应接口访问对应类的实例成员以及静态成员。此外 TypeInfo 的子类 ClassTypeInfo 还提供了接口用于访问类公开的构造函数以及它的成员变量、属性、函数。仓颉的反射被设计为只能访问到类型内 public 的成员,意味着 private 和 protected 修饰的成员在反射中是不可见的。
例如当想要在运行时对类的某一实例成员变量进行获取与修改。
import std.reflect.*
public class Foo {
public static var param1 = 20
public var param2 = 10
}
main(): Unit{
let obj = Foo()
let info = TypeInfo.of(obj)
let staticVarInfo = info.getStaticVariable("param1")
let instanceVarInfo = info.getInstanceVariable("param2")
println("成员变量初始值")
print("Foo 的静态成员变量 ${staticVarInfo} = ")
println((staticVarInfo.getValue() as Int64).getOrThrow())
print("obj 的实例成员变量 ${instanceVarInfo} = ")
println((instanceVarInfo.getValue(obj) as Int64).getOrThrow())
println("更改成员变量")
staticVarInfo.setValue(8)
instanceVarInfo.setValue(obj, 25)
print("Foo 的静态成员变量 ${staticVarInfo} = ")
println((staticVarInfo.getValue() as Int64).getOrThrow())
print("obj 的实例成员变量 ${instanceVarInfo} = ")
println((instanceVarInfo.getValue(obj) as Int64).getOrThrow())
return
}
编译并执行上面的代码,会输出:
成员变量初始值
Foo 的静态成员变量 static param1: Int64 = 20
obj 的实例成员变量 param2: Int64 = 10
更改成员变量
Foo 的静态成员变量 static param1: Int64 = 8
obj 的实例成员变量 param2: Int64 = 25
同时也可以通过反射对属性进行检查以及修改。
import std.reflect.*
public class Foo {
public let _p1: Int64 = 1
public prop p1: Int64 {
get() { _p1 }
}
public var _p2: Int64 = 2
public mut prop p2: Int64 {
get() { _p2 }
set(v) { _p2 = v }
}
}
main(): Unit{
let obj = Foo()
let info = TypeInfo.of(obj)
let instanceProps = info.instanceProperties.toArray()
println("obj的实例成员属性包含${instanceProps}")
let PropInfo1 = info.getInstanceProperty("p1")
let PropInfo2 = info.getInstanceProperty("p2")
println((PropInfo1.getValue(obj) as Int64).getOrThrow())
println((PropInfo2.getValue(obj) as Int64).getOrThrow())
if (PropInfo1.isMutable()) {
PropInfo1.setValue(obj, 10)
}
if (PropInfo2.isMutable()) {
PropInfo2.setValue(obj, 20)
}
println((PropInfo1.getValue(obj) as Int64).getOrThrow())
println((PropInfo2.getValue(obj) as Int64).getOrThrow())
return
}
编译并执行上面的代码,会输出:
obj 的实例成员属性包含[prop p1: Int64, mut prop p2: Int64]
1
2
1
20
还可以通过反射机制进行函数调用。
import std.reflect.*
public class Foo {
public static func f1(v0: Int64, v1: Int64): Int64 {
return v0 + v1
}
}
main(): Unit {
var num = 0
let intInfo = TypeInfo.of<Int64>()
let funcInfo = TypeInfo.of<Foo>().getStaticFunction("f1", intInfo, intInfo)
num = (funcInfo.apply(TypeInfo.of<Foo>(), [1, 1]) as Int64).getOrThrow()
println(num)
}
编译并执行上面的代码,会输出:
2
注解
仓颉中提供了一些内置编译标记用来支持一些特殊情况的处理。
确保正确使用整数运算溢出策略的内置编译标记
仓颉中提供三种内置编译标记来控制整数溢出的处理策略,即 @OverflowThrowing,@OverflowWrapping 和 @OverflowSaturating ,这些编译标记当前只能标记于函数声明之上,作用于函数内的整数运算和整型转换。它们分别对应以下三种溢出处理策略:
-
抛出异常(throwing):当整数运算溢出时,抛出异常。
@OverflowThrowing func add(a: Int8, b: Int8){ return a + b } main() { add(100,29) /* 100 + 29 在数学上等于 129, * 在 Int8 的表示范围上发生了上溢出, * 程序抛出异常 */ 0 }需要注意的是,对于整数溢出行为是 throwing 的场景,若整数溢出可提前在编译期检测出来,则编译器会直接给出报错。
@OverflowThrowing main() { let res: Int8 = Int8(100) + Int8(29) // Error, arithmetic operation '+' overflow // 100 + 29 在数学上等于 129,在 Int8 的表示范围上发生了上溢出,编译器检测出来并报错 let con: UInt8 = UInt8(-132) // Error, integer type conversion overflow /* -132 在 UInt8 的表示范围上发生了下溢出, * 程序抛出异常 */ 0 } -
高位截断(wrapping):当整数运算的结果超出用于接收它的内存空间所能表示的数据范围时,则截断超出该内存空间的部分。
@OverflowWrapping main() { let res: Int8 = Int8(105) * Int8(4) /* 105 * 4 在数学上等于 420, * 对应的二进制为 1 1010 0100, * 超过了用于接收该结果的 8 位内存空间, * 截断后的结果在二进制上表示为 1010 0100, * 对应为有符号整数 -92 */ let temp: Int16 = Int16(-132) let con: UInt8 = UInt8(temp) /* -132 对应的二进制为 1111 1111 0111 1100, * 超过了用于接收该结果的 8 位内存空间, * 截断后的结果在二进制上表示为 0111 1100 * 对应为有符号整数 124 */ 0 } -
饱和(saturating):当整数运算溢出时,选择对应固定精度的极值作为结果。
@OverflowSaturating main() { let res: Int8 = Int8(-100) - Int8(45) /* -100 - 45 在数学上等于 -145, * 在 Int8 的表示范围上发生了下溢出, * 选择 Int8 的最小值 -128 作为结果 */ let con: Int8 = Int8(1024) /* 1024 在 Int8 的表示范围上发生了上溢出, * 选择 Int8 的最大值 127 作为结果 */ 0 }
默认情况下(即未标注该类内置编译标记时),采取抛出异常(@OverflowThrowing)的处理策略。
实际情况下需要根据业务场景的需求正确选择溢出策略。例如要在 Int32 上实现某种安全运算,使得计算结果和计算过程在数学上相等,就需要使用抛出异常的策略。
【反例】
// 计算结果被高位截断
@OverflowWrapping
func operation(a: Int32, b: Int32): Int32 {
a + b // No exception will be thrown when overflow occurs
}
该错误例子使用了高位截断的溢出策略,比如当传入的参数 a 和 b 较大导致结果溢出时,会产生高位截断的情况,导致函数返回结果和计算表达式 a + b 在数学上不是相等关系。
【正例】
// 安全
@OverflowThrowing
func operation(a: Int32, b: Int32): Int32 {
a + b
}
main() {
try {
operation(Int32.Max, 1)
} catch (e: ArithmeticException) {
println(e.message)
//Handle error
}
0
}
该正确例子使用了抛出异常的溢出策略,当传入的参数 a 和 b 较大导致整数溢出时,operation 函数会抛出异常。
下面总结了可能造成整数溢出的数学操作符。
| 操作符 | 溢出 | 操作符 | 溢出 | 操作符 | 溢出 | 操作符 | 溢出 |
|---|---|---|---|---|---|---|---|
+ | Y | -= | Y | << | N | < | N |
- | Y | *= | Y | >> | N | > | N |
* | Y | /= | Y | & | N | >= | N |
/ | Y | %= | N | | | N | <= | N |
% | N | <<= | N | ^ | N | == | N |
++ | Y | >>= | N | **= | Y | ||
-- | Y | &= | N | ! | N | ||
= | N | |= | N | != | N | ||
+= | Y | ^= | N | ** | Y |
测试框架内置编译标记
在测试中使用 mock 时,当 mock 的是与静态和顶级声明相关内容时,需要通过测试框架内置编译标记来指示编译器做一些准备工作,才能正常使用 mock。
测试框架内置编译标记 @EnsurePreparedToMock 只能在 lambda 表达式上使用,lambda 表达式调用静态和顶级声明作为其最后一个表达式,然后编译器将准备这个声明以供 mock。
例如:
package prod
public func test(a: String, b: String): String {
a + b
}
package test
import prod.*
import std.unittest.mock.*
@Test
public class TestA {
@TestCase
func case1(): Unit {
{ =>
let matcher0 = Matchers.eq("z")
let matcher1 = Matchers.eq("y")
let stubCall = @EnsurePreparedToMock { => return(test(matcher0.value(), matcher1.value())) }
ConfigureMock.stubFunction(stubCall,[matcher0.withDescription(#"eq("z")"#), matcher1.withDescription(#"eq("y")"#)], Option<String>.None, "test", #"test("z", "y")"#, 15)
}().returns("mocked value")
println(test("z", "y")) // prints "mocked value"
}
}
上述示例中,ConfigureMock.stubFunction 为函数 test 注册了一个桩,returns 为定义的桩设置返回值。
注意:
通常,标准库的 mock 接口可用于定义 mock 声明,并且在常规情况下不应直接使用此内置注释。相反,应该使用相应的标准库函数。这些标准库函数在内部使用
@EnsurePreparedToMock。
使用 @EnsurePreparedToMock 注解的约束:
- 仅当使用测试和 mock 相关编译选项进行编译时才允许使用(使用
--test/--test-only和--mock=on/--mock=runtime-error编译选项)。 - 只能应用于具有合适的最后一个表达式的 lambda。
- lambda 的最后一个表达式应该是调用、成员访问或引用表达式,要求是:
- 顶级函数或变量;
- 静态函数、属性或字段;
- foreign 声明;
- 不是局部函数或变量;
- 非私有声明;
- 不是 const 表达式或声明;
- 必须是来自通过 mock 模式构建的包的声明。
自定义注解
自定义注解机制用来让反射(详见反射章节)获取标注内容,目的是在类型元数据之外提供更多的有用信息,以支持更复杂的逻辑。
开发者可以通过自定义类型标注 @Annotation 方式创建自己的自定义注解。@Annotation 只能修饰 class,并且不能是 abstract 或 open 或 sealed 修饰的 class。当一个 class 声明它标注了 @Annotation,那么它必须要提供至少一个 const init 函数,否则编译器会报错。
开发者也可以使用 @!Annotation 的语法创建自定义注解。这是为后续功能预留的语法,当前版本下与 @Annotation 等效。
下面的例子定义了一个自定义注解 @Version,并用其修饰 A, B 和 C。在 main 中,通过反射获取到类上的 @Version 注解信息,并将其打印出来。
package pkg
import std.reflect.TypeInfo
@Annotation
public class Version {
let code: String
const init(code: String) {
this.code = code
}
}
@Version["1.0"]
class A {}
@Version["1.1"]
class B {}
main() {
let objects = [A(), B()]
for (obj in objects) {
let annOpt = TypeInfo.of(obj).findAnnotation<Version>()
if (let Some(ann) <- annOpt) {
println(ann.code)
}
}
}
编译并执行上述代码,输出结果为:
1.0
1.1
注解信息需要在编译时生成信息并绑定到类型上,自定义注解在使用时必须使用 const init 构建出合法的实例。注解声明语法与声明宏语法一致,后面的 [] 括号中需要按顺序或命名参数规则传入参数,且参数必须是 const 表达式(详见常量求值章节)。对于拥有无参构造函数的注解类型,声明时允许省略括号。
下面的例子中定义了一个拥有无参 const init 的自定义注解 @Marked,使用时 @Marked 和 @Marked[] 这两种写法均可。
package pkg
import std.reflect.TypeInfo
@Annotation
public class Marked {
const init() {}
}
@Marked
class A {}
@Marked[]
class B {}
main() {
if (TypeInfo.of(A()).findAnnotation<Marked>().isSome()) {
println("A is Marked")
}
if (TypeInfo.of(B()).findAnnotation<Marked>().isSome()) {
println("B is Marked")
}
}
编译并执行上述代码,输出结果为:
A is Marked
B is Marked
对于同一个注解目标,同一个注解类不允许声明多次,即不可重复。
@Marked
@Marked // Error
class A {}
Annotation 不会被继承,因此一个类型的注解元数据只会来自它定义时声明的注解。如果需要父类型的注解元数据信息,需要开发者自己用反射接口查询。
下面的例子中,A 被 @Marked 注解修饰,B 继承 A,但是 B 没有 A 的注解。
package pkg
import std.reflect.TypeInfo
@Annotation
public class Marked {
const init() {}
}
@Marked
open class A {}
class B <: A {}
main() {
if (TypeInfo.of(A()).findAnnotation<Marked>().isSome()) {
println("A is Marked")
}
if (TypeInfo.of(B()).findAnnotation<Marked>().isSome()) {
println("B is Marked")
}
}
编译并执行上述代码,输出结果为:
A is Marked
自定义注解可以用在类型声明(class、struct、enum、interface)、成员函数/构造函数中的参数、构造函数声明、成员函数声明、成员变量声明、成员属性声明。也可以限制自己可以使用的位置,这样可以减少开发者的误用,这类注解需要在声明 @Annotation 时标注 target 参数,参数类型为 Array<AnnotationKind>。其中,AnnotationKind 是标准库中定义的 enum。当没有限定 target 的时候,该自定义注解可以用在以上全部位置。当限定 target 时,只能用在声明的列表中。
public enum AnnotationKind {
| Type
| Parameter
| Init
| MemberProperty
| MemberFunction
| MemberVariable
}
下面的例子中,自定义注解通过 target 限定只能用在成员函数上,用在其他位置会编译报错。
@Annotation[target: [MemberFunction]]
public class Marked {
const init() {}
}
class A {
@Marked // Ok, member funciton
func marked() {}
}
@Marked // Error, type
class B {}
main() {}
仓颉-C 互操作
为了兼容已有的生态,仓颉支持调用 C 语言的函数,也支持 C 语言调用仓颉的函数。
仓颉调用 C 的函数
在仓颉中要调用 C 的函数,需要在仓颉语言中用 @C 和 foreign 关键字声明这个函数,但 @C 在修饰 foreign 声明的时候,可以省略。
举个例子,假设要调用 C 的 rand 和 printf 函数,它的函数签名如下:
// stdlib.h
int rand();
// stdio.h
int printf (const char *fmt, ...);
那么在仓颉中调用这两个函数的方式如下:
// declare the function by `foreign` keyword, and omit `@C`
foreign func rand(): Int32
foreign func printf(fmt: CString, ...): Int32
main() {
// call this function by `unsafe` block
let r = unsafe { rand() }
println("random number ${r}")
unsafe {
var fmt = LibC.mallocCString("Hello, No.%d\n")
printf(fmt, 1)
LibC.free(fmt)
}
}
需要注意的是:
foreign修饰函数声明,代表该函数为外部函数。被foreign修饰的函数只能有函数声明,不能有函数实现。foreign声明的函数,参数和返回类型必须符合 C 和仓颉数据类型之间的映射关系(详情请参见类型映射)。- 由于 C 侧函数很可能产生不安全操作,所以调用
foreign修饰的函数需要被unsafe块包裹,否则会发生编译错误。 @C修饰的foreign关键字只能用来修饰函数声明,不可用来修饰其他声明,否则会发生编译错误。@C只支持修饰foreign函数、顶层作用域中的非泛型函数和struct类型。foreign函数不支持命名参数和参数默认值。foreign函数允许变长参数,使用...表达,只能用于参数列表的最后。变长参数均需要满足CType约束,但不必是同一类型。- 仓颉(CJNative 后端)虽然提供了栈扩容能力,但是由于 C 侧函数实际使用栈大小仓颉无法感知,所以 ffi 调用进入 C 函数后,仍然存在栈溢出的风险(可能导致程序运行时崩溃或者产生不可预期的行为),需要开发者根据实际情况,修改
cjStackSize的配置。
一些不合法的 foreign 声明的示例代码如下:
foreign func rand(): Int32 { // compiler error
return 0
}
@C
foreign var a: Int32 = 0 // compiler error
@C
foreign class A{} // compiler error
@C
foreign interface B{} // compiler error
CFunc
仓颉中的 CFunc 指可以被 C 语言代码调用的函数,共有以下三种形式:
@C修饰的foreign函数@C修饰的仓颉函数- 类型为
CFunc的lambda表达式,与普通的 lambda 表达式不同,CFunc lambda不能捕获变量。
// Case 1
foreign func free(ptr: CPointer<Int8>): Unit
// Case 2
@C
func callableInC(ptr: CPointer<Int8>) {
print("This function is defined in Cangjie.")
}
// Case 3
let f1: CFunc<(CPointer<Int8>) -> Unit> = { ptr =>
print("This function is defined with CFunc lambda.")
}
以上三种形式声明/定义的函数的类型均为 CFunc<(CPointer<Int8>) -> Unit>。CFunc 对应 C 语言的函数指针类型。这个类型为泛型类型,其泛型参数表示该 CFunc 入参和返回值类型,使用方式如下:
foreign func atexit(cb: CFunc<() -> Unit>): Int32
与 foreign 函数一样,其他形式的 CFunc 的参数和返回类型必须满足 CType 约束,且不支持命名参数和参数默认值。
CFunc 在仓颉代码中被调用时,需要处在 unsafe 上下文中。
仓颉语言支持将一个 CPointer<T> 类型的变量类型转换为一个具体的 CFunc,其中 CPointer 的泛型参数 T 可以是满足 CType 约束的任意类型,使用方式如下:
main() {
var ptr = CPointer<Int8>()
var f = CFunc<() -> Unit>(ptr)
unsafe { f() } // core dumped when running, because the pointer is nullptr.
}
注意:
将一个指针强制类型转换为
CFunc并进行函数调用是危险行为,需要用户保证指针指向的是一个切实可用的函数地址,否则将发生运行时错误。
inout 参数
在仓颉中调用 CFunc 时,其实参可以使用 inout 关键字修饰,组成引用传值表达式,此时,该参数按引用传递。引用传值表达式的类型为 CPointer<T>,其中 T 为 inout 修饰的表达式的类型。
引用传值表达式具有以下约束:
- 仅可用于对
CFunc的调用处。 - 其修饰对象的类型必须满足
CType约束,但不可以是CString。 - 其修饰对象不可以是用
let定义的,不可以是字面量、入参、其他表达式的值等临时变量。 - 通过仓颉侧引用传值表达式传递到 C 侧的指针,仅保证在函数调用期间有效,即此种场景下 C 侧不应该保存指针以留作后用。
inout 修饰的变量,可以是定义在顶层作用域中的变量、局部变量、struct 中的成员变量,但不能直接或间接来源于 class 的实例成员变量。
下面是一个例子:
foreign func foo1(ptr: CPointer<Int32>): Unit
@C
func foo2(ptr: CPointer<Int32>): Unit {
let n = unsafe { ptr.read() }
println("*ptr = ${n}")
}
let foo3: CFunc<(CPointer<Int32>) -> Unit> = { ptr =>
let n = unsafe { ptr.read() }
println("*ptr = ${n}")
}
struct Data {
var n: Int32 = 0
}
class A {
var data = Data()
}
main() {
var n: Int32 = 0
unsafe {
foo1(inout n) // OK
foo2(inout n) // OK
foo3(inout n) // OK
}
var data = Data()
var a = A()
unsafe {
foo1(inout data.n) // OK
foo1(inout a.data.n) // Error, n is derived indirectly from instance member variables of class A
}
}
注意:
使用宏扩展特性时,在宏的定义中,暂时不能使用
inout参数特性。
unsafe
在引入与 C 语言的互操作过程中,同时也引入了 C 的许多不安全因素,因此在仓颉中使用 unsafe 关键字,用于对跨 C 调用的不安全行为进行标识。
关于 unsafe 关键字,有以下几点说明:
unsafe可以修饰函数、表达式,也可以修饰一段作用域。- 被
@C修饰的函数,被调用处需要在unsafe上下文中。 - 在调用
CFunc时,使用处需要在unsafe上下文中。 foreign函数在仓颉中进行调用,被调用处需要在unsafe上下文中。- 当被调用函数被
unsafe修饰时,被调用处需要在unsafe上下文中。
使用方式如下:
foreign func rand(): Int32
@C
func foo(): Unit {
println("foo")
}
var foo1: CFunc<() -> Unit> = { =>
println("foo1")
}
main(): Int64 {
unsafe {
rand() // Call foreign func.
foo() // Call @C func.
foo1() // Call CFunc var.
}
0
}
需要注意的是,普通 lambda 无法传递 unsafe 属性,当 unsafe 的 lambda 逃逸后,可以不在 unsafe 上下文中直接调用而未产生任何编译错误。当需要在 lambda 中调用 unsafe 函数时,建议在 unsafe 块中进行调用,参考如下用例:
unsafe func A(){}
unsafe func B(){
var f = { =>
unsafe { A() } // Avoid calling A() directly without unsafe in a normal lambda.
}
return f
}
main() {
var f = unsafe{ B() }
f()
println("Hello World")
}
调用约定
函数调用约定描述调用者和被调用者双方如何进行函数调用(如参数如何传递、栈由谁清理等),函数调用和被调用双方必须使用相同的调用约定才能正常运行。仓颉编程语言通过 @CallingConv 来表示各种调用约定,支持的调用约定如下:
- CDECL:
CDECL表示 clang 的 C 编译器在不同平台上默认使用的调用约定。 - STDCALL:
STDCALL表示 Win32 API 使用的调用约定。
通过 C 语言互操作机制调用的 C 函数,未指定调用约定时将采用默认的 CDECL 调用约定。如下调用 C 标准库函数 rand 示例:
@CallingConv[CDECL] // Can be omitted in default.
foreign func rand(): Int32
main() {
println(unsafe { rand() })
}
@CallingConv 只能用于修饰 foreign 块、单个 foreign 函数和顶层作用域中的 CFunc 函数。当 @CallingConv 修饰 foreign 块时,会为 foreign 块中的每个函数分别加上相同的 @CallingConv 修饰。
使用说明
-
操作系统线程局部变量使用约束
仓颉和 C 语言互操作时,使用操作系统线程的局部变量存在风险,说明如下:
- 线程局部变量包括 C 语言提供的
thread_local定义的变量和使用pthread_key_create创建的变量。 - 仓颉具备仓颉线程调度能力,支持仓颉线程的切换和恢复,仓颉线程被调度到哪个操作系统线程是随机的,从而在仓颉线程上调用其他语言的线程局部变量是有风险的。
如下示例中,仓颉调用 C 语言的线程局部变量存在风险:
// C language logic using thread_local static thread_local int64_t count = 0; int64_t getCount() { count++; return count; }foreign func getCount(): Int64 // Cangjie invokes the preceding C language logic spawn { let r1 = unsafe { getCount() } // r1 equals 1 sleep(Duration.second * 10) let r2 = unsafe { getCount() } // r2 may not be equal to 2 } - 线程局部变量包括 C 语言提供的
-
线程绑定使用约束
仓颉调用 C 语言执行互操作逻辑时,仓颉线程调度到哪个操作系统线程是随机的,线程优先级和线程亲和性等与线程绑定的行为不建议使用。
-
同步原语使用说明
仓颉调用 C 语言执行互操作逻辑时,当前这个仓颉线程会等待互操作逻辑执行结束,不建议在其他语言中出现可能导致长时间等待的阻塞性行为。
-
对进程 fork 场景的支持说明
仓颉调用 C 语言执行互操作逻辑时,如果在 C 语言中以
fork()方式创建子进程,子进程中不支持执行仓颉逻辑。同一进程中其他操作系统线程不受影响。 -
进程退出时的说明
仓颉调用 C 语言执行互操作逻辑时,如果在 C 语言中退出进程,进程内共享的资源已经释放,可能导致非法访问等错误。
类型映射
基础类型
仓颉与 C 语言支持基本数据类型的映射,总体原则是:
- 仓颉的类型不包含指向托管内存的引用类型;
- 仓颉的类型和 C 的类型具有同样的内存布局。
比如说,一些基本的类型映射关系如下:
| Cangjie Type | C Type | Size (byte) |
|---|---|---|
Unit | void | 0 |
Bool | bool | 1 |
UInt8 | char | 1 |
Int8 | int8_t | 1 |
UInt8 | uint8_t | 1 |
Int16 | int16_t | 2 |
UInt16 | uint16_t | 2 |
Int32 | int32_t | 4 |
UInt32 | uint32_t | 4 |
Int64 | int64_t | 8 |
UInt64 | uint64_t | 8 |
IntNative | ssize_t | platform dependent |
UIntNative | size_t | platform dependent |
Float32 | float | 4 |
Float64 | double | 8 |
说明:
int类型、long类型等由于其在不同平台上的不确定性,需要程序员自行指定对应仓颉编程语言类型。在 C 互操作场景中,与 C 语言类似,Unit类型仅可作为CFunc中的返回类型和CPointer的泛型参数。
仓颉也支持与 C 语言的结构体和指针类型的映射。
结构体
对于结构体类型,仓颉用 @C 修饰的 struct 来对应。比如说 C 语言里面有这样的一个结构体:
typedef struct {
long long x;
long long y;
long long z;
} Point3D;
那么它对应的仓颉类型可以这样定义:
@C
struct Point3D {
var x: Int64 = 0
var y: Int64 = 0
var z: Int64 = 0
}
如果 C 语言里有这样的一个函数:
Point3D addPoint(Point3D p1, Point3D p2);
那么对应的,在仓颉里面可以这样声明这个函数:
foreign func addPoint(p1: Point3D, p2: Point3D): Point3D
用 @C 修饰的 struct 必须满足以下限制:
- 成员变量的类型必须满足
CType约束 - 不能实现或者扩展
interfaces - 不能作为
enum的关联值类型 - 不允许被闭包捕获
- 不能具有泛型参数
用 @C 修饰的 struct 自动满足 CType 约束。
指针
对于指针类型,仓颉提供 CPointer<T> 类型来对应 C 侧的指针类型,其泛型参数 T 需要满足 CType 约束。比如对于 malloc 函数,在 C 里面的签名为:
void* malloc(size_t size);
那么在仓颉中,它可以声明为:
foreign func malloc(size: UIntNative): CPointer<Unit>
CPointer 可以进行读写、偏移计算、判空以及转为指针的整型形式等,详细 API 可以参考《仓颉编程语言库 API》。其中读写和偏移计算为不安全行为,当不合法的指针调用这些函数时,可能发生未定义行为,这些 unsafe 函数需要在 unsafe 块中调用。
CPointer 的使用示例如下:
foreign func malloc(size: UIntNative): CPointer<Unit>
foreign func free(ptr: CPointer<Unit>): Unit
@C
struct Point3D {
var x: Int64
var y: Int64
var z: Int64
init(x: Int64, y: Int64, z: Int64) {
this.x = x
this.y = y
this.z = z
}
}
main() {
let p1 = CPointer<Point3D>() // create a CPointer with null value
if (p1.isNull()) { // check if the pointer is null
print("p1 is a null pointer")
}
let sizeofPoint3D: UIntNative = 24
var p2 = unsafe { malloc(sizeofPoint3D) } // malloc a Point3D in heap
var p3 = unsafe { CPointer<Point3D>(p2) } // pointer type cast
unsafe { p3.write(Point3D(1, 2, 3)) } // write data through pointer
let p4: Point3D = unsafe { p3.read() } // read data through pointer
let p5: CPointer<Point3D> = unsafe { p3 + 1 } // offset of pointer
unsafe { free(p2) }
}
仓颉语言支持 CPointer 之间的强制类型转换,转换前后的 CPointer 的泛型参数 T 均需要满足 CType 的约束,使用方式如下:
main() {
var pInt8 = CPointer<Int8>()
var pUInt8 = CPointer<UInt8>(pInt8) // CPointer<Int8> convert to CPointer<UInt8>
0
}
仓颉语言支持将一个 CFunc 类型的变量类型转换为一个具体的 CPointer,其中 CPointer 的泛型参数 T 可以是满足 CType 约束的任意类型,使用方式如下:
foreign func rand(): Int32
main() {
var ptr = CPointer<Int8>(rand)
0
}
注意:
将一个
CFunc强制类型转换为指针通常是安全的,但是不应该对转换后的指针执行任何的read,write操作,可能会导致运行时错误。
数组
仓颉使用 VArray 类型与 C 的数组类型映射,VArray 可以作为函数参数和 @C struct 成员。当 VArray<T, $N> 中的元素类型 T 满足 CType 约束时, VArray<T, $N> 类型也满足 CType 约束。
作为函数参数类型:
当 VArray 作为 CFunc 的参数时, CFunc 的函数签名仅可以是 CPointer<T> 类型或 VArray<T, $N> 类型。当函数签名中的参数类型为 VArray<T, $N> 时,传递的参数仍以 CPointer<T> 形式传递。
VArray 作为参数的使用示例如下:
foreign func cfoo1(a: CPointer<Int32>): Unit
foreign func cfoo2(a: VArray<Int32, $3>): Unit
对应的 C 侧函数定义可以是:
void cfoo1(int *a) { ... }
void cfoo2(int a[3]) { ... }
调用 CFunc 时,需要通过 inout 修饰 VArray 类型变量:
var a: VArray<Int32, $3> = [1, 2, 3]
unsafe {
cfoo1(inout a)
cfoo2(inout a)
}
VArray 不允许作为 CFunc 的返回值类型。
作为 @C struct 成员:
当 VArray 作为 @C struct 成员时,它的内存布局与 C 侧的结构体排布一致,需要保证仓颉侧声明长度与类型也与 C 完全一致:
struct S {
int a[2];
int b[0];
}
在仓颉中,可以声明为如下结构体与 C 代码对应:
@C
struct S {
var a = VArray<Int32, $2>(repeat: 0)
var b = VArray<Int32, $0>(repeat: 0)
}
注意:
C 语言中允许结构体的最后一个字段为未指明长度的数组类型,该数组被称为柔性数组(flexible array),仓颉不支持包含柔性数组的结构体的映射。
字符串
特别地,对于 C 语言中的字符串类型,仓颉中设计了一个 CString 类型来对应。为简化为 C 语言字符串的操作,CString 提供了以下成员函数:
init(p: CPointer<UInt8>)通过 CPointer 构造一个 CStringfunc getChars()获取字符串的地址,类型为CPointer<UInt8>func size(): Int64计算该字符串的长度func isEmpty(): Bool判断该字符串的长度是否为 0,如果字符串的指针为空返回 truefunc isNotEmpty(): Bool判断该字符串的长度是否不为 0,如果字符串的指针为空返回 falsefunc isNull(): Bool判断该字符串的指针是否为 nullfunc startsWith(str: CString): Bool判断该字符串是否以 str 开头func endsWith(str: CString): Bool判断该字符串是否以 str 结尾func equals(rhs: CString): Bool判断该字符串是否与 rhs 相等func equalsLower(rhs: CString): Bool判断该字符串是否与 rhs 相等,忽略大小写func subCString(start: UInt64): CString从 start 开始截取子串,返回的子串存储在新分配的空间中func subCString(start: UInt64, len: UInt64): CString从 start 开始截取长度为 len 的子串,返回的子串存储在新分配的空间中func compare(str: CString): Int32该字符串与 str 比较,返回结果与 C 语言的strcmp(this, str)一样func toString(): String用该字符串构造一个新的 String 对象func asResource(): CStringResource获取 CString 的 Resource 类型
另外,将 String 类型转换为 CString 类型,可以通过调用 LibC 中的 mallocCString 接口,使用完成后需要对 CString 进行释放。
CString 的使用示例如下:
foreign func strlen(s: CString): UIntNative
main() {
var s1 = unsafe { LibC.mallocCString("hello") }
var s2 = unsafe { LibC.mallocCString("world") }
let t1: Int64 = s1.size()
let t2: Bool = s2.isEmpty()
let t3: Bool = s1.equals(s2)
let t4: Bool = s1.startsWith(s2)
let t5: Int32 = s1.compare(s2)
let length = unsafe { strlen(s1) }
unsafe {
LibC.free(s1)
LibC.free(s2)
}
}
sizeOf/alignOf
仓颉还提供了 sizeOf 和 alignOf 两个函数,用于获取上述 C 互操作类型的内存占用和内存对齐数值(单位:字节),函数声明如下:
public func sizeOf<T>(): UIntNative where T <: CType
public func alignOf<T>(): UIntNative where T <: CType
使用示例:
@C
struct Data {
var a: Int64 = 0
var b: Float32 = 0.0
}
main() {
println(sizeOf<Data>())
println(alignOf<Data>())
}
在 64 位机器上运行,将输出:
16
8
CType
除类型映射一节提供的与 C 侧类型进行映射的类型外,仓颉还提供了一个 CType 接口,接口本身不包含任何方法,它可以作为所有 C 互操作支持的类型的父类型,便于在泛型约束中使用。
需要注意的是:
CType接口是仓颉中的一个接口类型,它本身不满足CType约束;CType接口不允许被继承、扩展;CType接口不会突破子类型的使用限制。
CType 的使用示例如下:
func foo<T>(x: T): Unit where T <: CType {
match (x) {
case i32: Int32 => println(i32)
case ptr: CPointer<Int8> => println(ptr.isNull())
case f: CFunc<() -> Unit> => unsafe { f() }
case _ => println("match failed")
}
}
main() {
var i32: Int32 = 1
var ptr = CPointer<Int8>()
var f: CFunc<() -> Unit> = { => println("Hello") }
var f64 = 1.0
foo(i32)
foo(ptr)
foo(f)
foo(f64)
}
执行结果如下:
1
true
Hello
match failed
C 调用仓颉的函数
仓颉提供 CFunc 类型来对应 C 侧的函数指针类型。C 侧的函数指针可以传递到仓颉,仓颉也可以构造出对应 C 的函数指针的变量传递到 C 侧。
假设一个 C 的库 API 如下:
typedef void (*callback)(int);
void set_callback(callback cb);
对应的,在仓颉里面这个函数可以声明为:
foreign func set_callback(cb: CFunc<(Int32) -> Unit>): Unit
CFunc 类型的变量可以从 C 侧传递过来,也可以在仓颉侧构造出来。在仓颉侧构造 CFunc 类型有两种办法,一个是用 @C 修饰的函数,另外一个是标记为 CFunc 类型的闭包。
@C 修饰的函数,表明它的函数签名是满足 C 的调用规则的,定义还是写在仓颉这边。foreign 修饰的函数定义是在 C 侧的。
注意:
foreign修饰的函数与@C修饰的函数,这两种CFunc的命名不建议使用CJ_(不区分大小写)作为前缀,否则可能与标准库及运行时等编译器内部符号出现冲突,导致未定义行为。
示例如下:
@C
func myCallback(s: Int32): Unit {
println("handle ${s} in callback")
}
main() {
// the argument is a function qualified by `@C`
unsafe { set_callback(myCallback) }
// the argument is a lambda with `CFunc` type
let f: CFunc<(Int32) -> Unit> = { i => println("handle ${i} in callback") }
unsafe { set_callback(f) }
}
假设 C 函数编译出来的库是 "libmyfunc.so",那么需要使用 cjc -L. -lmyfunc test.cj -o test.out 编译命令,使仓颉编译器去链接这个库。最终就能生成想要的可执行程序。
另外,在编译 C 代码时,请打开 -fstack-protector-all/-fstack-protector-strong 栈保护选项,仓颉侧代码默认拥有溢出检查与栈保护功能。在引入 C 代码后,需要同步保证 unsafe 块中的溢出的安全性。
编译选项
使用 C 互操作通常需要手动链接 C 的库,仓颉编译器提供了相应的编译选项。
-
--library-path <value>,-L <value>,-L<value>:指定要链接的库文件所在的目录。--library-path <value>指定的路径会被加入链接器的库文件搜索路径。另外环境变量LIBRARY_PATH中指定的路径也会被加入链接器的库文件搜索路径中,通过--library-path指定的路径会比LIBRARY_PATH中的路径拥有更高的优先级。 -
--library <value>,-l <value>,-l<value>:指定要链接的库文件。给定的库文件会被直接传给链接器,库文件名的格式应为
lib[arg].[extension]。
关于仓颉编译器支持的所有编译选项,详情请参见 "附录 > cjc 编译选项"。
示例
这里演示如何使用 C 互操作以及 write/read 接口对一个结构体进行赋值和读取值。
C 代码如下:
// draw.c
#include<stdio.h>
#include<stdint.h>
typedef struct {
int64_t x;
int64_t y;
} Point;
typedef struct {
float x;
float y;
float z;
} Cube;
int32_t drawPicture(Point* point, Cube* cube) {
point->x = 1;
point->y = 2;
printf("Draw Point finished.\n");
printf("Before draw cube\n");
printf("%f\n", cube->x);
printf("%f\n", cube->y);
printf("%f\n", cube->z);
cube->x = 4.4;
cube->y = 5.5;
cube->z = 6.6;
printf("Draw Cube finished.\n");
}
仓颉代码如下:
// main.cj
@C
struct Point {
var x: Int64 = 0
var y: Int64 = 0
}
@C
struct Cube {
var x: Float32 = 0.0
var y: Float32 = 0.0
var z: Float32 = 0.0
init(x: Float32, y: Float32, z: Float32) {
this.x = x
this.y = y
this.z = z
}
}
foreign func drawPicture(point: CPointer<Point>, cube: CPointer<Cube>): Int32
main() {
let pPoint = unsafe { LibC.malloc<Point>() }
let pCube = unsafe { LibC.malloc<Cube>() }
var cube = Cube(1.1, 2.2, 3.3)
unsafe {
pCube.write(cube)
drawPicture(pPoint, pCube) // in which x, y will be changed
println(pPoint.read().x)
println(pPoint.read().y)
println(pCube.read().x)
println(pCube.read().y)
println(pCube.read().z)
LibC.free(pPoint)
LibC.free(pCube)
}
}
编译仓颉代码的命令如下(以 CJNative 后端为例):
cjc -L . -l draw ./main.cj
其中编译命令中 -L . 表示链接库时从当前目录查找(假设 libdraw.so 存在于当前目录),-l draw 表示链接的库的名字,编译成功后默认生成二进制文件 main,执行二进制文件的命令如下:
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
运行结果如下:
Draw Point finished.
Before draw cube
1.100000
2.200000
3.300000
Draw Cube finished.
1
2
4.400000
5.500000
6.600000
cjc 使用
cjc是仓颉编程语言的编译命令,其提供了丰富的功能及对应的编译选项,本章将对基本使用方法进行介绍。
cjc-frontend (仓颉前端编译器)会随 cjc 一起通过 Cangjie SDK 提供,cjc-frontend 能够将仓颉源码编译至仓颉的中间表示 (LLVM IR)。 cjc-frontend 仅进行仓颉代码的前端编译,虽然 cjc-frontend 和 cjc 共享部分编译选项,但编译流程会在前端编译结束时中止。使用 cjc 时仓颉编译器会自动进行前端、后端的编译以及链接工作。cjc-frontend 仅作为前端编译器的实体体现提供,除编译器开发者外,仓颉代码的编译应优先使用 cjc 。
cjc 基本使用方法
本节介绍 cjc 的基本使用方法。关于编译选项详情,请查阅 cjc 编译选项章节。
cjc 的使用方式如下:
cjc [option] file...
假如有一个名为 hello.cj 的仓颉文件:
main() {
println("Hello, World!")
}
可以使用以下命令来编译此文件:
$ cjc hello.cj
此时工作目录下会新增可执行文件 main ,cjc 默认会将给定源代码文件编译成可执行文件,并将可执行文件命名为 main。
以上为不给任何编译选项时 cjc 的默认行为,可以通过使用编译选项来控制 cjc 的行为,例如让 cjc 进行整包编译,又或者是指定输出文件的名字。
cjpm 介绍
CJPM(Cangjie Package Manager) 是仓颉语言的官方包管理工具,用来管理、维护仓颉项目的模块系统,并提供更简易统一的编译入口,支持自定义编译命令。通过包管理器自动依赖管理实现对引入的多版本三方依赖软件进行分析合并,无需开发者担心多版本依赖冲突问题,大大减轻开发者负担;同时提供基于仓颉语言原生的自定义构建机制,允许开发者在构建的不同阶段增加预处理和后处理流程,实现构建流程可灵活定制,能够满足开发者不同业务场景下的编译构建诉求。
cjpm 基本使用方法
通过 cjpm -h 即可查看主界面,由几个板块组成,从上到下分别是: 当前命令说明、使用示例(Usage)、支持的可用命令(Available subcommands)、支持的配置项(Available options)、更多提示内容。
Cangjie Package Manager
Usage:
cjpm [subcommand] [option]
Available subcommands:
init Init a new cangjie module
check Check the dependencies
update Update cjpm.lock
tree Display the package dependencies in the source code
build Compile the current module
run Compile and run an executable product
test Unittest a local package or module
bench Run benchmarks in a local package or module
clean Clean up the target directory
install Install a cangjie binary
uninstall Uninstall a cangjie binary
Available options:
-h, --help help for cjpm
-v, --version version for cjpm
Use "cjpm [subcommand] --help" for more information about a command.
cjpm init 用来初始化一个新的仓颉模块或者工作空间。初始化模块时会默认在当前文件夹创建 cjpm.toml 文件,并且新建 src 源码文件夹,在 src 下生成默认的 main.cj 文件。自定义参数初始化功能支持可以通过 cjpm init -h 查看。
例如:
输入: cjpm init
输出: cjpm init success
cjpm build 用来构建当前仓颉项目,执行该命令前会先检查依赖项,检查通过后调用 cjc 进行构建。支持全量编译、增量编译、交叉编译、并行编译等,更多编译功能支持可以通过 cjpm build -h 查看。通过 cjpm build -V 命令可以打印所有的编译过程命令。
例如:
输入: cjpm build -V
输出:
compile package module1.package1: cjc --import-path target -p "src/package1" --output-type=staticlib -o target/release/module1/libmodule1.package1.a
compile package module1: cjc --import-path target -L target/release/module1 -lmodule1.package1 -p "src" --output-type=exe --output-dir target/release/bin -o main
cjpm build success
cjpm.toml 配置文件说明
配置文件 cjpm.toml 用来配置一些基础信息、依赖项、编译选项等内容,cjpm 主要通过这个文件进行解析执行。
配置文件代码如下所示:
[package] # 单模块配置字段,与 workspace 字段不能同时存在
cjc-version = "0.49.1" # 所需 `cjc` 的最低版本要求,必需
name = "demo" # 模块名及模块 root 包名,必需
description = "nothing here" # 描述信息,非必需
version = "1.0.0" # 模块版本信息,必需
compile-option = "" # 额外编译命令选项,非必需
override-compile-option = "" # 额外全局编译命令选项,非必需
link-option = "" # 链接器透传选项,可透传安全编译命令,非必需
output-type = "executable" # 编译输出产物类型,必需
src-dir = "" # 指定源码存放路径,非必需
target-dir = "" # 指定产物存放路径,非必需
package-configuration = {} # 单包配置选项,非必需
[workspace] # 工作空间管理字段,与 package 字段不能同时存在
members = [] # 工作空间成员模块列表,必需
build-members = [] # 工作空间编译模块列表,需要是成员模块列表的子集,非必需
test-members = [] # 工作空间测试模块列表,需要是编译模块列表的子集,非必需
compile-option = "" # 应用于所有工作空间成员模块的额外编译命令选项,非必需
override-compile-option = "" # 应用于所有工作空间成员模块的额外全局编译命令选项,非必需
link-option = "" # 应用于所有工作空间成员模块的链接器透传选项,非必需
target-dir = "" # 指定产物存放路径,非必需
[dependencies] # 源码依赖配置项,非必需
coo = { git = "xxx",branch = "dev" , version = "1.0.0"} # 导入 `git` 依赖,`version`字段可缺省
doo = { path = "./pro1" ,version = "1.0.0"} # 导入源码依赖,`version`字段可缺省
[test-dependencies] # 测试阶段的依赖配置项,格式和 dependencies 相同,非必需
[script-dependencies] # 构建脚本的依赖配置项,格式和 dependencies 相同,非必需
[replace] # 依赖替换配置项,格式和 dependencies 相同,非必需
[ffi.c] # 导入 C 语言的库依赖,非必需
clib1.path = "xxx"
[profile] # 命令剖面配置项,非必需
build = {} # build 命令配置项
test = {} # test 命令配置项
bench = {} # bench 命令配置项
customized-option = {} # 自定义透传选项
[target.x86_64-unknown-linux-gnu] # 后端和平台隔离配置项,非必需
compile-option = "value1" # 额外编译命令选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
override-compile-option = "value2" # 额外全局编译命令选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
link-option = "value3" # 链接器透传选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
[target.x86_64-w64-mingw32.dependencies] # 适用于对应 target 的源码依赖配置项,非必需
[target.x86_64-w64-mingw32.test-dependencies] # 适用于对应 target 的测试阶段依赖配置项,非必需
[target.x86_64-unknown-linux-gnu.bin-dependencies] # 仓颉二进制库依赖,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
path-option = ["./test/pro0", "./test/pro1"] # 以文件目录形式配置二进制库依赖
[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option] # 以单文件形式配置二进制库依赖
"pro0.xoo" = "./test/pro0/pro0.xoo.cjo"
"pro0.yoo" = "./test/pro0/pro0.yoo.cjo"
"pro1.zoo" = "./test/pro1/pro1.zoo.cjo"
条件编译
开发者可以通过预定义或自定义的条件完成条件编译;仓颉目前支持导入和声明的条件编译。
导入和声明的条件编译
仓颉支持使用内置编译标记 @When 来完成条件编译,编译条件使用 [] 括起来,[] 内支持输入一组或多组编译条件。@When 可以作用于导入节点和除 package 外的声明节点。
使用方法
以内置 os 编译条件为例,其使用方法如下:
@When[os == "Linux"]
class mc{}
main(): Int64 {
var a = mc()
return 0
}
在上面代码中,开发者在 Linux 系统中可以正确编译执行;在非 Linux 系统中,则会遇到找不到 mc 类定义的编译错误。
值得注意的是:
-
仓颉不支持编译条件嵌套,以下写法均不允许:
@When[os == "Windows"] @When[os == "Linux"] // Error, illegal nested when conditional compilation import std.ast.* @When[os == "Windows"] @When[os == "Linux"] // Error, illegal nested when conditional compilation func A(){} -
@When[...]作为内置编译标记,在导入前处理,由宏展开生成的代码中含有@When[...]会编译报错,如:@M0 // macro which returns the input @When[os == "Linux"] // Error, unexpected when conditional compilation directive func A(){}
内置编译条件变量
仓颉提供的内置条件变量有: os、 backend、 arch、 cjc_version、 debug 和 test。
os
os 表示目标平台的操作系统。os 支持 == 和 != 两种操作符。支持的操作系统有:Windows、Linux、macOS。
使用方式如下:
@When[os == "Linux"]
func foo() {
print("Linux, ")
}
@When[os == "Windows"]
func foo() {
print("Windows, ")
}
@When[os != "Windows"]
func fee() {
println("NOT Windows")
}
@When[os != "Linux"]
func fee() {
println("NOT Linux")
}
main() {
foo()
fee()
}
如果在 Windows 环境下编译执行,会得到 Windows, NOT Linux 的信息;如果是在 Linux 环境下,则会得到 Linux, NOT Windows 的信息。
backend
仓颉是多后端语言,backend 表示目标平台的后端类型,用于支持多种后端条件编译。backend 条件支持 == 和 != 两种操作符。
支持的后端有:cjnative、cjvm。
使用方式如下:
@When[backend == "cjnative"]
func foo() {
print("cjnative backend, ")
}
@When[backend == "cjvm"]
func foo() {
print("cjvm backend, ")
}
@When[backend != "cjnative"]
func fee() {
println("NOT cjnative backend")
}
@When[backend != "cjvm"]
func fee() {
println("NOT cjvm backend")
}
main() {
foo()
fee()
}
用 cjnative 后端的发布包编译执行,会得到 cjnative backend, NOT cjvm backend 的信息;用 cjvm 后端的发布包编译执行,则会得到 cjvm backend, NOT cjnative backend 的信息。
arch
arch 表示目标平台的处理器架构。arch 条件支持 == 和 != 两种操作符。
支持的处理器架构有:x86_64、aarch64。
使用方式如下:
@When[arch == "aarch64"]
var arch = "aarch64"
@When[arch == "x86_64"]
var arch = "x86_64"
main() {
println(arch)
}
在 x86_64 架构的目标平台编译执行,会得到 x86_64 的信息;在 aarch64 架构的目标平台编译执行,会得到 aarch64 的信息。
cjc_version
cjc_version 是仓颉内置的条件,开发者可以根据当前仓颉编译器的版本选择要编译的代码。cjc_version 条件支持 ==、!=、>、<、>=、<= 六种操作符,格式为 xx.xx.xx 支持每个 xx 支持 1-2 位数字,计算规则为补位 (补齐 2 位) 比较,例如:0.18.8 < 0.18.11, 0.18.8 == 0.18.08。
使用方式如下:
@When[cjc_version == "0.18.6"]
func foo() {
println("cjc_version equals 0.18.6")
}
@When[cjc_version != "0.18.6"]
func foo() {
println("cjc_version is NOT equal to 0.18.6")
}
@When[cjc_version > "0.18.6"]
func fnn() {
println("cjc_version is greater than 0.18.6")
}
@When[cjc_version <= "0.18.6"]
func fnn() {
println("cjc_version is less than or equal to 0.18.6")
}
@When[cjc_version < "0.18.6"]
func fee() {
println("cjc_version is less than 0.18.6")
}
@When[cjc_version >= "0.18.6"]
func fee() {
println("cjc_version is greater than or equal to 0.18.6")
}
main() {
foo()
fnn()
fee()
}
根据 cjc 的版本,上面代码的执行输出结果会有不同。
debug
debug 表示当前是否启用了调试模式即开启 -g 编译选项, 可以用于在编译代码时进行调试和发布版本之间的切换。debug 条件仅支持逻辑非运算符(!)。
使用方式如下:
@When[debug]
func foo() {
println("debug")
}
@When[!debug]
func foo() {
println("NOT debug")
}
main() {
foo()
}
启用 -g 编译执行会得到 cjc debug 的信息,如果没有启用 -g 编译执行会得到 NOT debug 的信息。
test
test 表示当前是否启用了单元测试选项 --test。test 条件仅支持逻辑非运算符(!)。可以用于区分测试代码与普通代码。
使用方式如下:
@When[test]
@Test
class Tests {
@TestCase
public func case1(): Unit {
@Expect("run", foo())
}
}
func foo() {
"run"
}
@When[!test]
main () {
println(foo())
}
使用 --test 编译执行得到的测试结果,不使用 --test 也可正常完成编译运行得到 run 的信息。
自定义编译条件变量
仓颉允许开发者自定义编译条件变量和取值,自定义的条件变量必须是一个合法的标识符且不允许和内置条件变量同名,其值是一个字符串字面量。自定义条件支持 == 和 != 两种运算符。和内置条件变量不同点在于自定义的条件需要开发者在编译时通过 --cfg 编译选项或者在配置文件 cfg.toml 中定义。
配置自定义条件变量
配置自定义条件变量的方式有两种:在编译选项中直接配置键值对或在配置文件配置键值对。
开发者可以使用 --cfg <value> 以键值对的形式向编译器传递自定义编译条件变量或者指定配置文件 cfg.toml 的搜索路径。
-
选项值需要使用双引号括起来。
-
若选项值中包含
=则会按照键值对的形式直接进行配置(若路径中包含=则需要通过\转义),多个键值对可以使用逗号,分隔。如:$ cjc --cfg "feature = lion, platform = dsp" source.cj -
允许多次使用
--cfg编译选项配置,例如:$ cjc --cfg "feature = lion" --cfg "platform = dsp" source.cj -
不允许多次定义同一个条件变量,例如:
$ cjc --cfg "feature = lion" --cfg "feature = meta" source.cj$ cjc --cfg "feature = lion, feature = meta" source.cj上述两条编译指令都会报错。
-
若选项值中不包含
=或存在通过\转义的=则将选项值作为配置文件cfg.toml的搜索路径传递给编译器,例如:$ cjc --cfg "./cfg" source.cj若
./cfg目录下存在cfg.toml,则编译器会在编译时自动获取./cfg/cfg.toml中配置的自定义编译条件。cfg.toml文件中应采用键值对的方式配置自定义条件变量,每个键值对独占一行,键名是一个合法的仓颉普通标识符,键值是一个双引号括起来的字符串,字符串不支持转义。cfg.toml文件中也支持全行注释和行末注释,例如:feature = "lion" platform = "dsp" # 全行注释 feature = "meta" # 行末注释 -
多次使用
--cfg配置cfg.toml文件的搜索路径时,按照传入的顺序依次搜索cfg.toml文件,若在所有传入的搜索路径下都没有找到cfg.toml文件,则在默认路径下搜索配置文件cfg.toml。 -
多次使用
--cfg编译选项进行配置时,若某次以键值对的形式直接进行配置,则会忽略配置文件cfg.toml中的配置。 -
若未使用
--cfg编译选项,编译器会在默认路径(通过--package或-p指定的package目录或cjc执行目录)下搜索配置文件cfg.toml。
多条件编译
仓颉条件编译允许开发者自由组合多个条件编译选项。支持逻辑运算符组合多个条件,支持括号运算符明确优先级。
使用方式如下:
//source.cj
@When[(test || feature == "lion") && !debug]
func fee() {
println("feature lion")
}
main() {
fee()
}
使用如下编译命令编译运行上段代码:
$ cjc --cfg="feature=lion" source.cj -o runner.out
会得到输出结果如下:
feature lion
部署仓颉运行时
为了使仓颉可执行程序能够在不同的操作系统环境中正常运行,仓颉语言提供了一套运行时(runtime)环境。该运行时环境为仓颉可执行程序提供了对内存和其他系统资源的访问,例如在运行过程中依赖的仓颉动态库。
安装完整的仓颉工具链包含了仓颉代码编译环境和仓颉运行时的安装(详情请参见安装仓颉工具链章节)。如果不需要编译代码,仅仅是运行可执行程序,也可以在环境中独立部署运行时。
本节介绍仓颉运行时的部署。
值得注意的是,编译时使用全静态链接仓颉库,运行时模块已在编译时嵌入到可执行文件中,因此无需在运行环境额外部署运行时,可直接在运行环境中运行编译所得的可执行文件。
Linux
-
首先请前往仓颉官方发布渠道,下载适配平台架构的安装包:
cangjie-sdk-linux-x64-x.y.z.tar.gz:适用于 x86_64 架构 Linux 系统的仓颉工具链。cangjie-sdk-linux-aarch64-x.y.z.tar.gz:适用于 aarch64 架构 Linux 系统的仓颉工具链。
-
请将下载的安装包解压到合适的目录。
解压完成后,可以在当前工作路径下看到一个名为
cangjie的目录,其中存放了仓颉工具链的全部内容。cangjie目录下的runtime目录,即为运行时库,存放了仓颉runtime的全部动态库。 -
请在运行环境执行如下命令完成
runtime的部署(其中${CANGJIE_HOME}请修改为cangjie目录所在的路径,${hw_arch}请修改为对应的硬件架构):export LD_LIBRARY_PATH=${CANGJIE_HOME}/runtime/lib/linux_${hw_arch}_llvm:${LD_LIBRARY_PATH}
macOS
-
首先请前往仓颉官方发布渠道,下载适配平台架构的安装包:
cangjie-sdk-mac-aarch64-x.y.z.tar.gz:适用于 aarch64/arm64 架构 macOS 系统的仓颉工具链。
-
请将下载的安装包解压到合适的目录。
解压完成后,可以在当前工作路径下看到一个名为
cangjie的目录,其中存放了仓颉工具链的全部内容。cangjie目录下的runtime目录,即为运行时库,存放了仓颉runtime的全部动态库。 -
请在运行环境执行如下命令完成
runtime的部署(其中${CANGJIE_HOME}请修改为cangjie目录所在的路径,${hw_arch}请修改为对应的硬件架构):export DYLD_LIBRARY_PATH=${CANGJIE_HOME}/runtime/lib/darwin_${hw_arch}_llvm:${DYLD_LIBRARY_PATH}
Windows
-
首先请前往仓颉官方发布渠道,下载适配平台架构的安装包:
cangjie-sdk-windows-x64-x.y.z.zip:适用于 x86_64 架构 Windows 系统的仓颉工具链。
-
请将下载的安装包解压到合适的目录。
解压完成后,可以在当前工作路径下看到一个名为
cangjie的目录,其中存放了仓颉工具链的全部内容。cangjie目录下的runtime目录,即为运行时库,存放了仓颉runtime的全部动态库。 -
此处为开发者提供三种环境下部署
runtime的方法,可以根据使用习惯及环境配置,选择一种执行(其中${CANGJIE_HOME}请修改为cangjie目录所在的路径,${hw_arch}请修改为对应的硬件架构):-
若使用 Windows 命令提示符(CMD)环境,请执行:
set "PATH=${CANGJIE_HOME}\runtime\lib\windows_x86_64_llvm;%PATH%;" -
若使用 PowerShell 环境,请执行:
$env:PATH = "${CANGJIE_HOME}\runtime\lib\windows_x86_64_llvm;" + $env:Path -
若使用 MSYS shell、bash 等环境,请执行:
export PATH=${CANGJIE_HOME}/runtime/lib/windows_x86_64_llvm
-
运行仓颉可执行程序
直接运行
Linux / macOS
-
首先请查阅部署仓颉运行时章节完成运行时库的部署。
-
将编译得到的可执行文件
main拷贝至运行环境中,执行可执行文件即可。./main值得注意的是,使用
cjpm编译得到的可执行文件main在target/release/bin目录下。
Windows
-
首先请查阅部署仓颉运行时章节,完成运行时库的部署。
-
将编译得到的可执行文件
main.exe拷贝至运行环境中,执行可执行文件即可。.\main.exe值得注意的是,使用
cjpm编译得到的可执行文件main.exe在target\release\bin目录下。
使用 cjpm 运行
开发者常用 cjpm 来管理、编译、运行仓颉项目。
开发者可以根据安装仓颉工具链章节,在运行环境上安装完整的仓颉工具链。 安装完成后,将整个仓颉项目拷贝至运行环境,使用 cjpm run 命令运行仓颉项目即可。
cjc 编译选项
本章介绍常用的 cjc 编译选项。若某一选项同时适用于 cjc-frontend,则该选项会有 [frontend] 上标;若该选项在 cjc-frontend 下行为与 cjc 不同,选项会有额外说明。
-
两个横杠开头的选项为长选项,如
--xxxx。 如果长选项有可选参数,那么选项和参数之间需要用等号连接,如--xxxx=<value>。 如果长选项有必选参数,那么选项和参数之间既可以用空格隔开,也可以用等号连接,如--xxxx <value>与--xxxx=<value>等价。 -
一个横杠开头的选项为短选项,如
-x。 对于短选项,如果其后有参数,选项和参数之间可以用空格隔开,也可以不隔开,如-x <value>与-x<value>等价。
基本选项
--output-type=[exe|staticlib|dylib] [frontend]
指定输出文件的类型。exe 模式下会生成可执行文件,staticlib 模式下会生成静态库文件( .a 文件),dylib 模式下会生成动态库文件(Linux 平台为 .so 文件、Windows 平台为 .dll 文件,macOS 平台为 .dylib 文件)。
cjc 默认为 exe 模式。
除了可以将 .cj 文件编译成一个可执行文件以外,也可以将其编译成一个静态或者是动态的链接库,例如使用:
$ cjc tool.cj --output-type=dylib
可以将 tool.cj 编译成一个动态链接库,在 Linux 平台上,cjc 会生成一个名为 libtool.so 的动态链接库文件。
值得注意的是,若编译可执行程序时链接了仓颉的动态库文件,必须同时指定 --dy-std 选项,详情请见 --dy-std 选项说明。
[frontend] 在 cjc-frontend 中,编译流程仅进行至 LLVM IR,因此输出总是 .bc 文件,但不同的 --output-type 类型仍会影响前端编译的策略。
--package, -p [frontend]
编译包,使用此选项时需要指定一个目录作为输入,目录中的源码文件需要属于同一个包。
假设有文件 log/printer.cj:
package log
public func printLog(message: String) {
println("[Log]: ${message}")
}
与文件 main.cj:
import log.*
main() {
printLog("Everything is great")
}
可以使用
$ cjc -p log --output-type=staticlib
来编译 log 包,cjc 会在当前目录下生成一个 liblog.a 文件。
可以使用 liblog.a 文件来编译 main.cj ,编译命令如下:
$ cjc main.cj liblog.a
cjc 会将 main.cj 与 liblog.a 一同编译成一个可执行文件 main 。
--module-name <value> [frontend]
指定要编译的模块的名称。
假设有文件 my_module/src/log/printer.cj:
package log
public func printLog(message: String) {
println("[Log]: ${message}")
}
与文件 main.cj:
import my_module.log.*
main() {
printLog("Everything is great")
}
可以使用
$ cjc -p my_module/src/log --module-name my_module --output-type=staticlib -o my_module/liblog.a
来编译 log 包并指定其模块名为 my_module,cjc 会在 my_module 目录下生成一个 my_module/liblog.a 文件。
然后可以使用 liblog.a 文件来编译导入了 log 包的 main.cj ,编译命令如下:
$ cjc main.cj my_module/liblog.a
cjc 会将 main.cj 与 liblog.a 一同编译成一个可执行文件 main 。
--output <value>, -o <value>, -o<value> [frontend]
指定输出文件的路径,编译器的输出将被写入指定文件。
例如,以下命令会将输出的可执行文件名称指定为 a.out。
cjc main.cj -o a.out
注意:
编译目标平台为
Windows时,使用-o选项指定的可执行文件名称不允许为cjc.exe;编译目标平台为非Windows时,不允许为cjc,否则可能导致运行错误。
--library <value>, -l <value>, -l<value>
指定要链接的库文件。
给定的库文件会被直接传给链接器,此编译选项一般需要和 --library-path <value> 配合使用。
文件名的格式应为 lib[arg].[extension]。当需要链接库 a 时,可以使用选项 -l a,库文件搜索目录下的 liba.a、liba.so(或链接 Windows 目标程序时会搜索 liba.dll)等文件会被链接器搜索到并根据需要被链接至最终输出中。
--library-path <value>, -L <value>, -L<value>
指定要链接的库文件所在的目录。
使用 --library <value> 选项时,通常也需要使用此选项来指定要链接的库文件所在的目录。
--library-path <value> 指定的路径会被加入链接器的库文件搜索路径。此外,环境变量 LIBRARY_PATH 中指定的路径也会被加入链接器的库文件搜索路径中,通过 --library-path 指定的路径会比 LIBRARY_PATH 中的路径拥有更高的优先级。
假设有从以下 C 语言源文件通过 C 语言编译器编译得到的动态库文件 libcProg.so,
#include <stdio.h>
void printHello() {
printf("Hello World\n");
}
与仓颉文件 main.cj:
foreign func printHello(): Unit
main(): Int64 {
unsafe {
printHello()
}
return 0
}
可以使用
cjc main.cj -L . -l cProg
来编译 main.cj 并指定要链接的 cProg 库,这里 cjc 会输出一个可执行文件 main。
执行 main 会有如下输出:
$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
Hello World
值得注意的是,由于使用了动态库文件,这里需要将库文件所在目录加入 $LD_LIBRARY_PATH 以保证 main 能够在执行时进行动态链接。
-g [frontend]
生成带有调试信息的可执行文件或库文件。
注意:
-g只能配合-O0使用,如果使用更高的优化级别可能会导致调试功能出现异常。
--trimpath <value> [frontend]
移除调试信息中源文件路径信息的前缀。
编译仓颉代码时,cjc 会保存源文件(.cj 文件)的绝对路径信息以在运行时提供调试与异常信息。
使用此选项可以将指定的路径前缀从源文件路径信息中移除,cjc 的输出文件中的源文件路径信息不会包含用户指定的部分。
可以多次使用 --trimpath 指定多个不同的路径前缀;对于每个源文件路径,编译器会将第一个匹配到的前缀从路径中移除。
--coverage [frontend]
生成支持统计代码覆盖率的可执行程序。编译器会为每一个编译单元生成一个后缀名为 gcno 的代码信息文件。在执行程序后,每一个编译单元都会生成一个后缀名为 gcda 的执行统计文件。根据这两个文件,配合使用 cjcov 工具可以生成本次执行下的代码覆盖率报表。
注意:
--coverage只能配合-O0使用,如果使用更高的优化级别,编译器将告警并强制使用-O0。--coverage用于编译生成可执行程序,如果用于生成静态库或者动态库,那么在最终使用该库时可能出现链接错误。
--int-overflow=[throwing|wrapping|saturating] [frontend]
指定固定精度整数运算的溢出策略,默认为 throwing。
throwing策略下,整数运算溢出时会抛出异常。wrapping策略下,整数运算溢出时会回转至对应固定精度整数的另一端。saturating策略下,整数运算溢出时会选择对应固定精度的极值作为结果。
--diagnostic-format=[default|noColor|json] [frontend]
注意:
Windows 版本暂不支持输出带颜色渲染的错误信息。
指定错误信息的输出格式,默认为 default 。
default错误信息默认格式输出(带颜色)noColor错误信息默认格式输出(无颜色)json错误信息json格式输出
--verbose, -V [frontend]
cjc 会打印出编译器版本信息、工具链依赖的相关信息以及编译过程中执行的命令。
--help, -h [frontend]
打印可用的编译选项。
使用此选项时,编译器仅会打印编译选项相关信息,不会对任何输入文件进行编译。
--version, -v [frontend]
打印编译器版本信息。
使用此选项时,编译器仅会打印版本信息,不会对任何输入文件进行编译。
--save-temps <value>
保留编译过程中生成的中间文件并保存至 <value> 路径下。
编译器会保留编译过程中生成的 .bc、.o 等中间文件。
--import-path <value> [frontend]
指定导入模块的 AST 文件的搜索路径。
假设已有以下目录结构,libs/myModule 目录中包含 myModule 模块的库文件和 log 包的 AST 导出文件:
.
├── libs
| └── myModule
| ├── log.cjo
| └── libmyModule.a
└── main.cj
且有如下 main.cj 文件:
import myModule.log.printLog
main() {
printLog("Everything is great")
}
可以通过使用 --import-path ./libs 来将 ./libs 加入导入模块的 AST 文件搜索路径,cjc 会使用 ./libs/myModule/log.cjo 文件来对 main.cj 文件进行语义检查与编译。
--import-path 提供与 CANGJIE_PATH 环境变量相同的功能,但通过 --import-path 设置的路径拥有更高的优先级。
--scan-dependency [frontend]
通过 --scan-dependency 指令可以获得指定包源码或者一个包的 cjo 文件对于其他包的直接依赖以及其他信息,以 json 格式输出。
// this file is placed under directory pkgA
macro package pkgA
import pkgB.*
import std.io.*
import pkgB.subB.*
cjc --scan-dependency --package pkgA
或
cjc --scan-dependency pkgA.cjo
{
"package": "pkgA",
"isMacro": true,
"dependencies": [
{
"package": "pkgB",
"isStd": false,
"imports": [
{
"file": "pkgA/pkgA.cj",
"begin": {
"line": 2,
"column": 1
},
"end": {
"line": 2,
"column": 14
}
}
]
},
{
"package": "pkgB.subB",
"isStd": false,
"imports": [
{
"file": "pkgA/pkgA.cj",
"begin": {
"line": 4,
"column": 1
},
"end": {
"line": 4,
"column": 19
}
}
]
},
{
"package": "std.io",
"isStd": true,
"imports": [
{
"file": "pkgA/pkgA.cj",
"begin": {
"line": 3,
"column": 1
},
"end": {
"line": 3,
"column": 16
}
}
]
}
]
}
--no-sub-pkg [frontend]
表明当前编译包没有子包。
开启该选项后,编译器可以进一步缩减 code size 大小。
--warn-off, -Woff <value> [frontend]
关闭编译期出现的全部或部分警告。
<value> 可以为 all 或者一个设定好的警告组别。当参数为 all 时,对于编译过程中生成的所有警告,编译器都不会打印;当参数为其他设定好的组别时,编译器将不会打印编译过程中生成的该组别警告。
在打印每个警告时,会有一行 #note 提示该警告属于什么组别并如何关闭它,可以通过 --help 打印所有可用的编译选项参数,来查阅具体的组别名称。
--warn-on, -Won <value> [frontend]
开启编译期出现的全部或部分警告。
--warn-on 的 <value> 与 --warn-off 的 <value> 取值范围相同,--warn-on 通常与 --warn-off 组合使用;比如,可以通过设定 -Woff all -Won <value> 来仅允许组别为 <value> 的警告被打印。
特别要注意的是,--warn-on 与 --warn-off 在使用上顺序敏感;针对同一组别,后设定的选项会覆盖之前选项的设定,比如,调换上例中两个编译选项的位置,使其变为 -Won <value> -Woff all,其效果将变为关闭所有警告。
--error-count-limit <value> [frontend]
限制编译器打印错误个数的上限。
参数 <value> 可以为 all 或一个非负整数。当参数为 all 时,编译器会打印编译过程中生成的所有错误;当参数为非负整数 N 时,编译器最多会打印 N 个错误。此选项默认值为 8。
--output-dir <value> [frontend]
控制编译器生成的中间文件与最终文件的保存目录。
控制编译器生成的中间文件的保存目录,例如 .cjo 文件。当指定 --output-dir <path1> 时也指定了 --output <path2>,则中间文件会被保存至 <path1>,最终输出会被保存至 <path1>/<path2> 。
注意:
同时指定此选项与
--output选项时,--output选项的参数必须是一个相对路径。
--static
静态链接仓颉库。
此选项仅在编译可执行文件时生效。
值得注意的是:
--static 选项仅适用于 Linux 平台,在其他平台不生效。
--static-std
静态链接仓颉库的 std 模块。
此选项仅在编译动态链接库或可执行文件时生效。
当编译可执行程序时(即指定了 --output-type=exe 时),cjc 默认静态链接仓颉库的 std 模块。
--dy-std
动态链接仓颉库的 std 模块。
此选项仅在编译动态链接库或可执行文件时生效。
当编译动态库时(即指定了 --output-type=dylib 时),cjc 默认动态链接仓颉库的 std 模块。
值得注意的是:
--static-std和--dy-std选项一起使用时,仅最后一个选项生效。- 当编译可执行程序时链接了仓颉动态库(即通过
--output-type=dylib选项编译的产物),必须显式指定--dy-std选项动态链接标准库,否则可能导致程序集中出现多份标准库,最终可能会导致运行时问题。
--static-libs
该选项已废弃,并会在未来版本被移除。当前版本使用该选项没有功能性作用。
--dy-libs
该选项已废弃,并会在未来版本被移除。当前版本使用该选项没有功能性作用。
--stack-trace-format=[default|simple|all]
指定异常调用栈打印格式,用来控制异常抛出时的栈帧信息显示,默认为 default 格式。
异常调用栈的格式说明如下:
default格式:省略泛型参数的函数名 (文件名:行号)simple格式:文件名:行号all格式:完整的函数名 (文件名:行号)
--lto=[full|thin]
使能且指定 LTO (Link Time Optimization 链接时优化)优化编译模式。
值得注意的是:
Windows以及macOS平台不支持该功能;- 当使能且指定
LTO(Link Time Optimization链接时优化)优化编译模式时,不允许同时使用如下优化编译选项:-Os、-Oz。
LTO 优化支持两种编译模式:
-
--lto=full:full LTO将所有编译模块合并到一起,在全局上进行优化,这种方式可以获得最大的优化潜力,同时也需要更长的编译时间。 -
--lto=thin:相比于full LTO,thin LTO在多模块上使用并行优化,同时默认支持链接时增量编译,编译时间比full LTO短,因为失去了更多的全局信息,所以优化效果不如full LTO。- 通常情况下优化效果对比:
full LTO>thin LTO> 常规静态链接编译。 - 通常情况下编译时间对比:
full LTO>thin LTO> 常规静态链接编译。
- 通常情况下优化效果对比:
LTO 优化使用场景:
-
使用以下命令编译可执行文件。
$ cjc test.cj --lto=full or $ cjc test.cj --lto=thin -
使用以下命令编译
LTO模式下需要的静态库(.bc文件),并且使用该库文件参与可执行文件编译。# 生成的静态库为 .bc 文件 $ cjc pkg.cj --lto=full --output-type=staticlib -o libpkg.bc # .bc 文件和源文件一起输入给仓颉编译器编译可执行文件 $ cjc test.cj libpkg.bc --lto=full注意:
LTO模式下的静态库(.bc文件)输入时需要将该文件的路径输入仓颉编译器。 -
在
LTO模式下,静态链接标准库(--static-std)时,标准库的代码也会参与LTO优化,并静态链接到可执行文件;动态链接标准库(--dy-std)时,在LTO模式下依旧使用标准库中的动态库参与链接。# 静态链接,标准库代码也参与 LTO 优化 $ cjc test.cj --lto=full --static-std # 动态链接,依旧使用动态库参与链接,标准库代码不会参与 LTO 优化 $ cjc test.cj --lto=full --dy-std
--compile-as-exe
该选项使能会隐藏 LTO 模式下加载的 bc 文件符号可见性,仅保留 package init 符号可见性。在此基础上,LLVM 原生优化会在此基础上执行激进的无用符号删除。该选项仅在 --lto 开启下有效。
# 编译通过
$ cjc test.cj --lto=[full|thin] --compile-as-exe
# 编译报错
$ cjc test.cj --compile-as-exe
--pgo-instr-gen
使能插桩编译,生成携带插桩信息的可执行程序。
编译 macOS 与 Windows 目标时暂不支持使用该功能。
PGO(全称 Profile-Guided Optimization)是一种常用的编译优化技术,通过使用运行时 profiling 信息进一步提升程序性能。Instrumentation-based PGO 是使用插桩信息的一种 PGO 优化手段,它通常包含三个步骤:
- 编译器对源码插桩编译,生成插桩后的可执行程序(instrumented program);
- 运行插桩后的可执行程序,生成配置文件;
- 编译器使用配置文件,再次对源码进行编译。
# 生成支持源码执行信息统计(携带插桩信息)的可执行程序 test
$ cjc test.cj --pgo-instr-gen -o test
# 运行可执行程序 test 结束后,生成 default.profraw 配置文件
$ ./test
--pgo-instr-use=<.profdata>
使用指定 profdata 配置文件指导编译并生成优化后的可执行程序。
编译 macOS 目标时暂不支持使用该功能。
注意:
--pgo-instr-use编译选项仅支持格式为profdata的配置文件。可使用llvm-profdata工具可将profraw配置文件转换为profdata配置文件。
# 将 `profraw` 文件转换为 `profdata` 文件。
$ LD_LIBRARY_PATH=$CANGJIE_HOME/third_party/llvm/lib:$LD_LIBRARY_PATH $CANGJIE_HOME/third_party/llvm/bin/llvm-profdata merge default.profraw -o default.profdata
# 使用指定 `default.profdata` 配置文件指导编译并生成优化后的可执行程序 `testOptimized`
$ cjc test.cj --pgo-instr-use=default.profdata -o testOptimized
--target <value> [frontend]
指定编译的目标平台的 triple。
参数 <value> 一般为符合以下格式的字符串:<arch>(-<vendor>)-<os>(-<env>)。其中:
<arch>表示目标平台的系统架构,例如aarch64,x86_64等;<vendor>表示开发目标平台的厂商,常见的例如pc,apple等,在没有明确平台厂商或厂商不重要的情况下也经常写作unknown或直接省略;<os>表示目标平台的操作系统,例如Linux,Win32等;<env>表示目标平台的 ABI 或标准规范,用于更细粒度地区分同一操作系统的不同运行环境,例如gnu,musl等。在操作系统不需要根据<env>进行更细地区分的时候,此项也可以省略。
目前,cjc 已支持交叉编译的本地平台和目标平台如下表所示:
| 本地平台 (host) | 目标平台 (target) |
|---|---|
| x86_64-linux-gnu | x86_64-windows-gnu |
| aarch64-linux-gnu | x86_64-windows-gnu |
在使用 --target 指定目标平台进行交叉编译之前,请准备好对应目标平台的交叉编译工具链,以及可以在本地平台上运行的、向该目标平台编译的对应 Cangjie SDK 版本。
--target-cpu <value>
注意:
该选项为实验性功能,使用该功能生成的二进制可能存在潜在的运行时问题,请注意使用该选项的风险。此选项必须配合
--experimental选项一同使用。
指定编译目标的 CPU 类型。
指定编译目标的 CPU 类型时,编译器在生成二进制时会尝试使用该 CPU 类型特有的扩展指令集,并尝试应用适用于该 CPU 类型的优化。为某个特定 CPU 类型生成的二进制通常会失去可移植性,该二进制可能无法在其他(拥有相同架构指令集的)CPU 上运行。
该选项支持以下经过测试的 CPU 类型:
x86-64 架构:
- generic
aarch64 架构:
- generic
- tsv110
generic 为通用 CPU 类型,指定 generic 时编译器会生成适用于该架构的通用指令,这样生成的二进制在操作系统和二进制本身的动态依赖一致的前提下,可以在基于该架构的各种 CPU 上运行,无关于具体的 CPU 类型。--target-cpu 选项的默认值为 generic。
该选项还支持以下 CPU 类型,但以下 CPU 类型未经过测试验证,请注意使用以下 CPU 类型生成的二进制可能会存在运行时问题。
x86-64 架构:
- alderlake
- amdfam10
- athlon
- athlon-4
- athlon-fx
- athlon-mp
- athlon-tbird
- athlon-xp
- athlon64
- athlon64-sse3
- atom
- barcelona
- bdver1
- bdver2
- bdver3
- bdver4
- bonnell
- broadwell
- btver1
- btver2
- c3
- c3-2
- cannonlake
- cascadelake
- cooperlake
- core-avx-i
- core-avx2
- core2
- corei7
- corei7-avx
- geode
- goldmont
- goldmont-plus
- haswell
- i386
- i486
- i586
- i686
- icelake-client
- icelake-server
- ivybridge
- k6
- k6-2
- k6-3
- k8
- k8-sse3
- knl
- knm
- lakemont
- nehalem
- nocona
- opteron
- opteron-sse3
- penryn
- pentium
- pentium-m
- pentium-mmx
- pentium2
- pentium3
- pentium3m
- pentium4
- pentium4m
- pentiumpro
- prescott
- rocketlake
- sandybridge
- sapphirerapids
- silvermont
- skx
- skylake
- skylake-avx512
- slm
- tigerlake
- tremont
- westmere
- winchip-c6
- winchip2
- x86-64
- x86-64-v2
- x86-64-v3
- x86-64-v4
- yonah
- znver1
- znver2
- znver3
aarch64 架构:
- a64fx
- ampere1
- apple-a10
- apple-a11
- apple-a12
- apple-a13
- apple-a14
- apple-a7
- apple-a8
- apple-a9
- apple-latest
- apple-m1
- apple-s4
- apple-s5
- carmel
- cortex-a34
- cortex-a35
- cortex-a510
- cortex-a53
- cortex-a55
- cortex-a57
- cortex-a65
- cortex-a65ae
- cortex-a710
- cortex-a72
- cortex-a73
- cortex-a75
- cortex-a76
- cortex-a76ae
- cortex-a77
- cortex-a78
- cortex-a78c
- cortex-r82
- cortex-x1
- cortex-x1c
- cortex-x2
- cyclone
- exynos-m3
- exynos-m4
- exynos-m5
- falkor
- kryo
- neoverse-512tvb
- neoverse-e1
- neoverse-n1
- neoverse-n2
- neoverse-v1
- saphira
- thunderx
- thunderx2t99
- thunderx3t110
- thunderxt81
- thunderxt83
- thunderxt88
除以上可选 CPU 类型外,该选项还可以使用 native 作为当前 CPU 类型。编译器会尝试识别当前机器的 CPU 类型,并使用该 CPU 类型作为目标类型生成二进制文件。
--toolchain <value>, -B <value>, -B<value>
指定编译工具链中,二进制文件存放的路径。
这些二进制文件包括编译器、链接器、工具链提供的 C 运行时目标文件(如 crt0.o、 crti.o 等)。
在准备好编译工具链后,可以在将其存放在一个自定义路径,然后通过 --toolchain <value> 向编译器传入该路径,即可让编译器调用到该路径下的二进制文件进行交叉编译。
--sysroot <value>
指定编译工具链的根目录路径。
对于目录结构固定的交叉编译工具链,如果没有指定该目录以外的二进制和动态库、静态库文件路径的需求,可以直接使用 --sysroot <value> 向编译器传入工具链的根目录路径,编译器会根据目标平台种类分析对应的目录结构,自动搜索所需的二进制文件和动态库、静态库文件。使用该选项后,无需再指定 --toolchain、--library-path 参数。
如果向 triple 为 arch-os-env 的平台进行交叉编译,且交叉编译工具链有以下目录结构:
/usr/sdk/arch-os-env
├── bin
| ├── arch-os-env-gcc (交叉编译器)
| ├── arch-os-env-ld (链接器)
| └── ...
├── lib
| ├── crt1.o (C 运行时目标文件)
| ├── crti.o
| ├── crtn.o
| ├── libc.so (动态库)
| ├── libm.so
| └── ...
└── ...
对于仓颉源文件 hello.cj ,可以使用以下命令,将 hello.cj 交叉编译至 arch-os-env 平台:
cjc --target=arch-os-env --toolchain /usr/sdk/arch-os-env/bin --toolchain /usr/sdk/arch-os-env/lib --library-path /usr/sdk/arch-os-env/lib hello.cj -o hello
也可以使用简写的参数:
cjc --target=arch-os-env -B/usr/sdk/arch-os-env/bin -B/usr/sdk/arch-os-env/lib -L/usr/sdk/arch-os-env/lib hello.cj -o hello
如果该工具链的目录符合惯例的目录结构,可以不使用 --toolchain、--library-path 参数,直接使用以下命令:
cjc --target=arch-os-env --sysroot /usr/sdk/arch-os-env hello.cj -o hello
--strip-all, -s
编译可执行文件或动态库时,指定该选项以删除输出文件中的符号表。
--discard-eh-frame
编译可执行文件或动态库时,指定该选项可以删除 eh_frame 段以及 eh_frame_hdr 段中的部分信息(涉及到 crt 的相关信息不作处理),减少可执行文件或动态库的大小,但会影响调试信息。
编译 macOS 目标时暂不支持使用该功能。
--set-runtime-rpath
将仓颉运行时库所在目录的绝对路径写入到二进制的 RPATH/RUNPATH 段中,使用该选项后在构建所在环境中运行该仓颉程序时无需再使用 LD_LIBRARY_PATH (适用于 Linux 平台) 或 DYLD_LIBRARY_PATH (适用于 macOS 平台) 设置仓颉运行时库目录。
编译 Windows 目标时不支持使用该功能。
--link-options <value>1
指定链接器选项。
cjc 会将该选项的参数透传给链接器。可用的参数会因系统或指定的链接器不同而不同。可以多次使用 --link-options 指定多个链接器选项。
1 上标表示链接器透传选项可能会因为链接器的不同而不同,具体支持的选项请查阅链接器文档。
--disable-reflection
关闭反射选项,即编译过程中不生成相关反射信息。
注意:
交叉编译至 aarch64-linux-ohos 目标时,默认关闭反射信息,该选项不生效。
--profile-compile-time [frontend]
输出各编译阶段时间消耗数据到一份文件中,该文件以 .time.prof 为后缀,保存在 --output 指定的目录中,若 --output 指定的是一个文件,则 .time.prof 与该文件同级。
--profile-compile-memory [frontend]
输出各编译阶段内存消耗数据到一份文件中,该文件以 .mem.prof 为后缀,保存在 --output 指定的目录中,若 --output 指定的是一个文件,则 .mem.prof 与该文件同级。
单元测试选项
--test [frontend]
unittest 测试框架提供的入口,由宏自动生成。当使用 cjc --test 选项编译时,程序入口不再是 main,而是 test_entry。unittest 测试框架的使用方法请参见《仓颉编程语言标准库 API》文档。
对于 pkgc 目录下的仓颉文件 a.cj:
import std.unittest.*
import std.unittest.testmacro.*
@Test
public class TestA {
@TestCase
public func case1(): Unit {
print("case1\n")
}
}
可以在 pkgc 目录下使用:
cjc a.cj --test
来编译 a.cj ,执行 main 会有如下输出:
注意:
不保证用例每次执行的用时都相同。
case1
--------------------------------------------------------------------------------------------------
TP: default, time elapsed: 29710 ns, Result:
TCS: TestA, time elapsed: 26881 ns, RESULT:
[ PASSED ] CASE: case1 (16747 ns)
Summary: TOTAL: 1
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
对于如下目录结构:
application
├── src
├── pkgc
| ├── a1.cj
| └── a2.cj
└── a3.cj
可以在 application目录下使用 -p 编译选项配合编译整包:
cjc pkgc --test -p
来编译整个 pkgc 包下的测试用例 a1.cj 和 a2.cj。
/*a1.cj*/
package a
import std.unittest.*
import std.unittest.testmacro.*
@Test
public class TestA {
@TestCase
public func caseA(): Unit {
print("case1\n")
}
}
/*a2.cj*/
package a
import std.unittest.*
import std.unittest.testmacro.*
@Test
public class TestB {
@TestCase
public func caseB(): Unit {
throw IndexOutOfBoundsException()
}
}
执行 main 会有如下输出(输出信息仅供参考):
case1
--------------------------------------------------------------------------------------------------
TP: a, time elapsed: 367800 ns, Result:
TCS: TestA, time elapsed: 16802 ns, RESULT:
[ PASSED ] CASE: caseA (14490 ns)
TCS: TestB, time elapsed: 347754 ns, RESULT:
[ ERROR ] CASE: caseB (345453 ns)
REASON: An exception has occurred:IndexOutOfBoundsException
at std/core.Exception::init()(std/core/exception.cj:23)
at std/core.IndexOutOfBoundsException::init()(std/core/index_out_of_bounds_exception.cj:9)
at a.TestB::caseB()(/home/houle/cjtest/application/pkgc/a2.cj:7)
at a.lambda.1()(/home/houle/cjtest/application/pkgc/a2.cj:7)
at std/unittest.TestCases::execute()(std/unittest/test_case.cj:92)
at std/unittest.UT::run(std/unittest::UTestRunner)(std/unittest/test_runner.cj:194)
at std/unittest.UTestRunner::doRun()(std/unittest/test_runner.cj:78)
at std/unittest.UT::run(std/unittest::UTestRunner)(std/unittest/test_runner.cj:200)
at std/unittest.UTestRunner::doRun()(std/unittest/test_runner.cj:78)
at std/unittest.UT::run(std/unittest::UTestRunner)(std/unittest/test_runner.cj:200)
at std/unittest.UTestRunner::doRun()(std/unittest/test_runner.cj:75)
at std/unittest.entryMain(std/unittest::TestPackage)(std/unittest/entry_main.cj:11)
Summary: TOTAL: 2
PASSED: 1, SKIPPED: 0, ERROR: 1
FAILED: 0
--------------------------------------------------------------------------------------------------
--test-only [frontend]
--test-only 选项用于单独编译包的测试部分。
如果启用此选项,编译器将仅编译包中的测试文件(以 _test.cj 结尾)。
注意:
使用此选项时,应单独以常规模式编译相同的包,然后通过
-L/-l链接选项添加依赖,或在使用LTO选项时添加依赖的.bc文件。否则,编译器将报缺少依赖的符号的错误。
示例:
/*main.cj*/
package my_pkg
func concatM(s1: String, s2: String): String {
return s1 + s2
}
main() {
println(concatM("a", "b"))
0
}
/*main_test.cj*/
package my_pkg
@Test
class Tests {
@TestCase
public func case1(): Unit {
@Expect("ac", concatM("a", "c"))
}
}
使用编译器编译的命令如下:
# Compile the production part of the package first, only `main.cj` file would be compiled here
cjc -p my_pkg --output-type=staticlib -o=output/libmain.a
# Compile the test part of the package, Only `main_test.cj` file would be compiled here
cjc -p my_pkg --test-only -L output -lmain --import-path output
--export-for-test [frontend]
在编译源码部分时增加该选项可导出一些原先不导出的类型声明,使同一包下的测试代码在用 --test-only 编译可使用。具体导出类型如下:
- 来源于其他的包的类型,在本包进行扩展的声明
- foreign 函数
典型使用场景如下:
代码结构为
src
├── foo.cj
├── bar.cj
├── foo_test.cj
└── bar_test.cj
// foo.cj
package my_pkg
class Foo { /*...*/ }
extend String {
func invertSlashes() { /*...*/ }
}
// bar.cj
package my_pkg
foreign func strlen(str: CPointer<UInt8>): Int32
// foo_test.cj
package my_pkg
@Test
class TestFoo {
@TestCase
func testInvertSlashes() {
@Assert("\\Users\\Admin\\Documents".invertSlashes(), "/Users/Admin/Documents")
}
}
// bar_test.cj
package my_pkg
@Test
class TestBar {
@TestCase
func testInvertSlashes() {
@Assert(strlen(LibC.mallocCString("abcde").getChars()), 5)
}
}
当需要分开编译同一包中的源码和测试代码时,我们可以使用以下命令:
# Compile the production part of the package first (`foo.cj` and `bar.cj` files)
cjc -p my_pkg --output-type=static --export-for-test -o=output/libmain.a
# Compile the test part of the package (`foo_test.cj` and `bar_test.cj` files)
cjc -p my_pkg --test-only -L output -lmain
在使用 --test-only 选项编译的同名包之外,使用 --export-for-test 选项将没有可见的效果。
注意:
本选项不建议在测试场景以外使用,当使能该选项编译源码时,二进制大小将增加。
--mock <on|off|runtime-error> [frontend]
如果传递了 on ,则该包将使能 mock 编译,该选项允许在测试用例中 mock 该包中的类。off 是一种显式禁用 mock 的方法。
注意:
在测试模式下(当使能
--test)自动启用对此包的 mock 支持,不需要显式传递--mock选项。
runtime-error 仅在测试模式下可用(当使能 --test 时),它允许编译带有 mock 代码的包,但不在编译器中做任何 mock 相关的处理(这些处理可能会造成一些开销并影响测试的运行时性能)。这对于带有 mock 代码用例进行基准测试时可能是有用的。使用此编译选项时,避免编译带有 mock 代码的用例并运行测试,否则将抛出运行时异常。
宏选项
cjc 支持以下宏选项,关于宏的更多内容请参见“宏的简介”章节。
--compile-macro [frontend]
编译宏定义文件,生成默认的宏定义动态库文件。
--debug-macro [frontend]
生成宏展开后的仓颉代码文件。该选项可用于调试宏展开功能。
--parallel-macro-expansion [frontend]
开启宏展开并行。该选项可用于缩短宏展开编译时间。
条件编译选项
cjc 支持以下条件编译选项,关于条件编译的更多内容请参见“条件编译”。
--cfg <value> [frontend]
指定自定义编译条件。
并行编译选项
cjc 支持以下并行编译选项,以获得更高的编译效率。
--jobs <value>, -j <value> [frontend]
设置并行编译时所允许的最大并行数。其中 value 必须是一个合理的非负整数,当 value 大于硬件支持的最大并行能力时,编译器将以硬件支持的最大并行能力执行并行编译。
如果该编译选项未设置,编译器会基于硬件能力自动计算最大并行数。
注意:
--jobs 1表示完全使用串行方式进行编译。
--aggressive-parallel-compile, --apc, --aggressive-parallel-compile=<value>, --apc=<value> [frontend]
开启此选项后,编译器会采用更加激进的策略(可能会对优化造成影响,从而导致程序运行性能下降)执行激进并行编译,以便获得更高的编译效率。其中 value 是一个可选参数,表示激进并行编译部分允许的最大并行数:
- 如果使用
value,则value必须是一个合理的非负整数,当value大于硬件支持的最大并行能力时,编译器会基于硬件能力自动计算最大并行数。建议将value设置为小于硬件的物理核数的非负整数。 - 如果不使用
value,则激进并行编译默认开启,且激进并行编译部分的并行数与--jobs一致。
此外,如果两次编译同一份代码时此选项的 value 值不同,或此选项的开关状态不同,编译器不保证这两次编译的产物的二进制一致性。
激进并行编译的开启或关闭规则如下:
-
在以下场景中,激进并行编译将由编译器强制关闭,无法启用:
--fobf-string--fobf-const--fobf-layout--fobf-cf-flatten--fobf-cf-bogus--lto--coverage- 编译 Windows 目标
- 编译 macOS 目标
-
若使用
--aggressive-parallel-compile=<value>或--apc=<value>,则激进并行编译的开关由value控制:value <= 1:关闭激进并行编译。value > 1:开启激进并行编译,且激进并行编译的并行数取决于value。
-
若使用
--aggressive-parallel-compile或--apc,则激进并行编译默认开启,且激进并行编译的并行数与--jobs一致。 -
若该编译选项未设置,编译器将根据场景默认开启或关闭激进并行编译:
-O0或-g:激进并行编译将由编译器默认开启,且激进并行编译的并行数与--jobs一致;可以通过--aggressive-parallel-compile=<value>或--apc=<value>且value <= 1关闭激进并行编译。- 非
-O0且非-g:激进并行编译将由编译器默认关闭;可以通过--aggressive-parallel-compile=<value>或--apc=<value>且value > 1开启激进并行编译。
优化选项
--fchir-constant-propagation [frontend]
开启 chir 常量传播优化。
--fno-chir-constant-propagation [frontend]
关闭 chir 常量传播优化。
--fchir-function-inlining [frontend]
开启 chir 函数内联优化。
--fno-chir-function-inlining [frontend]
关闭 chir 函数内联优化。
--fchir-devirtualization [frontend]
开启 chir 去虚函数调用优化。
--fno-chir-devirtualization [frontend]
关闭 chir 去虚函数调用优化。
--fast-math [frontend]
开启此选项后,编译器会对浮点数作一些激进且有可能损失精度的假设,以便优化浮点数运算。
-O<N> [frontend]
使用参数指定的代码优化级别。
指定越高的优化级别,编译器会越多地进行代码优化以生成更高效的程序,同时也可能会需要更长的编译时间。
cjc 默认使用 O0 级别的代码优化。当前 cjc 支持如下优化级别:O0、O1、O2、Os、Oz。
当优化等级等于 2 时,cjc 除了进行对应的优化外,还会开启以下选项:
--fchir-constant-propagation--fchir-function-inlining--fchir-devirtualization
当优化等级等于 s 时, cjc除了进行 O2 级别优化外,将针对 code size 进行优化。
当优化等级等于 z 时, cjc除了进行 Os 级别优化外,还将进一步缩减 code size 大小。
注意:
当优化等级等于 s 或 z 时,不允许同时使用链接时优化编译选项
--lto=[full|thin]。
-O [frontend]
使用 O1 级别的代码优化,等价于 -O1。
代码混淆选项
cjc 支持代码混淆功能,以提供对代码的额外安全保护,默认不开启。
cjc 支持以下代码混淆选项:
--fobf-string
开启字符串混淆。
混淆代码中出现的字符串常量,攻击者无法静态直接读取二进制程序中的字符串数据。
--fno-obf-string
关闭字符串混淆。
--fobf-const
开启常量混淆。
混淆代码中使用的数值常量,将数值运算指令替换成等效的、更复杂的数值运算指令序列。
--fno-obf-const
关闭常量混淆。
--fobf-layout
开启外形混淆。
外形混淆功能会混淆代码中的符号(包括函数名和全局变量名)、路径名、代码行号和函数排布顺序。使用该编译选项后,cjc 会在当前目录生成符号映射输出文件 *.obf.map。如果配置了 --obf-sym-output-mapping 选项,则 --obf-sym-output-mapping 的参数值将作为 cjc 生成的符号映射输出文件名。符号映射输出文件中包含混淆前后符号的映射关系,使用符号映射输出文件可以解混淆被混淆过的符号。
注意:
外形混淆功能和并行编译功能相互冲突,请勿同时开启。如果和并行编译同时开启,并行编译将失效。
--fno-obf-layout
关闭外形混淆。
--obf-sym-prefix <string>
指定外形混淆功能在混淆符号时添加的前缀字符串。
设置该选项后,所有被混淆符号都会加上该前缀。在编译混淆多个仓颉包时可能出现符号冲突的问题,可以使用该选项给不同的包指定不同的前缀,避免符号冲突。
--obf-sym-output-mapping <file>
指定外形混淆的符号映射输出文件。
符号映射输出文件记录了符号的原始名称、混淆后的名称和所属文件路径。使用符号映射输出文件可以解混淆被混淆过的符号。
--obf-sym-input-mapping <file,...>
指定外形混淆的符号映射输入文件。
外形混淆功能会使用这些文件中的映射关系对符号进行混淆。因此在编译存在调用关系的仓颉包,请使用被调用包的符号映射输出文件作为调用包混淆时的 --obf-sym-input-mapping 选项的参数,以此保证同一个符号在调用包和被调用包两者混淆时混淆结果一致。
--obf-apply-mapping-file <file>
提供自定义的外形混淆符号映射关系文件,外形混淆功能将按照文件里的映射关系混淆符号。
文件格式如下:
<original_symbol_name> <new_symbol_name>
其中 original_symbol_name 是混淆前的名称,new_symbol_name 是混淆后的名称。original_symbol_name 由多个 field 组成。field 表示字段名,可以是模块名、包名、类名、结构体名、枚举名、函数名或变量名。field 之间用分隔符 '.' 分隔。如果 field 是函数名,则需要将函数的参数类型用括号 '()' 修饰并附加在函数名后面。对于无参函数括号内的内容为空。如果 field 存在泛型参数,也需要用括号 '<>' 将具体的泛型参数附加在 field 后面。
外形混淆功能会将仓颉应用中的 original_symbol_name 替换为 new_symbol_name。对于不在该文件中的符号,外形混淆功能会正常使用随机名称进行替换。如果该文件中指定的映射关系和 --obf-sym-input-mapping 中的映射关系相冲突,编译器会抛出异常并停止编译。
--fobf-export-symbols
允许外形混淆功能混淆导出符号,该选项在开启外形混淆功能时默认开启。
开启该选项后,外形混淆功能会对导出符号进行混淆。
--fno-obf-export-symbols
禁止外形混淆功能混淆导出符号。
--fobf-source-path
允许外形混淆功能混淆符号的路径信息,该选项在开启外形混淆功能时默认开启。
开启该选项后,外形混淆功能会混淆异常堆栈信息中的路径信息,将路径名替换为字符串 "SOURCE"。
--fno-obf-source-path
禁止外形混淆功能混淆堆栈信息中的路径信息。
--fobf-line-number
允许外形混淆功能混淆堆栈信息中的行号信息。
开启该选项后,外形混淆功能会混淆异常堆栈信息中的行号信息,将行号替换为 0。
--fno-obf-line-number
禁止外形混淆功能混淆堆栈信息中的行号信息。
--fobf-cf-flatten
开启控制流平坦化混淆。
混淆代码中既存的控制流,使其转移逻辑变得复杂。
--fno-obf-cf-flatten
关闭控制流平坦化混淆。
--fobf-cf-bogus
开启虚假控制流混淆。
在代码中插入虚假的控制流,使代码逻辑变得复杂。
--fno-obf-cf-bogus
关闭虚假控制流混淆。
--fobf-all
开启所有混淆功能。
指定该选项等同于同时指定以下选项:
--fobf-string--fobf-const--fobf-layout--fobf-cf-flatten--fobf-cf-bogus
--obf-config <file>
指定代码混淆配置文件路径。
在配置文件中可以禁止混淆工具对某些函数或者符号进行混淆。
配置文件的具体格式如下:
obf_func1 name1
obf_func2 name2
...
第一个参数 obf_func 是具体的混淆功能:
obf-cf-bogus:虚假控制流混淆obf-cf-flatten:控制流平坦化混淆obf-const:常数混淆obf-layout:外形混淆
第二个参数 name 是需要被保留的对象,由多个 field 组成。field 表示字段名,可以是包名、类名、结构体名、枚举名、函数名或变量名。
field 之间用分隔符 '.' 分隔。如果 field 是函数名,则需要将函数的参数类型用括号 '()' 修饰并附加在函数名后面。对于无参函数括号内的内容为空。
例如,假设在包 packA 中有以下代码:
package packA
class MyClassA {
func funcA(a: String, b: Int64): String {
return a
}
}
如果要禁止控制流平坦化功能混淆 funcA,用户可以编写如下规则:
obf-cf-flatten packA.MyClassA.funcA(std.core.String, Int64)
用户也可以使用通配符编写更加灵活的规则,达到一条规则保留多个对象的效果。目前支持的通配符包含以下 3 类:
混淆功能通配符:
| 混淆功能通配符 | 说明 |
|---|---|
? | 匹配名称中的单个字符 |
* | 匹配名称中的任意数量字符 |
字段名通配符:
| 字段名通配符 | 说明 |
|---|---|
? | 匹配字段名中单个非分隔符 '.' 的字符 |
* | 匹配字段名中的不包含分隔符 '.' 和参数的任意数量字符 |
** | 匹配字段名中的任意数量字符,包括字段之间的分隔符 '.' 和参数。'**' 只有在单独作为一个 field 时才生效,否则会被当作 '*' 处理 |
函数的参数类型通配符:
| 参数类型通配符 | 说明 |
|---|---|
... | 匹配任意数量的参数 |
*** | 匹配一个任意类型的参数 |
说明:
参数类型也由字段名组成,因此也可以使用字段名通配符对单个参数类型进行匹配。
以下是通配符使用示例:
例子 1:
obf-cf-flatten pro?.myfunc()
该规则表示禁止 obf-cf-flatten 功能混淆函数 pro?.myfunc(),pro?.myfunc() 可以匹配 pro0.myfunc(),但不能匹配 pro00.myfunc()。
例子 2:
* pro0.**
该规则表示禁止任何混淆功能混淆包 pro0 下的任何函数和变量。
例子 3:
* pro*.myfunc(...)
该规则表示禁止任何混淆功能混淆函数 pro*.myfunc(...),pro*.myfunc(...) 可以匹配以 pro 开头的任意单层包内的 myfunc 函数,且可以为任意参数。
如果需要匹配多层包名,比如 pro0.mypack.myfunc(),请使用 pro*.**.myfunc(...)。请注意 '**' 只有单独作为字段名时才生效,因此 pro**.myfunc(...) 和 pro*.myfunc(...) 等价,无法匹配多层包名。如果要匹配以 pro 开头的所有包下的所有 myfunc 函数(包括类中名为 myfunc 的函数),请使用 pro*.**.myfunc(...)。
例子 4:
obf-cf-* pro0.MyClassA.myfunc(**.MyClassB, ***, ...)
该规则表示禁止 obf-cf-* 功能混淆函数 pro0.MyClassA.myfunc(**.MyClassB, ***, ...),其中 obf-cf-* 会匹配 obf-cf-bogus 和 obf-cf-flatten 两种混淆功能,pro0.MyClassA.myfunc(**.MyClassB, ***, ...) 会匹配函数 pro0.MyClassA.myfunc,且函数的第一个参数可以是任意包下的 MyClassB 类型,第二个参数可以是任意类型,后面可以接零至多个任意参数。
--obf-level <value>
指定混淆功能强度级别。
可指定 1-9 强度级别。默认强度级别为 5。级别数字越大,强度则越高,该选项会影响输出文件的大小以及执行开销。
--obf-seed <value>
指定混淆算法的随机数种子。
通过指定混淆算法的随机数种子,可以使同一份仓颉代码在不同构建时有不同的混淆结果。默认场景下,对于同一份仓颉代码,在每次混淆后都拥有相同的混淆结果。
安全编译选项
cjc 默认生成地址无关代码,在编译可执行文件时默认生成地址无关可执行文件。
在构建 Release 版本时,建议根据以下规则打开/关闭编译选项以提高安全性。
启用 --trimpath <value> [frontend]
从调试与异常信息中将指定的绝对路径前缀移除,使用该选项可以避免构建路径信息被写入二进制程序中。
使用该选项后,二进制中的源码路径信息通常不再完整,可能影响调试体验,建议在构建调试版本时关闭该选项。
启用 --strip-all, -s
移除二进制中的符号表,使用该选项可以删除运行时不需要的符号相关信息。
使用该选项后,二进制将无法调试,请在构建调试版本时关闭该选项。
禁用 --set-runtime-rpath
若可执行程序会被分发至不同环境运行,或其他普通用户对当前正在使用的仓颉运行时库目录拥有写权限,使用该选项可能导致安全风险,因此禁用该选项。
编译 Windows 目标时不涉及该选项。
启用 --link-options "-z noexecstack"1
设置线程栈不可执行。
仅编译 Linux 目标时可用。
启用 --link-options "-z relro"1
设置 GOT 表重定位只读。
仅编译 Linux 目标时可用。
启用 --link-options "-z now"1
设置立即绑定。
仅编译 Linux 目标时可用。
代码覆盖率插桩选项
注意:
Windows 和 macOS 版本目前不支持代码覆盖率插桩选项。
仓颉支持对代码覆盖率插桩(SanitizerCoverage,以下简称 SanCov),提供与 LLVM 的 SanitizerCoverage 一致的接口,编译器在函数级或 BasicBlock 级插入覆盖率反馈函数,用户只需要实现约定好的回调函数即可在运行过程中感知程序运行状态。
仓颉提供的 SanCov 功能以 package 为单位,即整个 package 只有全部插桩和全部不插桩两种情况。
--sanitizer-coverage-level=0/1/2
插桩级别:
- 0 表示不插桩;
- 1 表示函数级插桩,仅在函数入口处插入回调函数;
- 2 表示 BasicBlock 级插桩,在各个 BasicBlock 处插入回调函数。
如果不指定,默认值为 2。
该编译选项仅影响 --sanitizer-coverage-trace-pc-guard、--sanitizer-coverage-inline-8bit-counters 和 --sanitizer-coverage-inline-bool-flag 的插桩级别。
--sanitizer-coverage-trace-pc-guard
开启该选项,会在每个 Edge 插入函数调用 __sanitizer_cov_trace_pc_guard(uint32_t *guard_variable),受 sanitizer-coverage-level 影响。
值得注意的是,该功能存在与 gcc/llvm 实现不一致的地方:不会在 constructor 插入 void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop),而是在 package 初始化阶段插入函数调用 uint32_t *__cj_sancov_pc_guard_ctor(uint64_t edgeCount)。
__cj_sancov_pc_guard_ctor 回调函数需要开发者自行实现,开启 SanCov 的 package 会尽可能早地调用该回调函数,入参是该 Package 的 Edge 个数,返回值是通常是 calloc 创建的内存区域。
如果需要调用 __sanitizer_cov_trace_pc_guard_init,建议在 __cj_sancov_pc_guard_ctor 中调用,使用动态创建的缓冲区计算该函数的入参和返回值。
一个标准的 __cj_sancov_pc_guard_ctor 参考实现如下:
uint32_t *__cj_sancov_pc_guard_ctor(uint64_t edgeCount) {
uint32_t *p = (uint32_t *) calloc(edgeCount, sizeof(uint32_t));
__sanitizer_cov_trace_pc_guard_init(p, p + edgeCount);
return p;
}
--sanitizer-coverage-inline-8bit-counters
开启该选项后,会在每个 Edge 插入一个累加器,每经历过一次,该累加器加一,受 sanitizer-coverage-level 影响。
值得注意的是,该功能存在与 gcc/llvm 实现不一致的地方:不会在 constructor 插入 void __sanitizer_cov_8bit_counters_init(char *start, char *stop),而是在 package 初始化阶段插入函数调用 uint8_t *__cj_sancov_8bit_counters_ctor(uint64_t edgeCount)。
__cj_sancov_pc_guard_ctor 回调函数需要开发者自行实现,开启 SanCov 的 package 会尽可能早地调用该回调函数,入参是该 Package 的 Edge 个数,返回值是通常是 calloc 创建的内存区域。
如果需要调用 __sanitizer_cov_8bit_counters_init,建议在 __cj_sancov_8bit_counters_ctor 中调用,使用动态创建的缓冲区计算该函数的入参和返回值。
一个标准的 __cj_sancov_8bit_counters_ctor 参考实现如下:
uint8_t *__cj_sancov_8bit_counters_ctor(uint64_t edgeCount) {
uint8_t *p = (uint8_t *) calloc(edgeCount, sizeof(uint8_t));
__sanitizer_cov_8bit_counters_init(p, p + edgeCount);
return p;
}
--sanitizer-coverage-inline-bool-flag
开启该选项后,会在每个 Edge 插入布尔值,经历过的 Edge 对应的布尔值会被设置为 True,受 sanitizer-coverage-level 影响。
值得注意的是,该功能存在与 gcc/llvm 实现不一致的地方:不会在 constructor 插入 void __sanitizer_cov_bool_flag_init(bool *start, bool *stop),而是在 package 初始化阶段插入函数调用 bool *__cj_sancov_bool_flag_ctor(uint64_t edgeCount)。
__cj_sancov_bool_flag_ctor 回调函数需要开发者自行实现,开启 SanCov 的 package 会尽可能早地调用该回调函数,入参是该 Package 的 Edge 个数,返回值是通常是 calloc 创建的内存区域。
如果需要调用 __sanitizer_cov_bool_flag_init,建议在 __cj_sancov_bool_flag_ctor 中调用,使用动态创建的缓冲区计算该函数的入参和返回值。
一个标准的 __cj_sancov_bool_flag_ctor 参考实现如下:
bool *__cj_sancov_bool_flag_ctor(uint64_t edgeCount) {
bool *p = (bool *) calloc(edgeCount, sizeof(bool));
__sanitizer_cov_bool_flag_init(p, p + edgeCount);
return p;
}
--sanitizer-coverage-pc-table
该编译选项用于提供插桩点和源码之间的对应关系,当前只提供精确到函数级的对应关系。需要与 --sanitizer-coverage-trace-pc-guard、--sanitizer-coverage-inline-8bit-counters、--sanitizer-coverage-inline-bool-flag 共用,至少需要开启其中一项,可以同时开启多项。
值得注意的是,该功能存在与 gcc/llvm 实现不一致的地方:不会在 constructor 插入 void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, const uintptr_t *pcs_end);,而是在 package 初始化阶段插入函数调用 void __cj_sancov_pcs_init(int8_t *packageName, uint64_t n, int8_t **funcNameTable, int8_t **fileNameTable, uint64_t *lineNumberTable),各入参含义如下:
int8_t *packageName: 字符串,表示包名(插桩用 c 风格的 int8 数组作为入参来表达字符串,下同)。uint64_t n: 共有 n 个函数被插桩。int8_t **funcNameTable: 长度为 n 的字符串数组,第 i 个插桩点对应的函数名为 funcNameTable[i]。int8_t **fileNameTable: 长度为 n 的字符串数组,第 i 个插桩点对应的文件名为 fileNameTable[i]。uint64_t *lineNumberTable: 长度为 n 的 uint64 数组,第 i 个插桩点对应的行号为 lineNumberTable[i]。
如果需要调用 __sanitizer_cov_pcs_init,需要自行完成仓颉 pc-table 到 C 语言 pc-table 的转化。
--sanitizer-coverage-stack-depth
开启该编译选项后,由于仓颉无法获取 SP 指针的值,因此只能在每个函数入口处插入调用 __updateSancovStackDepth,在 C 侧实现该函数即可获得 SP 指针。
一个标准的 updateSancovStackDepth 实现如下:
thread_local void* __sancov_lowest_stack;
void __updateSancovStackDepth()
{
register void* sp = __builtin_frame_address(0);
if (sp < __sancov_lowest_stack) {
__sancov_lowest_stack = sp;
}
}
--sanitizer-coverage-trace-compares
开启该选项后,会在所有的 compare 指令和 match 指令调用前插入函数回调函数,具体列表如下,与 LLVM 系的 API 功能一致。参考 Tracing data flow。
void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2);
void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2);
void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2);
void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2);
void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2);
void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2);
void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2);
void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2);
void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases);
--sanitizer-coverage-trace-memcmp
该编译选项用于在 String 、 Array 等比较中反馈前缀比较信息。开启该选项后,会对 String 和 Array 的比较函数前插入函数回调函数。具体对于以下对各 String 和 Array 的 API,分别插入对应桩函数:
- String==: __sanitizer_weak_hook_memcmp
- String.startsWith: __sanitizer_weak_hook_memcmp
- String.endsWith: __sanitizer_weak_hook_memcmp
- String.indexOf: __sanitizer_weak_hook_strstr
- String.replace: __sanitizer_weak_hook_strstr
- String.contains: __sanitizer_weak_hook_strstr
- CString==: __sanitizer_weak_hook_strcmp
- CString.startswith: __sanitizer_weak_hook_memcmp
- CString.endswith: __sanitizer_weak_hook_strncmp
- CString.compare: __sanitizer_weak_hook_strcmp
- CString.equalsLower: __sanitizer_weak_hook_strcasecmp
- Array==: __sanitizer_weak_hook_memcmp
- ArrayList==: __sanitizer_weak_hook_memcmp
实验性功能选项
--experimental [frontend]
启用实验性功能,允许在命令行使用其他实验性功能选项。
注意:
使用实验性功能生成的二进制文件可能存在潜在的运行时问题,请注意使用该选项的风险。
其他功能
编译器报错信息显示颜色
对于 Windows 版本的仓颉编译器,仅在运行于 Windows 10 version 1511 (Build 10586) 或更高版本的系统时,编译器报错信息才会显示颜色,否则不显示颜色。
设置 build-id
通过 --link-options "--build-id=<arg>"1 可以透传链接器选项以设置 build-id。
编译 Windows 目标时不支持此功能。
设置 rpath
通过 --link-options "-rpath=<arg>"1 可以透传链接器选项以设置 rpath。
编译 Windows 目标时不支持此功能。
增量编译
通过 --incremental-compile[frontend]开启增量编译。开启后,cjc会在编译时根据前次编译的缓存文件加快此次编译的速度。
注意:
该选项为实验性功能,使用该功能生成的二进制有可能会存在潜在的运行时问题,请注意使用该选项的风险。此选项必须配合
--experimental选项一同使用。 指定此选项时会保存增量编译缓存及日志到输出文件路径下的.cached目录。
cjc 用到的环境变量
这里介绍一些仓颉编译器在编译代码的过程中可能使用到的环境变量。
TMPDIR 或者 TMP
仓颉编译器会将编译过程中生成的临时文件放置在临时目录中。默认情况下,Linux 和 macOS 操作系统会将其放在 /tmp 目录下,而 Windows 操作系统则会将其放在 C:\Windows\Temp 目录下。仓颉编译器还支持自定义临时文件存放目录,在 Linux 和 macOS 操作系统上,可以通过设置环境变量 TMPDIR 来更改临时文件目录,而在 Windows 操作系统上,则可以通过设置环境变量 TMP 来更改临时文件目录。
例如: 在 Linux shell 中
export TMPDIR=/home/xxxx
在 Windows cmd 中
set TMP=D:\\xxxx
Linux 版本工具链的支持与安装
仓颉工具链当前基于以下 Linux 发行版进行了完整功能测试:
- SUSE Linux Enterprise Server 12 SP5
- Ubuntu 18.04
- Ubuntu 20.04
- UnionTech OS Server 20
- Kylin Linux Advanced Server Release V10
适用于各 Linux 发行版的仓颉工具链依赖安装命令
注意:
当前仓颉工具链依赖的某些工具在一些 Linux 发行版上可能无法通过系统默认软件源直接安装。可参考下一节编译安装依赖工具进行手动安装。
SUSE Linux Enterprise Server 12 SP5
$ zypper install \
binutils \
glibc-devel \
gcc-c++
此外,还需要安装 OpenSSL 3,安装方法请参见编译安装依赖工具。
Ubuntu 18.04
$ apt-get install \
binutils \
libc-dev \
libc++-dev \
libgcc-7-dev
此外,还需要安装 OpenSSL 3,安装方法请参见编译安装依赖工具。
Ubuntu 20.04
$ apt-get install \
binutils \
libc-dev \
libc++-dev \
libgcc-9-dev
此外,还需要安装 OpenSSL 3,安装方法请参见编译安装依赖工具。
UnionTech OS Server 20
$ yum install \
binutils \
glibc-devel \
libstdc++-devel \
gcc \
此外,还需要安装 OpenSSL 3,安装方法请参见编译安装依赖工具。
Kylin Linux Advanced Server release V10
$ yum install \
binutils \
glibc-devel \
libstdc++-devel \
gcc \
此外,还需要安装 OpenSSL 3,安装方法请参见编译安装依赖工具。
其他 Linux 发行版
根据使用的 Linux 发行版的不同,可能需要参考以上系统的依赖安装命令,使用系统包管理工具安装对应依赖。若使用的系统没有提供相关软件包,可能需要自行安装链接工具、C 语言开发工具、C++ 开发工具、GCC 编译器、以及 OpenSSL 3 以正常使用仓颉工具链。
编译安装依赖工具
当前仓颉工具链中的部分标准库(以及部分工具)使用了 OpenSSL 3 开源软件。对于系统包管理工具未提供 OpenSSL 3 的场景,用户可能需要源码编译安装 OpenSSL 3,本节提供了 OpenSSL 3 源码编译的方法和步骤。
OpenSSL 3
从以下链接可以下载到 OpenSSL 3 的源码:
建议使用 OpenSSL 3.0.7 或更高版本。
注意:
请在执行以下编译和安装命令前仔细阅读注意事项,并根据实际情况调整命令。不正确的配置和安装可能会导致系统其他软件不可用。如果在编译安装过程中遇到问题或希望进行额外的安装配置,请参见 OpenSSL 源码中的
INSTALL文件或 OpenSSL 的 FAQ。
此处以 OpenSSL 3.0.7 为例,下载后使用以下命令解压压缩包:
$ tar xf openssl-3.0.7.tar.gz
解压完成后进入目录:
$ cd openssl-3.0.7
编译 OpenSSL:
注意:
如果系统已经安装了 OpenSSL,建议使用
--prefix=<path>选项指定一个自定义安装路径,例如--prefix=/usr/local/openssl-3.0.7或开发者的个人目录。在系统目录已经存在 OpenSSL 的场景下直接使用以下命令编译安装可能会使系统 OpenSSL 被覆盖,并导致依赖系统 OpenSSL 的应用不可用。
$ ./Configure --libdir=lib
$ make
测试 OpenSSL:
$ make test
将 OpenSSL 安装至系统目录(或先前指定的 --prefix 目录),可能需要提供 root 权限以成功执行以下命令:
$ make install
或
$ sudo make install
如果先前编译 OpenSSL 时没有通过 --prefix 设置自定义安装路径,则 OpenSSL 安装已经完成了。如果先前通过 --prefix 指定了自定义的安装路径,还需要设置以下变量,以使仓颉工具链可以找到 OpenSSL 3。
注意:
如果系统中原先存在其他版本的 OpenSSL,通过以下方式配置后,除了仓颉工具链外,其他编译开发工具默认使用的 OpenSSL 版本也可能受到影响。如果使用其他编译开发工具时出现 OpenSSL 不兼容的情况,请仅为仓颉开发环境配置以下变量。
请将 <prefix> 替换为指定的自定义安装路径。
$ export LIBRARY_PATH=<prefix>/lib:$LIBRARY_PATH
$ export LD_LIBRARY_PATH=<prefix>/lib:$LD_LIBRARY_PATH
通过以上方式所配置的环境变量仅在当前执行命令的 shell 会话窗口有效。若希望 shell 每次启动时都自动配置,可以在 $HOME/.bashrc、$HOME/.zshrc 或其他 shell 配置文件(依开发者的 shell 种类而定)加入以上命令。
若希望配置可以默认对所有用户生效,可以执行以下命令:
请将 <prefix> 替换为指定的自定义安装路径。
$ echo "export LIBRARY_PATH=<prefix>/lib:$LIBRARY_PATH" >> /etc/profile
$ echo "<prefix>/lib" >> /etc/ld.so.conf
$ ldconfig
执行完毕后重新打开 shell 会话窗口即可生效。
至此,OpenSSL 3 已经成功安装,可以回到原来的章节继续阅读或尝试运行仓颉编译器了。
runtime 环境变量使用手册
本节介绍 runtime(运行时)所提供的环境变量。
在 Linux shell 与 macOS shell 中,可以使用以下方式设置仓颉运行时提供的环境变量:
$ export VARIABLE=value
在 Windows cmd 中,可以使用以下方式设置仓颉运行时提供的环境变量:
> set VARIABLE=value
本节后续的示例均为 Linux shell 中的设置方式,若与运行平台不符,请根据运行平台选择合适的环境变量设置方式。
runtime 初始化可选配置
注意:
- 所有整型参数为 Int64 类型,浮点型参数为 Float64 类型;
- 所有参数如果未显式规定最大值,默认隐式最大值为该类型最大值;
- 所有参数若超出范围则设置无效,自动使用默认值。
cjHeapSize
指定仓颉堆的最大值,支持单位为 kb(KB)、mb(MB)、gb(GB),支持设置范围为[4MB, 系统物理内存],超出范围的设置无效,仍旧使用默认值。若物理内存低于 1GB,默认值为 64 MB,否则为 256 MB。
例如:
export cjHeapSize=4GB
cjRegionSize
指定 region 分配器 thread local buffer 的大小,支持单位为 kb(KB)、mb(MB)、gb(GB),支持设置范围为[4kb, 2048kb],超出范围的设置无效,仍旧使用默认值。默认值为 64 KB。
例如:
export cjRegionSize=1024kb
cjLargeThresholdSize
需要大量连续内存空间的对象(例如长数组)称为大对象。堆内频繁分配大对象可能导致堆内连续空间不足,从而触发堆溢出问题。通过增加大对象的最大值,可以提升堆内空间的连续性。
在仓颉语言中,大对象的阈值为 cjLargeThresholdSize 和 cjRegionSize 的较小者。cjLargeThresholdSize 支持的单位有 kb(KB)、mb(MB)、gb(GB),支持的范围是 [4KB, 2048KB],超出范围的设置无效,仍旧使用默认值。默认值为 32 KB。
说明:
较大的大对象阈值可能影响程序性能,开发者可根据实际情况设置。
例如:
export cjLargeThresholdSize=1024kb
cjExemptionThreshold
指定存活 region 的水线值,取值 (0,1],该值与 region 的大小相乘,若 region 中存活对象的大小大于相乘后的值,则该 region 不会被回收(其中死亡对象继续占用内存)。该值指定得越大,region 被回收的概率越大,堆中的碎片空间就越少,但频繁回收 region 也会影响性能。超出范围的设置无效,仍旧使用默认值。默认值为 0.8,即 80%。
例如:
export cjExemptionThreshold=0.8
cjHeapUtilization
指定仓颉堆的利用率,该参数用于 GC 后更新堆水线的参考依据之一,取值 (0, 1],堆水线是指当堆中对象总大小达到水线值时则进行 GC。该参数指定越小,则更新后的堆水线会越高,则触发 GC 的概率会相对变低。超出范围的设置无效,仍旧使用默认值。默认值为 0.8,即 80%。
例如:
export cjHeapUtilization=0.8
cjCacheRatio
指定堆缓存率,该参数用于 GC 后的堆缓存,堆内缓存率不高于此值。取值 [0, 1],超出范围的设置无效,仍旧使用默认值,默认值为 1。该参数仅在 openEuler 平台生效。
例如:
export cjCacheRatio=0.25
cjHeapGrowth
指定仓颉堆的增长率,该参数用于 GC 后更新堆水线的参考依据之一,取值必须大于 0。增长率的计算方式为 1 + cjHeapGrowth。该参数指定越大,则更新后的堆水线会越高,则触发 GC 的概率会相对变低。默认值为 0.15,表示增长率为 1.15。
例如:
export cjHeapGrowth=0.15
cjAllocationRate
指定仓颉运行时分配对象的速率,该值必须大于 0,单位为 MB/s,表示每秒可分配对象的数量。默认值为 10240,表示每秒可分配 10240 MB 对象。
例如:
export cjAllocationRate=10240
cjAllocationWaitTime
指定仓颉运行时分配对象时的等待时间,该值必须大于 0,支持单位为 s、ms、us、ns,推荐单位为纳秒(ns)。若本次分配对象距离上一次分配对象的时间间隔小于此值,则将等待。默认值为 1000 ns。
例如:
export cjAllocationWaitTime=1000ns
cjGCThreshold
指定仓颉堆的参考水线值,支持单位为 kb(KB)、mb(MB)、gb(GB), 取值必须为大于 0 的整数。当仓颉堆大小超过该值时,触发 GC。默认值为堆大小。
例如:
export cjGCThreshold=20480KB
cjGarbageThreshold
当 GC 发生时,如果 region 中死亡对象所占比率大于此环境变量,此 region 会被放入回收候选集中,后续可被回收(如果受到其他策略影响也可能不被回收),默认值为 0.5,无量纲,支持设置的区间为[0.0, 1.0]。
例如:
export cjGarbageThreshold=0.5
cjGCInterval
指定两次 GC 的间隔时间值,取值必须大于 0,支持单位为 s、ms、us、ns,推荐单位为毫秒(ms)。若本次 GC 距离上次 GC 的间隔小于此值,则本次 GC 将被忽略。该参数可以控制 GC 的频率。默认值为 150 ms。
例如:
export cjGCInterval=150ms
cjBackupGCInterval
指定 backup GC 的间隔值,取值必须大于 0,支持单位为 s、ms、us、ns,推荐单位为秒(s),当仓颉运行时在该参数设定时间内未触发 GC,则触发一次 backup GC。默认值为 240 秒,即 4 分钟。
例如:
export cjBackupGCInterval=240s
cjProcessorNum
指定仓颉线程的最大并发数,支持设置范围为 (0, CPU 核数 * 2],超出范围的设置无效,仍旧使用默认值。调用系统 API 获取 cpu 核数,若成功默认值为 cpu 核数,否则默认值为 8。
例如:
export cjProcessorNum=2
cjStackSize
指定仓颉线程的栈大小,支持单位为 kb(KB)、mb(MB)、gb(GB),支持设置范围为 Linux 平台下[64KB, 1GB],Windows 平台下[128KB, 1GB],超出范围的设置无效,仍旧使用默认值。默认值为 128KB。
例如:
export cjStackSize=100kb
运维日志可选配置
MRT_LOG_FILE_SIZE
指定 runtime 运维日志的文件大小,默认值为 10 MB,支持单位为 kb(KB)、mb(MB)、gb(GB),设置值需大于 0。
日志大小超过该值时,会重新回到日志开头进行打印。
最终生成日志大小略大于 MRT_LOG_FILE_SIZE。
例如:
export MRT_LOG_FILE_SIZE=100kb
MRT_LOG_PATH
指定 runtime 运维日志的输出路径,若该环境变量未设置或路径设置失败,则运维日志默认打印到 stdout(标准输出)或 stderr(标准错误)中。
例如:
export MRT_LOG_PATH=/home/cangjie/runtime/runtime_log.txt
MRT_LOG_LEVEL
指定 runtime 运维日志的最小输出级别,大于等于这个级别的日志会被打印,默认值为 e,支持设置值为[v|d|i|w|e|f|s]。v(VERBOSE)、d(DEBUGY)、i(INFO)、w(WARNING)、e(ERROR)、f(FATAL)、s(FATAL_WITHOUT_ABORT)。
例如:
export MRT_LOG_LEVEL=v
MRT_REPORT
指定 runtime GC 日志的输出路径,若该环境变量未设置或路径设置失败,该日志默认不打印。
例如:
export MRT_REPORT=/home/cangjie/runtime/gc_log.txt
MRT_LOG_CJTHREAD
指定 cjthread 日志的输出路径,若该环境变量未设置或路径设置失败,该日志默认不打印。
例如:
export MRT_LOG_CJTHREAD=/home/cangjie/runtime/cjthread_log.txt
cjHeapDumpOnOOM
指定是否要在发生堆溢出后输出堆快照文件,默认不开启。支持设置值为[on|off],设定为 on 时开启功能,设定 off 或者其他值不开启功能。
例如:
export cjHeapDumpOnOOM=on
cjHeapDumpLog
指定输出堆快照文件的路径。注意指定的路径必须存在,且应用执行者对其具有读写权限。如果不指定,堆快照文件将输出到当前执行目录。
例如:
export cjHeapDumpLog=/home/cangjie
运行环境可选配置
MRT_STACK_CHECK
开启 native stack overflow 检查,默认不开启,支持设置值为 1、true、TRUE 开启功能。
例如:
export MRT_STACK_CHECK=true
CJ_SOF_SIZE
当 StackOverflowError 发生时,将自动进行异常栈折叠方便用户阅读,折叠后栈帧层数默认值是 32。可以通过配置此环境变量控制折叠栈长度,支持设置为 int 范围内的整数。 CJ_SOF_SIZE = 0,打印所有调用栈; CJ_SOF_SIZE < 0,从栈底开始打印环境变量配置层数; CJ_SOF_SIZE > 0,从栈顶开始打印环境变量配置层数; CJ_SOF_SIZE 未配置,默认打印栈顶开始 32 层调用栈;
例如:
export CJ_SOF_SIZE=30
关键字
关键字是不能作为标识符使用的特殊字符串,仓颉语言的关键字如下表所示:
| 关键字 | 关键字 | 关键字 |
|---|---|---|
| as | abstract | break |
| Bool | case | catch |
| class | const | continue |
| Rune | do | else |
| enum | extend | for |
| func | false | finally |
| foreign | Float16 | Float32 |
| Float64 | if | in |
| is | init | import |
| interface | Int8 | Int16 |
| Int32 | Int64 | IntNative |
| let | mut | main |
| macro | match | Nothing |
| open | operator | override |
| prop | public | package |
| private | protected | quote |
| redef | return | spawn |
| super | static | struct |
| synchronized | try | this |
| true | type | throw |
| This | unsafe | Unit |
| UInt8 | UInt16 | UInt32 |
| UInt64 | UIntNative | var |
| VArray | where | while |
操作符
下表列出了仓颉支持的所有操作符的优先级及结合性,其中优先级一栏数值越小,对应操作符的优先级越高。
| 操作符 | 优先级 | 含义 | 示例 | 结合方向 |
|---|---|---|---|---|
@ | 0 | 宏调用 | @id | 右结合 |
. | 1 | 成员访问 | expr.id | 左结合 |
[] | 1 | 索引 | expr[expr] | 左结合 |
() | 1 | 函数调用 | expr(expr) | 左结合 |
++ | 2 | 自增 | var++ | 无 |
-- | 2 | 自减 | var-- | 无 |
? | 2 | 问号 | expr?.id, expr?[expr], expr?(expr), expr?{expr} | 无 |
! | 3 | 按位求反、逻辑非 | !expr | 右结合 |
- | 3 | 一元负号 | -expr | 右结合 |
** | 4 | 幂运算 | expr ** expr | 右结合 |
*, / | 5 | 乘法,除法 | expr * expr, expr / expr | 左结合 |
% | 5 | 取模 | expr % expr | 左结合 |
+, - | 6 | 加法,减法 | expr + expr, expr - expr | 左结合 |
<< | 7 | 按位左移 | expr << expr | 左结合 |
>> | 7 | 按位右移 | expr >> expr | 左结合 |
.. | 8 | 左闭右开区间操作符 | expr..expr | 无 |
..= | 8 | 左闭右闭区间操作符 | expr..=expr | 无 |
< | 9 | 小于 | expr < expr | 无 |
<= | 9 | 小于等于 | expr <= expr | 无 |
> | 9 | 大于 | expr > expr | 无 |
>= | 9 | 大于等于 | expr >= expr | 无 |
is | 9 | 类型检查 | expr is Type | 无 |
as | 9 | 类型转换 | expr as Type | 无 |
== | 10 | 判等 | expr == expr | 无 |
!= | 10 | 判不等 | expr != expr | 无 |
& | 11 | 按位与 | expr & expr | 左结合 |
^ | 12 | 按位异或 | expr ^ expr | 左结合 |
| | 13 | 按位或 | expr | expr | 左结合 |
&& | 14 | 逻辑与 | expr && expr | 左结合 |
|| | 15 | 逻辑或 | expr || expr | 左结合 |
?? | 16 | coalescing 操作符 | expr ?? expr | 右结合 |
|> | 17 | pipeline 操作符 | id |> expr | 左结合 |
~> | 17 | composition 操作符 | expr ~> expr | 左结合 |
= | 18 | 赋值 | id = expr | 无 |
**= | 18 | 复合运算符 | id **= expr | 无 |
*= | 18 | 复合运算符 | id *= expr | 无 |
/= | 18 | 复合运算符 | id /= expr | 无 |
%= | 18 | 复合运算符 | id %= expr | 无 |
+= | 18 | 复合运算符 | id += expr | 无 |
-= | 18 | 复合运算符 | id -= expr | 无 |
<<= | 18 | 复合运算符 | id <<= expr | 无 |
>>= | 18 | 复合运算符 | id >>= expr | 无 |
&= | 18 | 复合运算符 | id &= expr | 无 |
^= | 18 | 复合运算符 | id ^= expr | 无 |
|= | 18 | 复合运算符 | id |= expr | 无 |
&&= | 18 | 复合运算符 | id &&= expr | 无 |
||= | 18 | 复合运算符 | id ||= expr | 无 |
操作符函数
下表列出了仓颉支持的所有操作符函数。
| 操作符函数 | 函数签名 | 示例 |
|---|---|---|
[] (索引取值) | operator func [](index1: T1, index2: T2, ...): R | this[index1, index2, ...] |
[] (索引赋值) | operator func [](index1: T1, index2: T2, ..., value!: TN): R | this[index1, index2, ...] = value |
() | operator func ()(param1: T1, param2: T2, ...): R | this(param1, param2, ...) |
! | operator func !(): R | !this |
** | operator func **(other: T): R | this ** other |
* | operator func *(other: T): R | this * other |
/ | operator func /(other: T): R | this / other |
% | operator func %(other: T): R | this % other |
+ | operator func +(other: T): R | this + other |
- | operator func -(other: T): R | this - other |
<< | operator func <<(other: T): R | this << other |
>> | operator func >>(other: T): R | this >> other |
< | operator func <(other: T): R | this < other |
<= | operator func <=(other: T): R | this <= other |
> | operator func >(other: T): R | this > other |
>= | operator func >=(other: T): R | this >= other |
== | operator func ==(other: T): R | this == other |
!= | operator func !=(other: T): R | this != other |
& | operator func &(other: T): R | this & other |
^ | operator func ^(other: T): R | this ^ other |
| | operator func |(other: T): R | this | other |
TokenKind 类型
public enum TokenKind <: ToString {
DOT| /* "." */
COMMA| /* "," */
LPAREN| /* "(" */
RPAREN| /* ")" */
LSQUARE| /* "[" */
RSQUARE| /* "]" */
LCURL| /* "{" */
RCURL| /* "}" */
EXP| /* "**" */
MUL| /* "*" */
MOD| /* "%" */
DIV| /* "/" */
ADD| /* "+" */
SUB| /* "-" */
INCR| /* "++" */
DECR| /* "--" */
AND| /* "&&" */
OR| /* "||" */
COALESCING| /* "??" */
PIPELINE| /* "|>" */
COMPOSITION| /* "~>" */
NOT| /* "!" */
BITAND| /* "&" */
BITOR| /* "|" */
BITXOR| /* "^" */
BITNOT| /* "~" */
LSHIFT| /* "<<" */
RSHIFT| /* ">>" */
COLON| /* ":" */
SEMI| /* ";" */
ASSIGN| /* "=" */
ADD_ASSIGN| /* "+=" */
SUB_ASSIGN| /* "-=" */
MUL_ASSIGN| /* "*=" */
EXP_ASSIGN| /* "**=" */
DIV_ASSIGN| /* "/=" */
MOD_ASSIGN| /* "%=" */
AND_ASSIGN| /* "&&=" */
OR_ASSIGN| /* "||=" */
BITAND_ASSIGN| /* "&=" */
BITOR_ASSIGN| /* "|=" */
BITXOR_ASSIGN| /* "^=" */
LSHIFT_ASSIGN| /* "<<=" */
RSHIFT_ASSIGN| /* ">>=" */
ARROW| /* "->" */
BACKARROW| /* "<-" */
DOUBLE_ARROW| /* "=>" */
RANGEOP| /* ".." */
CLOSEDRANGEOP| /* "..=" */
ELLIPSIS| /* "..." */
HASH| /* "#" */
AT| /* "@" */
QUEST| /* "?" */
LT| /* "<" */
GT| /* ">" */
LE| /* "<=" */
GE| /* ">=" */
IS| /* "is" */
AS| /* "as" */
NOTEQ| /* "!=" */
EQUAL| /* "==" */
WILDCARD| /* "_" */
INT8| /* "Int8" */
INT16| /* "Int16" */
INT32| /* "Int32" */
INT64| /* "Int64" */
INTNATIVE| /* "IntNative" */
UINT8| /* "UInt8" */
UINT16| /* "UInt16" */
UINT32| /* "UInt32" */
UINT64| /* "UInt64" */
UINTNATIVE| /* "UIntNative" */
FLOAT16| /* "Float16" */
FLOAT32| /* "Float32" */
FLOAT64| /* "Float64" */
RUNE| /* "Rune" */
BOOLEAN| /* "Bool" */
NOTHING| /* "Nothing" */
UNIT| /* "Unit" */
STRUCT| /* "struct" */
ENUM| /* "enum" */
VARRAY| /* "VArray" */
THISTYPE| /* "This" */
PACKAGE| /* "package" */
IMPORT| /* "import" */
CLASS| /* "class" */
INTERFACE| /* "interface" */
FUNC| /* "func" */
MACRO| /* "macro" */
QUOTE| /* "quote" */
DOLLAR| /* "$" */
LET| /* "let" */
VAR| /* "var" */
CONST| /* "const" */
TYPE| /* "type" */
INIT| /* "init" */
THIS| /* "this" */
SUPER| /* "super" */
IF| /* "if" */
ELSE| /* "else" */
CASE| /* "case" */
TRY| /* "try" */
CATCH| /* "catch" */
FINALLY| /* "finally" */
FOR| /* "for" */
DO| /* "do" */
WHILE| /* "while" */
THROW| /* "throw" */
RETURN| /* "return" */
CONTINUE| /* "continue" */
BREAK| /* "break" */
IN| /* "in" */
NOT_IN| /* "!in" */
MATCH| /* "match" */
WHERE| /* "where" */
EXTEND| /* "extend" */
WITH| /* "with" */
PROP| /* "prop" */
STATIC| /* "static" */
PUBLIC| /* "public" */
PRIVATE| /* "private" */
INTERNAL| /* "internal" */
PROTECTED| /* "protected" */
OVERRIDE| /* "override" */
REDEF| /* "redef" */
ABSTRACT| /* "abstract" */
SEALED| /* "sealed" */
OPEN| /* "open" */
FOREIGN| /* "foreign" */
INOUT| /* "inout" */
MUT| /* "mut" */
UNSAFE| /* "unsafe" */
OPERATOR| /* "operator" */
SPAWN| /* "spawn" */
SYNCHRONIZED| /* "synchronized */
UPPERBOUND| /* "<:" */
MAIN| /* "main" */
IDENTIFIER| /* "x" */
PACKAGE_IDENTIFIER| /* "x-y" */
INTEGER_LITERAL| /* e.g. "1" */
RUNE_BYTE_LITERAL| /* e.g. "b'x'" */
FLOAT_LITERAL| /* e.g. "'1.0'" */
COMMENT| /* e.g. "//xx" */
NL| /* newline */
END| /* end of file */
SENTINEL| /* ";" */
RUNE_LITERAL| /* e.g. "r'x'" */
STRING_LITERAL| /* e.g. ""xx"" */
SINGLE_QUOTED_STRING_LITERAL|
/* e.g. "'xx'" */
JSTRING_LITERAL| /* e.g. "J"xx"" */
MULTILINE_STRING| /* e.g. """"aaa"""" */
MULTILINE_RAW_STRING| /* e.g. "#"aaa"#" */
BOOL_LITERAL| /* "true" or "false" */
UNIT_LITERAL| /* "()" */
DOLLAR_IDENTIFIER| /* e.g. "$x" */
ANNOTATION| /* e.g. "@When" */
AT_EXCL| /* e.g. "@!" */
ILLEGAL|
...
}
仓颉编程语言标准库概述
仓颉编程语言标准库(std)是安装仓颉 SDK 时默认自带的库。标准库预先定义了一组函数、类、结构体等,旨在提供常用的功能和工具,以便开发者能够更快速、更高效地编写程序。
仓颉标准库有其三项特点和追求:
- 使用方便:标准库随编译器、工具链一起发布,不需要用户另外下载,开箱即用。
- 功能通用:标准库提供了开发者最常使用的一些库能力,旨在为开发者解决大部分基础问题。
- 质量标杆:标准库追求在性能、代码风格等方面为其他仓颉库树立范例和标杆。
使用指导
在仓颉编程语言中,标准库包含了若干包(package),而包是编译的最小单元。每个包可以单独输出 AST(Abstract Syntax Trees,抽象语法树)文件、静态库文件、动态库文件等产物。包可以定义子包,从而构成树形结构。没有父包的包称为 root 包,root 包及其子包(包括子包的子包)构成的整棵树称为模块(module)。模块的名称与 root 包相同,是开发者发布的最小单元。
包的导入规则如下:
-
可以导入某个包中的一个顶层声明或定义,语法如下:
import fullPackageName.itemName其中 fullPackageName 为完整路径包名,itemName 为声明的名字,例如:
import std.collection.ArrayList -
如果要导入的多个 itemName 同属于一个 fullPackageName,可以使用:
import fullPackageName.{itemName[, itemName]*}例如:
import std.collection.{ArrayList, HashMap} -
还可以将 fullPackageName 包中所有 public 修饰的顶层声明或定义全部导入,语法如下:
import fullPackageName.*例如:
import std.collection.*
包列表
std 含若干包,提供丰富的基础功能:
| 包名 | 功能 |
|---|---|
| core | core 包是标准库的核心包,提供了适用仓颉语言编程最基本的一些 API 能力。 |
| argopt | argopt 包提供从命令行参数字符串解析出参数名和参数值的相关能力。 |
| ast | ast 包主要包含了仓颉源码的语法解析器和仓颉语法树节点,提供语法解析函数。 |
| binary | binary 包提供了基础数据类型和二进制字节数组的不同端序转换接口,以及端序反转接口。 |
| collection | collection 包提供了常见数据结构的高效实现、相关抽象的接口的定义以及在集合类型中常用的函数功能。 |
| collection.concurrent | collection.concurrent 包提供了并发安全的集合类型实现。 |
| console | console 包提供和标准输入、标准输出、标准错误进行交互的方法。 |
| convert | convert 包提供从字符串转到特定类型的 Convert 系列函数以及提供格式化能力,主要为将仓颉类型实例转换为格式化字符串。 |
| crypto.cipher | crypto.cipher 包提供对称加解密通用接口。 |
| crypto.digest | crypto.digest 包提供常用摘要算法的通用接口,包括 MD5、SHA1、SHA224、SHA256、SHA384、SHA512、HMAC、SM3。 |
| database.sql | database.sql 包提供仓颉访问数据库的接口。 |
| deriving | deriving 包提供一组宏来自动生成接口实现。 |
| env | env 包提供当前进程的相关信息与功能、包括环境变量、命令行参数、标准流、退出程序。 |
| fs | fs(file system)包提供对文件、文件夹、路径、文件元数据信息的一些操作函数。 |
| io | io 包提供程序与外部设备进行数据交换的能力。 |
| math | math 包提供常见的数学运算,常数定义,浮点数处理等功能。 |
| math.numeric | math.numeric 包对基础类型可表达范围之外提供扩展能力。 |
| net | net 包提供常见的网络通信功能。 |
| objectpool | objectpool 包提供了对象缓存和复用的功能。 |
| overflow | overflow 包提供了溢出处理相关能力。 |
| posix | posix 包封装 POSIX 系统调用,提供跨平台的系统操作接口。 |
| process | process 包主要提供 Process 进程操作接口,主要包括进程创建,标准流获取,进程等待,进程信息查询等。 |
| random | random 包提供生成伪随机数的能力。 |
| reflect | reflect 包提供了反射功能,使得程序在运行时能够获取到各种实例的类型信息,并进行各种读写和调用操作。 |
| regex | regex 包使用正则表达式分析处理文本的能力(支持 UTF-8 编码的 Unicode 字符串),支持查找、分割、替换、验证等功能。 |
| runtime | runtime 包的作用是与程序的运行时环境进行交互,提供了一系列函数和变量,用于控制、管理和监视程序的执行。 |
| sort | sort 包提供数组类型的排序函数。 |
| sync | sync 包提供并发编程相关的能力。 |
| time | time 包提供了与时间相关的类型,包括日期时间,时间间隔,单调时间和时区等,并提供了计算和比较的功能。 |
| unicode | unicode 包提供了按 unicode 编码标准处理字符的能力。 |
| unittest | unittest 包用于编写仓颉项目单元测试代码,提供包括代码编写、运行和调测在内的基本功能。 |
| unittest.mock | unittest.mock 包提供仓颉单元测试的 mock 框架,提供 API 用于创建和配置 mock 对象,这些 mock 对象与真实对象拥有签名一致的 API 。 |
| unittest.testmacro | unittest.testmacro 为单元测试框架提供了用户所需的宏。 |
| unittest.mock.mockmacro | unittest.mock.mockmacro 为 mock 框架提供了用户所需的宏。 |
| unittest.common | unittest.common 为单元测试框架提供了打印所需的类型和一些通用方法。 |
| unittest.diff | unittest.diff 为单元测试框架提供了打印差异对比信息所需的 API 。 |
| unittest.prop_test | unittest.prop_test 为单元测试框架提供了参数化测试所需的类型和一些通用方法。 |
std.core
功能介绍
core 包是标准库的核心包,提供了适用仓颉语言编程最基本的一些 API 能力。
提供了内置类型(有符号整型、无符号整型、浮点型等)、常用函数(print、println、eprint 等)、常用接口(ToString、Hashable、Equatable、Collection 等)、常用类和结构体(Array、String、Range 等)、常用异常类(Error、Exception 以及它们的一些细分子类)。
说明:
core 包不需要显式导入,默认导入。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| acquireArrayRawData(Array<T>) where T <: CType | 获取 Array<T> 中数据的原始指针实例,T 需要满足 CType 约束。 |
| alignOf<T>() where T <: CType | 获取类型 T 的内存对齐值。 |
| eprint(String, Bool) | 将指定字符串打印到标准错误文本流。 |
| eprintln(String) | 将指定字符串打印到标准错误文本流,末尾添加换行。 |
| eprint<T>(T, Bool) where T <: ToString | 将指定 T 类型实例的字符串表示打印到标准错误文本流。 |
| eprintln<T>(T) where T <: ToString | 将指定 T 类型实例的字符串表示打印到标准错误文本流,末尾添加换行。 |
| ifNone(Option<T>, () -> Unit) | 如果输入是 Option.None 类型数据,则执行 action 函数。 |
| ifSome(Option<T>, (T) -> Unit) | 如果输入是 Option.Some 类型数据,则执行 action 函数。 |
| max<T>(T, T, Array<T>) where T <: Comparable<T> | 获取一组数据中的最大值 |
| min<T>(T, T, Array<T>) where T <: Comparable<T> | 获取一组数据中的最小值 |
| print(Bool, Bool) | 向控制台输出 Bool 类型数据的字符串表达。 |
| print(Float16, Bool) | 向控制台输出 Float16 类型数据的字符串表达。 |
| print(Float32, Bool) | 向控制台输出 Float32 类型数据的字符串表达。 |
| print(Float64, Bool) | 向控制台输出 Float64 类型数据的字符串表达。 |
| print(Int16, Bool) | 向控制台输出 Int16 类型数据的字符串表达。 |
| print(Int32, Bool) | 向控制台输出 Int32 类型数据的字符串表达。 |
| print(Int64, Bool) | 向控制台输出 Int64 类型数据的字符串表达。 |
| print(Int8, Bool) | 向控制台输出 Int8 类型数据的字符串表达。 |
| print(Rune, Bool) | 向控制台输出 Rune 类型数据的字符串表达。 |
| print(String, Bool) | 向控制台输出指定字符串。 |
| print(UInt16, Bool) | 向控制台输出 UInt16 类型数据的字符串表达。 |
| print(UInt32, Bool) | 向控制台输出 UInt32 类型数据的字符串表达。 |
| print(UInt64, Bool) | 向控制台输出 UInt64 类型数据的字符串表达。 |
| print(UInt8, Bool) | 向控制台输出 UInt8 类型数据的字符串表达。 |
| print<T>(T, Bool) where T <: ToString | 向控制台输出 T 类型实例的字符串表示。 |
| println() | 向标准输出(stdout)输出换行符。 |
| println(Bool) | 向控制台输出 Bool 类型数据的字符串表达,末尾添加换行。 |
| println(Float16) | 向控制台输出 Float16 类型数据的字符串表达,末尾添加换行。 |
| println(Float32) | 向控制台输出 Float32 类型数据的字符串表达,末尾添加换行。 |
| println(Float64) | 向控制台输出 Float64 类型数据的字符串表达,末尾添加换行。 |
| println(Int16) | 向控制台输出 Int16 类型数据的字符串表达,末尾添加换行。 |
| println(Int32) | 向控制台输出 Int32 类型数据的字符串表达,末尾添加换行。 |
| println(Int64) | 向控制台输出 Int64 类型数据的字符串表达,末尾添加换行。 |
| println(Int8) | 向控制台输出 Int8 类型数据的字符串表达,末尾添加换行。 |
| println(Rune) | 向控制台输出 Rune 类型数据的字符串表达,末尾添加换行。 |
| println(String) | 向控制台输出指定字符串,末尾添加换行。 |
| println(UInt16) | 向控制台输出 UInt16 类型数据的字符串表达,末尾添加换行。 |
| println(UInt32) | 向控制台输出 UInt32 类型数据的字符串表达,末尾添加换行。 |
| println(UInt64) | 向控制台输出 UInt64 类型数据的字符串表达,末尾添加换行。 |
| println(UInt8) | 向控制台输出 UInt8 类型数据的字符串表达,末尾添加换行。 |
| println<T>(T) where T <: ToString | 向控制台输出 T 类型实例的字符串表示,末尾添加换行。 |
| readln() | 接受控制台输入,直到遇到换行或EOF结束。 |
| refEq(Object, Object) | 判断两个 Object 实例的内存地址是否相同。 |
| releaseArrayRawData(CPointerHandle<T>) where T <: CType | 释放原始指针实例,该实例通过 acquireArrayRawData 获取。 |
| sizeOf<T>() where T <: CType | 获取类型 T 所占用的内存空间大小。 |
| sleep(Duration) | 休眠当前线程。 |
| zeroValue<T>() | 获取一个已全零初始化的 T 类型实例。 |
类型别名
内置类型
| 内置类型名 | 功能 |
|---|---|
| Int8 | 表示 8 位有符号整型,表示范围为 [-2^7, 2^7 - 1]。 |
| Int16 | 表示 16 位有符号整型,表示范围为 [-2^{15}, 2^{15} - 1]。 |
| Int32 | 表示 32 位有符号整型,表示范围为 [-2^{31}, 2^{31} - 1]。 |
| Int64 | 表示 64 位有符号整型,表示范围为 [-2^{63}, 2^{63} - 1]。 |
| IntNative | 表示平台相关的有符号整型,其长度与当前系统的位宽一致。 |
| UInt8 | 表示 8 位无符号整型,表示范围为 [0 ~ 2^8 - 1]。 |
| UInt16 | 表示 16 位无符号整型,表示范围为 [0 ~ 2^{16} - 1]。 |
| UInt32 | 表示 32 位无符号整型,表示范围为 [0 ~ 2^{32} - 1]。 |
| UInt64 | 表示 64 位无符号整型,表示范围为 [0 ~ 2^{64} - 1]。 |
| UIntNative | 表示平台相关的无符号整型,其长度与当前系统的位宽一致。 |
| Float16 | 表示 16 位浮点数,符合 IEEE 754 中的半精度格式(binary16)。 |
| Float32 | 表示 32 位浮点数,符合 IEEE 754 中的单精度格式(binary32)。 |
| Float64 | 表示 64 位浮点数,符合 IEEE 754 中的双精度格式(binary64)。 |
| Bool | 表示布尔类型,有 true 和 false 两种取值。 |
| Rune | 表示 unicode 字符集中的字符。 |
| Unit | 表示仓颉语言中只关心副作用而不关心值的表达式的类型。 |
| CPointer<T> | 表示 T 类型实例的指针,在与 C 语言互操作的场景下使用,对应 C 语言的 T*。 |
| CString | 表示 C 风格字符串,在与 C 语言互操作的场景下使用。 |
接口
| 接口名 | 功能 |
|---|---|
| Any | Any 是所有类型的父类型,所有 interface 都默认继承它,所有非 interface 类型都默认实现它。 |
| Hasher | 该接口用于处理哈希组合运算。 |
| ThreadContext | 仓颉线程上下文接口。 |
| Countable<T> | 该接口表示类型可数。 |
| Collection<T> | 该接口用来表示集合,通常容器类型应该实现该接口。 |
| Less<T> | 该接口表示小于计算。 |
| Greater<T> | 该接口表示大于计算。 |
| LessOrEqual<T> | 该接口表示小于等于计算。 |
| GreaterOrEqual<T> | 该接口表示大于等于计算。 |
| Comparable<T> | 该接口表示比较运算,是等于、小于、大于、小于等于、大于等于接口的集合体。 |
| Equal<T> | 该接口用于支持判等操作。 |
| NotEqual<T> | 该接口用于支持判不等操作。 |
| Equatable<T> | 该接口是判等和判不等两个接口的集合体。 |
| Hashable | 该接口用于计算哈希值。 |
| Iterable<E> | 该接口表示可迭代,实现了该接口的类型(通常为容器类型)可以在 for-in 语句中实现迭代,也可以获取其对应的迭代器类型实例,调用 next 函数实现迭代。 |
| Resource | 该接口用于资源管理,通常用于内存、句柄等资源的关闭和释放。 |
| ToString | 该接口用来提供具体类型的字符串表示。 |
| CType | 表示支持与 C 语言互操作的接口。 |
类
| 类名 | 功能 |
|---|---|
| ArrayIterator<T> | 数组迭代器,迭代功能详述见 Iterable 和 Iterator 接口说明。 |
| Box<T> | Box 类型提供了为其他类型添加一层 class 封装的能力。 |
| Future<T> | Future<T> 实例代表一个仓颉线程任务,可用于获取仓颉线程的计算结果,向仓颉线程发送取消信号。 |
| Iterator<T> | 该类表示迭代器,提供 next 方法支持对容器内的成员进行迭代遍历。 |
| Object | 构造一个 object 实例。 |
| RangeIterator<T> <: Iterator<T> where T <: Countable<T> & Comparable<T> & Equatable<T> | Range 类型的迭代器,迭代功能详述见 Iterable 和 Iterator 接口说明。 |
| StackTraceElement | 表示一个异常堆栈的具体信息,包括异常发生的类名、函数名、文件名、行号。 |
| StringBuilder | 该类主要用于字符串的构建。 |
| Thread | Thread 类代表一个仓颉类,可用于获取线程 ID 及名字、查询线程是否存在取消请求、注册线程未处理异常的处理函数等。 |
| ThreadLocal<T> | 该类表示仓颉线程局部变量。 |
枚举
| 枚举名 | 功能 |
|---|---|
| AnnotationKind | 表示自定义注解希望支持的位置。 |
| Endian | 枚举类型 Endian 表示运行平台的端序,分为大端序和小端序。 |
| Ordering | Ordering 表示比较大小的结果,它包含三种情况:小于,大于和等于。 |
| Option<T> | Option<T> 是对 T 类型的封装,表示可能有值也可能无值。 |
结构体
| 结构体名 | 功能 |
|---|---|
| Array<T> | 仓颉数组类型,用来表示单一类型的元素构成的有序序列。 |
| CPointerHandle<T> where T <: CType | 表示 Array 数组的原始指针,该类型中的泛型参数应该满足 CType 约束。 |
| CPointerResource<T> where T <: CType | 该结构体表示 CPointer 对应的资源管理类型,其实例可以通过 CPointer 的成员函数 asResource 获取。 |
| CStringResource | 该结构体表示 CString 对应的资源管理类型,其实例可以通过 CString 的成员函数 asResource 获取。 |
| DefaultHasher | 该结构体提供了默认哈希算法实现。 |
| Duration | 表示时间间隔,是一个描述一段时间的时间类型,提供了常用的静态实例,以及计算、比较等功能。 |
| LibC | 提供了仓颉中较为高频使用的 C 接口,如申请、释放堆上 CType 实例。 |
| Range<T> where T <: Countable<T> & Comparable<T> & Equatable<T> | 该类是区间类型,用于表示一个拥有固定范围和步长的 T 的序列,要求 T 是可数的,有序的。 |
| String | 该结构体表示仓颉字符串,提供了构造、查找、拼接等一系列字符串操作。 |
异常类
| 异常类名 | 功能 |
|---|---|
| ArithmeticException | 算术异常类,发生算术异常时使用。 |
| Error | Error 是所有错误类的父类。该类不可被继承,不可初始化,但是可以被捕获到。 |
| Exception | Exception 是所有异常类的父类。 |
| IllegalArgumentException | 表示参数非法的异常类。 |
| IllegalFormatException | 表示变量的格式无效或不标准时的异常类。 |
| IllegalMemoryException | 表示内存操作错误的异常类。 |
| IllegalStateException | 表示状态非法的异常类。 |
| IncompatiblePackageException | 表示包不兼容的异常类。 |
| IndexOutOfBoundsException | 表示索引越界的异常类。 |
| InternalError | 表示内部错误的错误类,该类不可初始化,但是可以被捕获到。 |
| NegativeArraySizeException | 表示数组大小为负数的异常类。 |
| NoneValueException | 表示 Option<T> 实例的值为 None 的异常类,通常在 getOrThrow 函数中被抛出。 |
| OutOfMemoryError | 表示内存不足错误的错误类,该类不可被继承,不可初始化,但是可以被捕获到。 |
| OverflowException | 表示算术运算溢出的异常类。 |
| SpawnException | 线程异常类,表示线程处理过程中发生异常。 |
| StackOverflowError | 表示堆栈溢出错误的错误类,该类不可被继承,不可初始化,但是可以被捕获到。 |
| TimeoutException | 当阻塞操作超时时引发异常。 |
| UnsupportedException | 表示功能未支持的异常类。 |
函数
func acquireArrayRawData<T>(Array<T>) where T <: CType
public unsafe func acquireArrayRawData<T>(arr: Array<T>): CPointerHandle<T> where T <: CType
功能:获取 Array<T> 中数据的原始指针实例,指针实例指向数组首元素的地址,T 需要满足 CType 约束。
注意:
指针使用完后需要及时用 releaseArrayRawData 函数释放该指针。 指针的获取和释放之间仅可包含简单的 foreign C 函数调用等逻辑,不构造例如 CString 等的仓颉对象,否则可能造成不可预期现象。
参数:
- arr: Array<T> - 待获取原始指针的数组。
返回值:
- CPointerHandle<T> - 数组的原始指针实例。
示例:
main() {
var arr: Array<Int64> = [1, 2, 3, 4]
var cptrHandle: CPointerHandle<Int64> = unsafe { acquireArrayRawData(arr) }
var cptr: CPointer<Int64> = cptrHandle.pointer
let num: Int64 = unsafe { cptr.read() }
println("The first element of the array is ${num} ")
unsafe { releaseArrayRawData<Int64>(cptrHandle) }
}
运行结果:
The first element of the array is 1
func alignOf<T>() where T <: CType
public func alignOf<T>(): UIntNative where T <: CType
功能:获取类型 T 的内存对齐值。
返回值:
- UIntNative - 类型 T 满足内存对齐要求的字节数。
示例:
@C
struct Data {
var a: Int64 = 0
var b: Float32 = 0.0
}
main() {
let alignSizeInt8: UIntNative = alignOf<Int8>()
println("The memory alignment requirement for Int64 type is ${alignSizeInt8} byte")
let alignSizeInt32: UIntNative = alignOf<Int32>()
println("The memory alignment requirement for Int64 type is ${alignSizeInt32} bytes")
let alignSizeInt64: UIntNative = alignOf<Int64>()
println("The memory alignment requirement for Int64 type is ${alignSizeInt64} bytes")
let alignSizeData: UIntNative = alignOf<Data>()
println("The memory alignment requirement for Int64 type is ${alignSizeData} bytes")
}
运行结果:
The memory alignment requirement for Int64 type is 1 byte
The memory alignment requirement for Int64 type is 4 bytes
The memory alignment requirement for Int64 type is 8 bytes
The memory alignment requirement for Int64 type is 8 bytes
func eprint(String, Bool)
public func eprint(str: String, flush!: Bool = true): Unit
功能:将指定字符串打印到标准错误文本流。
如抛出异常时,消息将打印到标准错误文本流(stderr),而不是标准输出(stdout)。
参数:
- str: String - 待输出的字符串。
- flush!: Bool - 是否将缓存数据区的内容立即刷新写入与标准错误流相关的文件和设备中,true表示立即刷新,false表示暂不刷新 ,默认 false。
示例:
main() {
try {
throw NegativeArraySizeException("I am an Exception!")
} catch (e: NegativeArraySizeException) {
eprint("NegativeArraySizeException is caught!", flush: true)
}
}
运行结果:
NegativeArraySizeException is caught!
func eprintln(String)
public func eprintln(str: String): Unit
功能:将指定字符串打印到标准错误文本流,末尾添加换行。
如抛出异常时,消息将打印到标准错误文本流(stderr),而不是标准输出(stdout)。
参数:
- str: String - 待输出的字符串。
示例:
main() {
try {
throw NegativeArraySizeException("I am an Exception!")
} catch (e: NegativeArraySizeException) {
eprintln("NegativeArraySizeException is caught!")
}
}
运行结果:
NegativeArraySizeException is caught!
func eprint<T>(T, Bool) where T <: ToString
public func eprint<T>(arg: T, flush!: Bool = false): Unit where T <: ToString
功能:将指定 T 类型实例的字符串表示打印到标准错误文本流。
如抛出异常时,消息将打印到标准错误文本流(stderr),而不是标准输出(stdout)。
参数:
- arg: T - 待打印的 T 类型实例,该函数将打印其 toString 的返回值。
- flush!: Bool - 是否清空缓存,true 清空,false 不清空,默认 false。
示例:
class Rectangle <: ToString{
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
public func toString(): String{
return "width: ${this.width}, height: ${this.height}"
}
}
main() {
try {
throw NegativeArraySizeException("I am an Exception!")
} catch (e: NegativeArraySizeException) {
eprint<Rectangle>(Rectangle(10,20), flush: true)
}
}
运行结果:
width: 10, height: 20
func eprintln<T>(T) where T <: ToString
public func eprintln<T>(arg: T): Unit where T <: ToString
功能:将指定 T 类型实例的字符串表示打印到标准错误文本流,末尾添加换行。
如抛出异常时,消息将打印到标准错误文本流(stderr),而不是标准输出(stdout)。
参数:
- arg: T - 待打印的 T 类型实例,该函数将打印其 toString 的返回值。
示例:
class Rectangle <: ToString{
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
public func toString(): String{
return "width: ${this.width}, height: ${this.height}"
}
}
main() {
try {
throw NegativeArraySizeException("I am an Exception!")
} catch (e: NegativeArraySizeException) {
eprintln<Rectangle>(Rectangle(10,20))
}
}
运行结果:
width: 10, height: 20
func ifNone<T>(Option<T>, () -> Unit)
public func ifNone<T>(o: Option<T>, action: () -> Unit): Unit
功能:如果输入是 Option.None 类型数据,则执行 action 函数。
参数:
示例:
main() {
let num: Option<Int64> = None
ifNone<Int64>(num,{=> println("num is None")})
}
运行结果:
num is None
func ifSome<T>(Option<T>, (T) -> Unit)
public func ifSome<T>(o: Option<T>, action: (T) -> Unit): Unit
功能:如果输入是 Option.Some 类型数据,则执行 action 函数。
参数:
- o: Option<T> - 待判断是否为 Option.Some 的 Option<T> 类型实例,同时其封装的
T类型实例将作为 action 函数的输入。 - action: (T) ->Unit - 待执行函数。
示例:
main() {
let num: Option<Int64> = Some(200)
ifSome<Int64>(num,{numValue: Int64 => println("num is ${numValue}")})
}
运行结果:
num is 200
func max<T>(T, T, Array<T>) where T <: Comparable<T>
public func max<T>(a: T, b: T, others: Array<T>): T where T <: Comparable<T>
功能:根据 T 类型的 Comparable 接口实现,返回一组数据中的最大值,由于此函数的第三个参数是一个变长参数,支持获取二个以上的数据的比较。
注意:
浮点数类型的比较也将按照 Comparable 的结果进行比较,如果浮点书中有非数
NaN,结果将不正确,此时建议使用 Float16、Float32、Float64 的static func max方法。
参数:
- a: T - 第一个待比较的数。
- b: T - 第二个待比较的数。
- others: Array<T> - 其他待比较的数。
返回值:
- T - 返回参数中的最大值。
示例:
class Rectangle <: Comparable<Rectangle> & ToString{
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public prop area: Int64 {
get() {
return this.width * this.height
}
}
public func compare(t: Rectangle): Ordering {
if (t.area > this.area) {
return Ordering.LT
} else if (t.area == this.area) {
return Ordering.EQ
} else {
Ordering.GT
}
}
public func toString(): String{
return "width: ${this.width}, height: ${this.height}, area: ${this.area}"
}
}
main() {
var r1: Rectangle = Rectangle(10, 20)
var r2: Rectangle = Rectangle(20, 30)
println("The larger one is ${max(r1, r2)}")
}
运行结果:
The larger one is width: 20, height: 30, area: 600
func min<T>(T, T, Array<T>) where T <: Comparable<T>
public func min<T>(a: T, b: T, others: Array<T>): T where T <: Comparable<T>
功能:根据 T 类型的 Comparable 接口实现,返回一组数据中的最小值,由于此函数的第三个参数是一个变长参数,支持获取二个以上的数据的比较。
注意:
浮点数类型的比较也将按照Comparable的结果进行比较,如果浮点书中有非数
NaN,结果将不正确,此时建议使用 Float16、Float32、Float64 的static func min方法。
参数:
- a: T - 第一个待比较的数。
- b: T - 第二个待比较的数。
- others: Array<T> - 其他待比较的数。
返回值:
- T - 返回参数中的最小值。
示例:
class Rectangle <: Comparable<Rectangle> & ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public prop area: Int64 {
get() {
return this.width * this.height
}
}
public func compare(t: Rectangle): Ordering {
if (t.area > this.area) {
return Ordering.LT
} else if (t.area == this.area) {
return Ordering.EQ
} else {
Ordering.GT
}
}
public func toString(): String {
return "width: ${this.width}, height: ${this.height}, area: ${this.area}"
}
}
main() {
var r1: Rectangle = Rectangle(10, 20)
var r2: Rectangle = Rectangle(20, 30)
println("The smaller one is ${min(r1, r2)}")
}
运行结果:
The smaller one is width: 10, height: 20, area: 200
func print(Bool, Bool)
public func print(b: Bool, flush!: Bool = false): Unit
功能:向控制台输出 Bool 类型数据的字符串表达。
注意:
参数:
示例:
main() {
var flag: Bool = false
print(flag)
flag = true
println()
print(flag)
}
运行结果:
false
true
func print(Float16, Bool)
public func print(f: Float16, flush!: Bool = false): Unit
功能:向控制台输出 Float16 类型数据的小数点后六位的字符串表达,即超出六位的小数位不会输出,不足六位的小数位会补零。
参数:
示例:
main() {
var num1: Float16 = 0.76
var num2: Float16 = 0.68
print(num1)
println()
print(num2)
}
运行结果:
0.759766
0.680176
注意:
仓颉采用IEEE 754格式表示浮点数,保存数值可能会有误差。
func print(Float32, Bool)
public func print(f: Float32, flush!: Bool = false): Unit
功能:向控制台输出 Float32 类型数据的小数点后六位的字符串表达,即超出六位的小数位不会输出,不足六位的小数位会补零。
参数:
示例:
main() {
var num1: Float32 = 0.759766
var num2: Float32 = 0.680176
print(num1)
println()
print(num2)
}
运行结果:
0.759766
0.680176
func print(Float64, Bool)
public func print(f: Float64, flush!: Bool = false): Unit
功能:向控制台输出 Float64 类型数据的小数点后六位的字符串表达,即超出六位的小数位不会输出,不足六位的小数位会补零。
参数:
示例:
main() {
var num1: Float64 = 0.76453
var num2: Float64 = 0.683456
print(num1)
println()
print(num2)
}
运行结果:
0.764530
0.683456
func print(Int16, Bool)
public func print(i: Int16, flush!: Bool = false): Unit
功能:向控制台输出 Int16 类型数据的字符串表达。
参数:
示例:
main() {
var num1: Int16 = 10
var num2: Int16 = 2222
print(num1)
println()
print(num2)
}
运行结果:
10
2222
func print(Int32, Bool)
public func print(i: Int32, flush!: Bool = false): Unit
功能:向控制台输出 Int32 类型数据的字符串表达。
参数:
示例:
main() {
var num1: Int32 = 1024
var num2: Int32 = 2048
print(num1)
println()
print(num2)
}
运行结果:
1024
2048
func print(Int64, Bool)
public func print(i: Int64, flush!: Bool = false): Unit
功能:向控制台输出 Int64 类型数据的字符串表达。
参数:
示例:
main() {
var num1: Int64 = 1024
var num2: Int64 = 2048
print(num1)
println()
print(num2)
}
运行结果:
1024
2048
func print(Int8, Bool)
public func print(i: Int8, flush!: Bool = false): Unit
功能:向控制台输出 Int8 类型数据的字符串表达。
参数:
示例:
main() {
var num1: Int8 = 8
var num2: Int8 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func print(Rune, Bool)
public func print(c: Rune, flush!: Bool = false): Unit
功能:向控制台输出 Rune 类型数据的字符串表达。
参数:
示例:
main() {
var char: Rune = r'a'
print(char)
}
运行结果:
a
func print(String, Bool)
public func print(str: String, flush!: Bool = false): Unit
功能:向控制台输出指定字符串。
参数:
示例:
main() {
var str: String = "I like Cangjie"
print(str)
}
运行结果:
I like Cangjie
func print(UInt16, Bool)
public func print(i: UInt16, flush!: Bool = false): Unit
功能:向控制台输出 UInt16 类型数据的字符串表达。
参数:
示例:
main() {
var num1: UInt16 = 8
var num2: UInt16 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func print(UInt32, Bool)
public func print(i: UInt32, flush!: Bool = false): Unit
功能:向控制台输出 UInt32 类型数据的字符串表达。
参数:
示例:
main() {
var num1: UInt16 = 8
var num2: UInt16 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func print(UInt64, Bool)
public func print(i: UInt64, flush!: Bool = false): Unit
功能:向控制台输出 UInt64 类型数据的字符串表达。
参数:
示例:
main() {
var num1: UInt64 = 8
var num2: UInt64 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func print(UInt8, Bool)
public func print(i: UInt8, flush!: Bool = false): Unit
功能:向控制台输出 UInt8 类型数据的字符串表达。
参数:
示例:
main() {
var num1: UInt8 = 8
var num2: UInt8 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func print<T>(T, Bool) where T <: ToString
public func print<T>(arg: T, flush!: Bool = false): Unit where T <: ToString
功能:向控制台输出 T 类型实例的字符串表示。
参数:
示例:
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() {
width * height
}
public func toString(): String {
return "width: ${this.width}, height: ${this.height}"
}
}
main() {
print<Rectangle>(Rectangle(10, 20))
}
运行结果:
width: 10, height: 20
func println()
public func println(): Unit
功能:向标准输出(stdout)输出换行符。
示例:
main() {
var num1: UInt8 = 8
var num2: UInt8 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func println(Bool)
public func println(b: Bool): Unit
功能:向控制台输出 Bool 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var flag1: Bool = true
var flag2: Bool = false
println(flag1)
println(flag2)
}
运行结果:
true
false
func println(Float16)
public func println(f: Float16): Unit
功能:向控制台输出 Float16 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: Float16 = 3.1415
var num2: Float16 = 3.141592
println(num1)
println(num2)
}
运行结果:
3.140625
3.140625
func println(Float32)
public func println(f: Float32): Unit
功能:向控制台输出 Float32 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: Float32 = 3.1415
var num2: Float32 = 3.141592
println(num1)
println(num2)
}
运行结果:
3.141500
3.141592
func println(Float64)
public func println(f: Float64): Unit
功能:向控制台输出 Float64 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: Float64 = 3.1415
var num2: Float64 = 3.141592
println(num1)
println(num2)
}
运行结果:
3.141500
3.141592
func println(Int16)
public func println(i: Int16): Unit
功能:向控制台输出 Int16 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: Int16 = 8
var num2: Int16 = 32
println(num1)
println(num2)
}
运行结果:
8
32
func println(Int32)
public func println(i: Int32): Unit
功能:向控制台输出 Int32 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: Int32 = 8
var num2: Int32 = 32
println(num1)
println(num2)
}
运行结果:
8
32
func println(Int64)
public func println(i: Int64): Unit
功能:向控制台输出 Int64 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: Int64 = 8
var num2: Int64 = 32
println(num1)
println(num2)
}
运行结果:
8
32
func println(Int8)
public func println(i: Int8): Unit
功能:向控制台输出 Int8 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: Int8 = 8
var num2: Int8 = 32
println(num1)
println(num2)
}
运行结果:
8
32
func println(Rune)
public func println(c: Rune): Unit
功能:向控制台输出 Rune 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var char1: Rune = r'a'
var char2: Rune = r'b'
println(char1)
println(char2)
}
运行结果:
a
b
func println(String)
public func println(str: String): Unit
功能:向控制台输出指定字符串,末尾添加换行。
参数:
- str: String - 待输出的字符串。
示例:
main() {
var str1: String = "I like Cangjie"
var str2: String = "I like programming"
println(str1)
println(str2)
}
运行结果:
I like Cangjie
I like programming
func println(UInt16)
public func println(i: UInt16): Unit
功能:向控制台输出 UInt16 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: UInt16 = 8
var num2: UInt16 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func println(UInt32)
public func println(i: UInt32): Unit
功能:向控制台输出 UInt32 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: UInt32 = 8
var num2: UInt32 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func println(UInt64)
public func println(i: UInt64): Unit
功能:向控制台输出 UInt64 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: UInt64 = 8
var num2: UInt64 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func println(UInt8)
public func println(i: UInt8): Unit
功能:向控制台输出 UInt8 类型数据的字符串表达,末尾添加换行。
参数:
示例:
main() {
var num1: UInt8 = 8
var num2: UInt8 = 32
print(num1)
println()
print(num2)
}
运行结果:
8
32
func println<T>(T) where T <: ToString
public func println<T>(arg: T): Unit where T <: ToString
功能:向控制台输出 T 类型实例的字符串表示,末尾添加换行。
参数:
- arg: T - 待输出的数据,支持实现了 ToString 接口的类型。
示例:
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "width: ${this.width}, height: ${this.height}"
}
}
main() {
println<Rectangle>(Rectangle(10, 20))
println<Rectangle>(Rectangle(5, 10))
}
运行结果:
width: 10, height: 20
width: 5, height: 10
func readln()
public func readln(): String
功能:接受控制台输入,直到遇到换行或EOF结束。
返回值:
- String - 接受到的字符串。
示例:
main() {
var str: String = readln() // Console input 12345 234 and enter
println(str)
}
运行结果:
12345 234
func refEq(Object, Object)
public func refEq(a: Object, b: Object): Bool
功能:判断两个 Object 实例的内存地址是否相同。
参数:
返回值:
示例:
class Rectangle {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
}
main() {
var r1: Rectangle = Rectangle(10, 20)
var r2: Rectangle = r1
var r3: Rectangle = Rectangle(5, 6)
println(refEq(r1, r2))
println(refEq(r1, r3))
}
运行结果:
true
false
func releaseArrayRawData<T>(CPointerHandle<T>) where T <: CType
public unsafe func releaseArrayRawData<T>(handle: CPointerHandle<T>): Unit where T <: CType
功能:释放原始指针实例,该实例通过 acquireArrayRawData 获取。
参数:
- handle: CPointerHandle<T> - 待释放的指针实例。
示例:
main() {
var arr: Array<Int64> = [1, 2, 3, 4]
var cptrHandle: CPointerHandle<Int64> = unsafe { acquireArrayRawData(arr) }
var cptr: CPointer<Int64> = cptrHandle.pointer
let num: Int64 = unsafe { cptr.read() }
println("The first element of the array is ${num} ")
unsafe { releaseArrayRawData<Int64>(cptrHandle) }
}
运行结果:
The first element of the array is 1
func sizeOf<T>() where T <: CType
public func sizeOf<T>(): UIntNative where T <: CType
功能:获取类型 T 所占用的内存空间大小。
返回值:
- UIntNative - 类型 T 所占用内存空间的字节数。
示例:
@C
struct Data {
var a: Int64 = 0
var b: Float32 = 0.0
}
main() {
let sizeInt8: UIntNative = sizeOf<Int8>()
println("The size of Int8 is ${sizeInt8} byte")
let sizeInt32: UIntNative = sizeOf<Int32>()
println("The size of Int32 is ${sizeInt32} bytes")
let sizeInt64: UIntNative = sizeOf<Int64>()
println("The size of Int64 is ${sizeInt64} bytes")
let sizeData: UIntNative = sizeOf<Data>()
println("The size of Rectangle is ${sizeData} bytes")
}
运行结果:
The size of Int8 is 1 byte
The size of Int32 is 4 bytes
The size of Int64 is 8 bytes
The size of Rectangle is 16 bytes
func sleep(Duration)
public func sleep(dur: Duration): Unit
功能:休眠当前线程。
若 dur 小于等于 Duration.Zero,当前线程会让出运行权。
参数:
- dur: Duration - 线程休眠的时长。
示例:
import std.sync.*
import std.time.*
main(): Int64 {
spawn {
=>
println("New thread starts")
println("New thread ends")
}
println("Main thread")
println("The main thread starts to sleep.")
/* dur == 1 秒 */
sleep(1000 * Duration.millisecond)
println("The main thread ends sleep.")
return 0
}
在启动主线程后,执行到sleep函数的时候,主线程会让出系统执行权,并睡眠 1 秒后重新唤醒竞争系统执行权,继续执行剩余逻辑。在主线程睡眠期间,自定义线程拿到执行权,开始执行。运行结果:
Main thread
The main thread starts to sleep.
New thread starts
New thread ends
The main thread ends sleep.
func zeroValue<T>()
public unsafe func zeroValue<T>(): T
功能:获取一个已全零初始化的 T 类型实例。
注意:
通过该函数获取到的实例一定要赋值为正常初始化的值再使用,否则将引发程序崩溃。
返回值:
- T - 一个已全零初始化的 T 类型实例。
示例:
main(): Int64 {
var m = MyClass<Student>()
m.set(1, Student())
var s = m.get(1)
println(s)
s = m.get(2)
// 底下代码解除注释,运行时就会出错,因为其并不是 Student 对象
// println(s)
return 0
}
class MyClass<T> {
var myData: Array<T>
public init() {
// 用 zeroValue<T>() 对 Array 进行全零初始化
myData = Array<T>(10, repeat: unsafe { zeroValue<T>() })
}
public func get(index: Int64): T {
myData[index]
}
public func set(index: Int64, element: T): Unit {
myData[index] = element
}
}
class Student <: ToString {
public func toString() { "student" }
}
示例结果:
student
类型别名
type Byte
public type Byte = UInt8
type Int
public type Int = Int64
type UInt
public type UInt = UInt64
内置类型
Bool
功能:表示布尔类型,有 true 和 false 两种取值。
extend Bool <: Equatable<Bool>
extend Bool <: Equatable<Bool>
功能:为 Bool 类型扩展 Equatable<Bool> 接口,支持判等操作。
父类型:
extend Bool <: Hashable
extend Bool <: Hashable
功能:为 Bool 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
示例:
main() {
var flag: Bool = false
println(flag.hashCode())
flag = true
println(flag.hashCode())
}
运行结果:
0
1
extend Bool <: ToString
extend Bool <: ToString
功能:为 Bool 类型其扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 Bool 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
示例:
main() {
var flag: Bool = false
let str1: String = flag.toString()
println(str1)
flag = true
let str2: String = flag.toString()
println(str2)
}
运行结果:
false
true
CPointer<T>
功能:表示 T 类型实例的指针,在与 C 语言互操作的场景下使用,对应 C 语言的 T*。
其中 T 必须满足 CType 约束。
CPointer 类型必须满足:
- 大小和对齐与平台相关。
- 对它做加减法算术运算、读写内存,是需要在 unsafe 上下文操作的。
- CPointer<T1> 可以在 unsafe 上下文中使用类型强制转换,变成 CPointer<T2> 类型。
extend<T> CPointer<T>
extend<T> CPointer<T>
功能:为 CPointer<T> 扩展一些必要的指针使用相关接口,包含判空、读写数据等接口。
其中泛型 T 为指针类型,其满足 CType 约束。对 CPointer 做运算需要在 unsafe 上下文中进行。
func asResource()
public func asResource(): CPointerResource<T>
功能:获取该指针 CPointerResource 实例,该实例可以在 try-with-resource 语法上下文中实现内容自动释放。
返回值:
- CPointerResource<T> - 当前指针对应的 CPointerResource 实例。
示例:
foreign func malloc(size: UIntNative): CPointer<Unit>
main() {
let sizeofInt64: UIntNative = 8
var p1 = unsafe { malloc(sizeofInt64) }
var ptr = unsafe { CPointer<Int64>(p1) }
unsafe { ptr.write(10) }
var ptrResource: CPointerResource<Int64> = ptr.asResource()
try (r = ptrResource) {
var p = r.value
let num: Int64 = unsafe { p.read() }
println(num)
}
println(ptrResource.isClosed())
}
运行结果:
10
true
func isNotNull()
public func isNotNull(): Bool
功能:判断指针是否不为空。
返回值:
- Bool - 如果不为空返回 true,否则返回 false。
示例:
foreign func malloc(size: UIntNative): CPointer<Unit>
foreign func free(ptr: CPointer<Unit>): Unit
main() {
let p1 = CPointer<Int64>()
println(p1.isNotNull())
let sizeofInt64: UIntNative = 8
var p2 = unsafe { malloc(sizeofInt64) }
println(p2.isNotNull())
unsafe { free(p2) }
}
运行结果:
false
true
func isNull()
public func isNull(): Bool
功能:判断指针是否为空。
返回值:
- Bool - 如果为空返回 true,否则返回 false。
示例:
foreign func malloc(size: UIntNative): CPointer<Unit>
foreign func free(ptr: CPointer<Unit>): Unit
main() {
let sizeofInt64: UIntNative = 8
var p1 = unsafe { malloc(sizeofInt64) }
var ptr = unsafe { CPointer<Int64>(p1) }
unsafe { ptr.write(10) }
let num: Int64 = unsafe { ptr.read() }
println(num)
unsafe { free(p1) }
}
运行结果:
10
func read()
public unsafe func read(): T
功能:读取第一个数据,该接口需要用户保证指针的合法性,否则发生未定义行为。
返回值:
- T - 该对象类型的第一个数据。
示例:
foreign func malloc(size: UIntNative): CPointer<Unit>
foreign func free(ptr: CPointer<Unit>): Unit
main() {
let p1 = CPointer<Int64>()
println(p1.isNull())
let sizeofInt64: UIntNative = 8
var p2 = unsafe { malloc(sizeofInt64) }
println(p2.isNull())
unsafe { free(p2) }
}
运行结果:
true
false
func read(Int64)
public unsafe func read(idx: Int64): T
功能:根据下标读取对应的数据,该接口需要用户保证指针的合法性,否则发生未定义行为。
参数:
- idx: Int64 - 要获取数据的下标。
返回值:
- T - 输入下标对应的数据。
示例:
main() {
var arr: Array<Int64> = [1, 2, 3, 4]
var cptrHandle: CPointerHandle<Int64> = unsafe { acquireArrayRawData(arr) }
var cptr: CPointer<Int64> = cptrHandle.pointer
let num: Int64 = unsafe { cptr.read(2) }
println("The third element of the array is ${num} ")
unsafe { releaseArrayRawData<Int64>(cptrHandle) }
}
运行结果:
The third element of the array is 3
func toUIntNative()
public func toUIntNative(): UIntNative
功能:获取该指针的整型形式。
返回值:
- UIntNative - 该指针的整型形式。
示例:
foreign func malloc(size: UIntNative): CPointer<Unit>
foreign func free(ptr: CPointer<Unit>): Unit
main() {
let sizeofInt64: UIntNative = 8
var p = unsafe { malloc(sizeofInt64) }
var p1 = unsafe { CPointer<Int64>(p) }
unsafe { p1.write(8) }
println(p1.toUIntNative())
unsafe { free(p) }
}
运行结果:
93954490863648
func write(Int64, T)
public unsafe func write(idx: Int64, value: T): Unit
功能:在指定下标位置写入一个数据,该接口需要用户保证指针的合法性,否则发生未定义行为。
参数:
- idx: Int64 - 指定的下标位置。
- value: T - 写入的数据。
示例:
main() {
var arr: Array<Int64> = [1, 2, 3, 4]
var cptrHandle: CPointerHandle<Int64> = unsafe { acquireArrayRawData(arr) }
var cptr: CPointer<Int64> = cptrHandle.pointer
unsafe { cptr.write(2, 6) }
println("The third element of the array is ${arr[2]} ")
// The first element of the array is 1
unsafe { releaseArrayRawData<Int64>(cptrHandle) }
}
运行结果:
The third element of the array is 6
func write(T)
public unsafe func write(value: T): Unit
功能:写入一个数据,该数据总是在第一个,该接口需要用户保证指针的合法性,否则发生未定义行为。
参数:
- value: T - 要写入的数据。
示例:
foreign func malloc(size: UIntNative): CPointer<Unit>
foreign func free(ptr: CPointer<Unit>): Unit
main() {
let sizeofInt64: UIntNative = 8
var p = unsafe { malloc(sizeofInt64) }
var p1 = unsafe { CPointer<Int64>(p) }
unsafe { p1.write(8) }
let value: Int64 = unsafe { p1.read() }
println(value)
unsafe{ free(p) }
}
运行结果:
8
operator func +(Int64)
public unsafe operator func +(offset: Int64): CPointer<T>
功能:CPointer 对象指针后移,同 C 语言的指针加法操作。
参数:
- offset: Int64 - 偏移量。
返回值:
- CPointer<T> - 返回偏移后的指针。
示例:
main() {
var arr: Array<Int64> = [1, 2, 3, 4]
var cptrHandle: CPointerHandle<Int64> = unsafe { acquireArrayRawData(arr) }
var cptr: CPointer<Int64> = cptrHandle.pointer
let num1: Int64 = unsafe { cptr.read() }
println(num1)
cptr = unsafe { cptr + 1 }
let num2: Int64 = unsafe { cptr.read() }
println(num2)
unsafe { releaseArrayRawData<Int64>(cptrHandle) }
}
运行结果:
1
2
operator func -(Int64)
public unsafe operator func -(offset: Int64): CPointer<T>
功能:CPointer 对象指针前移,同 C 语言的指针减法操作。
参数:
- offset: Int64 - 偏移量。
返回值:
- CPointer<T> - 返回偏移后的指针。
示例:
main() {
var arr: Array<Int64> = [1, 2, 3, 4]
var cptrHandle: CPointerHandle<Int64> = unsafe { acquireArrayRawData(arr) }
var cptr: CPointer<Int64> = cptrHandle.pointer
let num1: Int64 = unsafe { cptr.read() }
println(num1)
cptr = unsafe { cptr + 1 }
let num2: Int64 = unsafe { cptr.read() }
println(num2)
cptr = unsafe { cptr - 1 }
let num3: Int64 = unsafe { cptr.read() }
println(num3)
unsafe { releaseArrayRawData<Int64>(cptrHandle) }
}
运行结果:
1
2
1
CString
功能:表示 C 风格字符串,在与 C 语言互操作的场景下使用。
可以通过 CString 的构造函数或 LibC 的 mallocCString 创建 C 风格字符串,如需在仓颉端释放,则调用 LibC 的 free 方法。
extend CString <: ToString
extend CString <: ToString
功能:为 CString 类型扩展一些字符串指针常用方法,包括判空、获取长度、判等、获取子串等。
父类型:
func asResource()
public func asResource(): CStringResource
功能:获取当前 CString 实例对应的 CStringResource C 字符串资源类型实例。
CStringResource 实现了 Resource 接口,可以在 try-with-resource 语法上下文中实现资源自动释放。
返回值:
- CStringResource - 对应的 CStringResource C 字符串资源类型实例。
示例:
foreign func malloc(size: UIntNative): CPointer<Unit>
main() {
var str: CString = unsafe { LibC.mallocCString("hello") }
var ptrResource: CStringResource = str.asResource()
try (r = ptrResource) {
var p = r.value
println(p.size())
}
println(ptrResource.isClosed())
}
运行结果:
5
true
func compare(CString)
public func compare(str: CString): Int32
功能:按字典序比较两个字符串,同 C 语言中的 strcmp。
参数:
- str: CString - 比较的目标字符串。
返回值:
- Int32 - 两者相等返回 0,如果当前字符串比参数 str 小,返回 -1,否则返回 1。
异常:
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
var str2: CString = unsafe { LibC.mallocCString("hello") }
println(str1.compare(str2))
var str3: CString = unsafe { LibC.mallocCString("hello") }
var str4: CString = unsafe { LibC.mallocCString("hellow") }
println(str3.compare(str4))
var str5: CString = unsafe { LibC.mallocCString("hello") }
var str6: CString = unsafe { LibC.mallocCString("allow") }
println(str5.compare(str6))
unsafe {
LibC.free(str1)
LibC.free(str2)
LibC.free(str3)
LibC.free(str4)
LibC.free(str5)
LibC.free(str6)
}
}
运行结果:
0
-1
1
func endsWith(CString)
public func endsWith(suffix: CString): Bool
功能:判断字符串是否包含指定后缀。
参数:
- suffix: CString - 匹配的目标后缀字符串。
返回值:
- Bool - 如果该字符串包含 suffix 后缀,返回 true,如果该字符串不包含 suffix 后缀,返回 false,特别地,如果原字符串或者 suffix 后缀字符串指针为空,均返回 false。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
var str2: CString = unsafe { LibC.mallocCString("lo") }
var str3: CString = unsafe { LibC.mallocCString("ao") }
println(str1.endsWith(str2))
println(str1.endsWith(str3))
unsafe {
LibC.free(str1)
LibC.free(str2)
LibC.free(str3)
}
}
运行结果:
true
false
func equals(CString)
public func equals(rhs: CString): Bool
功能:判断两个字符串是否相等。
参数:
- rhs: CString - 比较的目标字符串。
返回值:
- Bool - 如果两个字符串相等,返回 true,否则返回 false。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
var str2: CString = unsafe { LibC.mallocCString("hello") }
var str3: CString = unsafe { LibC.mallocCString("Hello") }
println(str1.equals(str2))
println(str1.equals(str3))
unsafe {
LibC.free(str1)
LibC.free(str2)
LibC.free(str3)
}
}
运行结果:
true
false
func equalsLower(CString)
public func equalsLower(rhs: CString): Bool
功能:判断两个字符串是否相等,忽略大小写。
参数:
- rhs: CString - 匹配的目标字符串。
返回值:
- Bool - 如果两个字符串忽略大小写相等,返回 true,否则返回 false。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
var str2: CString = unsafe { LibC.mallocCString("HELLO") }
var str3: CString = unsafe { LibC.mallocCString("Hello") }
println(str1.equalsLower(str2))
println(str1.equalsLower(str3))
unsafe {
LibC.free(str1)
LibC.free(str2)
LibC.free(str3)
}
}
运行结果:
true
true
func getChars()
public func getChars(): CPointer<UInt8>
功能:获取该字符串的指针。
返回值:
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
var ptr: CPointer<UInt8> = unsafe { str1.getChars() }
var c: UInt8 = unsafe { ptr.read() }
println(c) // h的ascii码为104
unsafe{
LibC.free(str1)
}
}
运行结果:
104
func isEmpty()
public func isEmpty(): Bool
功能:判断字符串是否为空字符串。
返回值:
- Bool - 如果为空字符串或字符串指针为空,返回 true,否则返回 false。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
println(str1.isEmpty())
unsafe {
LibC.free(str1)
}
}
运行结果:
false
func isNotEmpty()
public func isNotEmpty(): Bool
功能:判断字符串是否不为空字符串。
返回值:
- Bool - 如果不为空字符串,返回 true,如果字符串指针为空,返回 false。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
println(str1.isNotEmpty())
unsafe {
LibC.free(str1)
}
}
运行结果:
true
func isNull()
public func isNull(): Bool
功能:判断字符串指针是否为空。
返回值:
- Bool - 如果字符串指针为空,返回 true,否则返回 false。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
println(str1.isNull())
unsafe {
LibC.free(str1)
}
}
运行结果:
false
func size()
public func size(): Int64
功能:返回该字符串长度,同 C 语言中的 strlen。
返回值:
- Int64 - 字符串长度。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
println(str1.size())
unsafe {
LibC.free(str1)
}
}
运行结果:
5
func startsWith(CString)
public func startsWith(prefix: CString): Bool
功能:判断字符串是否包含指定前缀。
参数:
- prefix: CString - 匹配的目标前缀字符串。
返回值:
- Bool - 如果该字符串包含 prefix 前缀,返回 true,如果该字符串不包含 prefix 前缀,返回 false,特别地,如果原字符串或者 prefix 前缀字符串指针为空,均返回 false。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
var str2: CString = unsafe { LibC.mallocCString("he") }
println(str1.startsWith(str2))
unsafe {
LibC.free(str1)
LibC.free(str2)
}
}
运行结果:
true
func subCString(UIntNative)
public func subCString(beginIndex: UIntNative): CString
功能:截取指定位置开始至字符串结束的子串。
注意:
- 该接口返回为字符串的副本,返回的子串使用完后需要手动 free。
- 如果 beginIndex 与字符串长度相等,将返回空指针。
参数:
- beginIndex: UIntNative - 截取的起始位置,取值范围为 [0, this.size()]。
返回值:
- CString - 截取的子串。
异常:
- IndexOutOfBoundsException - 如果 beginIndex 大于字符串长度,抛出异常。
- IllegalMemoryException - 如果内存申请失败或内存拷贝失败时,抛出异常。
示例:
main() {
let index: UIntNative = 2
var str1: CString = unsafe { LibC.mallocCString("hello") }
var str2: CString = str1.subCString(index)
println(str2)
unsafe {
LibC.free(str1)
LibC.free(str2)
}
}
运行结果:
llo
func subCString(UIntNative, UIntNative)
public func subCString(beginIndex: UIntNative, subLen: UIntNative): CString
功能:截取字符串的子串,指定起始位置和截取长度。
如果截取的末尾位置超出字符串长度,截取至字符串末尾。
注意:
- 该接口返回为字符串的副本,返回的子串使用完后需要手动 free。
- 如果 beginIndex 等于于字符串长度,或 subLen 等于 0,返回空指针。
参数:
- beginIndex: UIntNative - 截取的起始位置,取值范围为 [0, this.size()]。
- subLen: UIntNative - 截取长度,取值范围为 [0, UIntNative.Max]。
返回值:
- CString - 截取的子串。
异常:
- IndexOutOfBoundsException - 如果 beginIndex 大于字符串长度,抛出异常。
- IllegalMemoryException - 如果内存申请失败或内存拷贝失败时,抛出异常。
示例:
main() {
let index: UIntNative = 2
let len: UIntNative = 2
var str1: CString = unsafe { LibC.mallocCString("hello") }
var str2: CString = str1.subCString(index, len)
println(str2)
unsafe {
LibC.free(str1)
LibC.free(str2)
}
}
运行结果:
ll
func toString()
public func toString(): String
功能:将 CString 类型转为仓颉的 String 类型。
返回值:
- String - 转换后的字符串。
异常:
- IllegalArgumentException - 不合法的 UTF-8 字节序列。
示例:
main() {
var str1: CString = unsafe { LibC.mallocCString("hello") }
println(str1.toString())
unsafe {
LibC.free(str1)
}
}
运行结果:
hello
Float16
功能:表示 16 位浮点数,符合 IEEE 754 中的半精度格式(binary16)。
extend Float16
extend Float16
功能:拓展半精度浮点数以支持一些数学常数。
static prop Inf
public static prop Inf: Float16
功能:获取半精度浮点数的无穷数。
类型:Float16
static prop Max
public static prop Max: Float16
功能:获取半精度浮点数的最大值。
类型:Float16
static prop Min
public static prop Min: Float16
功能:获取半精度浮点数的最小值。
类型:Float16
static prop MinDenormal
public static prop MinDenormal: Float16
功能:获取半精度浮点数的最小次正规数。最小的正的次正规数是以 IEEE 双精度格式表示的最小正数。
类型:Float16
static prop MinNormal
public static prop MinNormal: Float16
功能:获取半精度浮点数的最小正规数。
类型:Float16
static prop NaN
public static prop NaN: Float16
功能:获取半精度浮点数的非数。
类型:Float16
static func max(Float16, Float16, Array<Float16>)
public static func max(a: Float16, b: Float16, others: Array<Float16>): Float16
功能:返回一组Float16中的最大值,此函数的第三个参数是一个变长参数,可以获取二个以上的Float16最大值,如果参数中有 NaN,该函数会返回 NaN。
参数:
返回值:
- Float16 - 返回参数中的最大值。
static func min(Float16, Float16, Array<Float16>)
public static func min(a: Float16, b: Float16, others: Array<Float16>): Float16
功能:返回一组Float16中的最小值,此函数的第三个参数是一个变长参数,可以获取二个以上的Float16最小值,如果参数中有 NaN,该函数会返回 NaN。
参数:
返回值:
- Float16 - 返回参数中的最小值。
func isInf()
public func isInf(): Bool
功能:判断某个浮点数 Float16 是否为无穷数值。
返回值:
func isNaN()
public func isNaN(): Bool
功能:判断某个浮点数 Float16 是否为非数值。
返回值:
func isNormal()
public func isNormal(): Bool
功能:判断某个浮点数 Float16 是否为常规数值。
返回值:
extend Float16 <: Comparable<Float16>
extend Float16 <: Comparable<Float16>
功能:为 Float16 类型扩展 Comparable<Float16> 接口,支持比较操作。
父类型:
func compare(Float16)
public func compare(rhs: Float16): Ordering
功能:判断当前 Float16 值与指定 Float16 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: Float16 = 0.12
var num2: Float16 = 0.234
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend Float16
extend Float16
功能:支持与 UInt16 互相转换。
static func fromBits(UInt16)
public static func fromBits(bits: UInt16): Float16
功能:将指定的 UInt16 数转换为 Float16 数。
参数:
- bits: UInt16 - 要转换的数字。
返回值:
- Float16 - 转换结果,其位与参数 bits 值相同。
示例:
main() {
let v = Float16.fromBits(0x4A40)
println(v)
}
运行结果:
12.500000
func toBits()
public func toBits(): UInt16
功能:将指定的 Float16 数转换为以位表示的对应 UInt16 数。
返回值:
示例:
main() {
println(12.5f16.toBits()) // 0x4A40 19008
}
运行结果:
19008
extend Float16 <: Hashable
extend Float16 <: Hashable
功能:为 Float16 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Float16 <: ToString
extend Float16 <: ToString
功能:为 Float16 类型其扩展 ToString 接口,实现向 String 类型的转换。默认保留 6 位小数。
父类型:
func toString()
public func toString(): String
功能:将 Float16 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Float32
功能:表示 32 位浮点数,符合 IEEE 754 中的单精度格式(binary32)。
extend Float32
extend Float32
功能:拓展单精度浮点数以支持一些数学常数。
static prop Inf
public static prop Inf: Float32
功能:获取单精度浮点数的无穷数。
类型:Float32
static prop Max
public static prop Max: Float32
功能:获取单精度浮点数的最大值。
类型:Float32
static prop Min
public static prop Min: Float32
功能:获取单精度浮点数的最小值。
类型:Float32
static prop MinDenormal
public static prop MinDenormal: Float32
功能:获取单精度浮点数的最小次正规数。
类型:Float32
static prop MinNormal
public static prop MinNormal: Float32
功能:获取单精度浮点数的最小正规数。
类型:Float32
static prop NaN
public static prop NaN: Float32
功能:获取单精度浮点数的非数。
类型:Float32
static func max(Float32, Float32, Array<Float32>)
public static func max(a: Float32, b: Float32, others: Array<Float32>): Float32
功能:返回一组Float32中的最大值,此函数的第三个参数是一个变长参数,可以获取二个以上的Float32最大值,如果参数中有 NaN,该函数会返回 NaN。
参数:
返回值:
- Float32 - 返回参数中的最大值。
static func min(Float32, Float32, Array<Float32>)
public static func min(a: Float32, b: Float32, others: Array<Float32>): Float32
功能:返回一组Float32中的最小值,此函数的第三个参数是一个变长参数,可以获取二个以上的Float32最小值,如果参数中有 NaN,该函数会返回 NaN。
参数:
返回值:
- Float32 - 返回参数中的最小值。
func isInf()
public func isInf(): Bool
功能:判断某个浮点数 Float32 是否为无穷数值。
返回值:
func isNaN()
public func isNaN(): Bool
功能:判断某个浮点数 Float32 是否为非数值。
返回值:
func isNormal()
public func isNormal(): Bool
功能:判断某个浮点数 Float32 是否为常规数值。
返回值:
extend Float32 <: Comparable<Float32>
extend Float32 <: Comparable<Float32>
功能:为 Float32 类型扩展 Comparable<Float32> 接口,支持比较操作。
父类型:
func compare(Float32)
public func compare(rhs: Float32): Ordering
功能:判断当前 Float32 值与指定 Float32 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: Float32 = 0.12
var num2: Float32 = 0.234
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend Float32
extend Float32
功能:支持与 UInt32 互相转换。
static func fromBits(UInt32)
public static func fromBits(bits: UInt32): Float32
功能:将指定的 UInt32 类型转换为 Float32 类型。
参数:
- bits: UInt32 - 要转换的数字。
返回值:
- Float32 - 转换结果,其位与参数 bits 值相同。
示例:
main() {
let v = Float16.fromBits(0x4A40u16)
println(v)
}
运行结果:
12.500000
func toBits()
public func toBits(): UInt32
功能:将指定的 Float32 数转换为以位表示的对应 UInt32 数。
返回值:
示例:
main() {
println(13.88f32.toBits()) // 0x415E147B 1096684667
}
运行结果:
1096684667
extend Float32 <: Hashable
extend Float32 <: Hashable
功能:为 Float32 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Float32 <: ToString
extend Float32 <: ToString
功能:为 Float32 类型其扩展 ToString 接口,实现向 String 类型的转换。默认保留 6 位小数。
父类型:
func toString()
public func toString(): String
功能:将 Float32 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Float64
功能:表示 64 位浮点数,符合 IEEE 754 中的双精度格式(binary64)。
extend Float64
extend Float64
功能:拓展双精度浮点数以支持一些数学常数。
static prop Inf
public static prop Inf: Float64
功能:获取双精度浮点数的无穷数。
类型:Float64
static prop Max
public static prop Max: Float64
功能:获取双精度浮点数的最大值。
类型:Float64
static prop Min
public static prop Min: Float64
功能:获取双精度浮点数的最小值。
类型:Float64
static prop MinDenormal
public static prop MinDenormal: Float64
功能:获取双精度浮点数的最小次正规数。
类型:Float64
static prop MinNormal
public static prop MinNormal: Float64
功能:获取双精度浮点数的最小正规数。
类型:Float64
static prop NaN
public static prop NaN: Float64
功能:获取双精度浮点数的非数。
类型:Float64
static func max(Float64, Float64, Array<Float64>)
public static func max(a: Float64, b: Float64, others: Array<Float64>): Float64
功能:返回一组Float64中的最大值,此函数的第三个参数是一个变长参数,可以获取二个以上的Float64最大值,如果参数中有 NaN,该函数会返回 NaN。
参数:
返回值:
- Float64 - 返回参数中的最大值。
static func min(Float64, Float64, Array<Float64>)
public static func min(a: Float64, b: Float64, others: Array<Float64>): Float64
功能:返回一组Float64中的最小值,此函数的第三个参数是一个变长参数,可以获取二个以上的Float64最小值,如果参数中有 NaN,该函数会返回 NaN。
参数:
返回值:
- Float64 - 返回参数中的最小值。
func isInf()
public func isInf(): Bool
功能:判断某个浮点数 Float64 是否为无穷数值。
返回值:
func isNaN()
public func isNaN(): Bool
功能:判断某个浮点数 Float64 是否为非数值。
返回值:
func isNormal()
public func isNormal(): Bool
功能:判断某个浮点数 Float64 是否为常规数值。
返回值:
extend Float64 <: Comparable<Float64>
extend Float64 <: Comparable<Float64>
功能:为 Float64 类型扩展 Comparable<Float64> 接口,支持比较操作。
父类型:
func compare(Float64)
public func compare(rhs: Float64): Ordering
功能:判断当前 Float64 值与指定 Float64 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: Float64 = 0.12
var num2: Float64 = 0.234
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend Float64
extend Float64
功能:支持与 UInt64 互相转换。
static func fromBits(UInt64)
public static func fromBits(bits: UInt64): Float64
功能:将指定的 UInt64 数转换为 Float64 数。
参数:
- bits: UInt64 - 要转换的数字。
返回值:
- Float64 - 转换结果,其位与参数 bits 值相同。
示例:
main() {
let v = Float64.fromBits(0x402BC28F5C28F5C3)
println(v)
}
运行结果:
13.880000
func toBits()
public func toBits(): UInt64
功能:将指定的 Float64 数转换为以位表示的对应 UInt64 数。
返回值:
示例:
main() {
println(13.88f64.toBits()) // 0x402BC28F5C28F5C3 4624003363408246211
}
运行结果:
4624003363408246211
extend Float64 <: Hashable
extend Float64 <: Hashable
功能:为 Float64 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Float64 <: ToString
extend Float64 <: ToString
功能:为 Float64 类型其扩展 ToString 接口,实现向 String 类型的转换。默认保留 6 位小数。
父类型:
func toString()
public func toString(): String
功能:将 Float64 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Int16
功能:表示 16 位有符号整型,表示范围为 [-2^{15}, 2^{15} - 1]。
extend Int16
extend Int16
功能:拓展 16 位有符号整数以支持一些数学常数。
static prop Max
public static prop Max: Int16
功能:获取 16 位有符号整数的最大值。
类型:Int16
static prop Min
public static prop Min: Int16
功能:获取 16 位有符号整数的最小值。
类型:Int16
extend Int16 <: Comparable<Int16>
extend Int16 <: Comparable<Int16>
功能:为 Int16 类型扩展 Comparable<Int16> 接口,支持比较操作。
父类型:
func compare(Int16)
public func compare(rhs: Int16): Ordering
功能:判断当前 Int16 值与指定 Int16 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: Int16 = 2
var num2: Int16 = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend Int16 <: Countable<Int16>
extend Int16 <: Countable<Int16>
功能:为 Int16 类型扩展 Countable<Int16> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): Int16
功能:获取在数轴上当前 Int16 位置往右移动 right 后对应位置的 Int16 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num1: Int16 = 32767
var num2: Int16 = 3
println(num1.next(5))
println(num2.next(10))
}
运行结果:
-32764
13
func position()
public func position(): Int64
功能:获取当前 Int16 值的位置信息,即将该 Int16 转换为 Int64 值。
返回值:
示例:
main() {
var num1: Int16 = 32767
var num2: Int16 = 3
println(num1.position())
println(num2.position())
}
运行结果:
32767
3
extend Int16 <: Hashable
extend Int16 <: Hashable
功能:为 Int16 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Int16 <: ToString
extend Int16 <: ToString
功能:这里为 Int16 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 Int16 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Int32
功能:表示 32 位有符号整型,表示范围为 [-2^{31}, 2^{31} - 1]。
extend Int32
extend Int32
功能:拓展 32 位有符号整数以支持一些数学常数。
static prop Max
public static prop Max: Int32
功能:获取 32 位有符号整数的最大值。
类型:Int32
static prop Min
public static prop Min: Int32
功能:获取 32 位有符号整数的最小值。
类型:Int32
extend Int32 <: Comparable<Int32>
extend Int32 <: Comparable<Int32>
功能:为 Int32 类型扩展 Comparable<Int32> 接口,支持比较操作。
父类型:
func compare(Int32)
public func compare(rhs: Int32): Ordering
功能:判断当前 Int32 值与指定 Int32 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: Int32 = 8
var num2: Int32 = 10
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend Int32 <: Countable<Int32>
extend Int32 <: Countable<Int32>
功能:为 Int32 类型扩展 Countable<Int32> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): Int32
功能:获取在数轴上当前 Int32 位置往右移动 right 后对应位置的 Int32 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: Int32 = 3
println(num.next(10))
}
运行结果:
13
func position()
public func position(): Int64
功能:获取当前 Int32 值的位置信息,即将该 Int32 转换为 Int64 值。
返回值:
示例:
main() {
var num: Int32 = 3
println(num.position())
}
运行结果:
3
extend Int32 <: Hashable
extend Int32 <: Hashable
功能:为 Int32 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Int32 <: ToString
extend Int32 <: ToString
功能:这里为 Int32 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 Int32 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Int64
功能:表示 64 位有符号整型,表示范围为 [-2^{63}, 2^{63} - 1]。
extend Int64
extend Int64
功能:拓展 64 位有符号整数以支持一些数学常数。
static prop Max
public static prop Max: Int64
功能:获取 64 位有符号整数的最大值。
类型:Int64
static prop Min
public static prop Min: Int64
功能:获取 64 位有符号整数的最小值。
类型:Int64
extend Int64 <: Comparable<Int64>
extend Int64 <: Comparable<Int64>
功能:为 Int64 类型扩展 Comparable<Int64> 接口,支持比较操作。
父类型:
func compare(Int64)
public func compare(rhs: Int64): Ordering
功能:判断当前 Int64 值与指定 Int64 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: Int64 = 2
var num2: Int64 = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend Int64 <: Countable<Int64>
extend Int64 <: Countable<Int64>
功能:为 Int64 类型扩展 Countable<Int64> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): Int64
功能:获取在数轴上当前 Int64 位置往右移动 right 后对应位置的 Int64 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: Int64 = 3
println(num.next(10))
}
运行结果:
13
func position()
public func position(): Int64
功能:获取当前 Int64 值的位置信息,即返回该 Int64 值本身。
返回值:
示例:
main() {
var num: Int64 = 3
println(num.position())
}
运行结果:
3
extend Int64 <: Hashable
extend Int64 <: Hashable
功能:为 Int64 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Int64 <: ToString
extend Int64 <: ToString
功能:这里为 Int64 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 Int64 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Int8
功能:表示 8 位有符号整型,表示范围为 [-2^7, 2^7 - 1]。
extend Int8
extend Int8
功能:拓展 8 位有符号整数以支持一些数学常数。
static prop Max
public static prop Max: Int8
功能:获取 8 位有符号整数的最大值。
类型:Int8
static prop Min
public static prop Min: Int8
功能:获取 8 位有符号整数的最小值。
类型:Int8
extend Int8 <: Comparable<Int8>
extend Int8 <: Comparable<Int8>
功能:为 Int8 类型扩展 Comparable<Int8> 接口,支持比较操作。
父类型:
func compare(Int8)
public func compare(rhs: Int8): Ordering
功能:判断当前 Int8 值与指定 Int8 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: Int8 = 2
var num2: Int8 = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend Int8 <: Countable<Int8>
extend Int8 <: Countable<Int8>
功能:为 Int8 类型扩展 Countable<Int8> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): Int8
功能:获取在数轴上当前 Int8 位置往右移动 right 后对应位置的 Int8 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: Int8 = 3
println(num.next(5))
}
运行结果:
8
func position()
public func position(): Int64
功能:获取当前 Int8 值的位置信息,即将该 Int8 转换为 Int64 值。
返回值:
示例:
main() {
var num: Int8 = 3
println(num.position())
}
运行结果:
3
extend Int8 <: Hashable
extend Int8 <: Hashable
功能:为 Int8 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Int8 <: ToString
extend Int8 <: ToString
功能:这里为 Int8 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 Int8 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
IntNative
功能:表示平台相关的有符号整型,其长度与当前系统的位宽一致。
extend IntNative
extend IntNative
功能:拓展平台相关有符号整数以支持一些数学常数。
static prop Max
public static prop Max: IntNative
功能:获取平台相关有符号整数的最大值。
类型:IntNative
static prop Min
public static prop Min: IntNative
功能:获取平台相关有符号整数的最小值。
类型:IntNative
extend IntNative <: Comparable<IntNative>
extend IntNative <: Comparable<IntNative>
功能:为 IntNative 类型扩展 Comparable<IntNative> 接口,支持比较操作。
父类型:
func compare(IntNative)
public func compare(rhs: IntNative): Ordering
功能:判断当前 IntNative 值与指定 IntNative 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: IntNative = 8
var num2: IntNative = 10
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend IntNative <: Countable<IntNative>
extend IntNative <: Countable<IntNative>
功能:为 IntNative 类型扩展 Countable<IntNative> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): IntNative
功能:获取在数轴上当前 IntNative 位置往右移动 right 后对应位置的 IntNative 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: IntNative = 8
println(num.next(4))
}
运行结果:
12
func position()
public func position(): Int64
功能:获取当前 IntNative 值的位置信息,即将该 IntNative 转换为 Int64 值。
返回值:
示例:
main() {
var num: IntNative = 8
println(num.position())
}
运行结果:
8
extend IntNative <: Hashable
extend IntNative <: Hashable
功能:为 IntNative 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend IntNative <: ToString
extend IntNative <: ToString
功能:这里为 IntNative 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 IntNative 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Rune
功能:表示 unicode 字符集中的字符。
表示范围为 Unicode scalar value,即从 \u{0000} 到 \u{D7FF},以及从 \u{E000} 到 \u{10FFF} 的字符。
extend Rune
extend Rune
功能:为 Rune 类型实现一系列扩展方法,主要为在 Ascii 字符集范围内的一些字符判断、转换等操作。
static func fromUtf8(Array<UInt8>, Int64)
public static func fromUtf8(arr: Array<UInt8>, index: Int64): (Rune, Int64)
功能:将字节数组中的指定元素,根据 UTF-8 编码规则转换成字符,并告知字符占用字节长度。
参数:
返回值:
异常:
- IllegalArgumentException - 不合法的 UTF-8 字节序列。
示例:
main() {
var arr: Array<UInt8> = [4u8, 8u8, 65u8] // A <=> 65
var tuple = Rune.fromUtf8(arr, 2)
println(tuple[0]) // Rune
println(tuple[1]) // len
}
运行结果:
A
1
static func getPreviousFromUtf8(Array<UInt8>, Int64)
public static func getPreviousFromUtf8(arr: Array<UInt8>, index: Int64): (Rune, Int64)
功能:获取字节数组中指定索引对应的字节所在的 UTF-8 编码字符,同时返回该字符首位字节码在数组中的索引。
当指定了一个索引,那么函数会找到数组对应索引位置并且根据 UTF-8 规则,查看该字节码是否是字符的首位字节码,如果不是就继续向前遍历,直到该字节码是首位字节码,然后利用字节码序列找到对应的字符。
参数:
返回值:
异常:
- IllegalArgumentException - 如果找不到对应首位字节码,即指定字节所在位置的字节不符合 UTF-8 编码,抛出异常。
static func intoUtf8Array(Rune, Array<UInt8>, Int64)
public static func intoUtf8Array(c: Rune, arr: Array<UInt8>, index: Int64): Int64
功能:该函数会把字符转成字节码序列然后覆盖 Array 数组内指定位置的字节码。
参数:
返回值:
- Int64 - 字符的字节码长度,例如中文是三个字节码长度。
示例:
main() {
var arr: Array<UInt8> = [ 1u8, 2u8, 3u8, 230u8, 136u8, 145u8]
var len: Int64 = Rune.intoUtf8Array(r'爱', arr, 2)
println(len)
println(arr[2]) // 字符爱的utf-8编码的第一个字节
}
运行结果:
3
231
static func utf8Size(Array<UInt8>, Int64)
public static func utf8Size(arr: Array<UInt8>, index: Int64): Int64
功能:该函数会返回字节数组指定索引位置为起始的字符占用的字节数。
在 UTF-8 编码中,ASCII 码首位字节第一位不为 1,其他长度的字符首位字节开头 1 的个数表明了该字符对应的字节码长度,该函数通过扫描首位,判断字节码长度。如果索引对应的不是首位字节码,就会抛出异常。
参数:
返回值:
- Int64 - 字符的字节码长度,例如中文是三个字节码长度。
异常:
- IllegalArgumentException - 如果索引位置的字节码不符合首位字节码规则,会抛出异常。
示例:
main() {
var arr: Array<UInt8> = [ 1u8, 2u8, 231u8, 136u8, 177u8, 145u8]
var len: Int64 = Rune.utf8Size(arr, 2)
println(len) // 索引为2-4的数组元素为中文字符爱的utf-8编码,占用三字节
}
运行结果:
3
static func utf8Size(Rune)
public static func utf8Size(c: Rune): Int64
功能:返回字符对应的 UTF-8 编码的字节码长度,例如中文字符的字节码长度是 3。
参数:
- c: Rune - 待计算 UTF-8 字节码长度的字符。
返回值:
- Int64 - 字符的 UTF-8 字节码长度。
示例:
main() {
var char: Rune = r'爱'
var len: Int64 = Rune.utf8Size(char)
println(len) // 中文字符爱的utf-8编码,占用三字节
}
运行结果:
3
func isAscii()
public func isAscii(): Bool
功能:判断字符是否是 Ascii 中的字符。
返回值:
- Bool - 如果是 Ascii 字符返回 true,否则返回 false。
func isAsciiControl()
public func isAsciiControl(): Bool
功能:判断字符是否是 Ascii 控制字符。其取值范围为 [00, 1F] 和 {7F} 的并集。
返回值:
- Bool - 如果是 Ascii 控制字符返回 true,否则返回 false。
func isAsciiGraphic()
public func isAsciiGraphic(): Bool
功能:判断字符是否是 Ascii 图形字符。其取值范围为 [21, 7E]。
返回值:
- Bool - 如果是 Ascii 图形字符返回 true,否则返回 false。
func isAsciiHex()
public func isAsciiHex(): Bool
功能:判断字符是否是 Ascii 十六进制字符。
返回值:
- Bool - 如果是 Ascii 十六进制字符返回 true,否则返回 false。
func isAsciiLetter()
public func isAsciiLetter(): Bool
功能:判断字符是否是 Ascii 字母字符。
返回值:
- Bool - 如果是 Ascii 字母字符返回 true,否则返回 false。
func isAsciiLowerCase()
public func isAsciiLowerCase(): Bool
功能:判断字符是否是 Ascii 小写字符。
返回值:
- Bool - 如果是 Ascii 小写字符返回 true,否则返回 false。
func isAsciiNumber()
public func isAsciiNumber(): Bool
功能:判断字符是否是 Ascii 数字字符。
返回值:
- Bool - 如果是 Ascii 数字字符返回 true,否则返回 false。
func isAsciiNumberOrLetter()
public func isAsciiNumberOrLetter(): Bool
功能:判断字符是否是 Ascii 数字或拉丁字母字符。
返回值:
- Bool - 如果是 Ascii 数字或拉丁字母字符返回 true,否则返回 false。
func isAsciiOct()
public func isAsciiOct(): Bool
功能:判断字符是否是 Ascii 八进制字符。
返回值:
- Bool - 如果是 Ascii 八进制字符返回 true,否则返回 false。
func isAsciiPunctuation()
public func isAsciiPunctuation(): Bool
功能:判断字符是否是 Ascii 标点符号字符。其取值范围为 [21, 2F]、[3A, 40]、[5B, 60] 和 [7B, 7E] 的并集。
返回值:
- Bool - 如果是 Ascii 标点符号字符返回 true,否则返回 false。
func isAsciiUpperCase()
public func isAsciiUpperCase(): Bool
功能:判断字符是否是 Ascii 大写字符。
返回值:
- Bool - 如果是 Ascii 大写字符返回 true,否则返回 false。
func isAsciiWhiteSpace()
public func isAsciiWhiteSpace(): Bool
功能:判断字符是否是 Ascii 空白字符。其取值范围为 [09, 0D] 和 {20} 的并集。
返回值:
- Bool - 如果是 Ascii 空白字符返回 true,否则返回 false。
func toAsciiLowerCase()
public func toAsciiLowerCase(): Rune
功能:将字符转换为 Ascii 小写字符,如果无法转换则保持现状。
返回值:
func toAsciiUpperCase()
public func toAsciiUpperCase(): Rune
功能:将字符转换为 Ascii 大写字符,如果无法转换则保持现状。
返回值:
extend Rune <: Comparable<Rune>
extend Rune <: Comparable<Rune>
功能:为 Rune 类型扩展 Comparable<Rune> 接口,支持比较操作。
父类型:
func compare(Rune)
public func compare(rhs: Rune): Ordering
功能:判断当前 Rune 实例与指定 Rune 实例的大小关系。
Rune 的大小关系指的是它们对应的 unicode 码点的大小关系。
参数:
返回值:
示例:
main() {
var char1: Rune = r'i'
var char2: Rune = r'j'
println(char1.compare(char2))
}
运行结果:
Ordering.LT
extend Rune <: Countable<Rune>
extend Rune <: Countable<Rune>
功能:为 Rune 类型扩展 Countable<Rune> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): Rune
功能:获取当前 Rune 值往右数 right 后所到位置的 Rune 值。
参数:
- right: Int64 - 往右数的个数。
返回值:
异常:
- OverflowException - 如果与 Int64 数进行加法运算后为不合法的 Unicode 值,抛出异常。
func position()
public func position(): Int64
功能:获取当前 Rune 值的位置信息,即将该 Rune 转换为 Int64 值。
返回值:
extend Rune <: Hashable
extend Rune <: Hashable
功能:为 Rune 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend Rune <: ToString
extend Rune <: ToString
功能:这里为 Rune 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 Rune 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
UInt16
功能:表示 16 位无符号整型,表示范围为 [0, 2^{16} - 1]。
extend UInt16
extend UInt16
功能:拓展 16 位无符号整数以支持一些数学常数。
static prop Max
public static prop Max: UInt16
功能:获取 16 位无符号整数的最大值。
类型:UInt16
static prop Min
public static prop Min: UInt16
功能:获取 16 位无符号整数的最小值。
类型:UInt16
extend UInt16 <: Comparable<UInt16>
extend UInt16 <: Comparable<UInt16>
功能:为 UInt16 类型扩展 Comparable<UInt16> 接口,支持比较操作。
父类型:
func compare(UInt16)
public func compare(rhs: UInt16): Ordering
功能:判断当前 UInt16 值与指定 UInt16 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: UInt16 = 2
var num2: UInt16 = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend UInt16 <: Countable<UInt16>
extend UInt16 <: Countable<UInt16>
功能:为 UInt16 类型扩展 Countable<UInt16> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): UInt16
功能:获取在数轴上当前 UInt16 位置往右移动 right 后对应位置的 UInt16 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: UInt16 = 3
println(num.next(10))
}
运行结果:
13
func position()
public func position(): Int64
功能:获取当前 UInt16 值的位置信息,即将该 UInt16 转换为 Int64 值。
返回值:
示例:
main() {
var num: UInt16 = 8
println(num.position())
}
运行结果:
8
extend UInt16 <: Hashable
extend UInt16 <: Hashable
功能:为 UInt16 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend UInt16 <: ToString
extend UInt16 <: ToString
功能:这里为 UInt16 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 UInt16 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
UInt32
功能:表示 32 位无符号整型,表示范围为 [0, 2^{32} - 1]。
extend UInt32
extend UInt32
功能:拓展 32 位无符号整数以支持一些数学常数。
static prop Max
public static prop Max: UInt32
功能:获取 32 位无符号整数的最大值。
类型:UInt32
static prop Min
public static prop Min: UInt32
功能:获取 32 位无符号整数的最小值。
类型:UInt32
extend UInt32 <: Comparable<UInt32>
extend UInt32 <: Comparable<UInt32>
功能:为 UInt32 类型扩展 Comparable<UInt32> 接口,支持比较操作。
父类型:
func compare(UInt32)
public func compare(rhs: UInt32): Ordering
功能:判断当前 UInt32 值与指定 UInt32 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: UInt32 = 2
var num2: UInt32 = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend UInt32 <: Countable<UInt32>
extend UInt32 <: Countable<UInt32>
功能:为 UInt32 类型扩展 Countable<UInt32> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): UInt32
功能:获取在数轴上当前 UInt32 位置往右移动 right 后对应位置的 UInt32 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: UInt32 = 3
println(num.next(10))
}
运行结果:
13
func position()
public func position(): Int64
功能:获取当前 UInt32 值的位置信息,即将该 UInt32 转换为 UInt64 值。
返回值:
示例:
main() {
var num: UInt32 = 8
println(num.position())
}
运行结果:
8
extend UInt32 <: Hashable
extend UInt32 <: Hashable
功能:为 UInt32 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend UInt32 <: ToString
extend UInt32 <: ToString
功能:这里为 UInt32 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 UInt32 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
UInt64
功能:表示 64 位无符号整型,表示范围为 [0, 2^{64} - 1]。
extend UInt64
extend UInt64
功能:拓展 64 位无符号整数以支持一些数学常数。
static prop Max
public static prop Max: UInt64
功能:获取 64 位无符号整数的最大值。
类型:UInt64
static prop Min
public static prop Min: UInt64
功能:获取 64 位无符号整数的最小值。
类型:UInt64
extend UInt64 <: Comparable<UInt64>
extend UInt64 <: Comparable<UInt64>
功能:为 UInt64 类型扩展 Comparable<UInt64> 接口,支持比较操作。
父类型:
func compare(UInt64)
public func compare(rhs: UInt64): Ordering
功能:判断当前 UInt64 值与指定 UInt64 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: UInt64 = 2
var num2: UInt64 = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend UInt64 <: Countable<UInt64>
extend UInt64 <: Countable<UInt64>
功能:为 UInt64 类型扩展 Countable<UInt64> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): UInt64
功能:获取在数轴上当前 UInt64 位置往右移动 right 后对应位置的 UInt64 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: UInt64 = 3
println(num.next(10))
}
运行结果:
13
func position()
public func position(): Int64
功能:获取当前 UInt64 值的位置信息,即将该 UInt64 转换为 Int64 值。
返回值:
示例:
main() {
var num: UInt64 = 8
println(num.position())
}
运行结果:
8
extend UInt64 <: Hashable
extend UInt64 <: Hashable
功能:为 UInt64 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend UInt64 <: ToString
extend UInt64 <: ToString
功能:这里为 UInt64 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 UInt64 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
UInt8
功能:表示 8 位无符号整型,表示范围为 [0, 2^8 - 1]。
extend UInt8
extend UInt8
功能:拓展 8 位无符号整数以支持一些数学常数。
static prop Max
public static prop Max: UInt8
功能:获取 8 位无符号整数的最大值。
类型:UInt8
static prop Min
public static prop Min: UInt8
功能:获取 8 位无符号整数的最小值。
类型:UInt8
extend UInt8 <: Comparable<UInt8>
extend UInt8 <: Comparable<UInt8>
功能:为 UInt8 类型扩展 Comparable<UInt8> 接口,支持比较操作。
父类型:
func compare(UInt8)
public func compare(rhs: UInt8): Ordering
功能:判断当前 UInt8 值与指定 UInt8 值的大小关系。
参数:
返回值:
示例:
main() {
var num1: UInt8 = 2
var num2: UInt8 = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend UInt8 <: Countable<UInt8>
extend UInt8 <: Countable<UInt8>
功能:为 UInt8 类型扩展 Countable<UInt8> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): UInt8
功能:获取在数轴上当前 UInt8 位置往右移动 right 后对应位置的 UInt8 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
示例:
main() {
var num: UInt8 = 3
println(num.next(10))
}
运行结果:
13
func position()
public func position(): Int64
功能:获取当前 UInt8 值的位置信息,即将该 UInt8 转换为 Int64 值。
返回值:
示例:
main() {
var num: UInt8 = 8
println(num.position())
}
运行结果:
8
extend UInt8 <: Hashable
extend UInt8 <: Hashable
功能:为 UInt8 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend UInt8 <: ToString
extend UInt8 <: ToString
功能:这里为 UInt8 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 UInt8 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
UIntNative
功能:表示平台相关的无符号整型,其长度与当前系统的位宽一致。
extend UIntNative
extend UIntNative
功能:拓展平台相关无符号整数以支持一些数学常数。
static prop Max
public static prop Max: UIntNative
功能:获取平台相关无符号整数的最大值。
类型:UIntNative
static prop Min
public static prop Min: UIntNative
功能:获取平台相关无符号整数的最小值。
类型:UIntNative
extend UIntNative <: Comparable<UIntNative>
extend UIntNative <: Comparable<UIntNative>
功能:为 UIntNative 类型扩展 Comparable<UIntNative> 接口,支持比较操作。
父类型:
func compare(UIntNative)
public func compare(rhs: UIntNative): Ordering
功能:判断当前 UIntNative 值与指定 UIntNative 值的大小关系。
参数:
- rhs: UIntNative - 待比较的另一个 UIntNative 值。
返回值:
示例:
main() {
var num1: UIntNative = 2
var num2: UIntNative = 3
println(num1.compare(num2))
}
运行结果:
Ordering.LT
extend UIntNative <: Countable
extend UIntNative <: Countable<UIntNative>
功能:为 UIntNative 类型扩展 Countable<UIntNative> 接口,支持计数操作。
父类型:
func next(Int64)
public func next(right: Int64): UIntNative
功能:获取在数轴上当前 UIntNative 位置往右移动 right 后对应位置的 UIntNative 值。如果值溢出,则会从数轴最左边继续移动。
参数:
- right: Int64 - 往右数的个数。
返回值:
- UIntNative - 往右数
right后所到位置的 UIntNative 值。
示例:
main() {
var num: UIntNative = 3
println(num.next(10))
}
运行结果:
13
func position()
public func position(): Int64
功能:获取当前 UIntNative 值的位置信息,即将该 UIntNative 转换为 Int64 值。
返回值:
- Int64 - 当前 UIntNative 值的位置信息。
示例:
main() {
var num: UIntNative = 8
println(num.position())
}
运行结果:
8
extend UIntNative <: Hashable
extend UIntNative <: Hashable
功能:为 UIntNative 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend UIntNative <: ToString
extend UIntNative <: ToString
功能:这里为 UIntNative 类型扩展 ToString 接口,实现向 String 类型的转换。
父类型:
func toString()
public func toString(): String
功能:将 UIntNative 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
Unit
功能:表示仓颉语言中只关心副作用而不关心值的表达式的类型。
例如,print 函数、赋值表达式、复合赋值表达式、自增和自减表达式、循环表达式,它们的类型都是 Unit。
Unit 类型只有一个值,也是它的字面量:()。除了赋值、判等和判不等外,Unit 类型不支持其他操作。
extend Unit <: Equatable<Unit>
extend Unit <: Equatable<Unit>
功能:为 Unit 类型扩展 Equatable<Unit> 接口。
父类型:
extend Unit <: Hashable
extend Unit <: Hashable
功能:为 Unit 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值,Unit 的哈希值为 0。
返回值:
- Int64 - 哈希值。
extend Unit <: ToString
extend Unit <: ToString
功能:为 Unit 类型其扩展 ToString 接口,实现向 String 类型的转换。
Unit 的字符串表示是 "()"。
父类型:
func toString()
public func toString(): String
功能:将 Unit 值转换为可输出的字符串。
返回值:
- String - 转化后的字符串。
接口
interface Any
public interface Any
功能:Any 是所有类型的父类型,所有 interface 都默认继承它,所有非 interface 类型都默认实现它。
extend Byte
extend Byte
功能:为 Byte 类型实现一系列扩展方法,主要为在 Ascii 字符集范围内的一些字符判断、转换等操作。
func isAscii()
public func isAscii(): Bool
功能:判断 Byte 是否是在 Ascii 范围内。
返回值:
func isAsciiControl()
public func isAsciiControl(): Bool
功能:判断 Byte 是否是在 Ascii 控制字符范围内。其取值范围为 [00, 1F] 和 {7F} 的并集。
返回值:
func isAsciiGraphic()
public func isAsciiGraphic(): Bool
功能:判断 Byte 是否是在 Ascii 图形字符范围内。其取值范围为 [21, 7E]。
返回值:
func isAsciiHex()
public func isAsciiHex(): Bool
功能:判断 Byte 是否是在 Ascii 十六进制数字范围内。
返回值:
func isAsciiLetter()
public func isAsciiLetter(): Bool
功能:判断 Byte 是否是在 Ascii 拉丁字母范围内。
返回值:
func isAsciiLowerCase()
public func isAsciiLowerCase(): Bool
功能:判断 Byte 是否是在 Ascii 小写拉丁字母范围内。
返回值:
func isAsciiNumber()
public func isAsciiNumber(): Bool
功能:判断 Byte 是否是在 Ascii 十进制数字范围内。
返回值:
func isAsciiNumberOrLetter()
public func isAsciiNumberOrLetter(): Bool
功能:判断 Byte 是否是在 Ascii 十进制数字和拉丁字母范围内。
返回值:
func isAsciiOct()
public func isAsciiOct(): Bool
功能:判断 Byte 是否是在 Ascii 八进制数字范围内。
返回值:
func isAsciiPunctuation()
public func isAsciiPunctuation(): Bool
功能:判断 Byte 是否是在 Ascii 标点符号范围内。其取值范围为 [21, 2F]、[3A, 40]、[5B, 60] 和 [7B, 7E] 的并集。
返回值:
func isAsciiUpperCase()
public func isAsciiUpperCase(): Bool
功能:判断 Byte 是否是在 Ascii 大写拉丁字母范围内。
返回值:
func isAsciiWhiteSpace()
public func isAsciiWhiteSpace(): Bool
功能:判断 Byte 是否是在 Ascii 空白字符范围内。其取值范围为 [09, 0D] 和 {20} 的并集。
返回值:
func toAsciiLowerCase()
public func toAsciiLowerCase(): Byte
功能:将 Byte 换为对应的 Ascii 小写字符 Byte,如果无法转换则保持现状。
返回值:
func toAsciiUpperCase()
public func toAsciiUpperCase(): Byte
功能:将 Byte 换为对应的 Ascii 大写字符 Byte,如果无法转换则保持现状。
返回值:
interface CType
sealed interface CType
功能:表示支持与 C 语言互操作的接口。
CType 接口是一个语言内置的空接口,它是 CType 约束的具体实现,所有 C 互操作支持的类型都隐式地实现了该接口,因此所有 C 互操作支持的类型都可以作为 CType 类型的子类型使用。
注意:
示例:
@C
struct Data {}
@C
func foo() {}
main() {
var c: CType = Data() // ok
c = 0 // ok
c = true // ok
c = CString(CPointer<UInt8>()) // ok
c = CPointer<Int8>() // ok
c = foo // ok
}
interface Collection<T>
public interface Collection<T> <: Iterable<T> {
prop size: Int64
func isEmpty(): Bool
func toArray(): Array<T>
}
功能:该接口用来表示集合,通常容器类型应该实现该接口。
父类型:
- Iterable<T>
prop size
prop size: Int64
功能:获取当前集合的大小,即集合中元素的个数。
类型:Int64
func isEmpty()
func isEmpty(): Bool
功能:判断当前集合是否为空。
返回值:
- Bool - 如果为空返回 true,否则返回 false。
func toArray()
func toArray(): Array<T>
功能:将当前集合转为数组类型。
返回值:
- Array<T> - 转换得到的数组。
interface Comparable<T>
public interface Comparable<T> <: Equatable<T> & Less<T> & Greater<T> & LessOrEqual<T> & GreaterOrEqual<T> {
func compare(that: T): Ordering
operator func <(rhs: T): Bool
operator func <=(rhs: T): Bool
operator func ==(rhs: T): Bool
operator func >(rhs: T): Bool
operator func >=(rhs: T): Bool
}
功能:该接口表示比较运算,是等于、不等于、小于、大于、小于等于、大于等于接口的集合体。
该接口中提供运算符 ==、!=、<、<=、>、>= 重载的默认实现,默认实现根据 compare 函数的返回值来确定其返回值。例如:如果 a.compare(b) 的返回值为 EQ,则 a == b 返回 true,否则返回 false。
父类型:
- Equatable<T>
- Less<T>
- Greater<T>
- LessOrEqual<T>
- GreaterOrEqual<T>
func compare(T)
func compare(that: T): Ordering
功能:判断当前 T 类型实例与参数指向的 T 类型实例的大小关系。
参数:
- that: T - 待与当前实例比较的另一个实例。
返回值:
operator func <(T)
operator func <(rhs: T): Bool
功能:判断当前 T 类型实例是否小于参数指向的 T 类型实例,该函数是此接口的一个默认实现函数。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果小于,返回 true,否则返回 false。
operator func <=(T)
operator func <=(rhs: T): Bool
功能:判断当前 T 类型实例是否小于等于参数指向的 T 类型实例,该函数是此接口的一个默认实现函数。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果小于等于,返回 true,否则返回 false。
operator func ==(T)
operator func ==(rhs: T): Bool
功能:判断两个实例是否相等,该函数是此接口的一个默认实现函数。
参数:
- rhs: T - 待比较的另一个实例。
返回值:
- Bool - 如果相等,返回 true,否则返回 false。
operator func >(T)
operator func >(rhs: T): Bool
功能:判断当前 T 类型实例是否大于参数指向的 T 类型实例,该函数是此接口的一个默认实现函数。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果大于,返回 true,否则返回 false。
operator func >=(T)
operator func >=(rhs: T): Bool
功能:判断当前 T 类型实例是否大于等于参数指向的 T 类型实例,该函数是此接口的一个默认实现函数。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果大于等于,返回 true,否则返回 false。
interface Countable<T>
public interface Countable<T> {
func next(right: Int64): T
func position(): Int64
}
功能:该接口表示类型可数。
可数类型的每一个实例都对应一个位置信息(Int64 值),可以通过往后数数得到其他的该类型实例。
func next(Int64)
func next(right: Int64): T
功能:获取当前实例向右移动 right 后对应位置的 T 类型实例。
参数:
- right: Int64 - 往右数的个数。
返回值:
- T - 向右移动
right后对应位置的T类型实例。
func position()
func position(): Int64
功能:获取当前可数实例的位置信息,即将当前实例转为 Int64 类型。
返回值:
extend Float64
extend Float64
功能:拓展了 Float64 类型作为左操作数和 Duration 类型作为右操作数的乘法运算。
operator func *(Duration)
public operator func *(r: Duration): Duration
功能:实现 Float64 类型和 Duration 类型的乘法,即 Float64 * Duration 运算。
参数:
返回值:
异常:
- ArithmeticException - 当相乘后的结果超出 Duration 的表示范围时,抛出异常。
extend Int64
extend Int64
功能:拓展了 Int64 类型作为左操作数和 Duration 类型作为右操作数的乘法运算。
operator func *(Duration)
public operator func *(r: Duration): Duration
功能:实现 Int64 类型和 Duration 类型的乘法,即 Int64 * Duration 运算。
例如 2 * Duration.second 返回表示时间间隔为 2 秒的 Duration 实例。
参数:
- r: Duration - 乘法的右操作数。
返回值:
异常:
- ArithmeticException - 当相乘后的结果超出 Duration 的表示范围时,抛出异常。
interface Equal<T>
public interface Equal<T> {
operator func ==(rhs: T): Bool
}
功能:该接口用于支持判等操作。
operator func ==(T)
operator func ==(rhs: T): Bool
功能:判断两个实例是否相等。
参数:
- rhs: T - 待比较的另一个实例。
返回值:
- Bool - 如果相等,返回 true,否则返回 false。
interface Equatable<T>
public interface Equatable<T> <: Equal<T> & NotEqual<T> {
operator func !=(rhs: T): Bool
}
功能:该接口是判等和判不等两个接口的集合体。
该接口中提供运算符 != 重载的默认实现,默认实现根据 == 运算的返回值来确定其返回值。例如:如果 a == b 的返回值为 true,则 a != b 返回 false,否则返回 true。
已为部分仓颉类型实现该接口,包括:Unit、Bool 、Rune、Int64、Int32、Int16、Int8、UIntNative、UInt64、UInt32、UInt16、UInt8、Float64、Float32、Float16、String、Array、Box、ArrayList、HashSet。
父类型:
operator func !=(T)
operator func !=(rhs: T): Bool
功能:判断两个实例是否不相等,该函数是此接口的一个默认实现函数。
参数:
- rhs: T - 待比较的另一个实例。
返回值:
- Bool - 如果不相等,返回 true,否则返回 false。
interface GreaterOrEqual<T>
public interface GreaterOrEqual<T> {
operator func >=(rhs: T): Bool
}
功能:该接口表示大于等于计算。
operator func >=(T)
operator func >=(rhs: T): Bool
功能:判断当前 T 类型实例是否大于等于参数指向的 T 类型实例。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果大于等于,返回 true,否则返回 false。
interface Greater<T>
public interface Greater<T> {
operator func >(rhs: T): Bool
}
功能:该接口表示大于计算。
operator func >(T)
operator func >(rhs: T): Bool
功能:判断当前 T 类型实例是否大于参数指向的 T 类型实例。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果大于,返回 true,否则返回 false。
interface Hashable
public interface Hashable {
func hashCode(): Int64
}
功能:该接口用于计算哈希值。
已为部分仓颉类型实现该接口,包括:Bool、Rune、IntNative、Int64、Int32、Int16、Int8、UIntNative、UInt64、UInt32、UInt16、UInt8、Float64、Float32、Float16、String、Box。
func hashCode()
func hashCode(): Int64
功能:获得实例类型的哈希值。
返回值:
- Int64 - 返回实例类型的哈希值。
interface Hasher
public interface Hasher {
func finish(): Int64
mut func reset(): Unit
mut func write(value: Bool): Unit
mut func write(value: Rune): Unit
mut func write(value: Int8): Unit
mut func write(value: Int16): Unit
mut func write(value: Int32): Unit
mut func write(value: Int64): Unit
mut func write(value: UInt8): Unit
mut func write(value: UInt16): Unit
mut func write(value: UInt32): Unit
mut func write(value: UInt64): Unit
mut func write(value: Float16): Unit
mut func write(value: Float32): Unit
mut func write(value: Float64): Unit
mut func write(value: String): Unit
}
功能:该接口用于处理哈希组合运算。
可以使用一系列 write 函数传入不同数据类型实例,并计算它们的组合哈希值。
func finish()
func finish(): Int64
功能:获取哈希运算的结果。
返回值:
- Int64 - 经过计算后的哈希值。
func reset()
mut func reset(): Unit
功能:重置哈希值到 0。
func write(Bool)
mut func write(value: Bool): Unit
功能:把想要哈希运算的 Bool 值传入,然后进行哈希组合运算。
参数:
- value: Bool - 待运算的值。
func write(Float16)
mut func write(value: Float16): Unit
功能:通过该函数把想要哈希运算的 Float16 值传入,然后进行哈希组合运算。
参数:
- value: Float16 - 待运算的值。
func write(Float32)
mut func write(value: Float32): Unit
功能:通过该函数把想要哈希运算的 Float32 值传入,然后进行哈希组合运算。
参数:
- value: Float32 - 待运算的值。
func write(Float64)
mut func write(value: Float64): Unit
功能:通过该函数把想要哈希运算的 Float64 值传入,然后进行哈希组合运算。
参数:
- value: Float64 - 待运算的值。
func write(Int16)
mut func write(value: Int16): Unit
功能:通过该函数把想要哈希运算的 Int16 值传入,然后进行哈希组合运算。
参数:
- value: Int16 - 待运算的值。
func write(Int32)
mut func write(value: Int32): Unit
功能:通过该函数把想要哈希运算的 Int32 值传入,然后进行哈希组合运算。
参数:
- value: Int32 - 待运算的值。
func write(Int64)
mut func write(value: Int64): Unit
功能:通过该函数把想要哈希运算的 Int64 值传入,然后进行哈希组合运算。
参数:
- value: Int64 - 待运算的值。
func write(Int8)
mut func write(value: Int8): Unit
功能:通过该函数把想要哈希运算的 Int8 值传入,然后进行哈希组合运算。
参数:
- value: Int8 - 待运算的值。
func write(Rune)
mut func write(value: Rune): Unit
功能:通过该函数把想要哈希运算的 Rune 值传入,然后进行哈希组合运算。
参数:
- value: Rune - 待运算的值。
func write(String)
mut func write(value: String): Unit
功能:通过该函数把想要哈希运算的 String 值传入,然后进行哈希组合运算。
参数:
- value: String - 待运算的值。
func write(UInt16)
mut func write(value: UInt16): Unit
功能:通过该函数把想要哈希运算的 UInt16 值传入,然后进行哈希组合运算。
参数:
- value: UInt16 - 待运算的值。
func write(UInt32)
mut func write(value: UInt32): Unit
功能:通过该函数把想要哈希运算的 UInt32 值传入,然后进行哈希组合运算。
参数:
- value: UInt32 - 待运算的值。
func write(UInt64)
mut func write(value: UInt64): Unit
功能:通过该函数把想要哈希运算的 UInt64 值传入,然后进行哈希组合运算。
参数:
- value: UInt64 - 待运算的值。
func write(UInt8)
mut func write(value: UInt8): Unit
功能:通过该函数把想要哈希运算的 UInt8 值传入,然后进行哈希组合运算。
参数:
- value: UInt8 - 待运算的值。
interface Iterable<E>
public interface Iterable<E> {
func iterator(): Iterator<E>
}
功能:该接口表示可迭代,实现了该接口的类型(通常为容器类型)可以在 for-in 语句中实现迭代,也可以获取其对应的迭代器类型实例,调用 next 函数实现迭代。
本包已经为 Array、ArrayList、HashMap 等基础容器类型实现了该接口,用户可以为其他类型实现该接口,使之支持迭代遍历的功能。
func iterator()
func iterator(): Iterator<E>
功能:获取迭代器。
返回值:
- Iterator<E> - 迭代器。
interface LessOrEqual<T>
public interface LessOrEqual<T> {
operator func <=(rhs: T): Bool
}
功能:该接口表示小于等于计算。
operator func <=(T)
operator func <=(rhs: T): Bool
功能:判断当前 T 类型实例是否小于等于参数指向的 T 类型实例。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果小于等于,返回 true,否则返回 false。
interface Less<T>
public interface Less<T> {
operator func <(rhs: T): Bool
}
功能:该接口表示小于计算。
operator func <(T)
operator func <(rhs: T): Bool
功能:判断当前 T 类型实例是否小于参数指向的 T 类型实例。
参数:
- rhs: T - 待与当前实例比较的另一个实例。
返回值:
- Bool - 如果小于,返回 true,否则返回 false。
interface NotEqual<T>
public interface NotEqual<T> {
operator func !=(rhs: T): Bool
}
功能:该接口用于支持判不等操作。
operator func !=(T)
operator func !=(rhs: T): Bool
功能:判断两个实例是否不相等。
参数:
- rhs: T - 待比较的另一个实例。
返回值:
- Bool - 如果不相等,返回 true,否则返回 false。
interface Resource
public interface Resource {
func close(): Unit
func isClosed(): Bool
}
功能:该接口用于资源管理,通常用于内存、句柄等资源的关闭和释放。
实现了该接口的类型可以在 try-with-resource 语法上下文中实现自动资源释放。
func isClosed()
func isClosed(): Bool
功能:判断资源是否已经关闭。
返回值:
- Bool - 如果已经关闭返回 true,否则返回 false。
func close()
func close(): Unit
功能:关闭资源。
interface ThreadContext
public interface ThreadContext {
func end(): Unit
func hasEnded(): Bool
}
功能:仓颉线程上下文接口。
用户创建 thread 时,除了缺省 spawn 表达式入参,也可以通过传入不同 ThreadContext 类型的实例,选择不同的线程上下文,然后一定程度上控制并发行为。
目前不允许用户自行实现 ThreadContext 接口,仓颉语言根据使用场景,提供了 MainThreadContext, 具体定义可在终端框架库中查阅。
注意:
在 cjvm 后端,
spawn传入 ThreadContext 类型的参数时,无任何作用。
func end()
func end(): Unit
功能:结束方法,用于向当前 context 发送结束请求。
func hasEnded()
func hasEnded(): Bool
功能:检查方法,用于检查当前 context 是否已结束。
返回值:
- Bool - 如果结束返回 true,否则返回 false。
interface ToString
public interface ToString {
func toString(): String
}
功能:该接口用来提供具体类型的字符串表示。
func toString()
func toString(): String
功能:获取实例类型的字符串表示。
返回值:
- String - 返回实例类型的字符串表示。
类
class ArrayIterator<T>
public class ArrayIterator<T> <: Iterator<T> {
public init(data: Array<T>)
}
功能:数组迭代器,迭代功能详述见 Iterable 和 Iterator 说明。
父类型:
- Iterator<T>
init(Array<T>)
public init(data: Array<T>)
功能:给定一个 Array 数组实例,创建其对应的迭代器,用来迭代遍历该数组实例中全部对象。
参数:
- data: Array<T> - 数组实例。
func next()
public func next(): Option<T>
功能:返回数组迭代器中的下一个值。
返回值:
示例:
main() {
var arr: Array<Int64> = [1, 2, 3, 4]
var arrIterator: ArrayIterator<Int64> = ArrayIterator(arr)
var num: Option<Int64>
while (true) {
num = arrIterator.next()
if (num.isNone()) {
break
}
println(num.getOrDefault({=> -1}))
}
}
运行结果:
1
2
3
4
class Box<T>
public class Box<T> {
public var value: T
public init(v: T)
}
功能:Box 类型提供了为其他类型添加一层 class 封装的能力。
如果 T 类型本身不具备引用能力,如 struct 类型,封装后 Box<T> 类型将可被引用。
var value
public var value: T
功能:获取或修改被包装的值。
类型:T
init(T)
public init(v: T)
功能:给定 T 类型实例,构造对应的 Box<T> 实例。
参数:
- v: T - 任意类型实例。
extend<T> Box<T> <: Comparable<Box<T>> where T <: Comparable<T>
extend<T> Box<T> <: Comparable<Box<T>> where T <: Comparable<T>
功能:为 Box<T> 类扩展 Comparable<Box<T>> 接口,提供比较大小的能力。
Box<T> 实例的大小关系与其封装的 T 实例大小关系相同。
父类型:
- Comparable<Box<T>>
func compare(Box<T>)
public func compare(that: Box<T>): Ordering
功能:判断当前 Box 实例与另一个 Box 实例的大小关系。
参数:
返回值:
示例:
struct Data <: Comparable<Data> {
var a: Int64 = 0
var b: Int64 = 0
public init(a: Int64, b: Int64) {
this.a = a
this.b = b
}
public func compare(d: Data) {
let tValue: Int64 = this.a + this.b
let dValue: Int64 = d.a + d.b
if (tValue > dValue) {
return Ordering.GT
} else if (tValue == dValue) {
return Ordering.EQ
} else {
return Ordering.LT
}
}
}
main() {
var data1: Box<Data> = Box<Data>(Data(12, 12))
var data2: Box<Data> = Box<Data>(Data(7, 12))
println(data1.compare(data2))
}
运行结果:
Ordering.GT
operator func !=(Box<T>)
public operator func !=(that: Box<T>): Bool
功能:比较 Box 对象是否不相等。
参数:
返回值:
operator func <(Box<T>)
public operator func <(that: Box<T>): Bool
功能:比较 Box 对象的大小。
参数:
返回值:
operator func <=(Box<T>)
public operator func <=(that: Box<T>): Bool
功能:比较 Box 对象的大小。
参数:
返回值:
operator func ==(Box<T>)
public operator func ==(that: Box<T>): Bool
功能:比较 Box 对象是否相等。
参数:
返回值:
operator func >(Box<T>)
public operator func >(that: Box<T>): Bool
功能:比较 Box 对象的大小。
参数:
返回值:
operator func >=(Box<T>)
public operator func >=(that: Box<T>): Bool
功能:比较 Box 对象的大小。
参数:
返回值:
extend<T> Box<T> <: Hashable where T <: Hashable
extend<T> Box<T> <: Hashable where T <: Hashable
功能:为 Box<T> 类扩展 Hashable 接口,提供比较大小的能力。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取 Box 对象的哈希值。
实际上该值为 Box 中封装的 T 类型实例的哈希值。
返回值:
extend<T> Box<T> <: ToString where T <: ToString
extend<T> Box<T> <: ToString where T <: ToString
功能:为 Box<T> 类型扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:获取 Box 对象的字符串表示,字符串内容为当前实例封装的 T 类型实例的字符串表示。
返回值:
- String - 转换后的字符串。
class Future<T>
public class Future<T>
功能:Future<T> 实例代表一个仓颉线程任务,可用于获取仓颉线程的计算结果,向仓颉线程发送取消信号。
spawn 表达式的返回类型是 Future<T>,其中 T 的类型取决于 spawn 表达式中的闭包的返回值类型。
prop thread
public prop thread: Thread
功能:获得对应仓颉线程的 Thread 实例。
类型:Thread
func cancel()
public func cancel(): Unit
功能:给当前 Future 实例对应的仓颉线程发送取消请求。该方法不会立即停止线程执行,仅发送请求,相应地,Thread 类的函数 hasPendingCancellation 可用于检查线程是否存在取消请求,开发者可以通过该检查来自行决定是否提前终止线程以及如何终止线程。
示例:
main(): Unit {
/* 创建线程 */
let future = spawn {
while (true) {
if (Thread.currentThread.hasPendingCancellation) {
return 0
}
}
return 1
}
/* 向线程发送取消请求 */
future.cancel()
let res = future.get()
println(res)
}
运行结果:
0
func get()
public func get(): T
功能:阻塞当前线程,等待并获取当前 Future<T> 对象对应的线程的结果。
返回值:
- T - 当前 Future<T> 实例代表的线程运行结束后的返回值。
示例:
main(): Int64 {
let fut: Future<Int64> = spawn {
=>
sleep(1000 * Duration.millisecond) /* 睡眠 1 秒 */
return 1
}
/* 等待线程完成 */
let result: Int64 = fut.get()
println(result)
return 0
}
运行结果:
1
func get(Duration)
public func get(timeout: Duration): T
功能:阻塞当前线程,等待指定时长并获取当前 Future<T> 对象对应的线程的返回值。
需指定等待的超时时间,如果相应的线程在指定时间内未完成执行,则该函数将抛出异常TimeoutException。如果 timeout <= Duration.Zero,等同于 get(),即不限制等待时长。如果线程抛出异常退出执行,在 get 调用处将继续抛出该异常。
参数:
- timeout: Duration - 等待时间。
返回值:
- T - 返回指定时长后仓颉线程执行结果。
异常:
- TimeoutException - 如果相应的线程在指定时间内未完成执行,则该函数将抛出此异常。
示例:
main(): Int64 {
let fut: Future<Int64> = spawn {
=>
sleep(1000 * Duration.millisecond) /* 睡眠 1 秒 */
return 1
}
let result: Int64 = fut.get(2000 * Duration.millisecond)
/* 最大等待时间为 2 秒, 超过该时间抛出 TimeoutException */
println(result)
return 0
}
运行结果:
1
func tryGet()
public func tryGet(): Option<T>
功能:尝试获取执行结果,不会阻塞当前线程。如果相应的线程未完成,则该函数返回 None。
返回值:
- Option<T> - 如果当前仓颉线程未完成返回
None,否则返回执行结果。
示例:
main(): Int64 {
let fut: Future<Int64> = spawn {
=>
sleep(1000 * Duration.millisecond) /* 睡眠 1 秒 */
return 1
}
/* 主线程等待 4 秒,保证创建线程已经完成 */
sleep(4000 * Duration.millisecond)
/* 尝试获取创建线程的运行结果 */
let result: Option<Int64> = fut.tryGet()
println(result)
return 0
}
运行结果:
Some(1)
class Iterator<T>
public abstract class Iterator<T> <: Iterable<T>
功能:该类表示迭代器,提供 next 方法支持对容器内的成员进行迭代遍历。
父类型:
- Iterable<T>
func iterator()
public func iterator() : Iterator<T>
功能:返回迭代器自身。
返回值:
- Iterator<T> - 迭代器自身。
func next()
public func next(): Option<T>
功能:获取迭代过程中的下一个元素。
返回值:
- Option<T> - 迭代过程中的下一个元素。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
var iter = arr.iterator() /* 获取容器的迭代器对象 */
while (true) { /* 使用迭代器进行遍历 */
match (iter.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
1
2
3
4
5
extend<T> Iterator<T>
extend<T> Iterator<T>
功能:扩展 Iterator<T> 类型。
迭代器的方法主要包含中间操作和终止操作。中间操作(如 skip()、map())会产生一个新的迭代器。而终止操作(如 count()、all())会根据迭代器产生的元素计算结果,而不产生新的迭代器。每种迭代器方法都会消耗迭代器中不同数量的元素,详见各方法描述。
func all((T) -> Bool)
public func all(predicate: (T)-> Bool): Bool
功能:判断迭代器所有元素是否都满足条件。此方法会重复获取并消耗迭代器中元素直到某个元素不满足条件。
参数:
- predicate: (T) -> Bool - 给定的条件。
返回值:
- Bool - 元素是否都满足条件。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取容器的迭代器对象 */
var iter = arr.iterator()
var flag: Bool = iter.all({v: Int64 => v > 0})
println(flag)
return 0
}
运行结果:
true
func any((T) -> Bool)
public func any(predicate: (T)-> Bool): Bool
功能:判断迭代器是否存在任意一个满足条件的元素。此方法会重复获取并消耗迭代器中元素直到某个元素满足条件。
参数:
- predicate: (T) -> Bool - 给定的条件。
返回值:
- Bool - 是否存在任意满足条件的元素。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取容器的迭代器对象 */
var iter = arr.iterator()
var flag: Bool = iter.any({v: Int64 => v > 4})
println(flag)
return 0
}
运行结果:
true
func at(Int64)
public func at(n: Int64): Option<T>
功能:获取当前迭代器第 n 个元素,n 从 0 开始计数。此方法会消耗指定元素前的所有元素(包括指定元素)。
参数:
- n: Int64 - 给定的元素序号,序号从 0 开始。
返回值:
- Option<T> - 返回对应位置元素,若 n 大于剩余元素数量则返回 None。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取容器的迭代器对象 */
var iter = arr.iterator()
var num: Option<Int64> = iter.at(2)
println(num)
return 0
}
运行结果:
Some(3)
func concat(Iterator<T>)
public func concat(other: Iterator<T>): Iterator<T>
功能:串联两个迭代器,当前迭代器在先,参数表示的迭代器在后。
参数:
- other: Iterator<T> - 要串联在后面的迭代器。
返回值:
- Iterator<T> - 返回串联后的新迭代器。
示例:
main(): Int64 {
var arr1: Array<Int64> = [1, 2]
var arr2: Array<Int64> = [3, 4]
/* 获取容器的迭代器对象 */
var iter1 = arr1.iterator()
var iter2 = arr2.iterator()
/* 合并两个迭代器 */
var iter = iter1.concat(iter2)
/* 使用迭代器进行遍历 */
while (true) {
match (iter.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
1
2
3
4
func count()
public func count(): Int64
功能:统计当前迭代器包含元素数量。此方法会消耗迭代器中所有元素来计算迭代器中的元素数量。
注意:
该方法会消耗迭代器,即使用该方法后迭代器内不再包含任何元素。
返回值:
- Int64 - 返回迭代器包含元素数量。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2]
/* 获取容器的迭代器对象 */
var iter = arr.iterator()
let len: Int64 = iter.count()
println(len)
/* 使用迭代器进行遍历,但是count消耗了迭代器中的元素,因此不会打印 */
while (true) {
match (iter.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
2
func enumerate()
public func enumerate(): Iterator<(Int64, T)>
功能:用于获取带索引的迭代器。
返回值:
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2]
/* 获取容器的迭代器对象 */
var iter = arr.iterator()
var iter1 = iter.enumerate()
/* 使用迭代器进行遍历 */
while (true) {
match (iter1.next()) {
case Some(i) =>
print(i[0].toString() + ' ')
print(i[1])
println()
case None => break
}
}
return 0
}
运行结果:
0 1
1 2
func filter((T) -> Bool)
public func filter(predicate: (T)-> Bool): Iterator<T>
功能:筛选出满足条件的元素。
参数:
- predicate: (T) -> Bool - 给定的条件,条件为
true的元素会按顺序出现在返回的迭代器里。
返回值:
- Iterator<T> - 返回一个新迭代器。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取过滤后的迭代器对象 */
var iter = arr.iterator()
var iter1 = iter.filter({value: Int64 => value > 2})
/* 使用迭代器进行遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
3
4
5
func filterMap<R>((T) -> Option<R>)
public func filterMap<R>(transform: (T) -> Option<R>): Iterator<R>
功能:同时进行筛选操作和映射操作,返回一个新的迭代器。
参数:
- transform: (T) -> Option<T> - 给定的映射函数。函数返回值为 Some 对应 filter 的 predicate 为 true,反之表示 false。
返回值:
- Iterator<R> - 返回一个新迭代器。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取过滤后的迭代器对象,对元素进行过滤和映射,映射需返回Option类型 */
var iter = arr.iterator()
var iter1 = iter.filterMap({
value: Int64 => if (value > 2) {
return Some(value + 1)
} else {
return None<Int64>
}
})
/* 使用迭代器进行遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
4
5
6
func first()
public func first(): Option<T>
功能:获取当前迭代器的头部元素。此方法会获取并消耗第一个元素。
返回值:
- Option<T> - 返回头部元素,若为空则返回 None。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取迭代器对象 */
var iter = arr.iterator()
var head: Option<Int64> = iter.first()
println(head)
return 0
}
运行结果:
Some(1)
func flatMap<R>((T) -> Iterator<R>)
public func flatMap<R>(transform: (T) -> Iterator<R>): Iterator<R>
功能:创建一个带 flatten 功能的映射。
参数:
- transform: (T) -> Iterable<R> - 给定的映射函数。
返回值:
示例:
main(): Int64 {
var arr: Array<Array<Int64>> = [[1], [2], [3], [4, 5]]
/* 获取带flatten功能的迭代器对象 */
var iter = arr.iterator()
var iter1 = iter.flatMap({value => value.iterator()})
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
1
2
3
4
5
func fold<R>(R, (R, T) -> R)
public func fold<R>(initial: R, operation: (R, T)->R): R
功能:使用指定初始值,从左向右计算。此方法会消耗迭代器中的所有元素。
参数:
- initial: R - 给定的 R 类型的初始值。
- operation: (R, T) -> R - 给定的计算函数。
返回值:
- R - 返回最终计算得到的值。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取迭代器对象,对数组元素进行求和 */
var iter = arr.iterator()
var sum: Int64 = iter.fold(0, {total, value => total + value})
println(sum)
return 0
}
运行结果:
15
func forEach((T) -> Unit)
public func forEach(action: (T)-> Unit): Unit
功能:遍历当前迭代器所有元素,对每个元素执行给定的操作。此方法会消耗迭代器中的所有元素。
参数:
- action: (T) -> Unit - 给定的操作函数。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
var iter = arr.iterator()
iter.forEach({value => println(value)})
return 0
}
运行结果:
1
2
3
4
5
func inspect((T) -> Unit)
public func inspect(action: (T) -> Unit): Iterator<T>
功能:迭代器每次调用 next() 对当前元素执行额外操作(不会消耗迭代器中元素)。
参数:
- action: (T) -> Unit - 给定的操作函数。
返回值:
- Iterator<T> - 返回一个新迭代器。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2]
/* 获取迭代器对象,并为next函数附加额外操作 */
var iter = arr.iterator()
var iter1 = iter.inspect({value => println("Logging: Processing ${value}")})
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println("Processing ${i} !")
case None => break
}
}
return 0
}
运行结果:
Logging: Processing 1
Processing 1 !
Logging: Processing 2
Processing 2 !
func intersperse(T)
public func intersperse(separator: T): Iterator<T>
功能:迭代器每两个元素之间插入一个给定的新元素。
参数:
- separator: T - 给定的元素。
返回值:
- Iterator<T> - 返回一个新迭代器。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2]
/* 获取迭代器对象,每两个元素之间插入一个0 */
var iter = arr.iterator()
var iter1 = iter.intersperse(0)
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
1
0
2
func isEmpty()
public func isEmpty(): Bool
功能:判断当前迭代器是否为空。此方法会调用 next() ,根据其返回值判断当前迭代器是否为空。因此如果当前迭代器不为空,则会消耗一个元素。
返回值:
- Bool - 返回当前迭代器是否为空。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2]
/* 获取迭代器对象 */
var iter = arr.iterator()
/* 判断迭代器中是否有元素,如果有会消耗一个元素 */
println(iter.isEmpty())
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter.next()) {
case Some(i) => println(i)
case None => break
}
}
println(iter.isEmpty())
return 0
}
运行结果:
false
2
true
func last()
public func last(): Option<T>
功能:获取当前迭代器尾部元素。此方法会获取并消耗迭代器中的所有元素,并返回最后一个元素。
返回值:
- Option<T> - 返回尾部元素,若为空则返回 None。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2]
/* 获取迭代器对象 */
var iter = arr.iterator()
println(iter.last())
return 0
}
运行结果:
Some(2)
func map<R>((T) -> R)
public func map<R>(transform: (T)-> R): Iterator<R>
功能:创建一个映射。
参数:
- transform: (T) ->R - 给定的映射函数。
返回值:
- Iterator<R> - 返回一个映射。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4]
/* 获取迭代器对象,并对元素进行映射,获取新的迭代器对象 */
var iter = arr.iterator()
var iter1 = iter.map({value => value * 2})
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
2
4
6
8
func none((T) -> Bool)
public func none(predicate: (T)-> Bool): Bool
功能:判断当前迭代器中所有元素是否都不满足条件。此方法会重复获取并消耗迭代器中元素直到某个元素满足条件。
参数:
- predicate: (T) -> Bool - 给定的条件。
返回值:
- Bool - 当前迭代器中元素是否都不满足条件。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4]
/* 获取迭代器对象,并对元素进行映射,获取新的迭代器对象 */
var iter1 = arr.iterator()
var iter2 = arr.iterator()
/* 存在元素大于2,返回false */
var flag1: Bool = iter1.none({value => value > 2})
println(flag1)
/* 不存在元素大于5,返回true */
var flag2: Bool = iter2.none({value => value > 5})
println(flag2)
return 0
}
运行结果:
false
true
func reduce((T, T) -> T)
public func reduce(operation: (T, T) -> T): Option<T>
功能:使用第一个元素作为初始值,从左向右计算。此方法会消耗迭代器中的所有元素。
参数:
- operation: (T, T) -> T - 给定的计算函数。
返回值:
- Option<T> - 返回计算结果。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取迭代器对象,对数组元素进行求和 */
var iter = arr.iterator()
var sum: Option<Int64> = iter.reduce({total, value => total + value})
println(sum)
return 0
}
运行结果:
Some(15)
func skip(Int64)
public func skip(count: Int64): Iterator<T>
功能:从前往后从当前迭代器跳过特定个数。
当 count 小于 0 时,抛出异常。当 count 等于 0 时,相当没有跳过任何元素,返回原迭代器。当 count 大于0并且count小于迭代器的大小时,跳过 count 个元素后,返回含有剩下的元素的新迭代器。当 count 大于等于迭代器的大小时,跳过所有元素,返回空迭代器。
参数:
- count: Int64 - 要跳过的个数。
返回值:
- Iterator<T> - 返回一个跳过指定数量元素的迭代器。
异常:
- IllegalArgumentException - 当 count < 0 时,抛出异常。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取迭代器对象,跳过前两个元素 */
var iter = arr.iterator()
var iter1 = iter.skip(2)
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
3
4
5
func step(Int64)
public func step(count: Int64): Iterator<T>
功能:迭代器每次调用 next() 跳过特定个数。
当 count 小于等于 0 时,抛出异常。当 count 大于 0 时,每次调用 next() 跳过 count 次,直到迭代器为空。
参数:
- count: Int64 - 每次调用 next() 要跳过的个数。
返回值:
- Iterator<T> - 返回一个新迭代器,这个迭代器每次调用 next() 会跳过特定个数。
异常:
- IllegalArgumentException - 当 count <= 0 时,抛出异常。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取迭代器对象,每次调用 next() 会跳过两个元素 */
var iter = arr.iterator()
var iter1 = iter.step(2)
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
1
3
5
func take(Int64)
public func take(count: Int64): Iterator<T>
功能:从当前迭代器取出特定个数。
从前往后取出当前迭代器特定个数的元素。当 count 小于 0 时,抛出异常。当 count 等于 0 时,不取元素,返回空迭代器。当 count 大于 0 小于迭代器的大小时,取前 count 个元素,返回新迭代器。当 count 大于等于迭代器的大小时,取所有元素,返回原迭代器。
参数:
- count: Int64 - 要取出的个数。
返回值:
- Iterator<T> - 返回一个取出指定数量元素的迭代器。
异常:
- IllegalArgumentException - 当 count < 0 时,抛出异常。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4, 5]
/* 获取迭代器对象,取出前三个元素 */
var iter = arr.iterator()
var iter1 = iter.take(3)
/* 使用迭代器进行展开遍历 */
while (true) {
match (iter1.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
1
2
3
func zip<R>(Iterator<R>)
public func zip<R>(it: Iterator<R>): Iterator<(T, R)>
功能:将两个迭代器合并成一个(长度取决于短的那个迭代器)。
参数:
- it: Iterator<R> - 要合并的其中一个迭代器。
返回值:
- Iterator<(T, R)> - 返回一个新迭代器。
示例:
main(): Int64 {
var arr1: Array<Int64> = [1, 2, 3, 4]
var arr2: Array<Int64> = [4, 5, 6]
/* 获取迭代器对象并合并,新迭代器中的元素为对应索引位置元素的元组 */
var iter1 = arr1.iterator()
var iter2 = arr2.iterator()
var iter = iter1.zip(iter2)
/* 使用迭代器进行遍历,长度取决于较短的迭代器 */
while (true) {
match (iter.next()) {
case Some(i) => println("The current element is (${i[0]}, ${i[1]}) ")
case None => break
}
}
return 0
}
运行结果:
The current element is (1, 4)
The current element is (2, 5)
The current element is (3, 6)
extend<T> Iterator<T> where T <: Comparable<T>
extend<T> Iterator<T> where T <: Comparable<T>
功能:为 Iterator<T> 类型扩展 Comparable<T> 接口,支持比较操作。
func max()
public func max(): Option<T>
功能:筛选最大的元素。此方法会消耗迭代器中的所有元素。
返回值:
- Option<T> - 返回最大的元素,若为空则返回 None。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4]
/* 获取迭代器对象,使用 max() 求最大值 */
var iter = arr.iterator()
match(iter.max()) {
case Some(i)=> println(i)
case None=> println("None!")
}
return 0
}
运行结果:
4
func min()
public func min(): Option<T>
功能:筛选最小的元素。此方法会消耗迭代器中的所有元素。
返回值:
- Option<T> - 返回最小的元素,若为空则返回 None。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4]
/* 获取迭代器对象,使用 min() 求最小值 */
var iter = arr.iterator()
match(iter.min()) {
case Some(i)=> println(i)
case None=> println("None!")
}
return 0
}
运行结果:
1
extend<T> Iterator<T> where T <: Equatable<T>
extend<T> Iterator<T> where T <: Equatable<T>
功能:为 Iterator<T> 类型扩展 扩展 Equatable<T> 接口,支持判等操作。
func contains(T)
public func contains(element: T): Bool
功能:遍历所有元素,判断是否包含指定元素。此方法会重复获取并消耗迭代器中元素直到某个元素与参数 element 相等。
参数:
- element: T - 要查找的元素。
返回值:
- Bool - 是否包含指定元素。
示例:
main(): Int64 {
var arr: Array<Int64> = [1, 2, 3, 4]
/* 获取迭代器对象,查找是否包含元素 3 */
var iter = arr.iterator()
println(iter.contains(3))
/* 使用迭代器进行遍历,输出剩余元素 */
while (true) {
match (iter.next()) {
case Some(i) => println(i)
case None => break
}
}
return 0
}
运行结果:
true
4
class Object
public open class Object <: Any {
public const init()
}
功能:Object 是所有 class 的父类,所有 class 都默认继承它。Object 类中不包含任何成员,即 Object 是一个“空”的类。
父类型:
init()
public const init()
功能:构造一个 object 实例。
class RangeIterator<T> <: Iterator<T> where T <: Countable<T> & Comparable<T> & Equatable<T>
public class RangeIterator<T> <: Iterator<T> where T <: Countable<T> & Comparable<T> & Equatable<T>
功能:Range 类型的迭代器,迭代功能详述见 Iterable 和 Iterator 接口说明。
父类型:
- Iterator<T>
func next()
public func next(): Option<T>
功能:获取 Range 迭代器中的下一个值。
返回值:
class StackTraceElement
public open class StackTraceElement {
public let declaringClass: String
public let methodName: String
public let fileName: String
public let lineNumber: Int64
public init(declaringClass: String, methodName: String, fileName: String, lineNumber: Int64)
}
功能:表示一个异常堆栈的具体信息,包括异常发生的类名、函数名、文件名、行号。
let declaringClass
public let declaringClass: String
功能:获取异常发生的类名。
类型:String
let fileName
public let fileName: String
功能:获取异常发生的文件名。
类型:String
let lineNumber
public let lineNumber: Int64
功能:获取异常发生的行号。
类型:Int64
let methodName
public let methodName: String
功能:获取异常发生的函数名。
类型:String
init(String, String, String, Int64)
public init(declaringClass: String, methodName: String, fileName: String, lineNumber: Int64)
功能:构造一个异常堆栈实例,指定类名、函数名、文件名、行号。
参数:
- declaringClass: String - 类名。
- methodName: String - 函数名。
- fileName: String - 文件名。
- lineNumber: Int64 - 行号。
class StringBuilder
public class StringBuilder <: ToString {
public init()
public init(str: String)
public init(r: Rune, n: Int64)
public init(value: Array<Rune>)
public init(capacity: Int64)
}
功能:该类主要用于字符串的构建。
StringBuilder 在字符串的构建上效率高于 String:
- 在功能上支持传入多个类型的值,该类将自动将其转换为 String 类型对象,并追加到构造的字符串中。
- 在性能上使用动态扩容算法,减少内存申请频率,构造字符串的速度更快,占用内存资源通常更少。
注意:
StringBuilder 仅支持 UTF-8 编码的字符数据。
父类型:
prop capacity
public prop capacity: Int64
功能:获取 StringBuilder 实例此时能容纳字符串的长度,该值会随扩容的发生而变大。
类型:Int64
prop size
public prop size: Int64
功能:获取 StringBuilder 实例中字符串长度。
类型:Int64
init()
public init()
功能:构造一个初始容量为 32 的空 StringBuilder 实例。
init(Array<Rune>)
public init(value: Array<Rune>)
功能:使用参数 value 指定的字符数组初始化一个 StringBuilder 实例,该实例的初始容量为 value 大小,初始内容为 value 包含的字符内容。
参数:
- value: Array<Rune> - 初始化 StringBuilder 实例的字符数组。
init(Int64)
public init(capacity: Int64)
功能:使用参数 capacity 指定的容量初始化一个空 StringBuilder 实例,该实例的初始容量为 value 大小,初始内容为若干 \0 字符。
参数:
- capacity: Int64 - 初始化 StringBuilder 的字节容量,取值范围为 (0, Int64.Max]。
异常:
- IllegalArgumentException - 当参数
capacity的值小于等于 0 时,抛出异常。
init(Rune, Int64)
public init(r: Rune, n: Int64)
功能:使用 n 个 r 字符初始化 StringBuilder 实例,该实例的初始容量为 n,初始内容为 n 个 r 字符。
参数:
- r: Rune - 初始化 StringBuilder 实例的字符。
- n: Int64 - 字符
r的数量,取值范围为 [0, Int64.Max]。
异常:
- IllegalArgumentException - 当参数
n小于 0 时,抛出异常。
init(String)
public init(str: String)
功能:根据指定初始字符串构造 StringBuilder 实例,该实例的初始容量为指定字符串的大小,初始内容为指定字符串。
参数:
- str: String - 初始化 StringBuilder 实例的字符串。
func append(Array<Rune>)
public func append(runeArr: Array<Rune>): Unit
功能:在 StringBuilder 末尾插入一个 Rune 数组中所有字符。
参数:
- runeArr: Array<Rune> - 插入的
Rune数组。
func append<T>(Array<T>) where T <: ToString
public func append<T>(val: Array<T>): Unit where T <: ToString
功能:在 StringBuilder 末尾插入参数 val 指定的 Array<T> 的字符串表示,类型 T 需要实现 ToString 接口。
参数:
func append(Bool)
public func append(b: Bool): Unit
功能:在 StringBuilder 末尾插入参数 b 的字符串表示。
参数:
func append(CString)
public func append(cstr: CString): Unit
功能:在 StringBuilder 末尾插入参数 cstr 指定 CString 中的内容。
参数:
func append(Float16)
public func append(n: Float16): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(Float32)
public func append(n: Float32): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(Float64)
public func append(n: Float64): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(Int16)
public func append(n: Int16): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(Int32)
public func append(n: Int32): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(Int64)
public func append(n: Int64): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(Int8)
public func append(n: Int8): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(Rune)
public func append(r: Rune): Unit
功能:在 StringBuilder 末尾插入参数 r 指定的字符。
参数:
- r: Rune - 插入的字符。
func append(String)
public func append(str: String): Unit
功能:在 StringBuilder 末尾插入参数 str 指定的字符串。
参数:
- str: String - 插入的字符串。
func append(StringBuilder)
public func append(sb: StringBuilder): Unit
功能:在 StringBuilder 末尾插入参数 sb 指定的 StringBuilder 中的内容。
参数:
- sb: StringBuilder - 插入的 StringBuilder 实例。
func append<T>(T) where T <: ToString
public func append<T>(v: T): Unit where T <: ToString
功能:在 StringBuilder 末尾插入参数 v 指定 T 类型的字符串表示,类型 T 需要实现 ToString 接口。
参数:
- v: T - 插入的
T类型实例。
func append(UInt16)
public func append(n: UInt16): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(UInt32)
public func append(n: UInt32): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(UInt64)
public func append(n: UInt64): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func append(UInt8)
public func append(n: UInt8): Unit
功能:在 StringBuilder 末尾插入参数 n 的字符串表示。
参数:
func appendFromUtf8(Array<Byte>)
public func appendFromUtf8(arr: Array<Byte>): Unit
功能:在 StringBuilder 末尾插入参数 arr 指向的字节数组。
该函数要求参数 arr 符合 UTF-8 编码,如果不符合,将抛出异常。
参数:
异常:
- IllegalArgumentException - 当字节数组不符合 utf8 编码规则时,抛出异常。
func appendFromUtf8Unchecked(Array<Byte>)
public unsafe func appendFromUtf8Unchecked(arr: Array<Byte>): Unit
功能:在 StringBuilder 末尾插入参数 arr 指向的字节数组。
相较于 appendFromUtf8 函数,它并没有针对于字节数组进行 UTF-8 相关规则的检查,所以它所构建的字符串并不一定保证是合法的,甚至出现非预期的异常,如果不是某些场景下的速度考虑,请优先使用安全的 appendFromUtf8 函数。
参数:
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:将 StringBuilder 扩容 additional 大小。
当 additional 小于等于零,或剩余容量大于等于 additional 时,不发生扩容;当剩余容量小于 additional 时,扩容至当前容量的 1.5 倍(向下取整)与 size + additional 的最大值。
参数:
- additional: Int64 - 指定 StringBuilder 的扩容大小。
func reset(Option<Int64>)
public func reset(capacity!: Option<Int64> = None): Unit
功能:清空当前 StringBuilder,并将容量重置为 capacity 指定的值。
参数:
- capacity!: Option<Int64> - 重置后 StringBuilder 实例的容量大小,取值范围为
None和 (Some(0),Some(Int64.Max)],默认值None表示采用默认大小容量(32)。
异常:
- IllegalArgumentException - 当参数
capacity的值小于等于 0 时,抛出异常。
func toString()
public func toString(): String
功能:获取 StringBuilder 实例中的字符串。
注意:
该函数不会将字符串数据进行拷贝。
返回值:
- String - StringBuilder 实例中的字符串。
class Thread
public class Thread
功能:获取线程 ID 及名字、查询线程是否存在取消请求、注册线程未处理异常的处理函数等。
该类型实例无法通过构造得到,仅能通过 Future 对象的 thread 属性或是 Thread 类的 currentThread 静态属性获取。
static prop currentThread
public static prop currentThread: Thread
功能:获取当前执行线程的 Thread 对象。
类型:Thread
prop hasPendingCancellation
public prop hasPendingCancellation: Bool
功能:线程是否存在取消请求,即是否通过 future.cancel() 发送过取消请求,常见使用方为 Thread.currentThread.hasPendingCancellation。
类型:Bool
prop id
public prop id: Int64
功能:获取当前执行线程的标识,以 Int64 表示,所有存活的线程都有不同标识,但不保证当线程执行结束后复用它的标识。
类型:Int64
prop name
public mut prop name: String
功能:获取或设置线程的名称,获取设置都具有原子性。
类型:String
static func handleUncaughtExceptionBy((Thread, Exception) -> Unit)
public static func handleUncaughtExceptionBy(exHandler: (Thread, Exception) -> Unit): Unit
功能:注册线程未处理异常的处理函数。
当某一线程因异常而提前终止后,如果全局的未处理异常函数被注册,那么将调用该函数并结束线程,在该函数内抛出异常时,将向终端打印提示信息并结束线程,但不会打印异常调用栈信息;如果没有注册全局异常处理函数,那么默认会向终端打印异常调用栈信息。
多次注册处理函数时,后续的注册函数将覆盖之前的处理函数。
当有多个线程同时因异常而终止时,处理函数将被并发执行,因而开发者需要在处理函数中确保并发正确性。
处理函数的参数第一个参数类型为 Thread,是发生异常的线程,第二个参数类型为 Exception,是线程未处理的异常。
参数:
class ThreadLocal<T>
public class ThreadLocal<T>
功能:该类表示仓颉线程局部变量。
和普通变量相比,线程局部变量有不同的访问语义。当多个线程共享使用同一线程局部变量时,每个线程都有各自的一份值拷贝。线程对变量的访问会读写线程本地的值,而不会影响其他线程中变量的值。
func get()
public func get(): ?T
功能:获得仓颉线程局部变量的值。
返回值:
- ?T - 如果当前线程局部变量不为空值,返回该值,如果为空值,返回
None。
func set(?T)
public func set(value: ?T): Unit
功能:通过 value 设置仓颉线程局部变量的值,如果传入 None,该局部变量的值将被删除,在线程后续操作中将无法获取。
参数:
- value: ?T - 需要设置的局部变量的值。
枚举
enum AnnotationKind
public enum AnnotationKind {
| Type
| Parameter
| Init
| MemberProperty
| MemberFunction
| MemberVariable
| EnumConstructor
| GlobalFunction
| GlobalVariable
| Extension
| ...
}
功能:表示自定义注解希望支持的位置。
EnumConstructor
EnumConstructor
功能:枚举构造器声明。
Extension
Extension
功能:扩展声明。
Init
Init
功能:构造函数声明。
GlobalFunction
GlobalFunction
功能:全局函数声明。
GlobalVariable
GlobalVariable
功能:全局变量声明。
MemberFunction
MemberFunction
功能:成员函数声明。
MemberProperty
MemberProperty
功能:成员属性声明。
MemberVariable
MemberVariable
功能:成员变量声明。
Parameter
Parameter
功能:成员函数/构造函数中的参数(不包括枚举构造器的参数)。
Type
Type
功能:类型声明(class、struct、enum、interface)。
enum Endian
public enum Endian {
| Big
| Little
}
功能:枚举类型 Endian 表示运行平台的端序,分为大端序和小端序。
Big
Big
功能:表示大端序。
Little
Little
功能:表示小端序。
static prop Platform
public static prop Platform: Endian
功能:获取所在运行平台的端序。
类型:Endian
异常:
- UnsupportedException - 当所运行平台返回的端序无法识别时,抛出异常。
示例:
main() {
let e = Endian.Platform
match (e) {
case Big => println("BigEndian")
case Little => println("LittleEndian")
}
}
运行结果:
LittleEndian
enum Option<T>
public enum Option<T> {
| Some(T)
| None
}
功能:Option<T> 是对 T 类型的封装,表示可能有值也可能无值。
它包含两个构造器:Some 和 None。其中,Some 会携带一个参数,表示有值;None 不带参数,表示无值。当需要表示某个类型可能有值,也可能没有值的时候,可选择使用 Option 类型。
Option 类型的另一种写法是在类型名前加 ?,即对于任意类型 Type,?Type 等价于 Option<Type>。
None
None
功能:构造一个不带参数的 Option<T> 实例,表示无值。
Some(T)
Some(T)
功能:构造一个携带参数的 Option<T> 实例,表示有值。
func filter((T)->Bool)
public func filter(predicate: (T) -> Bool): Option<T>
功能:提供 Option 类型的“过滤”功能。
参数:
- predicate: (T) -> Bool - 过滤函数。
返回值:
func flatMap<R>((T) -> Option<R>)
public func flatMap<R>(transform: (T) -> Option<R>): Option<R>
功能:提供从 Option<T> 类型到 Option<R> 类型的映射函数,如果当前实例值是 Some,执行 transform 函数,并且返回结果,否则返回 None。
参数:
- transform: (T) -> Option<R> - 映射函数。
返回值:
func getOrDefault(() -> T)
public func getOrDefault(other: () -> T): T
功能:获得值或返回默认值。如果 Option 值是 Some,则返回类型为 T 的实例,如果 Option 值是 None,则调用入参,返回类型 T 的值。
参数:
- other: () -> T - 默认函数,如果当前实例的值是 None,调用该函数得到类型为
T的实例,并将其返回。
返回值:
示例:
main() {
var value1: Option<Int64> = Some(2)
println(value1.getOrDefault({=> 0}))
var value2: Option<Int64> = None
println(value2.getOrDefault({=> 0}))
}
运行结果:
2
0
func getOrThrow(() -> Exception)
public func getOrThrow(exception: ()->Exception): T
功能:获得值或抛出指定异常。
参数:
返回值:
- T - 如果当前实例值是 Some<T>,返回类型为
T的实例。
异常:
func getOrThrow()
public func getOrThrow(): T
功能:获得值或抛出异常。
返回值:
- T - 如果当前实例值是 Some<T>,返回类型为
T的实例。
异常:
- NoneValueException - 如果当前实例是 None,抛出异常。
func isNone()
public func isNone(): Bool
功能:判断当前实例值是否为 None。
返回值:
func isSome()
public func isSome(): Bool
功能:判断当前实例值是否为 Some。
返回值:
func map<R>((T)->R)
public func map<R>(transform: (T)-> R): Option<R>
功能:提供从 Option<T> 类型到 Option<R> 类型的映射函数,如果当前实例值是 Some,执行 transform 函数,并且返回 Some 封装的结果,否则返回 None。
参数:
- transform: (T)-> R - 映射函数。
返回值:
extend<T> Option<T> <: Equatable<Option<T>> where T <: Equatable<T>
extend<T> Option<T> <: Equatable<Option<T>> where T <: Equatable<T>
功能:为 Option<T> 枚举扩展 Equatable<Option<T>> 接口,支持判等操作。
父类型:
operator func !=(Option<T>)
public operator func !=(that: Option<T>): Bool
功能:判断当前实例与参数指向的 Option<T> 实例是否不等。
参数:
返回值:
- Bool - 如果不相等,则返回 true,否则返回 false。
operator func ==(Option<T>)
public operator func ==(that: Option<T>): Bool
功能:判断当前实例与参数指向的 Option<T> 实例是否相等。
如果两者同为 None,则相等;如果两者为 Some(v1) 和 Some(v2),且 v1 和 v2 相等,则相等。
参数:
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
extend<T> Option<T> <: Hashable where T <: Hashable
extend<T> Option<T> <: Hashable where T <: Hashable
Some<T> 的哈希值等于 T 的值对应的哈希值,None 的哈希值等于 Int64(0)。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值。
返回值:
- Int64 - 哈希值。
extend<T> Option<T> <: ToString where T <: ToString
extend<T> Option<T> <: ToString where T <: ToString
功能:为 Option<T> 枚举实现 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将 Option 转换为可输出的字符串,字符串内容为 "Some(${T.toString()})" 或 "None"。
返回值:
- String - 转化后的字符串。
extend<T> Option<Option<T>>
extend<T> Option<Option<T>>
功能:为 Option<Option<T>> 类型扩展实现某些功能。
func flatten()
public func flatten(): Option<T>
功能:将 Option<Option<T>> 类型展开,如果当前实例是 Some(Option<T>.Some(v)), 展开后的结果为 Some(v)。
返回值:
enum Ordering
public enum Ordering {
| LT
| GT
| EQ
}
功能:Ordering 表示比较大小的结果,它包含三种情况:小于,大于和等于。
EQ
EQ
功能:构造一个 Ordering 实例,表示等于。
GT
GT
功能:构造一个 Ordering 实例,表示大于。
LT
LT
功能:构造一个 Ordering 实例,表示小于。
extend Ordering <: Comparable
extend Ordering <: Comparable<Ordering>
功能:为 Ordering 类型其扩展 Comparable<Ordering> 接口,支持比较操作。
父类型:
func compare(Ordering)
public func compare(that: Ordering): Ordering
功能:判断当前 Ordering 实例与参数指定的 Ordering 实例的大小关系。
Ordering 枚举的大小关系为:GT > EQ > LT。
参数:
返回值:
- Ordering - 如果大于,返回 GT;如果等于,返回 EQ;如果小于,返回 LT。
extend Ordering <: Hashable
extend Ordering <: Hashable
功能:为 Ordering 类型其扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode
public func hashCode(): Int64
功能:获取哈希值,GT 的哈希值是 3,EQ 的哈希值是 2,LT 的哈希值是 1。
返回值:
- Int64 - 哈希值。
extend Ordering <: ToString
extend Ordering <: ToString
功能:为 Ordering 类型其扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将 Ordering 转换为可输出的字符串。
转换结果如下:
返回值:
- String - 转化后的字符串。
结构体
struct Array<T>
public struct Array<T> {
public const init()
public init(size: Int64, repeat!: T)
public init(size: Int64, initElement: (Int64) -> T)
}
功能:仓颉数组类型,用来表示单一类型的元素构成的有序序列。
T 表示数组的元素类型,T 可以是任意类型。
prop first
public prop first: Option<T>
功能:获取当前数组的第一个元素,如果当前数组为空,返回 None。
类型:Option<T>
prop last
public prop last: Option<T>
功能:获取当前数组的最后一个元素,如果当前数组为空,返回 None。
类型:Option<T>
init()
public const init()
功能:构造一个空数组。
init(Int64, (Int64) -> T)
public init(size: Int64, initElement: (Int64) -> T)
功能:创建指定长度的数组,其中元素根据初始化函数计算获取。
即:将 [0, size) 范围内的值分别传入初始化函数 initElement,执行得到数组对应下标的元素。
参数:
异常:
- NegativeArraySizeException - 当 size 小于 0,抛出异常。
init(Int64, T)
public init(size: Int64, repeat!: T)
功能:构造一个指定长度的数组,其中元素都用指定初始值进行初始化。
注意:
该构造函数不会拷贝 repeat, 如果 repeat 是一个引用类型,构造后数组的每一个元素都将指向相同的引用。
参数:
异常:
- NegativeArraySizeException - 当 size 小于 0,抛出异常。
func clone()
public func clone(): Array<T>
功能:克隆数组,将对数组数据进行深拷贝。
返回值:
- Array<T> - 克隆得到的新数组。
func clone(Range<Int64>)
public func clone(range: Range<Int64>) : Array<T>
功能:克隆数组的指定区间。
注意:
参数:
返回值:
- Array<T> - 克隆得到的新数组。
异常:
- IndexOutOfBoundsException - range 超出数组范围时,抛出异常。
示例:
main() {
let arr = [0, 1, 2, 3, 4, 5]
let new = arr.clone(1..4)
println(new)
}
运行结果:
[1, 2, 3]
func concat(Array<T>)
public func concat(other: Array<T>): Array<T>
功能:该函数将创建一个新的数组,数组内容是当前数组后面串联 other 指向的数组。
参数:
- other: Array<T> - 串联到当前数组末尾的数组。
返回值:
- Array<T> - 串联得到的新数组。
示例:
main() {
let arr = [0, 1, 2, 3, 4, 5]
let new = arr.concat([6, 7, 8, 9, 10])
println(new)
}
运行结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
func copyTo(Array<T>)
public func copyTo(dst: Array<T>): Unit
功能:将当前数组的全部元素拷贝到目标数组 dst 中。
拷贝长度为当前数组的长度,从目标数组的起始位置开始写入,要求当前数组的长度不大于目标数组的长度。
参数:
- dst: Array<T> - 目标数组。
异常:
- IllegalArgumentException - 当前数组的长度大于目标数组的长度。
func copyTo(Array<T>, Int64, Int64, Int64)
public func copyTo(dst: Array<T>, srcStart: Int64, dstStart: Int64, copyLen: Int64): Unit
功能:将当前数组中的一段数据拷贝到目标数组中。
参数:
- dst: Array<T> - 目标数组。
- srcStart: Int64 - 从 this 数组的 srcStart 下标开始拷贝,取值范围为 [0, this.size)。
- dstStart: Int64 - 从目标数组的 dstStart 下标开始写入,取值范围为 [0, dst.size)。
- copyLen: Int64 - 拷贝数组的长度,取值要求为 copyLen + srcStart < this.size,copyLen + dstStart < dst.size。
异常:
- IllegalArgumentException - copyLen 小于 0 则抛出此异常。
- IndexOutOfBoundsException - 如果参数不满足上述取值范围,抛出此异常。
示例:
main() {
let arr = [0, 1, 2, 3, 4, 5]
let new = [0, 0, 0, 0, 0, 0]
arr.copyTo(new, 2, 2, 4)
println(new)
}
运行结果:
[0, 0, 2, 3, 4, 5]
func fill(T)
public func fill(value: T): Unit
功能:将当前数组内所有元素都替换成指定的 value。
参数:
- value: T - 修改的目标值。
示例:
main() {
let arr = [0, 1, 2]
arr[1..3].fill(-1)
println(arr)
}
运行结果:
[0, -1, -1]
func get(Int64)
public func get(index: Int64): Option<T>
功能:获取数组中下标 index 对应的元素。
该函数结果将用 Option 封装,如果 index 越界,将返回 None。
也可以通过 [] 操作符获取数组指定下标的元素,该接口将在 index 越界时抛出异常。
参数:
- index: Int64 - 要获取的值的下标。
返回值:
- Option<T> - 当前数组中下标 index 对应的值。
示例:
main() {
let arr = [0, 1, 2]
let num = arr.get(0)
println(num)
}
运行结果:
Some(0)
func map<R>((T)->R)
public func map<R>(transform: (T)->R): Array<R>
功能:将当前数组内所有 T 类型元素根据 transform 映射为 R 类型的元素,组成新的数组。
参数:
- transform: (T)->R - 映射函数。
返回值:
- Array<R> - 原数组中所有元素映射后得到的元素组成的新数组。
示例:
main(): Int64 {
let arr = [0, 1, 2]
let arr1 = arr.map({value => value + 1})
println(arr1)
return 0
}
运行结果:
[1, 2, 3]
func repeat(Int64)
public func repeat(n: Int64): Array<T>
功能:重复当前数组若干次,得到新数组。
参数:
- n: Int64 - 重复次数。
返回值:
- Array<T> - 重复当前数组 n 次得到的新数组。
异常:
- IllegalArgumentException - 参数 n 小于等于 0。
示例:
main(): Int64 {
let arr = [0, 1, 2]
var arr1 = arr.repeat(2)
println(arr1)
return 0
}
运行结果:
[0, 1, 2, 0, 1, 2]
func reverse()
public func reverse(): Unit
功能:反转数组,将数组中元素的顺序进行反转。
示例:
main() {
let arr = [0, 1, 2, 3, 4, 5]
arr.reverse()
println(arr)
}
运行结果:
[5, 4, 3, 2, 1, 0]
func slice(Int64, Int64)
public func slice(start: Int64, len: Int64): Array<T>
功能:获取数组切片。
注意:
切片不会对数组数据进行拷贝,是对原数据特定区间的引用。
参数:
返回值:
- Array<T> - 返回切片后的数组。
异常:
- IndexOutOfBoundsException - 如果参数不符合上述取值范围,抛出异常。
示例:
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "width: ${this.width}, height: ${this.height}"
}
}
main(): Int64 {
let arr = [Rectangle(1, 2), Rectangle(3, 4), Rectangle(5, 6)]
let arr1 = arr.slice(1, 2)
println(arr1)
/* 由于 slice() 是对原数组的引用,在新数组上修改,原数组引用类型的元素也会变化 */
arr1[0].width = 5
println(arr)
return 0
}
运行结果:
[width: 3, height: 4, width: 5, height: 6]
[width: 1, height: 2, width: 5, height: 4, width: 5, height: 6]
func splitAt(Int64)
public func splitAt(mid: Int64): (Array<T>, Array<T>)
功能:从指定位置 mid 处分割数组。
得到的两个数组是原数组的切片,取值范围为 [0, mid), [mid, this.size)。
参数:
- mid: Int64 - 分割的位置,取值范围为 [0, this.size]。
返回值:
异常:
- IllegalArgumentException - mid 小于 0 或大于 this.size。
func swap(Int64, Int64)
public func swap(index1: Int64, index2: Int64): Unit
功能:交换指定位置的两个元素。
如果 index1 和 index2 指向同一个位置,将不做交换。
参数:
- index1: Int64 - 需要交换的两个元素的下标之一,取值范围为 [0, this.size)。
- index2: Int64 - 需要交换的两个元素的下标之一,取值范围为 [0, this.size)。
异常:
- IllegalArgumentException - index1 / index2 小于 0 或大于等于 this.size。
示例:
main(): Int64 {
let arr = [1, 2, 3, 4]
arr.swap(1, 2)
println(arr)
return 0
}
运行结果:
[1, 3, 2, 4]
operator func [](Int64)
public operator func [](index: Int64): T
功能:获取数组下标 index 对应的值。
该函数中如果 index 越界,将抛出异常。
也可以通过 get 函数获取数组指定下标的元素,get 函数将在 index 越界时返回 None。
参数:
返回值:
- T - 数组中下标 index 对应的值。
异常:
- IndexOutOfBoundsException - 如果 index 小于 0,或大于等于数组长度,抛出异常。
operator func [](Int64, T)
public operator func [](index: Int64, value!: T): Unit
功能:修改数组中下标 index 对应的值。
参数:
异常:
- IndexOutOfBoundsException - 如果 index 小于 0,或大于等于数组长度,抛出异常。
operator func [](Range<Int64>)
public operator func [](range: Range<Int64>): Array<T>
功能:根据给定区间获取数组切片。
注意:
参数:
返回值:
- Array<T> - 数组切片。
异常:
- IllegalArgumentException - 如果 range 的步长不等于 1,抛出异常。
- IndexOutOfBoundsException - 如果 range 表示的数组范围无效,抛出异常。
示例:
main() {
let arr = [0, 1, 2, 3, 4, 5]
let slice = arr[1..4]
arr[3] = 10
println(slice)
}
运行结果:
[1, 2, 10]
operator func [](Range<Int64>, Array<T>)
public operator func [](range: Range<Int64>, value!: Array<T>): Unit
功能:用指定的数组对本数组一个连续范围的元素赋值。
range 表示的区见的长度和目标数组 value 的大小需相等。
注意:
参数:
异常:
- IllegalArgumentException - 如果 range 的步长不等于 1,或 range 长度不等于 value 长度,抛出异常。
- IndexOutOfBoundsException - 如果 range 表示的数组范围无效,抛出异常。
示例:
main() {
let arr = [0, 1, 2, 3, 4, 5]
arr[1..3] = [10, 11]
println(arr)
}
运行结果:
[0, 10, 11, 3, 4, 5]
extend<T> Array<T> <: Collection<T>
extend<T> Array<T> <: Collection<T>
功能:为 Array<T> 类型实现 Collection 接口。
父类型:
- Collection<T>
prop size
public prop size: Int64
功能:获取元素数量。
类型:Int64
func isEmpty()
public func isEmpty(): Bool
功能:判断数组是否为空。
返回值:
- Bool - 如果数组为空,返回 true,否则,返回 false。
func iterator()
public func iterator(): Iterator<T>
功能:获取当前数组的迭代器,用于遍历数组。
返回值:
- Iterator<T> - 当前数组的迭代器。
func toArray()
public func toArray(): Array<T>
功能:根据当前 Array 实例拷贝一个新的 Array 实例。
返回值:
extend<T> Array<T> <: Equatable<Array<T>> where T <: Equatable<T>
extend<T> Array<T> <: Equatable<Array<T>> where T <: Equatable<T>
功能:为 Array<T> 类型扩展 Equatable<Array<T>> 接口实现,支持判等操作。
父类型:
func contains(T)
public func contains(element: T): Bool
功能:查找当前数组是否包含指定元素。
参数:
- element: T - 需要查找的目标元素。
返回值:
- Bool - 如果存在,则返回 true,否则返回 false。
示例:
main(): Int64 {
let arr = [1, 2, 3, 4]
println(arr.contains(1))
return 0
}
运行结果:
true
func indexOf(Array<T>)
public func indexOf(elements: Array<T>): Option<Int64>
功能:返回数组中子数组 elements 出现的第一个位置,如果数组中不包含此数组,返回 None。
注意:
当 T 的类型是 Int64 时,此函数的变长参数语法糖版本可能会和
public func indexOf(element: T, fromIndex: Int64): Option<Int64>产生歧义,根据优先级,当参数数量是 2 个时,会优先调用public func indexOf(element: T, fromIndex: Int64): Option<Int64>。
参数:
- elements: Array<T> - 需要定位的目标数组。
返回值:
示例:
main(): Int64 {
let arr = [1, 2, 3, 4]
let subArr = [2, 3]
println(arr.indexOf(subArr))
return 0
}
运行结果:
Some(1)
func indexOf(Array<T>, Int64)
public func indexOf(elements: Array<T>, fromIndex: Int64): Option<Int64>
功能:返回数组中在 fromIndex之后,子数组elements 出现的第一个位置,未找到返回 None。
函数会对 fromIndex 范围进行检查,fromIndex 小于 0 时,将会从第 0 位开始搜索,当 fromIndex 大于等于本数组的大小时,结果为 None。
参数:
返回值:
示例:
main(): Int64 {
let arr = [1, 2, 3, 4, 2, 3]
let subArr = [2, 3]
println(arr.indexOf(subArr, 3))
return 0
}
运行结果:
Some(4)
func indexOf(T)
public func indexOf(element: T): Option<Int64>
功能:获取数组中 element 出现的第一个位置,如果数组中不包含此元素,返回 None。
参数:
- element: T - 需要定位的元素。
返回值:
func indexOf(T, Int64)
public func indexOf(element: T, fromIndex: Int64): Option<Int64>
功能:返回数组中在 fromIndex之后, element 出现的第一个位置,未找到返回 None。
函数会从下标 fromIndex 开始查找,fromIndex 小于 0 时,将会从第 0 位开始搜索,当 fromIndex 大于等于本数组的大小时,结果为 None。
参数:
- element: T - 需要定位的元素。
- fromIndex: Int64 - 查找的起始位置。
返回值:
示例:
main(): Int64 {
let arr = [1, 2, 3, 4, 2, 3]
let subArr = [2, 3]
println(arr.lastIndexOf(subArr, 3))
return 0
}
运行结果:
Some(4)
func lastIndexOf(Array<T>)
public func lastIndexOf(elements: Array<T>): Option<Int64>
功能:返回数组中子数组 elements 出现的最后一个位置,如果数组中不存在此子数组,返回 None。
参数:
- elements: Array<T> - 需要定位的目标数组。
返回值:
func lastIndexOf(Array<T>, Int64)
public func lastIndexOf(elements: Array<T>, fromIndex: Int64): Option<Int64>
功能:从 fromIndex 开始向后搜索,返回数组中子数组 elements 出现的最后一个位置,如果数组中不存在此子数组,返回 None。
函数会对 fromIndex 范围进行检查,fromIndex 小于 0 时,将会从第 0 位开始搜索,当 fromIndex 大于等于本数组的大小时,结果为 None。
参数:
返回值:
func lastIndexOf(T)
public func lastIndexOf(element: T): Option<Int64>
功能:返回数组中 element 出现的最后一个位置,如果数组中不存在此元素,返回 None。
参数:
- element: T - 需要定位的目标元素。
返回值:
func lastIndexOf(T, Int64)
public func lastIndexOf(element: T, fromIndex: Int64): Option<Int64>
功能:从 fromIndex 开始向后搜索,返回数组中 element 出现的最后一个位置,如果数组中不存在此元素,返回 None。
函数会对 fromIndex 范围进行检查,fromIndex 小于 0 时,将会从第 0 位开始搜索,当 fromIndex 大于等于本数组的大小时,结果为 None。
参数:
- element: T - 需要定位的目标元素。
- fromIndex: Int64 - 搜索开始的位置。
返回值:
func removePrefix(Array<T>)
public func removePrefix(prefix: Array<T>): Array<T>
功能:删除前缀。
如果当前数组开头与 prefix 完全匹配,删除其前缀。返回值为当前数组删除前缀后得到的切片。
参数:
- prefix: Array<T> - 待删除的前缀。
返回值:
- Array<T> - 删除前缀后得到的原数组切片。
示例:
main(): Int64 {
let arr = [1, 2, 1, 2, 3].removePrefix([1, 2])
println(arr)
return 0
}
运行结果:
[1, 2, 3]
func removeSuffix(Array<T>)
public func removeSuffix(suffix: Array<T>): Array<T>
功能:删除后缀。
如果当前数组结尾与 suffix 完全匹配,删除其后缀。返回值为当前数组删除后缀后得到的切片。
参数:
- suffix: Array<T> - 待删除的后缀。
返回值:
- Array<T> - 删除后缀后得到的原数组切片。
示例:
main(): Int64 {
let arr = [1, 2, 3, 2, 3].removeSuffix([2, 3])
println(arr)
return 0
}
运行结果:
[1, 2, 3]
func trimEnd(Array<T>)
public func trimEnd(set: Array<T>): Array<T>
功能:修剪当前数组,从尾开始删除在指定集合 set 中的元素,直到第一个不在 set 中的元素为止,并返回当前数组的切片。
参数:
- set: Array<T> - 待删除的元素的集合。
返回值:
- Array<T> - 修剪后的数组切片。
示例:
main(): Int64 {
let arr = [2, 1, 2, 2, 3].trimEnd([2, 3])
println(arr)
return 0
}
运行结果:
[2, 1]
func trimEnd((T)->Bool)
public func trimEnd(predicate: (T)->Bool): Array<T>
功能:修剪当前数组,从尾开始删除符合过滤条件的函数,直到第一个不符合的元素为止,并返回当前数组的切片。
参数:
- predicate: (T)->Bool - 过滤条件。
返回值:
- Array<T> - 修剪后的数组切片。
func trimStart(Array<T>)
public func trimStart(set: Array<T>): Array<T>
功能:修剪当前数组,从头开始删除在指定集合 set 中的元素,直到第一个不在 set 中的元素为止,并返回当前数组的切片。
参数:
- set: Array<T> - 待删除的元素的集合。
返回值:
- Array<T> - 修剪后的数组切片。
示例:
main(): Int64 {
let arr = [1, 2, 1, 3, 1].trimStart([1, 2])
println(arr)
return 0
}
运行结果:
[3, 1]
func trimStart((T)->Bool)
public func trimStart(predicate: (T)->Bool): Array<T>
功能:修剪当前数组,从头开始删除符合过滤条件的函数,直到第一个不符合的元素为止,并返回当前数组的切片。
参数:
- predicate: (T)->Bool - 过滤条件。
返回值:
- Array<T> - 修剪后的数组切片。
operator func !=(Array<T>)
public operator const func !=(that: Array<T>): Bool
功能:判断当前实例与指定 Array<T> 实例是否不等。
参数:
返回值:
- Bool - 如果不相等,则返回 true;相等则返回 false。
operator func ==(Array<T>)
public operator const func ==(that: Array<T>): Bool
功能:判断当前实例与指定 Array<T> 实例是否相等。
两个 Array<T> 相等指的是其中的每个元素都相等。
参数:
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
extend<T> Array<T> where T <: ToString
extend<T> Array<T> <: ToString where T <: ToString
功能:为 Array<T> 类型扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将数组转换为可输出的字符串。
字符串形如 "[1, 2, 3, 4, 5]"
返回值:
- String - 转化后的字符串。
extend<T> Array<Array<T>>
extend<T> Array<Array<T>>
功能:为二维数组进行扩展,提供将其展开为一维数组的方法。
func flatten()
public func flatten(): Array<T>
功能:将当前二维数组展开为一维数组。
例如将 [[1, 2], [3, 4]] 展开为 [1, 2, 3, 4]。
返回值:
- Array<T> - 展开后的一维数组。
示例:
main(): Int64 {
let arr = [[1, 2], [3, 4]].flatten()
println(arr)
return 0
}
运行结果:
[1, 2, 3, 4]
struct CPointerHandle<T> where T <: CType
public struct CPointerHandle<T> where T <: CType {
public let array: Array<T>
public let pointer: CPointer<T>
public init()
public init(ptr: CPointer<T>, arr: Array<T>)
}
功能:表示 Array 数组的原始指针,该类型中的泛型参数应该满足 CType 约束。
let array
public let array: Array<T>
功能:原始指针对应的 Array 数组实例。
类型:Array<T>
let pointer
public let pointer: CPointer<T>
功能:获取指定 Array 数组对应的原始指针。
类型:CPointer<T>
init() (deprecated)
public init()
功能:构造一个默认 CPointerHandle 实例,其中原始指针为空指针,仓颉数组为空数组。
注意:
未来版本即将废弃不再使用,可使用 acquireArrayRawData 函数构造 CPointerHandle 实例。
init(CPointer<T>, Array<T>) (deprecated)
public init(ptr: CPointer<T>, arr: Array<T>)
功能:通过传入的 CPointer 和 Array 初始化一个 CPointerHandle。
参数:
注意:
未来版本即将废弃不再使用,可使用 acquireArrayRawData 函数构造 CPointerHandle 实例。
struct CPointerResource<T> where T <: CType
public struct CPointerResource<T> <: Resource where T <: CType {
public let value: CPointer<T>
}
功能:该结构体表示 CPointer 对应的资源管理类型,其实例可以通过 CPointer 的成员函数 asResource 获取。
父类型:
let value
public let value: CPointer<T>
功能:表示当前实例管理的 CPointer<T> 类型实例。
类型:CPointer<T>
func close()
public func close(): Unit
功能:释放其管理的 CPointer<T> 实例指向的内容。
func isClosed()
public func isClosed(): Bool
功能:判断该指针内容是否已被释放。
返回值:
- Bool - 返回 true 为已释放。
struct CStringResource
public struct CStringResource <: Resource {
public let value: CString
}
功能:该结构体表示 CString 对应的资源管理类型,其实例可以通过 CString 的成员函数 asResource 获取。
父类型:
let value
public let value: CString
功能:表示当前实例管理的 CString 资源。
类型:CString
func close()
public func close(): Unit
功能:释放当前实例管理的 CString 类型实例指向的内容。
func isClosed()
public func isClosed(): Bool
功能:判断该字符串是否被释放。
返回值:
- Bool - 返回 true 为已释放。
struct DefaultHasher
public struct DefaultHasher <: Hasher {
public init(res!: Int64 = 0)
}
功能:该结构体提供了默认哈希算法实现。
可以使用一系列 write 函数传入不同数据类型实例,并计算它们的组合哈希值。
父类型:
init(Int64)
public init(res!: Int64 = 0)
功能:构造函数,创建一个 DefaultHasher。
参数:
- res!: Int64 - 初始哈希值,默认为 0。
func finish()
public func finish(): Int64
功能:获取哈希运算的结果。
返回值:
- Int64 - 哈希运算的结果。
func reset()
public mut func reset(): Unit
功能:重置哈希值为 0。
func write(Bool)
public mut func write(value: Bool): Unit
功能:通过该函数把想要哈希运算的 Bool 值传入,然后进行哈希组合运算。
参数:
- value: Bool - 待运算的值。
func write(Float16)
public mut func write(value: Float16): Unit
功能:通过该函数把想要哈希运算的 Float16 值传入,然后进行哈希组合运算。
参数:
- value: Float16 - 待运算的值。
func write(Float32)
public mut func write(value: Float32): Unit
功能:通过该函数把想要哈希运算的 Float32 值传入,然后进行哈希组合运算。
参数:
- value: Float32 - 待运算的值。
func write(Float64)
public mut func write(value: Float64): Unit
功能:通过该函数把想要哈希运算的 Float64 值传入,然后进行哈希组合运算。
参数:
- value: Float64 - 待运算的值。
func write(Int16)
public mut func write(value: Int16): Unit
功能:通过该函数把想要哈希运算的 Int16 值传入,然后进行哈希组合运算。
参数:
- value: Int16 - 待运算的值。
func write(Int32)
public mut func write(value: Int32): Unit
功能:通过该函数把想要哈希运算的 Int32 值传入,然后进行哈希组合运算。
参数:
- value: Int32 - 待运算的值。
func write(Int64)
public mut func write(value: Int64): Unit
功能:通过该函数把想要哈希运算的 Int64 值传入,然后进行哈希组合运算。
参数:
- value: Int64 - 待运算的值。
func write(Int8)
public mut func write(value: Int8): Unit
功能:通过该函数把想要哈希运算的 Int8 值传入,然后进行哈希组合运算。
参数:
- value: Int8 - 待运算的值。
func write(Rune)
public mut func write(value: Rune): Unit
功能:通过该函数把想要哈希运算的 Rune 值传入,然后进行哈希组合运算。
参数:
- value: Rune - 待运算的值。
func write(String)
public mut func write(value: String): Unit
功能:通过该函数把想要哈希运算的 String 值传入,然后进行哈希组合运算。
参数:
- value: String - 待运算的值。
func write(UInt16)
public mut func write(value: UInt16): Unit
功能:通过该函数把想要哈希运算的 UInt16 值传入,然后进行哈希组合运算。
参数:
- value: UInt16 - 待运算的值。
func write(UInt32)
public mut func write(value: UInt32): Unit
功能:通过该函数把想要哈希运算的 UInt32 值传入,然后进行哈希组合运算。
参数:
- value: UInt32 - 待运算的值。
func write(UInt64)
public mut func write(value: UInt64): Unit
功能:通过该函数把想要哈希运算的 UInt64 值传入,然后进行哈希组合运算。
参数:
- value: UInt64 - 待运算的值。
func write(UInt8)
public mut func write(value: UInt8): Unit
功能:通过该函数把想要哈希运算的 UInt8 值传入,然后进行哈希组合运算。
参数:
- value: UInt8 - 待运算的值。
struct Duration
public struct Duration <: ToString & Hashable & Comparable<Duration> {
public static const Max: Duration = Duration(0x7FFF_FFFF_FFFF_FFFF, 999999999)
public static const Min: Duration = Duration(-0x8000_0000_0000_0000, 0)
public static const Zero: Duration = Duration(0, 0)
public static const day: Duration = Duration(24 * 60 * 60, 0)
public static const hour: Duration = Duration(60 * 60, 0)
public static const microsecond: Duration = Duration(0, 1000u32)
public static const millisecond: Duration = Duration(0, 1000000u32)
public static const minute: Duration = Duration(60, 0)
public static const nanosecond: Duration = Duration(0, 1)
public static const second: Duration = Duration(1, 0)
}
功能:Duration 表示时间间隔,是一个描述一段时间的时间类型,提供了常用的静态实例,以及计算、比较等功能。
说明:
父类型:
static const Max
public static const Max: Duration = Duration(0x7FFF_FFFF_FFFF_FFFF, 999999999)
功能:表示最大时间间隔的 Duration 实例。
类型:Duration
static const Min
public static const Min: Duration = Duration(-0x8000_0000_0000_0000, 0)
功能:表示最小时间间隔的 Duration 实例。
类型:Duration
static const Zero
public static const Zero: Duration = Duration(0, 0)
功能:表示 0 纳秒时间间隔的 Duration 实例。
类型:Duration
static const day
public static const day: Duration = Duration(24 * 60 * 60, 0)
功能:表示 1 天时间间隔的 Duration 实例。
类型:Duration
static const hour
public static const hour: Duration = Duration(60 * 60, 0)
功能:表示 1 小时时间间隔的 Duration 实例。
类型:Duration
static const microsecond
public static const microsecond: Duration = Duration(0, 1000u32)
功能:表示 1 微秒时间间隔的 Duration 实例。
类型:Duration
static const millisecond
public static const millisecond: Duration = Duration(0, 1000000u32)
功能:表示 1 毫秒时间间隔的 Duration 实例。
类型:Duration
static const minute
public static const minute: Duration = Duration(60, 0)
功能:表示 1 分钟时间间隔的 Duration 实例。
类型:Duration
static const nanosecond
public static const nanosecond: Duration = Duration(0, 1)
功能:表示 1 纳秒时间间隔的 Duration 实例。
类型:Duration
static const second
public static const second: Duration = Duration(1, 0)
功能:表示 1 秒时间间隔的 Duration 实例。
类型:Duration
func abs()
public func abs(): Duration
功能:返回一个新的 Duration 实例,其值大小为当前 Duration 实例绝对值。
返回值:
异常:
- ArithmeticException - 如果当前 Duration 实例等于 Duration.Min,会因为取绝对值超出 Duration 表示范围而抛出异常。
func compare(Duration)
public func compare(rhs: Duration): Ordering
功能:比较当前 Duration 实例与另一个 Duration 实例的关系,如果大于,返回 Ordering.GT;如果等于,返回 Ordering.EQ;如果小于,返回 Ordering.LT。
参数:
返回值:
func hashCode()
public func hashCode(): Int64
功能:获得当前 Duration 实例的哈希值。
返回值:
func toDays()
public func toDays(): Int64
功能:获得当前 Duration 实例以天为单位的整数大小。
返回值:
func toHours()
public func toHours(): Int64
功能:获得当前 Duration 实例以小时为单位的整数大小。
返回值:
func toMicroseconds()
public func toMicroseconds(): Int64
功能:获得当前 Duration 实例以微秒为单位的整数大小。
返回值:
异常:
- ArithmeticException - 当 Duration 实例以微秒为单位的大小超过 Int64 表示范围时,抛出异常。
func toMilliseconds()
public func toMilliseconds(): Int64
功能:获得当前 Duration 实例以毫秒为单位的整数大小。
返回值:
异常:
- ArithmeticException - 当 Duration 实例以毫秒为单位的大小超过 Int64 表示范围时,抛出异常。
func toMinutes()
public func toMinutes(): Int64
功能:获得当前 Duration 实例以分钟为单位的整数大小。
返回值:
func toNanoseconds()
public func toNanoseconds(): Int64
功能:获得当前 Duration 实例以纳秒为单位的整数大小,向绝对值小的方向取整。
返回值:
异常:
- ArithmeticException - 当 Duration 实例以“纳秒”为单位的大小超过 Int64 表示范围时,抛出异常。
func toSeconds()
public func toSeconds(): Int64
功能:获得当前 Duration 实例以秒为单位的整数大小。
返回值:
func toString()
public func toString(): String
功能:获得当前 Duration 实例的字符串表示,格式形如:"1d2h3m4s5ms6us7ns",表示“1天2小时3分钟4秒5毫秒6微秒7纳秒”。某个单位下数值为 0 时此项会被省略,特别地,当所有单位下数值都为 0 时,返回 "0s"。
返回值:
operator func !=(Duration)
public operator func !=(r: Duration): Bool
功能:判断当前 Duration 实例是否不等于 r。
参数:
返回值:
operator func *(Float64)
public operator func *(r: Float64): Duration
功能:实现 Duration 类型与 Float64 类型的乘法,即 Duration * Float64 运算。
参数:
- r: Float64 - 乘法的右操作数。
返回值:
异常:
- ArithmeticException - 当相乘后的结果超出 Duration 的表示范围时,抛出异常。
operator func *(Int64)
public operator func *(r: Int64): Duration
功能:实现 Duration 类型与 Int64 类型的乘法,即 Duration * Int64 运算。
参数:
- r: Int64 - 乘法的右操作数。
返回值:
异常:
- ArithmeticException - 当相乘后的结果超出 Duration 的表示范围时,抛出异常。
operator func +(Duration)
public operator func +(r: Duration): Duration
功能:实现 Duration 类型之间的加法,即 Duration + Duration 运算。
参数:
- r: Duration - 加法的右操作数。
返回值:
异常:
- ArithmeticException - 当相加后的结果超出 Duration 的表示范围时,抛出异常。
operator func -(Duration)
public operator func -(r: Duration): Duration
功能:实现 Duration 类型之间的减法,即 Duration - Duration 运算。
参数:
- r: Duration - 减法的右操作数。
返回值:
异常:
- ArithmeticException - 当相减后的结果超出 Duration 的表示范围时,抛出异常。
operator func /(Duration)
public operator func /(r: Duration): Float64
功能:实现 Duration 类型与 Duration 类型的除法,即 Duration / Duration 运算。
参数:
- r: Duration - 除数。
返回值:
异常:
- IllegalArgumentException - 当
r等于 Duration.Zero 时,抛出异常。
operator func /(Float64)
public operator func /(r: Float64): Duration
功能:实现 Duration 类型与 Float64 类型的除法,即 Duration / Float64 运算。
参数:
- r: Float64 - 除数。
返回值:
异常:
- IllegalArgumentException - 当
r等于 0 时,抛出异常。 - ArithmeticException - 当相除后的结果超出 Duration 的表示范围时,抛出异常。
operator func /(Int64)
public operator func /(r: Int64): Duration
功能:实现 Duration 类型与 Int64 类型的除法,即 Duration / Int64 运算。
参数:
- r: Int64 - 除数。
返回值:
异常:
- IllegalArgumentException - 当
r等于 0 时,抛出异常。 - ArithmeticException - 当相除后的结果超出 Duration 的表示范围时,抛出异常。
operator func <(Duration)
public operator func <(r: Duration): Bool
功能:判断当前 Duration 实例是否小于 r。
参数:
返回值:
operator func <=(Duration)
public operator func <=(r: Duration): Bool
功能:判断当前 Duration 实例是否小于等于 r。
参数:
返回值:
operator func ==(Duration)
public operator func ==(r: Duration): Bool
功能:判断当前 Duration 实例是否等于 r。
参数:
返回值:
operator func >(Duration)
public operator func >(r: Duration): Bool
功能:判断当前 Duration 实例是否大于 r。
参数:
返回值:
operator func >=(Duration)
public operator func >=(r: Duration): Bool
功能:判断当前 Duration 实例是否大于等于 r。
参数:
返回值:
struct LibC
public struct LibC
功能:提供了仓颉中较为高频使用的 C 接口,如申请、释放堆上 CType 实例。
static func free<T>(CPointer<T>) where T <: CType
public static unsafe func free<T>(p: CPointer<T>): Unit where T <: CType
功能:释放指针 p 指向的堆内存。
参数:
- p: CPointer<T> - 表示需要被释放的内存地址。
static func free(CString)
public static unsafe func free(cstr: CString): Unit
功能:释放 C 风格字符串。
参数:
- cstr: CString - 需要释放的 C 风格字符串。
static func mallocCString(String)
public static unsafe func mallocCString(str: String): CString
功能:通过 String 申请与之字符内容相同的 C 风格字符串。
构造的 C 风格字符串将以 '\0' 结束。当异常场景如系统内存不足时,返回字符串指针可能为空,故使用前需要进行空指针检查。
参数:
- str: String - 根据该仓颉字符串构造 C 字符串。
返回值:
- CString - 新构造的 C 风格字符串。
异常:
- IllegalMemoryException - 内存不足时,抛出异常。
示例:
main() {
var str = unsafe { LibC.mallocCString("I like Cangjie") }
println(str)
unsafe { LibC.free(str) }
}
运行结果:
I like Cangjie
static func malloc<T>(Int64) where T <: CType
public static func malloc<T>(count!: Int64 = 1): CPointer<T> where T <: CType
功能:在堆中申请指定个数的 T 实例,并返回其起始指针。
参数:
返回值:
- CPointer<T> - 申请的 T 类型指针。
异常:
- IllegalArgumentException - 入参为负数时,抛出异常。
示例:
main() {
var p = unsafe { LibC.malloc<Int64>(count: 1) }
unsafe { p.write(8) }
let value: Int64 = unsafe { p.read() }
println(value)
unsafe { LibC.free<Int64>(p) }
}
运行结果:
8
struct Range<T> where T <: Countable<T> & Comparable<T> & Equatable<T>
public struct Range<T> <: Iterable<T> where T <: Countable<T> & Comparable<T> & Equatable<T> {
public let end: T
public let hasEnd: Bool
public let hasStart: Bool
public let isClosed: Bool
public let start: T
public let step: Int64
public const init(start: T, end: T, step: Int64, hasStart: Bool, hasEnd: Bool, isClosed: Bool)
}
功能:该类是区间类型,用于表示一个拥有固定范围和步长的 T 的序列,要求 T 是可数的,有序的。
区间类型有对应的字面量表示,其格式为:
- 左闭右开区间:
start..end : step,它表示一个从 start 开始,以 step 为步长,到 end(不包含 end)为止的区间。 - 左闭右闭区间:
start..=end : step,它表示一个从 start 开始,以 step 为步长,到 end(包含 end)为止的区间。
注意:
父类型:
- Iterable<T>
let end
public let end: T
功能:表示结束值。
类型:T
let hasEnd
public let hasEnd: Bool
功能:表示是否包含结束值。
类型:Bool
let hasStart
public let hasStart: Bool
功能:表示是否包含开始值。
类型:Bool
let isClosed
public let isClosed: Bool
功能:表示区间开闭情况,为 true 表示左闭右闭,为 false 表示左闭右开。
类型:Bool
let start
public let start: T
功能:表示开始值。
类型:T
let step
public let step: Int64
功能:表示步长。
类型:Int64
init(T, T, Int64, Bool, Bool, Bool)
public const init(start: T, end: T, step: Int64, hasStart: Bool, hasEnd: Bool, isClosed: Bool)
功能:使用该构造函数创建 Range 序列。
参数:
- start: T - 开始值。
- end: T - 结束值。
- step: Int64 - 步长,取值不能为 0。
- hasStart: Bool - 是否有开始值。
- hasEnd: Bool - 是否有结束值。
- isClosed: Bool - true 代表左闭右闭,false 代表左闭右开。
异常:
- IllegalArgumentException - 当 step 等于 0 时, 抛出异常。
func isEmpty()
public const func isEmpty(): Bool
功能:判断该区间是否为空。
返回值:
- Bool - 如果为空,返回 true,否则返回 false。
func iterator()
public func iterator(): Iterator<T>
功能:获取当前区间的迭代器。
返回值:
- Iterator<T> - 当前区间的迭代器。
extend<T> Range<T> <: Equatable<Range<T>> where T <: Countable<T> & Comparable<T> & Equatable<T>
extend<T> Range<T> <: Equatable<Range<T>> where T <: Countable<T> & Comparable<T> & Equatable<T>
功能:为 Range<T> 类型扩展 Equatable<Range<T>> 接口。
父类型:
operator func ==(Range<T>)
public operator func ==(that: Range<T>): Bool
功能:判断两个 Range 实例是否相等。
两个 Range 实例相等指的是它们表示同一个区间,即 start、end、step、isClosed 值相等。
参数:
返回值:
- Bool - true 代表相等,false 代表不相等。
extend<T> Range<T> <: Hashable where T <: Hashable & Countable<T> & Comparable<T> & Equatable<T>
extend<T> Range<T> <: Hashable where T <: Hashable & Countable<T> & Comparable<T> & Equatable<T>
功能:为 Range 类型扩展 Hashable 接口,支持计算哈希值。
父类型:
func hashCode()
public func hashCode(): Int64
功能:获取哈希值,该值为 start、end、step、isClosed 的组合哈希运算结果。
返回值:
- Int64 - 哈希值。
struct String
public struct String <: Collection<Byte> & Equatable<String> & Comparable<String> & Hashable & ToString {
public static const empty: String = String()
public const init()
public init(value: Array<Rune>)
public init(value: Collection<Rune>)
}
功能:该结构体表示仓颉字符串,提供了构造、查找、拼接等一系列字符串操作。
注意:
String类型仅支持 UTF-8 编码。- 出于
String对象内存开销方面的优化,String的长度被限制在4GB大小,即String的最大长度不超过 UInt32 的最大值。
父类型:
static const empty
public static const empty: String = String()
功能:创建一个空的字符串并返回。
类型:String
prop size
public prop size: Int64
功能:获取字符串 UTF-8 编码后的字节长度。
类型:Int64
init()
public const init()
功能:构造一个空的字符串。
init(Array<Rune>)
public init(value: Array<Rune>)
功能:根据字符数组构造一个字符串,字符串内容为数组中的所有字符。
参数:
- value: Array<Rune> - 根据该字符数组构造字符串。
异常:
- IllegalArgumentException - 当试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
init(Collection<Rune>)
public init(value: Collection<Rune>)
功能:据字符集合构造一个字符串,字符串内容为集合中的所有字符。
参数:
- value: Collection<Rune> - 根据该字符集合构造字符串。
异常:
- IllegalArgumentException - 当试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
static func checkUtf8Encoding(Array<UInt8>)
public static func checkUtf8Encoding(data: Array<UInt8>): Bool
功能:检查一个 Byte 数组是否符合 UTF-8 编码。
参数:
返回值:
- Bool - 如果 Byte 数组符合 UTF-8 编码返回 true,否则返回 false。
static func fromUtf8(Array<UInt8>)
public static func fromUtf8(utf8Data: Array<UInt8>): String
功能:根据 UTF-8 编码的字节数组构造一个字符串。
参数:
返回值:
- String - 构造的字符串。
异常:
- IllegalArgumentException - 入参不符合 utf-8 序列规则,或者试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
static func fromUtf8Unchecked(Array<UInt8>)
public static unsafe func fromUtf8Unchecked(utf8Data: Array<UInt8>): String
功能:根据字节数组构造一个字符串。
相较于 fromUtf8 函数,它并没有针对于字节数组进行 UTF-8 相关规则的检查,所以它所构建的字符串并不一定保证是合法的,甚至出现非预期的异常,如果不是某些场景下的性能考虑,请优先使用安全的 fromUtf8 函数。
参数:
返回值:
- String - 构造的字符串。
异常:
- IllegalArgumentException - 当试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
static func join(Array<String>, String)
public static func join(strArray: Array<String>, delimiter!: String = String.empty): String
功能:连接字符串列表中的所有字符串,以指定分隔符分隔。
参数:
- strArray: Array<String> - 需要被连接的字符串数组,当数组为空时,返回空字符串。
- delimiter!: String - 用于连接的中间字符串,其默认值为 String.empty。
返回值:
- String - 连接后的新字符串。
异常:
- IllegalArgumentException - 当试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
示例:
main() {
var arr = ["I", "like", "Cangjie"]
var str = String.join(arr, delimiter: " ")
println(str)
}
运行结果:
I like Cangjie
static func withRawData(Array<UInt8>)
public static unsafe func withRawData(rawData: Array<UInt8>): String
功能:根据字节数组构造一个字符串。
相较于 fromUtf8Unchecked 函数,它没有做数组的拷贝,直接用传入的数组构造了字符串。
注意:
用户应该保证:
- rawData 在字符串构造后永远不会被修改。
- rawData 符合 UTF-8 编码。
否则程序行为是未定义的。 如果不是某些场景下的性能考虑,请优先使用安全的 fromUtf8 函数。
参数:
返回值:
- String - 构造的字符串。
异常:
- IllegalArgumentException - 当试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
func clone()
public func clone(): String
功能:返回原字符串的拷贝。
返回值:
- String - 拷贝得到的新字符串。
func compare(String)
public func compare(str: String): Ordering
功能:按字典序比较当前字符串和参数指定的字符串。
参数:
- str: String - 被比较的字符串。
返回值:
- Ordering - 返回 enum 值 Ordering 表示结果,Ordering.GT 表示当前字符串字典序大于 str 字符串,Ordering.LT 表示当前字符串字典序小于 str 字符串,Ordering.EQ 表示两个字符串字典序相等。
异常:
- IllegalArgumentException - 如果两个字符串的原始数据中存在无效的 UTF-8 编码,抛出异常。
func contains(String)
public func contains(str: String): Bool
功能:判断原字符串中是否包含字符串 str。
参数:
- str: String - 待搜索的字符串。
返回值:
- Bool - 如果字符串 str 在原字符串中,返回 true,否则返回 false。特别地,如果 str 字符串长度为 0,返回 true。
func count(String)
public func count(str: String): Int64
功能:返回子字符串 str 在原字符串中出现的次数。
参数:
- str: String - 被搜索的子字符串。
返回值:
- Int64 - 出现的次数,当 str 为空字符串时,返回原字符串中 Rune 的数量加一。
func endsWith(String)
public func endsWith(suffix: String): Bool
功能:判断原字符串是否以 suffix 字符串为后缀结尾。
参数:
- suffix: String - 被判断的后缀字符串。
返回值:
- Bool - 如果字符串 str 是原字符串的后缀,返回 true,否则返回 false,特别地,如果 str 字符串长度为 0,返回 true。
func equalsIgnoreAsciiCase(String): Bool
public func equalsIgnoreAsciiCase(that: String): Bool
功能:判断当前字符串和指定字符串是否相等,忽略大小写。
参数:
- that: String - 待比较的字符串。
返回值:
- Bool - 如果当前字符串与待比较字符串相等,返回 true,否则返回 false。
func get(Int64)
public func get(index: Int64): Option<Byte>
功能:返回字符串下标 index 对应的 UTF-8 编码字节值。
参数:
- index: Int64 - 要获取的字节值的下标。
返回值:
func hashCode()
public func hashCode(): Int64
功能:获取字符串的哈希值。
返回值:
- Int64 - 返回字符串的哈希值。
func indexOf(Byte)
public func indexOf(b: Byte): Option<Int64>
功能:获取指定字节 b 第一次出现的在原字符串内的索引。
参数:
- b: Byte - 待搜索的字节。
返回值:
func indexOf(Byte, Int64)
public func indexOf(b: Byte, fromIndex: Int64): Option<Int64>
功能:从原字符串指定索引开始搜索,获取指定字节第一次出现的在原字符串内的索引。
参数:
返回值:
- Option<Int64> - 如果搜索成功,返回指定字节第一次出现的索引,否则返回
None。特别地,当 fromIndex 小于零,效果同 0,当 fromIndex 大于等于原字符串长度,返回 Option<Int64>.None。
func indexOf(String)
public func indexOf(str: String): Option<Int64>
功能:返回指定字符串 str 在原字符串中第一次出现的起始索引。
参数:
- str: String - 待搜索的字符串。
返回值:
func indexOf(String, Int64)
public func indexOf(str: String, fromIndex: Int64): Option<Int64>
功能:从原字符串 fromIndex 索引开始搜索,获取指定字符串 str 第一次出现的在原字符串的起始索引。
参数:
返回值:
- Option<Int64> - 如果搜索成功,返回 str 第一次出现的索引,否则返回 None。特别地,当 str 是空字符串时,如果fromIndex 大于 0,返回 None,否则返回 Some(0)。当 fromIndex 小于零,效果同 0,当 fromIndex 大于等于原字符串长度返回 None。
func isAscii()
public func isAscii(): Bool
功能:判断字符串是否是一个 Ascii 字符串,如果字符串为空或没有 Ascii 以外的字符,则返回 true。
返回值:
- Bool - 是则返回 true,不是则返回 false。
func isAsciiBlank()
public func isAsciiBlank(): Bool
功能:判断字符串是否为空或者字符串中的所有 Rune 都是 ascii 码的空白字符(包括:0x09、0x10、0x11、0x12、0x13、0x20)。
返回值:
- Bool - 如果是返回 true,否则返回 false。
func isEmpty()
public func isEmpty(): Bool
功能:判断原字符串是否为空字符串。
返回值:
- Bool - 如果为空返回 true,否则返回 false。
func iterator()
public func iterator(): Iterator<Byte>
功能:获取字符串的 UTF-8 编码字节迭代器,可用于支持 for-in 循环。
返回值:
示例:
main() {
var str = "abc"
/* 迭代器元素为每个字符的 utf-8 编码 */
for (i in str) {
println(i)
}
}
运行结果:
97
98
99
func lastIndexOf(Byte)
public func lastIndexOf(b: Byte): Option<Int64>
功能:返回指定字节 b 最后一次出现的在原字符串内的索引。
参数:
- b: Byte - 待搜索的字节。
返回值:
func lastIndexOf(Byte, Int64)
public func lastIndexOf(b: Byte, fromIndex: Int64): Option<Int64>
功能:从原字符串 fromIndex 索引开始搜索,返回指定 UTF-8 编码字节 b 最后一次出现的在原字符串内的索引。
参数:
返回值:
- Option<Int64> - 如果搜索成功,返回指定字节最后一次出现的索引,否则返回
None。特别地,当 fromIndex 小于零,效果同 0,当 fromIndex 大于等于原字符串长度,返回None。
func lastIndexOf(String)
public func lastIndexOf(str: String): Option<Int64>
功能:返回指定字符串 str 最后一次出现的在原字符串的起始索引。
参数:
- str: String - 待搜索的字符串。
返回值:
func lastIndexOf(String, Int64)
public func lastIndexOf(str: String, fromIndex: Int64): Option<Int64>
功能:从原字符串指定索引开始搜索,获取指定字符串 str 最后一次出现的在原字符串的起始索引。
参数:
返回值:
- Option<Int64> - 如果这个字符串在位置 fromIndex 及其之后没有出现,则返回
None。特别地,当 str 是空字符串时,如果 fromIndex 大于 0,返回None,否则返回Some(0),当 fromIndex 小于零,效果同 0,当 fromIndex 大于等于原字符串长度返回None。
func lazySplit(String, Bool)
public func lazySplit(str: String, removeEmpty!: Bool = false): Iterator<String>
功能:对原字符串按照字符串 str 分隔符分割,该函数不立即对字符串进行分割,而是返回迭代器,使用迭代器进行遍历时再实际执行分隔操作。
当 str 未出现在原字符串中,返回大小为 1 的字符串迭代器,唯一的元素为原字符串。
参数:
返回值:
示例:
main() {
var str = "I like Cangjie"
var iter = str.lazySplit(" ")
while (true) {
match (iter.next()) {
case Some(i) => println(i)
case None => break
}
}
}
运行结果:
I
like
Cangjie
func lazySplit(String, Int64, Bool)
public func lazySplit(str: String, maxSplits: Int64, removeEmpty!: Bool = false): Iterator<String>
功能:对原字符串按照字符串 str 分隔符分割,该函数不立即对字符串进行分割,而是返回迭代器,使用迭代器进行遍历时再实际执行分隔操作。
- 当 maxSplit 为 0 时,返回空的字符串迭代器;
- 当 maxSplit 为 1 时,返回大小为 1 的字符串迭代器,唯一的元素为原字符串;
- 当 maxSplit 为负数时,直接返回分割后的字符串迭代器;
- 当 maxSplit 大于完整分割出来的子字符串数量时,返回完整分割的字符串迭代器;
- 当 str 未出现在原字符串中,返回大小为 1 的字符串迭代器,唯一的元素为原字符串;
- 当 str 为空时,对每个字符进行分割;当原字符串和分隔符都为空时,返回空字符串迭代器。
参数:
- str: String - 字符串分隔符。
- maxSplits: Int64 - 最多分割为 maxSplit 个子字符串。
- removeEmpty!: Bool - 移除分割结果中的空字符串,默认值为 false。
返回值:
func lines()
public func lines(): Iterator<String>
功能:获取字符串的行迭代器,每行都由换行符进行分隔,换行符是 \n \r \r\n 之一,结果中每行不包括换行符。
返回值:
示例:
main() {
var str = "I\rlike\nCangjie\r"
var iter = str.lines()
while (true) {
match (iter.next()) {
case Some(i) => println(i)
case None => break
}
}
}
运行结果:
I
like
Cangjie
func padEnd(Int64, String)
public func padEnd(totalWidth: Int64, padding!: String = " "): String
功能:按指定长度左对齐原字符串,如果原字符串长度小于指定长度,在其右侧添加指定字符串。
当指定长度小于字符串长度时,返回字符串本身,不会发生截断;当指定长度大于字符串长度时,在右侧添加 padding 字符串,当 padding 长度大于 1 时,返回字符串的长度可能大于指定长度。
参数:
返回值:
- String - 填充后的字符串。
异常:
- IllegalArgumentException - 如果 totalWidth 小于 0,抛出异常。
func padStart(Int64, String)
public func padStart(totalWidth: Int64, padding!: String = " "): String
功能:按指定长度右对齐原字符串,如果原字符串长度小于指定长度,在其左侧添加指定字符串。
当指定长度小于字符串长度时,返回字符串本身,不会发生截断;当指定长度大于字符串长度时,在左侧添加 padding 字符串,当 padding 长度大于 1 时,返回字符串的长度可能大于指定长度。
参数:
返回值:
- String - 填充后的字符串。
异常:
- IllegalArgumentException - 如果 totalWidth 小于 0,抛出异常。
func rawData()
public unsafe func rawData(): Array<Byte>
功能:获取字符串的 UTF-8 编码的原始字节数组。
注意:
用户不应该对获取的数组进行修改,这将破坏字符串的不可变性。
返回值:
func removePrefix(String)
public func removePrefix(prefix: String): String
功能:去除字符串的 prefix 前缀。
参数:
- prefix: String - 待去除的前缀。
返回值:
- String - 去除前缀后得到的新字符串。
func removeSuffix(String)
public func removeSuffix(suffix: String): String
功能:去除字符串的 suffix 后缀。
参数:
- suffix: String - 待去除的后缀。
返回值:
- String - 去除后缀后得到的新字符串。
func replace(String, String)
public func replace(old: String, new: String): String
功能:使用新字符串替换原字符串中旧字符串。
参数:
返回值:
- String - 替换后的新字符串。
异常:
- OutOfMemoryError - 如果此函数分配内存时产生错误,抛出异常。
func runes()
public func runes(): Iterator<Rune>
功能:获取字符串的 Rune 迭代器。
返回值:
- Iterator<Rune> - 字符串的 Rune 迭代器。
异常:
- IllegalArgumentException - 使用
for-in或者next()方法遍历迭代器时,如果读取到非法字符,抛出异常。
func split(String, Bool)
public func split(str: String, removeEmpty!: Bool = false): Array<String>
功能:对原字符串按照字符串 str 分隔符分割,指定是否删除空串。
当 str 未出现在原字符串中,返回长度为 1 的字符串数组,唯一的元素为原字符串。
参数:
返回值:
func split(String, Int64, Bool)
public func split(str: String, maxSplits: Int64, removeEmpty!: Bool = false): Array<String>
功能:对原字符串按照字符串 str 分隔符分割,指定最多分隔子串数,以及是否删除空串。
- 当 maxSplit 为 0 时,返回空的字符串数组;
- 当 maxSplit 为 1 时,返回长度为 1 的字符串数组,唯一的元素为原字符串;
- 当 maxSplit 为负数时,返回完整分割后的字符串数组;
- 当 maxSplit 大于完整分割出来的子字符串数量时,返回完整分割的字符串数组;
- 当 str 未出现在原字符串中,返回长度为 1 的字符串数组,唯一的元素为原字符串;
- 当 str 为空时,对每个字符进行分割;当原字符串和分隔符都为空时,返回空字符串数组。
参数:
- str: String - 字符串分隔符。
- maxSplits: Int64 - 最多分割为 maxSplit 个子字符串。
- removeEmpty!: Bool - 移除分割结果中的空字符串,默认值为 false。
返回值:
func startsWith(String)
public func startsWith(prefix: String): Bool
功能:判断原字符串是否以 prefix 字符串为前缀。
参数:
- prefix: String - 被判断的前缀字符串。
返回值:
- Bool - 如果字符串 str 是原字符串的前缀,返回 true,否则返回 false,特别地,如果 str 字符串长度为 0,返回 true。
func toArray()
public func toArray(): Array<Byte>
功能:获取字符串的 UTF-8 编码的字节数组。
返回值:
func toAsciiLower()
public func toAsciiLower(): String
功能:将该字符串中所有 Ascii 大写字母转化为 Ascii 小写字母。
返回值:
- String - 转换后的新字符串。
func toAsciiTitle()
public func toAsciiTitle(): String
功能:将该字符串标题化。
该函数只转换 Ascii 英文字符,当该英文字符是字符串中第一个字符或者该字符的前一个字符不是英文字符,则该字符大写,其他英文字符小写。
返回值:
- String - 转换后的新字符串。
func toAsciiUpper()
public func toAsciiUpper(): String
功能:将该字符串中所有 Ascii 小写字母转化为 Ascii 大写字母。
返回值:
- String - 转换后的新字符串。
func toRuneArray()
public func toRuneArray(): Array<Rune>
功能:获取字符串的 Rune 数组。如果原字符串为空字符串,则返回空数组。
返回值:
- Array<Rune> - 字符串的 Rune 数组。
func toString()
public func toString(): String
功能:获得字符串本身。
返回值:
- String - 返回字符串本身。
func trimAscii()
public func trimAscii(): String
功能:去除原字符串开头结尾以 whitespace 字符组成的子字符串。
whitespace 的 unicode 码点范围为 [0009, 000D] 和 [0020]。
返回值:
- String - 转换后的新字符串。
func trimAsciiEnd()
public func trimAsciiEnd(): String
功能:去除原字符串结尾以 whitespace 字符组成的子字符串。
返回值:
- String - 转换后的新字符串。
func trimAsciiStart()
public func trimAsciiStart(): String
功能:去除原字符串开头以 whitespace 字符组成的子字符串。
返回值:
- String - 转换后的新字符串。
func trimEnd((Rune)->Bool)
public func trimEnd(predicate: (Rune)->Bool): String
功能:修剪当前字符串,从尾开始删除符合过滤条件的 Rune 字符,直到第一个不符合过滤条件的 Rune 字符为止。
参数:
返回值:
- String - 修剪后得到的新字符串。
示例:
main() {
var str = "14122"
var subStr = str.trimEnd({c => c == r'2'})
println(subStr)
}
运行结果:
141
func trimEnd(Array<Rune>)
public func trimEnd(set: Array<Rune>): String
功能:修剪当前字符串,从尾开始删除在 set 中的 Rune 字符,直到第一个不在 set 中的 Rune 字符为止。
参数:
返回值:
- String - 修剪后得到的新字符串。
示例:
main() {
var str = "14122"
var subStr = str.trimEnd([r'1', r'2'])
println(subStr)
}
运行结果:
14
func trimEnd(String)
public func trimEnd(set: String): String
功能:修剪当前字符串,从尾开始删除在 set 中的 Rune 字符,直到第一个不在 set 中的 Rune 字符为止。
参数:
- set: String - 待删除的字符的集合。
返回值:
- String - 修剪后得到的新字符串。
示例:
main() {
var str = "14122"
var subStr = str.trimEnd("12")
println(subStr)
}
运行结果:
14
func trimStart((Rune)->Bool)
public func trimStart(predicate: (Rune)->Bool): String
功能:修剪当前字符串,从头开始删除符合过滤条件的 Rune 字符,直到第一个不符合过滤条件的 Rune 字符为止。
参数:
返回值:
- String - 修剪后得到的新字符串。
func trimStart(Array<Rune>)
public func trimStart(set: Array<Rune>): String
功能:修剪当前字符串,从头开始删除在 set 中的 Rune 字符,直到第一个不在 set 中的 Rune 字符为止。
例如 "12241".trimStart([r'1', r'2']) = "41"。
参数:
返回值:
- String - 修剪后得到的新字符串。
func trimStart(String)
public func trimStart(set: String): String
功能:修剪当前字符串,从头开始删除在 set 中的 Rune 字符,直到第一个不在 set 中的 Rune 字符为止。
例如 "12241".trimStart("12") = "41"。
参数:
- set: String - 待删除的字符的集合。
返回值:
- String - 修剪后得到的新字符串。
operator func !=(String)
public const operator func !=(right: String): Bool
功能:判断两个字符串是否不相等。
参数:
返回值:
- Bool - 不相等返回 true,相等返回 false。
operator func *(Int64)
public const operator func *(count: Int64): String
功能:原字符串重复 count 次。
参数:
- count: Int64 - 原字符串重复的次数。
返回值:
异常:
- IllegalArgumentException - 当试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
operator func +(String)
public const operator func +(right: String): String
功能:两个字符串相加,将 right 字符串拼接在原字符串的末尾。
参数:
- right: String - 待追加的字符串。
返回值:
- String - 返回拼接后的字符串。
异常:
- IllegalArgumentException - 当试图构造长度超过 UInt32 的最大值 的字符串时,抛出异常。
operator func <(String)
public const operator func <(right: String): Bool
功能:判断两个字符串大小。
参数:
- right: String - 待比较的字符串。
返回值:
- Bool - 原字符串字典序小于 right 时,返回 true,否则返回 false。
operator func <=(String)
public const operator func <=(right: String): Bool
功能:判断两个字符串大小。
参数:
- right: String - 待比较的字符串。
返回值:
- Bool - 原字符串字典序小于或等于 right 时,返回 true,否则返回 false。
operator func ==(String)
public const operator func ==(right: String): Bool
功能:判断两个字符串是否相等。
参数:
- right: String - 待比较的字符串。
返回值:
- Bool - 相等返回 true,不相等返回 false。
operator func >(String)
public const operator func >(right: String): Bool
功能:判断两个字符串大小。
参数:
- right: String - 待比较的字符串。
返回值:
- Bool - 原字符串字典序大于 right 时,返回 true,否则返回 false。
operator func >=(String)
public const operator func >=(right: String): Bool
功能:判断两个字符串大小。
参数:
- right: String - 待比较的字符串。
返回值:
- Bool - 原字符串字典序大于或等于 right 时,返回 true,否则返回 false。
operator func [](Int64)
public const operator func [](index: Int64): Byte
功能:返回指定索引 index 处的 UTF-8 编码字节。
参数:
- index: Int64 - 要获取 UTF-8 编码字节的下标。
返回值:
- Byte - 获取得到下标对应的 UTF-8 编码字节。
异常:
- IndexOutOfBoundsException - 如果 index 小于 0 或大于等于字符串长度,抛出异常。
operator func [](Range<Int64>)
public const operator func [](range: Range<Int64>): String
功能:根据给定区间获取当前字符串的切片。
注意:
参数:
返回值:
- String - 字符串切片。
异常:
- IndexOutOfBoundsException - 如果切片范围超过原字符串边界,抛出异常。
- IllegalArgumentException - 如果 range.step 不等于 1 或者范围起止点不是字符边界,抛出异常。
异常类
class ArithmeticException
public open class ArithmeticException <: Exception {
public init()
public init(message: String)
}
功能:算术异常类,发生算术异常时使用。
父类型:
init()
public init()
功能:构造一个默认的 ArithmeticException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 ArithmeticException 实例。
参数:
- message: String - 异常提示信息。
func getClassName()
protected open override func getClassName(): String
功能:获得类名。
返回值:
- String - 类名字符串。
class Error
public open class Error <: ToString
功能:Error 是所有错误类的基类。该类不可被继承,不可初始化,但是可以被捕获到。
父类型:
prop message
public open prop message: String
功能:获取错误信息。
类型:String
func getClassName()
protected open func getClassName(): String
功能:获得类名。
返回值:
- String - 类名。
func getStackTrace()
public func getStackTrace(): Array<StackTraceElement>
功能:获取堆栈信息,每一条堆栈信息用一个 StackTraceElement 实例表示,最终返回一个 StackTraceElement 的数组。
返回值:
- Array<StackTraceElement> - 堆栈信息数组。
func getStackTraceMessage()
public open func getStackTraceMessage(): String
功能:获取堆栈信息。
返回值:
- String - 堆栈信息。
func printStackTrace()
public open func printStackTrace(): Unit
功能:向控制台打印堆栈信息。
func toString()
public open func toString(): String
功能:获取当前 Error 实例的字符串值,包括类名和错误信息。
返回值:
- String - 错误信息字符串。
class Exception
public open class Exception <: ToString {
public init()
public init(message: String)
}
功能:Exception 是所有异常类的父类。
支持构造一个异常类,设置、获取异常信息,转换为字符串,获取、打印堆栈,设置异常名(用于字符串表示)。
父类型:
prop message
public open prop message: String
功能:获取异常信息。
类型:String
init()
public init()
功能:构造一个默认的 Exception 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 Exception 实例。
参数:
- message: String - 异常提示信息。
func getClassName()
protected open func getClassName(): String
功能:获得类名。
返回值:
- String - 类名。
func getStackTrace()
public func getStackTrace(): Array<StackTraceElement>
功能:获取堆栈信息,每一条堆栈信息用一个 StackTraceElement 实例表示,最终返回一个 StackTraceElement 的数组。
返回值:
- Array<StackTraceElement> - 堆栈信息数组。
func printStackTrace()
public func printStackTrace(): Unit
功能:向控制台打印堆栈信息。
func toString()
public open func toString(): String
功能:获取当前 Exception 实例的字符串值,包括类名和异常信息。
返回值:
- String - 异常字符串。
class IllegalArgumentException
public open class IllegalArgumentException <: Exception {
public init()
public init(message: String)
}
功能:表示参数非法的异常类。
父类型:
init()
public init()
功能:构造一个默认的 IllegalArgumentException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 IllegalArgumentException 实例。
参数:
- message: String - 异常提示信息。
func getClassName()
protected override open func getClassName(): String
功能:获得类名。
返回值:
- String - 类名。
class IllegalFormatException
public open class IllegalFormatException <: IllegalArgumentException {
public init()
public init(message: String)
}
功能:表示变量的格式无效或不标准时的异常类。
父类型:
init()
public init()
功能:构造一个默认的 IllegalFormatException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 IllegalFormatException 实例。
参数:
- message: String - 异常提示信息。
class IllegalMemoryException
public class IllegalMemoryException <: Exception {
public init()
public init(message: String)
}
功能:表示内存操作错误的异常类。
父类型:
init()
public init()
功能:构造一个默认的 IllegalMemoryException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据指定异常信息构造 IllegalMemoryException 实例。
参数:
- message: String - 异常提示信息。
class IllegalStateException
public class IllegalStateException <: Exception {
public init()
public init(message: String)
}
功能:表示状态非法的异常类。
父类型:
init()
public init()
功能:构造一个默认的 IllegalStateException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 IllegalStateException 实例。
参数:
- message: String - 异常提示信息。
class IncompatiblePackageException
public class IncompatiblePackageException <: Exception {
public init()
public init(message: String)
}
功能:表示包不兼容的异常类。
父类型:
init()
public init()
功能:构造一个默认的 IncompatiblePackageException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 IncompatiblePackageException实例。
参数:
- message: String - 异常提示信息。
class IndexOutOfBoundsException
public class IndexOutOfBoundsException <: Exception {
public init()
public init(message: String)
}
功能:表示索引越界的异常类。
父类型:
init()
public init()
功能:构造一个默认的 IndexOutOfBoundsException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 IndexOutOfBoundsException 实例。
参数:
- message: String - 异常提示信息。
class InternalError
public class InternalError <: Error
功能:表示内部错误的错误类,该类不可初始化,但是可以被捕获到。
父类型:
class NegativeArraySizeException
public class NegativeArraySizeException <: Exception {
public init()
public init(message: String)
}
功能:表示数组大小为负数的异常类。
父类型:
init()
public init()
功能:构造一个默认的 NegativeArraySizeException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 NegativeArraySizeException 实例。
参数:
- message: String - 异常提示信息。
class NoneValueException
public class NoneValueException <: Exception {
public init()
public init(message: String)
}
功能:表示 Option<T> 实例的值为 None 的异常类,通常在 getOrThrow 函数中被抛出。
父类型:
init()
public init()
功能:构造一个默认的 NoneValueException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 NoneValueException 实例。
参数:
- message: String - 异常提示信息。
class OutOfMemoryError
public class OutOfMemoryError <: Error
功能:表示内存不足错误的错误类,该类不可被继承,不可初始化,但是可以被捕获到。
父类型:
class OverflowException
public class OverflowException <: ArithmeticException {
public init()
public init(message: String)
}
功能:表示算术运算溢出的异常类。
父类型:
init()
public init()
功能:构造一个默认的 OverflowException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据指定异常信息构造 OverflowException 实例。
参数:
- message: String - 异常提示信息。
class SpawnException
public class SpawnException <: Exception {
public init()
public init(message: String)
}
功能:线程异常类,表示线程处理过程中发生异常。
父类型:
init()
public init()
功能:构造一个默认的 SpawnException 实例,默认错误信息为空。
init(String)
public init(message: String)
功能:根据异常信息构造一个 SpawnException 实例。
参数:
- message: String - 异常提示信息。
class StackOverflowError
public class StackOverflowError <: Error
功能:表示堆栈溢出错误的错误类,该类不可被继承,不可初始化,但是可以被捕获到。
父类型:
func printStackTrace()
public override func printStackTrace(): Unit
功能:向控制台打印堆栈信息。
class TimeoutException
public class TimeoutException <: Exception {
public init()
public init(message: String)
}
功能:当阻塞操作超时时引发异常。
父类型:
init()
public init()
功能:构造一个默认的 TimeoutException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据指定异常信息构造 TimeoutException 实例。
参数:
- message: String - 异常提示信息。
class UnsupportedException
public class UnsupportedException <: Exception {
public init()
public init(message: String)
}
功能:表示功能未支持的异常类。
父类型:
init()
public init()
功能:构造一个默认的 UnsupportedException 实例,默认异常信息为空。
init(String)
public init(message: String)
功能:根据指定异常信息构造 UnsupportedException 实例。
参数:
- message: String - 异常提示信息。
仓颉并发编程示例
spawn 的使用
主线程和新线程同时尝试打印一些文本。
代码如下:
main(): Int64 {
spawn { =>
for (i in 0..10) {
println("New thread, number = ${i}")
sleep(100 * Duration.millisecond) /* 睡眠 100 毫秒 */
}
}
for (i in 0..5) {
println("Main thread, number = ${i}")
sleep(100 * Duration.millisecond) /* 睡眠 100 毫秒 */
}
return 0
}
运行结果:
Main thread, number = 0
New thread, number = 0
Main thread, number = 1
New thread, number = 1
Main thread, number = 2
New thread, number = 2
Main thread, number = 3
New thread, number = 3
Main thread, number = 4
New thread, number = 4
New thread, number = 5
注意:
上述打印信息仅做参考,实际结果受运行时序影响,呈现随机性。
由于主线程不会等待新线程执行结束,因此程序退出时新线程并未执行结束。
Future 的 get 的使用
主线程等待创建线程执行完再执行。
代码如下:
main(): Int64 {
let fut: Future<Unit> = spawn { =>
for (i in 0..10) {
println("New thread, number = ${i}")
/* 睡眠 100 毫秒 */
sleep(100 * Duration.millisecond)
}
}
/* 等待线程完成 */
fut.get()
for (i in 0..5) {
println("Main thread, number = ${i}")
/* 睡眠 100 毫秒 */
sleep(100 * Duration.millisecond)
}
return 0
}
运行结果:
New thread, number = 0
New thread, number = 1
New thread, number = 2
New thread, number = 3
New thread, number = 4
New thread, number = 5
New thread, number = 6
New thread, number = 7
New thread, number = 8
New thread, number = 9
Main thread, number = 0
Main thread, number = 1
Main thread, number = 2
Main thread, number = 3
Main thread, number = 4
取消仓颉线程
子线程接收主线程发送的取消请求。
main(): Unit {
/* 创建线程 */
let future = spawn {
while (true) {
if (Thread.currentThread.hasPendingCancellation) {
return 0
}
}
return 1
}
/* 发起线程取消请求 */
future.cancel()
let res = future.get()
println(res)
}
运行结果:
0
使用 CString 与 C 代码交互示例
C 代码中分别提供两个函数: getCString 函数,用于返回一个 C 侧的字符串指针; printCString 函数,用于打印来自仓颉侧 CString 。
#include <stdio.h>
char *str = "CString in C code.";
char *getCString() { return str; }
void printCString(char *s) { printf("%s\n", s); }
在仓颉代码中,创建一个 CString 对象,传递给 C 侧打印。并且获取 C 侧字符串,在仓颉侧打印:
示例:
foreign func getCString(): CString
foreign func printCString(s: CString): Unit
main() {
// 仓颉侧构造 CString 实例,传递到 C 侧
unsafe {
let s: CString = LibC.mallocCString("CString in Cangjie code.")
printCString(s)
LibC.free(s)
}
unsafe {
// C 侧申请字符串指针,传递到仓颉侧成为 CString 实例,再转换为仓颉字符串 String 类型
let cs = getCString()
println(cs.toString())
}
// 在 try-with-resource 语法上下文中使用 CStringResource 自动管理 CString 内存
let cs = unsafe { LibC.mallocCString("CString in Cangjie code.") }
try (csr = cs.asResource()) {
unsafe { printCString(csr.value) }
}
0
}
运行结果:
CString in Cangjie code.
CString in C code.
CString in Cangjie code.
说明:
编译方式:先将 C 代码编译成静态库或动态库,然后编译仓颉代码并链接 C 库。 假设 C 文件为 test.c,仓颉文件为 test.cj,编译过程如下:
- 使用 gcc 命令
gcc -fPIC -shared test.c -o libtest.so,编出 C 库libtest.so。- 使用 cjc 命令
cjc -L . -l test test.cj,编出可执行文件main。
std.argopt
功能介绍
argopt 包提供从命令行参数字符串解析出参数名和参数值的相关能力。
命令行参数是在命令行中传递给程序的参数,它们用于指定程序的配置或行为。例如,一个命令行程序可能有一个参数来指定它要处理的文件的名称,或者一个参数来指定使用的数据库。这些参数通常会被解析并传递给程序的代码,以便程序可以根据这些参数正确地执行其功能。
命令行参数:通常以是否由 - 为前缀区分,可以分为选项和非选项。
- 选项:以
-为前缀。- 短选项:以单个
-为前缀且仅含单个字符的选项。 - 长选项:以
--为前缀的选项,一般包含多个字符。 - 短前缀长选项:以单个
-为前缀但包含多个字符的选项。 - 短选项组合:以
-为前缀,将多个短选项以任意顺序组合的选项。
- 短选项:以单个
- 非选项:不以
-为前缀。
注意:
单独的 "--" 后面出现的所有参数也会被视作非选项,如 "-f -- a -b --cde"中,"a"、 "-b"、 "--cde" 都是非选项。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| parseArguments | 根据给定的输入和规格,解析出对应的参数。 |
类
| 类名 | 功能 |
|---|---|
| ArgOpt (deprecated) | Argopt 用于解析命令行参数,并提供了获取解析结果的功能。 |
枚举
| 枚举名 | 功能 |
|---|---|
| ArgumentMode | 参数模式。 |
| ArgumentSpec | 参数规格。 |
结构体
| 结构体名 | 功能 |
|---|---|
| ParsedArguments | 参数解析结果。 |
异常类
| 异常类名 | 功能 |
|---|---|
| ArgumentParseException | 解析出错时抛出此异常。 |
函数
func parseArguments(Array<String>, Array<ArgumentSpec>)
public func parseArguments(args: Array<String>, specs: Array<ArgumentSpec>): ParsedArguments
功能:根据提供的参数规范 specs 解析命令行参数 args,返回一个结构化的对象,包含解析后的选项和非选项参数。
该函数将 args 中的每个参数与 specs 中定义的选项进行匹配。对于匹配成功的选项,它会将选项名称和对应的值加入到 options 中,未匹配的参数会被当作非选项参数处理,并添加到 nonOptions 中。此外,当解析到 -- 时,将提前终止选项扫描,其后的所有参数都将被视作非选项。
该函数支持 短选项、长选项、短前缀长选项、短选项组合、非选项、非法选项 的解析处理。
specs 的每个 ArgumentSpec 持有的 ArgumentMode 决定了参数的处理方式。
-
对于长选项,根据不同的 ArgumentMode 仅可以处理以下格式:
- RequiredValue:
--option=valueor--option value - OptionalValue:
--option=valueor--option - NoValue:
--option
- RequiredValue:
-
对于短选项,根据不同的 ArgumentMode 仅可以处理以下格式:
- RequiredValue:
-ovor-o v - OptionalValue:
-ovor-o - NoValue:
-o
- RequiredValue:
对于短选项组合的场景:
- 当解析到第一个非 NoValue 的选项时:
- 如果该选项为 OptionalValue,紧随选项后的内容若存在,则会被作为该选项的值来解析。
- 如果该选项为 RequiredValue,紧随选项后的内容会被作为该选项的值来解析。
- 如果一组短选项可以组合成长选项的字面值,那么视为长选项而非短选项组合,如 -abc 同时已定义了
abc的长选项和abc三个短选项,会被视作长选项解析。
如果 ArgumentSpec 提供了 lambda 回调函数,该回调会在解析成功后被调用,处理解析到的参数值。
如果传入的 args 存在对同一选项多次赋值的情况,则以最后一次的值作为该选项的值。
参数:
-
specs: Array<ArgumentSpec> - 参数的规范。
返回值:
- ParsedArguments - 参数解析的结果。
异常:
-
ArgumentParseException - 当参数解析失败或解析到
非法选项时,抛出异常。 -
IllegalArgumentException - 当定义了相同
name的 ArgumentSpec 时,抛出异常。
类
class Argopt (deprecated)
public class ArgOpt {
public init(shortArgFormat: String)
public init(longArgList: Array<String>)
public init(shortArgFormat: String, longArgList: Array<String>)
public init(args: Array<String>, shortArgFormat: String, longArgList: Array<String>)
}
功能:用于解析命令行参数,并提供了获取解析结果的功能。
一个命令行参数是由前缀符号、参数名及参数值组成。
其中, "-" 表示短参(短命令行参数)的前缀,"--" 表示长参(长命令行参数)的前缀。可解析的短参参数名只能是字母,可解析长参参数名字符串需满足:以字母开头,参数名中不能包含 "="。
例如:"-a123" 和 "--target=abc.txt" 为两个命令行参数,"a" 为短参名,"target" 为长参名。而 "-123" 和 "--tar=get=abc.txt" 则是错误的命令行参数。
该类允许用户指定参数名和参数字符串,并提供根据参数名解析字符串的方法。
用户指定短参名和长参名时格式如下:
- 短参名字符串的参数,格式为:"a:",规范为:一位字母和 ":" 的组合,例如:"ab:",该例仅解析 "b" 作为短参名。
- 长参名字符串数组参数,字符串格式为:"--testA=" 或 "testA=",规范为:"--" + 长参参数名 + "="(前缀"--"可省略)。
根据参数名解析命令行参数时,若命令行参数格式正确且有对应的参数名,可正确解析并被用户获取,否则不会解析。
例如:参数名为 "a:b:",命令行参数为 "-a123 -cofo",将解析出参数名为 "a",参数值为 "123" 的命令行参数。"-cofo" 则不会解析。
注意:
未来版本即将废弃,使用 parseArguments 代替。
init(Array<String>)
public init(longArgList: Array<String>)
功能:构造 ArgOpt 实例,并从列表的字符串中解析长参名。
参数:
异常:
- IllegalArgumentException - 当字符串数组中的长参名字符串不符合规范,或字符串不符合 UTF-8 编码,或不存在该 Unicode 字符时,抛出异常。
init(Array<String>, String, Array<String>)
public init(args: Array<String>, shortArgFormat: String, longArgList: Array<String>)
功能:构造 ArgOpt 实例,并从短参名字符串中解析短参名,从列表的字符串中解析长参名。若解析成功,则依据解析出的参数名从参数 args 指定的命令行参数中解析参数名的对应取值。
参数:
- args: Array<String> - 待解析的命令行参数字符串数组。
- shortArgFormat: String - 包含短参名的字符串。
- longArgList: Array<String> - 包含长参名的字符串数组。
异常:
- IllegalArgumentException - 当短参名字符串不符合规范,或字符串数组中的长参名字符串不符合规范,或字符串不符合 UTF-8 编码,或不存在该 Unicode 字符时,抛出异常。
init(String)
public init(shortArgFormat: String)
功能:构造 ArgOpt 实例,并从短参名字符串中解析短参名。
参数:
- shortArgFormat: String - 包含短参名的字符串。
异常:
- IllegalArgumentException - 当短参名字符串不符合规范,或字符串不符合 UTF-8 编码,或不存在该 Unicode 字符时,抛出异常。
init(String, Array<String>)
public init(shortArgFormat: String, longArgList: Array<String>)
功能:构造 ArgOpt 实例,并从短参名字符串中解析短参名,从列表的字符串中解析长参名。
参数:
异常:
- IllegalArgumentException - 当短参名字符串不符合规范,或字符串数组中的长参名字符串不符合规范,或字符串不符合 UTF-8 编码,或不存在该 Unicode 字符时,抛出异常。
func getArg(String)
public func getArg(arg: String): Option<String>
功能:返回参数 arg 指定参数的解析值。
参数:
- arg: String - 前缀和参数名组成的字符串(可省略前缀)。
返回值:
func getArgumentsMap()
public func getArgumentsMap(): HashMap<String, String>
功能:获取所有已解析的参数名和参数值,以哈希表的形式返回。
返回值:
func getUnparseArgs()
public func getUnparseArgs(): Array<String>
功能:返回未被解析的命令行参数。
返回值:
枚举
enum ArgumentMode
public enum ArgumentMode <: ToString & Equatable<ArgumentMode> {
| NoValue
| RequiredValue
| OptionalValue
}
功能:描述选项的参数模式。
父类型:
NoValue
NoValue
功能:表示选项的值是不存在的。
OptionalValue
OptionalValue
功能:表示选项的值是可选的。
RequiredValue
RequiredValue
功能:表示选项的值是必须的。
func toString()
public func toString(): String
功能:获取参数模式字符串。
返回值:
- String - 参数模式字符串。
operator func ==(ArgumentMode)
public operator func ==(that: ArgumentMode): Bool
功能:比较参数模式是否相同。
参数:
- that: ArgumentMode - 参数模式。
返回值:
- Bool - 相同时返回
true,否则返回false。
enum ArgumentSpec
public enum ArgumentSpec {
| Short(Rune, ArgumentMode)
| Short(Rune, ArgumentMode, (String) -> Unit)
| Long(String, ArgumentMode)
| Long(String, ArgumentMode, (String) -> Unit)
| Full(String, Rune, ArgumentMode)
| Full(String, Rune, ArgumentMode, (String) -> Unit)
| NonOptions((Array<String>) -> Unit)
}
功能:描述参数的规范。
Full(String, Rune, ArgumentMode)
Full(String, Rune, ArgumentMode)
功能:表示同时存在长选项和短选项。
Full(String, Rune, ArgumentMode, (String) -> Unit)
Full(String, Rune, ArgumentMode, (String) -> Unit)
功能:表示同时存在长选项和短选项,并持有一个 lambda 回调函数。
Long(String, ArgumentMode)
Long(String, ArgumentMode)
功能:表示是一个长选项规格。
Long(String, ArgumentMode, (String) -> Unit)
Long(String, ArgumentMode, (String) -> Unit)
功能:表示是一个长选项,同时持有一个 lambda 回调函数。
NonOptions((Array<String>) -> Unit)
NonOptions((Array<String>) -> Unit)
功能:表示是一个非选项。
Short(Rune, ArgumentMode)
Short(Rune, ArgumentMode)
功能:表示是一个短选项。
Short(Rune, ArgumentMode, (String) -> Unit)
Short(Rune, ArgumentMode, (String) -> Unit)
功能:表示是一个短选项,同时持有一个 lambda 回调函数。
结构体
struct ParsedArguments
public struct ParsedArguments {
}
功能:存储参数解析的结果。
prop nonOptions
public prop nonOptions: Array<String>
功能:存储参数解析得到的非选项。
prop options
public prop options: ReadOnlyMap<String, String>
功能:存储参数解析得到的选项。
类型:ReadOnlyMap
异常
class ArgumentParseException
public class ArgumentParseException <: Exception {
public init()
public init(message: String)
}
功能:参数解析异常类。当参数解析出错(如:不识别的选项、缺少值的选项)时,抛出此异常。
父类型:
init()
public init()
功能:构造一个不带异常信息的实例。
init(String)
public init(message: String)
功能:根据异常信息构造异常实例。
参数:
- message: String - 异常信息。
命令行解析
不带回调
示例:
import std.env.*
import std.argopt.*
main(args: Array<String>): Unit {
let argSpecs = [
Short(r'a', NoValue),
Long("test1", RequiredValue),
Full("test2", r'c', OptionalValue)
]
try {
var result = parseArguments(args, argSpecs)
println("Got a: ${result.options.contains('a')}")
println("Test1: ${result.options.get("test1")}")
println("Test2: ${result.options.get("test2")}")
println("c: ${result.options.get('c')}")
println("NonOptions: ${result.nonOptions}")
} catch (e: ArgumentParseException) {
println("Usage: error")
return
}
}
运行结果:
$ cjc main.cj && ./main -a --test1 t1val
Got a: true
Test1: Some(t1val)
Test2: None
c: None
NonOptions: []
$ cjc main.cj && ./main -a --test1
Usage: error
$ cjc main.cj && ./main -a --test1 t1val --test2
Got a: true
Test1: Some(t1val)
Test2: Some()
c: None
NonOptions: []
$ cjc main.cj && ./main -a --test1 t1val --test2 t2val
Got a: true
Test1: Some(t1val)
Test2: Some()
c: None
NonOptions: [t2val]
$ cjc main.cj && ./main -a --test1 t1val -ct2val
Got a: true
Test1: Some(t1val)
Test2: None
c: Some(t2val)
NonOptions: []
带回调
示例:
import std.argopt.*
main(args: Array<String>): Unit {
let argSpecs = [
Short(r'a', NoValue) {_ => println("Got a")},
Long("test1", RequiredValue) {v => println("Got test1: `${v}`")},
Full("test2", r'c', OptionalValue) {v => println("Got test2: `${v}`")},
NonOptions {v => println("Got NonOptions: ${v}")}
]
try {
parseArguments(args, argSpecs)
} catch (e: ArgumentParseException) {
println("Usage: xxxx")
}
}
运行结果:
$ cjc main.cj && ./main -a --test1 t1val --test2 t2val
Got a
Got test1: `t1val`
Got test2: ``
Got NonOptions: [t2val]
长命令行参数解析 (deprecated)
示例:
import std.argopt.*
main() {
let shortArgs: Array<String> = ["--test1=abc", "--test2=123", "--test3 xyz"]
let shortArgName: String = ""
let longArgName: Array<String> = ["--test1=", "test2=", "--test3="]
let ao: ArgOpt = ArgOpt(shortArgs, shortArgName, longArgName)
println(ao.getArg("--test1") ?? "None")
println(ao.getArg("--test2") ?? "None")
println(ao.getArg("--test3") ?? "None")
}
运行结果:
abc
123
None
短命令行参数解析 (deprecated)
示例:
import std.argopt.*
main() {
let shortArgs: Array<String> = ["-a123", "-bofo", "-cccc"]
let shortArgName: String = "a:b:c"
let longArgName: Array<String> = Array<String>()
let ao: ArgOpt = ArgOpt(shortArgs, shortArgName, longArgName)
println(ao.getArg("-a") ?? "None")
println(ao.getArg("-b") ?? "None")
println(ao.getArg("-c") ?? "None")
}
运行结果:
123
ofo
None
std.ast
功能介绍
ast 包主要包含了仓颉源码的语法解析器和仓颉语法树节点,提供语法解析函数。可将仓颉源码的词法单元(Tokens)解析为抽象语法树(Abstract Syntax Tree)节点对象。
仓颉 ast 包提供了 Macro With Context 的相关函数,用于在宏展开时获取展开过程中的上下文相关信息。在嵌套宏场景下,内层宏可以调用库函数 assertParentContext(String) 来保证内层宏调用一定嵌套在特定的外层宏调用中。如果内层宏调用这个函数时没有嵌套在给定的外层宏调用中,该函数将抛出一个错误。同时,函数 insideParentContext(String) 也用于检查内层宏调用是否嵌套在特定的外层宏调用中,但是返回一个布尔值。Macro With Context 的相关函数只能作为函数被直接调用,不能赋值给变量,不能作为实参或返回值使用。
Macro With Context 相关函数如下:
- assertParentContext(String)
- getChildMessages(String)
- insideParentContext(String)
- setItem(String, Bool)
- setItem(String, Int64)
- setItem(String, String)
- setItem(String, Tokens)
API 列表
函数
| 函数名 | 功能 |
|---|---|
| assertParentContext(String) | 检查当前宏调用是否在特定的宏调用内。若检查不符合预期,编译器出现一个错误提示。 |
| cangjieLex(String) | 将字符串转换为 Tokens 类型。 |
| cangjieLex(String, Bool) | 将字符串转换为 Tokens 类型。 |
| compareTokens(Tokens, Tokens) | 用于比较两个 Tokens 是否一致。 |
| diagReport(DiagReportLevel, Tokens, String, String) | 报错接口,在编译过程的宏展开阶段输出错误提示信息,支持 WARNING 和 ERROR 两个等级的报错。 |
| getChildMessages(String) | 获取特定内层宏发送的信息。 |
| getTokenKind(UInt16) | 将词法单元种类序号转化为 TokenKind。 |
| insideParentContext(String) | 检查当前宏调用是否在特定的宏调用内,返回一个布尔值。 |
| parseDecl(Tokens, String) | 用于解析一组词法单元,获取一个 Decl 类型的节点。 |
| parseDeclFragment(Tokens, Int64) | 用于解析一组词法单元,获取一个 Decl 类型的节点和继续解析节点的索引。 |
| parseExpr(Tokens) | 用于解析一组词法单元,获取一个 Expr 类型的节点。 |
| parseExprFragment(Tokens, Int64) | 用于解析一组词法单元,获取一个 Expr 类型的节点和继续解析节点的索引。 |
| parsePattern(Tokens) | 用于解析一组词法单元,获取一个 Pattern 类型的节点。 |
| parsePatternFragment(Tokens, Int64) | 用于解析一组词法单元,获取一个 Pattern 类型的节点和继续解析节点的索引。 |
| parseProgram(Tokens) | 用于解析单个仓颉文件的源码,获取一个 Program 类型的节点。 |
| parseType(Tokens) | 用于解析一组词法单元,获取一个 TypeNode 类型的节点。 |
| parseTypeFragment(Tokens, Int64) | 用于解析一组词法单元,获取一个 TypeNode 类型的节点和继续解析节点的索引。 |
| setItem(String, Bool) | 内层宏通过该接口发送 Bool 类型的信息到外层宏。 |
| setItem(String, Int64) | 内层宏通过该接口发送 Int64 类型的信息到外层宏。 |
| setItem(String, String) | 内层宏通过该接口发送 String 类型的信息到外层宏。 |
| setItem(String, Tokens) | 内层宏通过该接口发送 Tokens 类型的信息到外层宏。 |
接口
类
| 类名 | 功能 |
|---|---|
| Annotation | 表示编译器内置的注解节点。 |
| Argument | 表示函数调用的实参节点。 |
| ArrayLiteral | 表示 Array 字面量节点。 |
| AsExpr | 表示一个类型检查表达式。 |
| AssignExpr | 表示赋值表达式节点。 |
| BinaryExpr | 表示一个二元操作表达式节点。 |
| Block | 表示块节点。 |
| Body | 表示 Class 类型、 Struct 类型、 Interface 类型以及扩展中由 {} 和内部的一组声明节点组成的结构。 |
| CallExpr | 表示函数调用节点节点。 |
| ClassDecl | 类定义节点。 |
| ConstPattern | 表示常量模式节点。 |
| Constructor | 表示 enum 类型中的 Constructor 节点。 |
| Decl | 所有声明节点的父类,继承自 Node 节点,提供了所有声明节点的通用接口。 |
| DoWhileExpr | 表示 do-while 表达式。 |
| EnumDecl | 表示一个 Enum 定义节点。 |
| EnumPattern | 表示 enum 模式节点。 |
| ExceptTypePattern | 表示一个用于异常模式状态下的节点。 |
| Expr | 所有表达式节点的父类,继承自 Node 节点。 |
| ExtendDecl | 表示一个扩展定义节点。 |
| ForInExpr | 表示 for-in 表达式。 |
| FuncDecl | 表示一个函数定义节点。 |
| FuncParam | 表示函数参数节点,包括非命名参数和命名参数。 |
| FuncType | 表示函数类型节点。 |
| GenericConstraint | 表示一个泛型约束节点。 |
| GenericParam | 表示一个类型形参节点。 |
| IfExpr | 表示条件表达式。 |
| ImportContent | 表示包导入节点中的导入项。 |
| ImportList | 表示包导入节点。 |
| IncOrDecExpr | 表示包含自增操作符(++)或自减操作符(--)的表达式。 |
| InterfaceDecl | 表示接口定义节点。 |
| IsExpr | 表示一个类型检查表达式。 |
| JumpExpr | 表示循环表达式的循环体中的 break 和 continue。 |
| LambdaExpr | 表示 Lambda 表达式,是一个匿名的函数。 |
| LetPatternExpr | 表示 let 声明的解构匹配节点。 |
| LitConstExpr | 表示一个常量表达式节点。 |
| MacroDecl | 表示一个宏定义节点。 |
| MacroExpandDecl | 表示宏调用节点。 |
| MacroExpandExpr | 表示宏调用节点。 |
| MacroExpandParam | 表示宏调用节点。 |
| MacroMessage | 记录内层宏发送的信息。 |
| MainDecl | 表示一个 main 函数定义节点。 |
| MatchCase | 表示 match 表达式中的一个 case 节点。 |
| MatchExpr | 表示模式匹配表达式实现模式匹配。 |
| MemberAccess | 表示成员访问表达式。 |
| Modifier | 表示该定义具备某些特性,通常放在定义处的最前端。 |
| Node | 所有仓颉语法树节点的父类。 |
| OptionalExpr | 表示一个带有问号操作符的表达式节点。 |
| PackageHeader | 表示包声明节点。 |
| ParenExpr | 表示一个括号表达式节点,是指使用圆括号括起来的表达式。 |
| ParenType | 表示括号类型节点。 |
| Pattern | 所有模式匹配节点的父类,继承自 Node 节点。 |
| PrefixType | 表示带问号的前缀类型节点。 |
| PrimaryCtorDecl | 表示一个主构造函数节点。 |
| PrimitiveType | 表示一个基本类型节点。 |
| PrimitiveTypeExpr | 表示基本类型表达式节点。 |
| Program | 表示一个仓颉源码文件节点。 |
| PropDecl | 表示一个属性定义节点。 |
| QualifiedType | 表示一个用户自定义成员类型。 |
| QuoteExpr | 表示 quote 表达式节点。 |
| QuoteToken | 表示 quote 表达式节点内任意合法的 token。 |
| RangeExpr | 表示包含区间操作符的表达式。 |
| RefExpr | 表示一个使用自定义类型节点相关的表达式节点。 |
| RefType | 表示一个用户自定义类型节点。 |
| ReturnExpr | 表示 return 表达式节点。 |
| SpawnExpr | 表示 Spawn 表达式。 |
| StructDecl | 表示一个 Struct 节点。 |
| SubscriptExpr | 表示索引访问表达式。 |
| SynchronizedExpr | 表示 synchronized 表达式。 |
| ThisType | 表示 This 类型节点。 |
| ThrowExpr | 表示 throw 表达式节点。 |
| Tokens | 对 Token 序列进行封装的类型。 |
| TokensIterator | 实现 Tokens 的迭代器功能。 |
| TrailingClosureExpr | 表示尾随 Lambda 节点。 |
| TryExpr | 表示 try 表达式节点。 |
| TupleLiteral | 表示元组字面量节点。 |
| TuplePattern | 表示 Tuple 模式节点。 |
| TupleType | 表示元组类型节点。 |
| TypeAliasDecl | 表示类型别名节点。 |
| TypeConvExpr | 表示类型转换表达式。 |
| TypeNode | 所有类型节点的父类,继承自 Node。 |
| TypePattern | 表示类型模式节点。 |
| UnaryExpr | 表示一个一元操作表达式节点。 |
| VArrayExpr | 表示 VArray 的实例节点。 |
| VArrayType | 表示 VArray 类型节点。 |
| VarDecl | 表示变量定义节点。 |
| VarOrEnumPattern | 表示当模式的标识符为 Enum 构造器时的节点。 |
| VarPattern | 表示绑定模式节点。 |
| Visitor | 一个抽象类,其内部默认定义了访问不同类型 AST 节点访问(visit)函数。 |
| WhileExpr | 表示 while 表达式。 |
| WildcardExpr | 表示通配符表达式节点。 |
| WildcardPattern | 表示通配符模式节点。 |
枚举
| 枚举名 | 功能 |
|---|---|
| DiagReportLevel | 表示报错接口的信息等级,支持 ERROR 和 WARNING 两种格式。 |
| ImportKind | 表示导入语句的类型,包括单导入、别名导入、全导入和多导入四种类型。 |
| TokenKind | 表示仓颉编译内部所有的词法结构,包括符号、关键字、标识符、换行等。 |
结构体
异常类
| 异常类名 | 功能 |
|---|---|
| ASTException | ast 库的异常类,在 ast 库调用过程中发生异常时使用。 |
| MacroContextException | ast 库的上下文宏异常类,在上下文宏的相关接口中发生异常时使用。 |
| ParseASTException | ast 库的解析异常类,在节点解析过程中发生异常时使用。 |
函数
func assertParentContext(String)
public func assertParentContext(parentMacroName: String): Unit
功能:检查当前宏调用是否在特定的宏调用内。若检查不符合预期,编译器出现一个错误提示。
注意:
该函数只能作为函数被直接调用,不能作为赋值给变量,不能作为实参或返回值使用。
参数:
- parentMacroName: String - 待检查的外层宏调用的名字。
func cangjieLex(String)
public func cangjieLex(code: String): Tokens
功能:将字符串转换为 Tokens 对象。
参数:
- code: String - 待词法解析的字符串。
返回值:
异常:
- IllegalMemoryException - 当申请内存失败时,抛出异常。
- IllegalArgumentException - 当输入的 code 无法被正确的解析为 Tokens 时,抛出异常。
func cangjieLex(String, Bool)
public func cangjieLex(code: String, truncated: Bool): Tokens
功能:将字符串转换为 Tokens 对象。
参数:
返回值:
异常:
- IllegalMemoryException - 当申请内存失败,抛出异常时,抛出异常。
- IllegalArgumentException - 当输入的 code 无法被正确的解析为 Tokens 时,抛出异常。
func compareTokens(Tokens, Tokens)
public func compareTokens(tokens1: Tokens, tokens2: Tokens): Bool
功能:用于比较两个Tokens是否一致。
参数:
返回值:
func diagReport(DiagReportLevel, Tokens, String, String)
public func diagReport(level: DiagReportLevel, tokens: Tokens, message: String, hint: String): Unit
功能:报错接口,在编译过程的宏展开阶段输出错误提示信息,支持 WARNING 和 ERROR 两个等级的报错。
注意:
参数:
- level: DiagReportLevel - 报错信息等级。
- tokens: Tokens - 报错信息中所引用源码内容对应的 Tokens。
- message: String - 报错的主信息。
- hint: String - 辅助提示信息。
异常:
-
ASTException - 当输入的 Tokens 存在以下错误时,抛出异常。
func getChildMessages(String)
public func getChildMessages(children:String): ArrayList<MacroMessage>
功能:获取特定内层宏发送的信息。
注意:
该函数只能作为函数被直接调用,不能作为赋值给变量,不能作为实参或返回值使用。
参数:
- children: String - 待接收信息的内层宏名称。
返回值:
- ArrayList<MacroMessage> - 返回一组 MacroMessage 的对象。
func getTokenKind(UInt16)
public func getTokenKind(no: UInt16): TokenKind
功能:将词法单元种类序号转化为 TokenKind。
参数:
- no: UInt16 - 需要转换的序号。
返回值:
注意:
当前 SINGLE_QUOTED_STRING_LITERAL 和 STRING_LITERAL 共用序号 147,输入序号 147 只能获得 STRING_LITERAL,其他 TokenKind 无共用序号情况。
func insideParentContext(String)
public func insideParentContext(parentMacroName: String): Bool
功能:检查当前宏调用是否在特定的宏调用内,返回一个布尔值。
注意:
- 在嵌套宏场景下,内层宏也可以通过发送键/值对的方式与外层宏通信。当内层宏执行时,通过调用标准库函数 setItem 向外层宏发送信息;随后,当外层宏执行时,调用标准库函数 getChildMessages 接收每一个内层宏发送的信息(一组键/值对映射)。
- 该函数只能作为函数被直接调用,不能作为赋值给变量,不能作为实参或返回值使用。
参数:
- parentMacroName: String - 待检查的外层宏调用的名字。
返回值:
- Bool - 若当前宏嵌套在特定的宏调用内,返回 true。
func parseDecl(Tokens, String)
public func parseDecl(input: Tokens, astKind!: String = ""): Decl
功能:用于解析一组词法单元,获取一个 Decl 类型的节点。
注意:
该函数不支持解析 FuncParam 类型。
参数:
- input: Tokens - 待解析源码的词法单元。
- astKind!: String - 用于指定解析特定的节点类型,有效支持的值为:
PrimaryCtorDecl和PropMemberDecl。PrimaryCtorDecl: 解析主构造函数。PropMemberDecl: 解析prop声明的getter和setter函数。
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 Decl 节点时,抛出异常,异常中包含报错提示信息。
示例:
-
以下代码展示
astKind设为PropMemberDecl的案例。在这个参数下,可以使用parseDecl解析prop的getter和setter函数,解析结果为FuncDecl类型(如果不设置astKind,则会因为没有func关键字而无法解析)。import std.ast.* main() { let getter = quote( get() { _val } ) let setter = quote( set(v) { _val = v }) let getterDecl = parseDecl(getter, astKind: "PropMemberDecl") let setterDecl = parseDecl(setter, astKind: "PropMemberDecl") println((getterDecl as FuncDecl).getOrThrow().block.toTokens()) println((setterDecl as FuncDecl).getOrThrow().block.toTokens()) }运行结果:
{ _val } { _val = v } -
以下代码展示
astKind设为PrimaryCtorDecl的案例。在这个参数下,可以使用parseDecl解析主构造函数节点,解析结果为PrimaryCtorDecl类型(如果不设置astKind,则会因为没有func关键字而无法解析)。import std.ast.* main() { let ctor = quote( Point(var x: Int32, var y: Int32) {} ) let ctorDecl = parseDecl(ctor, astKind: "PrimaryCtorDecl") println(ctorDecl is PrimaryCtorDecl) println(ctorDecl.toTokens()) }运行结果:
true Point(var x: Int32, var y: Int32) { }
func parseDeclFragment(Tokens, Int64)
public func parseDeclFragment(input: Tokens, startFrom !: Int64 = 0): (Decl, Int64)
功能:用于解析一组词法单元,获取一个 Decl 类型的节点和继续解析节点的索引。
注意:
该函数不支持解析 FuncParam、 PropDecl、PrimaryCtorDecl 类型。
参数:
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 Decl 节点时,抛出异常,异常中包含报错提示信息。
func parseExpr(Tokens)
public func parseExpr(input: Tokens): Expr
功能:用于解析一组词法单元,获取一个 Expr 类型的节点。
参数:
- input: Tokens - 待解析源码的词法单元。
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 Expr 节点时,抛出异常,异常中包含报错提示信息。
func parseExprFragment(Tokens, Int64)
public func parseExprFragment(input: Tokens, startFrom !: Int64 = 0): (Expr, Int64)
功能:用于解析一组词法单元,获取一个 Expr 类型的节点和继续解析节点的索引。
参数:
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 Expr 节点时,抛出异常,异常中包含报错提示信息。
func parsePattern(Tokens)
public func parsePattern(input: Tokens): Pattern
功能:用于解析一组词法单元,获取一个 Pattern 类型的节点。
参数:
- input: Tokens - 待解析源码的词法单元。
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 Pattern 节点时,抛出异常,异常中包含报错提示信息。
func parsePatternFragment(Tokens, Int64)
public func parsePatternFragment(input: Tokens, startFrom !: Int64 = 0): (Pattern, Int64)
功能:用于解析一组词法单元,获取一个 Pattern 类型的节点和继续解析节点的索引。
参数:
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 Pattern 节点时,抛出异常,异常中包含报错提示信息。
func parseProgram(Tokens)
public func parseProgram(input: Tokens): Program
功能:用于解析单个仓颉文件的源码,获取一个 Program 类型的节点。
参数:
- input: Tokens - 待解析源码的词法单元。
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 Program 节点时,抛出异常,异常中包含报错提示信息。
func parseType(Tokens)
public func parseType(input: Tokens): TypeNode
功能:用于解析一组词法单元,获取一个 TypeNode 类型的节点。
参数:
- input: Tokens - 待解析源码的词法单元。
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 TypeNode 节点时,抛出异常。
func parseTypeFragment(Tokens, Int64)
public func parseTypeFragment(input: Tokens, startFrom !: Int64 = 0): (TypeNode, Int64)
功能:用于解析一组词法单元,获取一个 TypeNode 类型的节点和继续解析节点的索引。
参数:
返回值:
异常:
- ParseASTException - 当输入的 Tokens 类型无法构造为 TypeNode 节点时,抛出异常。
func setItem(String, Bool)
public func setItem(key: String, value: Bool): Unit
功能:内层宏通过该接口发送 Bool 类型的信息到外层宏。
注意:
该函数只能作为函数被直接调用,不能作为赋值给变量,不能作为实参或返回值使用。
参数:
func setItem(String, Int64)
public func setItem(key: String, value: Int64): Unit
功能:内层宏通过该接口发送 Int64 类型的信息到外层宏。
注意:
该函数只能作为函数被直接调用,不能作为赋值给变量,不能作为实参或返回值使用。
参数:
func setItem(String, String)
public func setItem(key: String, value: String): Unit
功能:内层宏通过该接口发送 String 类型的信息到外层宏。
注意:
该函数只能作为函数被直接调用,不能作为赋值给变量,不能作为实参或返回值使用。
参数:
func setItem(String, Tokens)
public func setItem(key: String, value: Tokens): Unit
功能:内层宏通过该接口发送 Tokens 类型的信息到外层宏。
注意:
该函数只能作为函数被直接调用,不能作为赋值给变量,不能作为实参或返回值使用。
参数:
接口
interface ToBytes
public interface ToBytes {
func toBytes(): Array<UInt8>
}
功能:提供对应类型的序列化功能。
func toBytes()
func toBytes(): Array<UInt8>
功能:提供对应类型的序列化功能。
返回值:
interface ToTokens
public interface ToTokens {
func toTokens(): Tokens
}
功能:实现对应类型的实例到 Tokens 类型转换的接口,作为支持 quote 插值操作必须实现的接口。
func toTokens()
func toTokens(): Tokens
功能:实现对应类型的实例到 Tokens 类型的转换。
返回值:
extend Array <: ToTokens
extend<T> Array<T> <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 Array 类型到 Tokens 类型的转换,仅支持数值类型、Rune 类型、Bool 类型、String 类型。
返回值:
extend ArrayList <: ToTokens
extend<T> ArrayList<T> <: ToTokens
功能:实现 ArrayList 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 ArrayList 类型到 Tokens 类型的转换,目前支持的类型有 Decl、Node、Constructor、Argument、FuncParam、MatchCase、Modifier、Annotation、ImportList、Pattern、TypeNode 等。
返回值:
extend Bool <: ToTokens
extend Bool <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
extend Float16 <: ToTokens
extend Float16 <: ToTokens
功能:实现 Float16 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 Float16 类型到 Tokens 类型的转换。
返回值:
extend Float32 <: ToTokens
extend Float32 <: ToTokens
功能:实现 Float32 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 Float32 类型到 Tokens 类型的转换。
返回值:
extend Float64 <: ToTokens
extend Float64 <: ToTokens
功能:实现 Float64 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 Float64 类型到 Tokens 类型的转换。
返回值:
extend Int16 <: ToTokens
extend Int16 <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
extend Int32 <: ToTokens
extend Int32 <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
extend Int64 <: ToTokens
extend Int64 <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
extend Int8 <: ToTokens
extend Int8 <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
extend Rune <: ToTokens
extend Rune <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
extend String <: ToTokens
extend String <: ToTokens
功能:实现 String 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 String 类型到 Tokens 类型的转换。
返回值:
extend Token <: ToTokens
extend Token <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
extend Tokens <: ToTokens
extend Tokens <: ToTokens
功能:实现 Tokens 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 Tokens 类型到 Tokens 类型的转换。
返回值:
extend UInt16 <: ToTokens
extend UInt16 <: ToTokens
功能:实现 UInt16 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 UInt16 类型到 Tokens 类型的转换。
返回值:
extend UInt32 <: ToTokens
extend UInt32 <: ToTokens
功能:实现 UInt32 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 UInt32 类型到 Tokens 类型的转换。
返回值:
extend UInt64 <: ToTokens
extend UInt64 <: ToTokens
功能:实现 UInt64 类型到 Tokens 类型的转换。
父类型:
func toTokens()
public func toTokens(): Tokens
功能:实现 UInt64 类型到 Tokens 类型的转换。
返回值:
extend UInt8 <: ToTokens
extend UInt8 <: ToTokens
父类型:
func toTokens()
public func toTokens(): Tokens
返回值:
类
class Annotation
public class Annotation <: Node {
public init()
public init(inputs: Tokens)
}
功能:表示编译器内置的注解节点。
一个 Annotation 节点:@CallingConv[xxx], @Attribute[xxx], @When[condition]等。
父类型:
prop arguments
public mut prop arguments: ArrayList<Argument>
功能:获取或设置 Annotation 中的参数序列,如 @CallingConv[xxx] 中的 xxx。
prop at
public mut prop at: Token
功能:获取或设置 Annotation 节点中的 @ 操作符或 @! 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
@操作符或@!操作符时,抛出异常。
prop attributes
public mut prop attributes: Tokens
功能:获取或设置 Attribute 中设置的属性值,仅用于 @Attribute,如 @Attribute[xxx] 中的 xxx。
类型:Tokens
prop condition
public mut prop condition: Expr
功能:获取或设置条件编译中的条件表达式,用于 @When,如 @When[xxx] 中的 xxx。
类型:Expr
异常:
- ASTException - 当 Annotation 节点中没有条件表达式时,抛出异常。
prop identifier
public mut prop identifier: Token
功能:获取或设置 Annotation 节点的标识符,如 @CallingConv[xxx] 中的 CallingConv。
类型:Token
init()
public init()
功能:构造一个默认的 Annotation 对象。
init(Tokens)
public init(inputs: Tokens)
功能:根据输入的词法单元,构造一个 Annotation 对象。
参数:
- inputs: Tokens - 将要构造 Annotation 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 Annotation 节点时,抛出异常。
class Argument
public class Argument <: Node {
public init()
}
功能:表示函数调用的实参节点。
例如 foo(arg:value) 中的 arg:value。
父类型:
prop colon
public mut prop colon: Token
功能:获取或设置 Argument 节点中的操作符 ":",可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ":" 操作符时,抛出异常。
prop expr
public mut prop expr: Expr
功能:获取或设置 Argument 节点中的表达式,如 arg:value 中的 value。
类型:Expr
prop identifier
public mut prop identifier: Token
功能:获取或设置 Argument 节点中的标识符,如 arg:value 中的 arg,可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当获取和设置的 Token 类型不是 IDENTIFIER 标识符或 Token 的字面量值是空时,抛出异常。
prop keyword
public mut prop keyword: Token
功能:获取或设置 Argument 节点中的关键字 inout,可能为 ILLEGAL 的词法单元。
类型:Token
init()
public init()
功能:构造一个默认的 Argument 对象。
class ArrayLiteral
public class ArrayLiteral <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 Array 字面量节点。
ArrayLiteral 节点:使用格式 [element1, element2, ... , elementN] 表示, 每个 element 是一个表达式。
父类型:
prop elements
public mut prop elements: ArrayList<Expr>
功能:获取或设置 ArrayLiteral 中的表达式列表。
prop lSquare
public mut prop lSquare: Token
功能:获取或设置 ArrayLiteral 中的 "["。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "[" 时,抛出异常。
prop rSquare
public mut prop rSquare: Token
功能:获取或设置 ArrayLiteral 中的 "]"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "]" 时,抛出异常。
init()
public init()
功能:构造一个默认的 ArrayLiteral 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ArrayLiteral 对象。
参数:
- inputs: Tokens - 将要构造 ArrayLiteral 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ArrayLiteral 节点时,抛出异常。
class AsExpr
public class AsExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示一个类型检查表达式。
一个 AsExpr 表达式:e as T,类型为 Option<T>。其中 e 可以是任何类型的表达式,T 可以是任何类型。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 AsExpr 节点中的表达式节点。
类型:Expr
prop keyword
public mut prop keyword: Token
功能:获取或设置 AsExpr 节点中的 as 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
as操作符时,抛出异常。
prop shiftType
public mut prop shiftType: TypeNode
功能:获取或设置 AsExpr 节点中的目标类型。
类型:TypeNode
init()
public init()
功能:构造一个默认的 AsExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 AsExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 AsExpr 节点时,抛出异常。
class AssignExpr
public class AssignExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示赋值表达式节点。
用于将左操作数的值修改为右操作数的值。一个 AssignExpr 节点:a = b。
父类型:
prop assign
public mut prop assign: Token
功能:获取或设置 AssignExpr 节点中的赋值操作符(如 = 等)。
类型:Token
异常:
- ASTException - 当设置的 Token 不是赋值操作符时,抛出异常。
prop leftExpr
public mut prop leftExpr: Expr
功能:获取或设置 AssignExpr 节点中的左操作数。
类型:Expr
prop rightExpr
public mut prop rightExpr: Expr
功能:获取或设置 AssignExpr 节点中的右操作数。
类型:Expr
init()
public init()
功能:构造一个默认的 AssignExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 AssignExpr 对象。
参数:
- inputs: Tokens - 将要构造 AssignExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 AssignExpr 节点时,抛出异常。
class BinaryExpr
public class BinaryExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示一个二元操作表达式节点。
一个 BinaryExpr 节点:a + b, a - b 等。
父类型:
prop leftExpr
public mut prop leftExpr: Expr
功能:获取或设置 BinaryExpr 节点中操作符左侧的表达式节点。
类型:Expr
prop op
public mut prop op: Token
功能:获取或设置 BinaryExpr 节点中的二元操作符。
类型:Token
prop rightExpr
public mut prop rightExpr: Expr
功能:获取或设置 BinaryExpr 节点中操作符右侧的表达式节点。
类型:Expr
init()
public init()
功能:构造一个默认的 BinaryExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 BinaryExpr 对象。
参数:
- inputs: Tokens - 将要构造 BinaryExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 BinaryExpr 节点时,抛出异常。
class Block
public class Block <: Expr {
public init()
}
功能:表示块节点。
Block 由一对匹配的大括号及其中可选的表达式声明序列组成的结构,简称 “块”。
父类型:
prop lBrace
public mut prop lBrace: Token
功能:获取或设置 Block 的 "{"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "{" 时,抛出异常。
prop nodes
public mut prop nodes: ArrayList<Node>
功能:获取或设置 Block 中的表达式或声明序列。
prop rBrace
public mut prop rBrace: Token
功能:获取或设置 Block 的 "}"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "}" 时,抛出异常。
init()
public init()
功能:构造一个默认的 Block 对象。
说明:
Block 节点无法脱离表达式或声明节点单独存在,因此不提供其他的构造函数。
class Body
public class Body <: Node {
public init()
public init(decls: ArrayList<Decl>)
}
功能:表示 Class 类型、 Struct 类型、 Interface 类型以及扩展中由 {} 和内部的一组声明节点组成的结构。
父类型:
prop decls
public mut prop decls: ArrayList<Decl>
功能:获取或设置 Body 内的声明节点集合。
prop lBrace
public mut prop lBrace: Token
功能:获取或设置 { 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
{词法单元时,抛出异常。
prop rBrace
public mut prop rBrace: Token
功能:获取或设置 } 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
}词法单元时,抛出异常。
init()
public init()
功能:构造一个默认的 Body 对象。
init(ArrayList<Decl>)
public init(decls: ArrayList<Decl>)
功能:构造一个 Body 对象。
参数:
class CallExpr
public class CallExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示函数调用节点节点。
一个 CallExpr 节点包括一个表达式后面紧跟参数列表,例如 foo(100)。
父类型:
prop arguments
public mut prop arguments: ArrayList<Argument>
功能:获取或设置 CallExpr 节点中函数参数。
prop callFunc
public mut prop callFunc: Expr
功能:获取或设置 CallExpr 节点中的函数调用节点。
类型:Expr
prop lParen
public mut prop lParen: Token
功能:获取或设置 CallExpr 节点中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 CallExpr 节点中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 CallExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 CallExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 CallExpr 节点时,抛出异常。
class ClassDecl
public class ClassDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:类定义节点。
类的定义使用 class 关键字,定义依次为:可缺省的修饰符、class 关键字、class 名、可选的类型参数、是否指定父类或父接口、可选的泛型约束、类体的定义。
父类型:
prop body
public mut prop body: Body
功能:获取或设置 ClassDecl 节点的类体。
类型:Body
prop superTypeBitAnds
public mut prop superTypeBitAnds: Tokens
功能:获取或设置 ClassDecl 节点的父类或父接口声明中的 & 操作符的词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是
&词法单元序列时,抛出异常。
prop superTypes
public mut prop superTypes: ArrayList<TypeNode>
功能:获取或设置 ClassDecl 节点的父类或者父接口。
prop upperBound
public mut prop upperBound: Token
功能:获取或设置 <: 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
<:操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 ClassDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ClassDecl 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ClassDecl 节点时,抛出异常。
class ConstPattern
public class ConstPattern <: Pattern {
public init()
public init(inputs: Tokens)
}
功能:表示常量模式节点。
常量模式可以是整数字面量、字符字节字面量、浮点数字面量、字符字面量、布尔字面量、字符串字面量等字面量,如 case 1 => 0 中的 1。
父类型:
prop litConstExpr
public mut prop litConstExpr: LitConstExpr
功能:获取或设置 ConstPattern 节点中的字面量表达式。
类型:LitConstExpr
init()
public init()
功能:构造一个默认的 ConstPattern 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ConstPattern 对象。
参数:
- inputs: Tokens - 将要构造 ConstPattern 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ConstPattern 节点时,抛出异常。
class Constructor
public class Constructor <: Node {
public init()
}
功能:表示 enum 类型中的 Constructor 节点。
一个 Constructor 节点:enum TimeUnit { Year | Month(Float32, Float32)} 中的 Year 和 Month(Float32, Float32)。
说明:
Constructor 可以没有参数,也可以有一组不同类型的参数。
父类型:
prop identifier
public mut prop identifier: Token
功能:获取或设置 Constructor 的标识符词法单元。
类型:Token
prop lParen
public mut prop lParen: Token
功能:获取或设置 Constructor 节点中的 "(" 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 Constructor 节点中的 ")" 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop typeArguments
public mut prop typeArguments: ArrayList<TypeNode>
功能:获取或设置 Constructor 节点可选的参数类型节点的集合。
init()
public init()
功能:构造一个默认的 Constructor 对象。
class Decl
public open class Decl <: Node
功能:所有声明节点的父类,继承自 Node 节点,提供了所有声明节点的通用接口。
说明:
类定义、接口定义、函数定义、变量定义、枚举定义、结构体定义、扩展定义、类型别名定义、宏定义等都属于 Decl 节点。
父类型:
prop annotations
public mut prop annotations: ArrayList<Annotation>
功能:获取或设置作用于 Decl 节点的注解列表。
类型:ArrayList<Annotation>
prop constraintCommas
public mut prop constraintCommas: Tokens
功能:获取或设置 Decl 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop genericConstraint
public mut prop genericConstraint: ArrayList<GenericConstraint>
功能:获取或设置定义节点的泛型约束,可能为空,如 func foo<T>() where T <: Comparable<T> {} 中的 where T <: Comparable<T>。
类型:ArrayList<GenericConstraint>
prop genericParam
public mut prop genericParam: GenericParam
功能:获取或设置形参列表,类型形参列表由 <> 括起,多个类型形参之间用逗号分隔。
类型:GenericParam
异常:
- ASTException - 当节点未定义类型形参列表时,抛出异常。
prop identifier
public mut open prop identifier: Token
功能:获取或设置定义节点的标识符,如 class foo {} 中的 foo。
类型:Token
prop isGenericDecl
public mut prop isGenericDecl: Bool
功能:判断是否是一个泛型节点。
类型:Bool - 是一个泛型节点为 true;反之为 false。
prop keyword
public mut prop keyword: Token
功能:获取或设置定义节点的关键字。
类型:Token
prop modifiers
public mut prop modifiers: ArrayList<Modifier>
功能:获取或设置修饰节点的修饰符列表。
func getAttrs()
public func getAttrs(): Tokens
功能:获取当前节点的属性(一般通过内置的 Attribute 来设置某个声明设置属性值)。
返回值:
- Tokens - 当前节点的属性。
func hasAttr(String)
public func hasAttr(attr: String): Bool
功能:判断当前节点是否具有某个属性(一般通过内置的 Attribute 来设置某个声明的属性值)。
参数:
- attr: String - 将要判断是否存在于该节点的属性。
返回值:
- Bool - 当前节点具有该属性时,返回 true;反之,返回 false。
class DoWhileExpr
public class DoWhileExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 do-while 表达式。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 DoWhileExpr 中的块表达式。
类型:Block
prop condition
public mut prop condition: Expr
功能:获取或设置关键字 DoWhileExpr 中的条件表达式。
类型:Expr
prop keywordD
public mut prop keywordD: Token
功能:获取或设置 DoWhileExpr 节点中 do 关键字,其中 keywordD 中的 D 为关键字 do 的首字母大写,代表关键字 do 。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
do关键字时,抛出异常。
prop keywordW
public mut prop keywordW: Token
功能:获取或设置 DoWhileExpr 节点中 while 关键字,其中 keywordW 中的 W 为关键字 while 的首字母大写,代表关键字 while 。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
while关键字时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 DoWhileExpr 中 while 关键字之后的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 DoWhileExpr 中 while 关键字之后的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 DoWhileExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 DoWhileExpr 对象。
参数:
- inputs: Tokens - 将要构造 DoWhileExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 DoWhileExpr 节点时,抛出异常。
class EnumDecl
public class EnumDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个 Enum 定义节点。
Enum 的定义使用 enum 关键字,定义依次为:可缺省的修饰符、enum 关键字、enum 名、可选的类型参数、是否指定父接口、可选的泛型约束、enum 体的定义。
父类型:
prop constructors
public mut prop constructors: ArrayList<Constructor>
功能:获取或设置 EnumDecl 节点内 constructor 的成员。
类型:ArrayList<Constructor>
prop annotations
public mut prop annotations: ArrayList<Annotation>
功能:获取或设置作用于 EnumDecl 节点的注解列表。
类型:ArrayList<Annotation>
prop decls
public mut prop decls: ArrayList<Decl>
功能:获取或设置 EnumDecl 节点内除 constructor 的其他成员。
prop ellipsis
public mut prop ellipsis: Token
功能:获取或设置 EnumDecl 节点中可选的 ... 词法单元,可能为 ILLEGAL 的词法单元类型。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
...词法单元时,抛出异常。
prop lBrace
public mut prop lBrace: Token
功能:获取或设置 EnumDecl 节点的 { 词法单元类型。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
{词法单元类型时,抛出异常。
prop rBrace
public mut prop rBrace: Token
功能:获取或设置 EnumDecl 节点的 } 词法单元类型。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
}词法单元类型时,抛出异常。
prop superTypeBitAnds
public mut prop superTypeBitAnds: Tokens
功能:获取或设置 EnumDecl 节点的父接口声明中的 & 操作符的词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是
&词法单元序列时,抛出异常。
prop superTypes
public mut prop superTypes: ArrayList<TypeNode>
功能:获取或设置 EnumDecl 节点的父接口。
prop upperBound
public mut prop upperBound: Token
功能:获取或设置 <: 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
<:操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 EnumDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 EnumDecl 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 EnumDecl 节点时,抛出异常。
class EnumPattern
public class EnumPattern <: Pattern {
public init()
public init(inputs: Tokens)
}
功能:表示 enum 模式节点。
用于匹配 enum 的 constructor, 如 case Year(n) => 1 中的 Year(n)。
父类型:
prop commas
public mut prop commas: Tokens
功能:获取或设置 EnumPattern 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop constructor
public mut prop constructor: Expr
功能:获取或设置 EnumPattern 节点中的构造器表达式节点。
类型:Expr
prop lParen
public mut prop lParen: Token
功能:获取或设置 EnumPattern 节点中的 "(" 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop patterns
public mut prop patterns: ArrayList<Pattern>
功能:获取或设置 EnumPattern 节点中有参构造器内的模式节点列表。
prop rParen
public mut prop rParen: Token
功能:获取或设置 EnumPattern 节点中的 ")" 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 EnumPattern 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 EnumPattern 对象。
参数:
- inputs: Tokens - 将要构造 EnumPattern 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 EnumPattern 节点时,抛出异常。
class ExceptTypePattern
public class ExceptTypePattern <: Pattern {
public init()
public init(inputs: Tokens)
}
功能:表示一个用于异常模式状态下的节点。
例如 e: Exception1 | Exception2。
父类型:
prop colon
public mut prop colon: Token
功能:获取或设置 ExceptTypePattern 节点中的 ":" 操作符的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ":" 操作符时,抛出异常。
prop pattern
public mut prop pattern: Pattern
功能:获取或设置 ExceptTypePattern 节点中的模式节点。
类型:Pattern
prop types
public mut prop types: ArrayList<TypeNode>
功能:获取或设置 ExceptTypePattern 节点中有类型列表。
init()
public init()
功能:构造一个默认的 ExceptTypePattern 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ExceptTypePattern 对象。
参数:
- inputs: Tokens - 将要构造 ExceptTypePattern 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ExceptTypePattern 节点时,抛出异常。
class Expr
public open class Expr <: Node
功能:所有表达式节点的父类,继承自 Node 节点。
表达式节点的 toTokens 方法会根据操作符优先级添加括号,例如已有一个 BinaryExpr 节点 a * b, 用户将左表达式内容 a 修改为 a + 1,修改后 toTokens 方法会为左表达式添加括号,toTokens 输出为 (a + 1) * b。
父类型:
class ExtendDecl
public class ExtendDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个扩展定义节点。
扩展的定义使用 extend 关键字,扩展定义依次为:extend 关键字、扩展类型、是否指定父接口、可选的泛型约束、扩展体的定义。
父类型:
prop body
public mut prop body: Body
功能:获取或设置 ExtendDecl 节点的类体。
类型:Body
prop extendType
public mut prop extendType: TypeNode
功能:获取或设置被扩展的类型。
类型:TypeNode
prop identifier
public mut override prop identifier: Token
功能:ExtendDecl 节点继承 Decl 节点,但是不支持 identifier 属性,使用时会抛出异常。
类型:Token
异常:
- ASTException - 当使用
identifier属性时,抛出异常。
prop superTypeBitAnds
public mut prop superTypeBitAnds: Tokens
功能:获取或设置 ExtendDecl 节点的父接口声明中的 & 操作符的词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是
&词法单元序列时,抛出异常。
prop superTypes
public mut prop superTypes: ArrayList<TypeNode>
功能:获取或设置 ExtendDecl 节点的父接口。
prop upperBound
public mut prop upperBound: Token
功能:获取或设置 <: 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
<:操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 ExtendDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ExtendDecl 对象。
参数:
- inputs: Tokens - 将要构造 ExtendDecl 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ExtendDecl 节点时,抛出异常。
class ForInExpr
public class ForInExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 for-in 表达式。
ForInExpr 类型中,关键字 for 之后是 Pattern, 此后是一个 in 关键字和表达式节点,最后是一个执行循环体 Block。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 ForInExpr 中的循环体。
类型:Block
prop expr
public mut prop expr: Expr
功能:获取或设置 ForInExpr 中的表达式。
类型:Expr
prop keywordF
public mut prop keywordF: Token
功能:获取或设置 ForInExpr 中的关键字 for。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
for关键字时,抛出异常。
prop keywordI
public mut prop keywordI: Token
功能:获取或设置 ForInExpr 中的关键字 in。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
in关键字时,抛出异常。
prop keywordW
public mut prop keywordW: Token
功能:获取或设置 ForInExpr 中的关键字 where。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
where关键字时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 ForInExpr 中关键字 for 后的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop pattern
public mut prop pattern: Pattern
功能:获取或设置 ForInExpr 中的 Pattern 节点。
类型:Pattern
prop patternGuard
public mut prop patternGuard: Expr
功能:获取或设置 ForInExpr 中的 patternGuard 条件表达式。
类型:Expr
异常:
- ASTException - 当 ForInExpr 节点中不存在
patternGuard表达式时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 ForInExpr 中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 ForInExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ForInExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ForInExpr 节点时,抛出异常。
class FuncDecl
public class FuncDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个函数定义节点。
由可选的函数修饰符,关键字 func ,函数名,可选的类型形参列表,函数参数,可缺省的函数返回类型来定义一个函数,函数定义时必须有函数体,函数体是一个块。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 FuncDecl 节点的函数体。
类型:Block
prop colon
public mut prop colon: Token
功能:获取或设置 FuncDecl 节点的冒号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是冒号时,抛出异常。
prop declType
public mut prop declType: TypeNode
功能:获取或设置 FuncDecl 节点的函数返回类型。
类型:TypeNode
异常:
- ASTException - 当 FuncDecl 节点的函数返回类型是一个缺省值时,抛出异常。
prop funcParams
public mut prop funcParams: ArrayList<FuncParam>
功能:获取或设置 FuncDecl 节点的函数参数。
prop lParen
public mut prop lParen: Token
功能:获取或设置 FuncDecl 节点的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop overloadOp
public mut prop overloadOp: Tokens
功能:获取或设置 FuncDecl 节点的重载操作符。
类型:Tokens
prop rParen
public mut prop rParen: Token
功能:获取或设置 FuncDecl 节点的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 FuncDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 FuncDecl 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 FuncDecl 节点时,抛出异常。
func isConst()
public func isConst(): Bool
功能:判断是否是一个 Const 类型的节点。
返回值:
- Bool - 是一个
Const类型的节点返回 true;反之,返回 false。
class FuncParam
public open class FuncParam <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示函数参数节点,包括非命名参数和命名参数。
一个 FuncParam 节点: func foo(a: Int64, b: Float64) {...} 中的 a: Int64 和 b: Float64。
父类型:
prop assign
public mut prop assign: Token
功能:获取或设置具有默认值的函数参数中的 =。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
=时,抛出异常。
prop colon
public mut prop colon: Token
功能:获取或设置置形参中的 ":"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ":" 时,抛出异常。
prop expr
public mut prop expr: Expr
功能:获取或设置具有默认值的函数参数的变量初始化节点。
类型:Expr
异常:
- ASTException - 当函数参数没有进行初始化时,抛出异常。
prop not
public mut prop not: Token
功能:获取或设置命名形参中的 !。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
!时,抛出异常。
prop paramType
public mut prop paramType: TypeNode
功能:获取或设置函数参数的类型。
类型:TypeNode
init()
public init()
功能:构造一个默认的 FuncParam 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 FuncParam 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 FuncParam 节点时,抛出异常。
func isMemberParam()
public func isMemberParam(): Bool
功能:当前的函数参数是否是主构造函数中的参数。
返回值:
- Bool - 布尔类型,如果是主构造函数中的参数,返回
true。
class FuncType
public class FuncType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示函数类型节点。
由函数的参数类型和返回类型组成,参数类型与返回类型之间用 -> 分隔,如:(Int32) -> Unit。
父类型:
prop arrow
public mut prop arrow: Token
功能:获取或设置 FuncType 节点参数类型与返回类型之间的 ->的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
->的词法单元时,抛出异常。
prop commas
public mut prop commas: Tokens
功能:获取或设置 FuncType 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop keyword
public mut prop keyword: Token
功能:获取或设置 FuncType 节点的中的关键字 CFunc 的词法单元,若不是一个 CFunc 类型,则获取一个 ILLEGAL 的词法单元。
类型:Token
prop lParen
public mut prop lParen: Token
功能:获取或设置 FuncType 节点的 "(" 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 FuncType 节点的 ")" 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop returnType
public mut prop returnType: TypeNode
功能:获取或设置 FuncType 返回类型节点。
类型:TypeNode
prop types
public mut prop types: ArrayList<TypeNode>
功能:获取或设置 FuncType 节点中函数的参数类型列表。
init()
public init()
功能:构造一个默认的 FuncType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 FuncType 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 FuncType 节点时,抛出异常。
class GenericConstraint
public class GenericConstraint <: Node {
public init()
}
功能:表示一个泛型约束节点。
一个 GenericConstraint 节点:interface Enumerable<U> where U <: Bounded {} 中的 where U <: Bounded。
说明:
通过
where之后的<:运算符来声明,由一个下界与一个上界来组成。其中<:左边称为约束的下界,下界只能为类型变元。<:右边称为约束上界,约束上界可以为类型。
父类型:
prop bitAnds
public mut prop bitAnds: Tokens
功能:获取或设置 GenericConstraint 节点中的 & 操作符的词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是
&词法单元序列时,抛出异常。
prop keyword
public mut prop keyword: Token
功能:获取或设置 GenericConstraint 节点中关键字 where 词法单元,可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
where关键字时,抛出异常。
prop typeArgument
public mut prop typeArgument: TypeNode
功能:获取或设置 GenericConstraint 节点中的约束下界。
类型:TypeNode
prop upperBound
public mut prop upperBound: Token
功能:获取或设置 GenericConstraint 节点中的 <: 运算符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
<:运算符时,抛出异常。
prop upperBounds
public mut prop upperBounds: ArrayList<TypeNode>
功能:获取或设置 GenericConstraint 节点约束上界的 TypeNode 类型节点的集合。
init()
public init()
功能:构造一个默认的 GenericConstraint 对象。
class GenericParam
public class GenericParam <: Node {
public init()
public init(parameters: Tokens)
}
功能:表示一个类型形参节点。
一个 GenericParam 节点:<T1, T2, T3>。
说明:
类型形参用
<>括起并用 "," 分隔多个类型形参名称。
父类型:
prop lAngle
public mut prop lAngle: Token
功能:获取或设置 GenericParam 节点中的左尖括号词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是左尖括号时,抛出异常。
prop parameters
public mut prop parameters: Tokens
功能:获取或设置 GenericParam 节点中的类型形参的 Tokens 类型,可能为空,如 <T1, T2, T3> 中的 T1 T2 和 T3。
类型:Tokens
prop rAngle
public mut prop rAngle: Token
功能:获取或设置 GenericParam 节点中的右尖括号词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是右尖括号时,抛出异常。
init()
public init()
功能:构造一个默认的 GenericParam 对象。
init(Tokens)
public init(parameters: Tokens)
功能:构造一个 GenericParam 对象。
参数:
- parameters: Tokens - 将要构造 GenericParam 的类型形参的词法单元集合 (Tokens)。
class IfExpr
public class IfExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示条件表达式。
可以根据判定条件是否成立来决定执行哪条代码分支。一个 IfExpr 节点中 if 是关键字,if 之后是一个小括号,小括号内可以是一个表达式或者一个 let 声明的解构匹配,接着是一个 Block,Block 之后是可选的 else 分支。 else 分支以 else 关键字开始,后接新的 if 表达式或一个 Block。
父类型:
prop condition
public mut prop condition: Expr
功能:获取或设置 IfExpr 节点中的 if 后的条件表达式。
类型:Expr
prop elseExpr
public mut prop elseExpr: Expr
功能:获取或设置 IfExpr 节点中 else 分支节点。
类型:Expr
异常:
- ASTException - 当前 IfExpr 节点没有 else 分支节点。
prop ifBlock
public mut prop ifBlock: Block
功能:获取或设置 IfExpr 节点中的 if 后的 block 节点。
类型:Block
prop keywordE
public mut prop keywordE: Token
功能:获取或设置 IfExpr 节点中 else 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
else关键字时,抛出异常。
prop keywordI
public mut prop keywordI: Token
功能:获取或设置 IfExpr 节点中的 if 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
if关键字时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 IfExpr 节点中的 if 后的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 IfExpr 节点中的 if 后的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 IfExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 IfExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 IfExpr 节点时,抛出异常。
class ImportContent
public class ImportContent <: Node {
public init()
}
父类型:
prop importKind
public mut prop importKind: ImportKind
功能:获取或设置 ImportContent 节点中导入类型。
类型:ImportKind
prop prefixPaths
public mut prop prefixPaths: Tokens
功能:获取或设置 ImportContent 节点中完整包名的前缀部分的词法单元序列,可能为空。如 import a.b.c 中的 a 和 b。
类型:Tokens
prop prefixDots
public mut prop prefixDots: Tokens
功能:获取或设置 ImportContent 节点中完整包名中用于分隔每层子包的词法单元序列,可能为空。如 import a.b.c 中的两个 "."。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "." 词法单元序列时,抛出异常。
prop identifier
public mut prop identifier: Token
功能:获取或设置 ImportContent 节点中被导入的项,它可能是包中的顶层定义或声明,也可能是子包的名字。
类型:Token
prop importAlias
public mut prop importAlias: Tokens
功能:获取或设置 ImportContent 节点中导入的定义或声明的别名词法单元序列,只有 importKind 为 ImportKind.Alias 时非空。如:import packageName.xxx as yyy 中的 as yyy。
类型:Tokens
prop lBrace
public mut prop lBrace: Token
功能:获取或设置 ImportContent 节点中的 { 操作符词法单元,只有 importKind 为 ImportKind.Multi 时非空。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
{操作符时,抛出异常。
prop items
public mut prop items: ArrayList<ImportContent>
功能:获取或设置 ImportContent 节点中被导入的所有项,只有 importKind 为 ImportKind.Multi 时非空。
类型:ArrayList<ImportContent>
prop commas
public mut prop commas: Tokens
功能:获取或设置 ImportContent 节点中的 "," 词法单元序列,只有 importKind 为 ImportKind.Multi 时非空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop rBrace
public mut prop rBrace: Token
功能:获取或设置 ImportContent 节点中的 } 操作符词法单元,只有 importKind 为 ImportKind.Multi 时非空。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
}操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 ImportContent 对象。
func isImportAlias()
public func isImportAlias(): Bool
功能:判断 ImportContent 节点是否对导入项取了别名。
返回值:
- Bool - ImportContent 节点是否对导入项取了别名。
func isImportAll()
public func isImportAll(): Bool
功能:判断 ImportContent 节点是否为全导入。
返回值:
- Bool - ImportContent 节点是否为全导入。
func isImportMulti()
public func isImportMulti(): Bool
功能:判断 ImportContent 节点是否导入了多个顶级定义或声明。
返回值:
- Bool - ImportContent 节点是否导入了多个顶级定义或声明。
func isImportSingle()
public func isImportSingle(): Bool
功能:判断 ImportContent 节点是否为单导入。
返回值:
- Bool - ImportContent 节点是否为单导入。
class ImportList
public class ImportList <: Node {
public init()
public init(inputs: Tokens)
}
功能:表示包导入节点。
一个 ImportList 节点: import moduleName.packageName.foo as bar。
说明:
导入节点以可选的访问性修饰符(
public/protected/internal/private)加关键字import开头。以import pkga.pkgb.item为例,pkga.pkgb为导入的顶级定义或声明所在的包的名字,item为导入的顶级定义或声明。
父类型:
prop modifier
public mut prop modifier: Token
功能:获取或设置 ImportList 节点中的修饰符,可能为 ILLEGAL 的词法单元。
类型:Token
prop keywordI
public mut prop keywordI: Token
功能:获取或设置 ImportList 节点中的 import 关键字的词法单元,I 为关键字首字母。
类型:Token
prop content
public mut prop content: ImportContent
功能:获取或设置 ImportList 节点中的被导入的具体项。如 import a.b.c 中的 a.b.c 部分。
init()
public init()
功能:构造一个默认的 ImportList 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ImportList 对象。
参数:
- inputs: Tokens - 将要构造 ImportList 类型的词法单元集合 (Tokens) 序列。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ImportList 节点时,抛出异常。
func isImportMulti()
public func isImportMulti(): Bool
功能:判断 ImportList 节点是否导入了多个顶级定义或声明。
返回值:
- Bool - 如果 ImportList 节点导入了多个顶级定义或声明,返回 true;反之,返回 false。
class IncOrDecExpr
public class IncOrDecExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示包含自增操作符(++)或自减操作符(--)的表达式。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 IncOrDecExpr 中的表达式。
类型:Expr
prop op
public mut prop op: Token
功能:获取或设置 IncOrDecExpr 中的操作符。
类型:Token
init()
public init()
功能:构造一个默认的 IncOrDecExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 IncOrDecExpr 对象。
参数:
- inputs: Tokens - 将要构造 IncOrDecExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 IncOrDecExpr 节点时,抛出异常。
class InterfaceDecl
public class InterfaceDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示接口定义节点。
接口的定义使用 interface 关键字,接口定义依次为:可缺省的修饰符、interface 关键字、接口名、可选的类型参数、是否指定父接口、可选的泛型约束、接口体的定义。
父类型:
prop body
public mut prop body: Body
功能:获取或设置 InterfaceDecl 节点的类体。
类型:Body
prop superTypeBitAnds
public mut prop superTypeBitAnds: Tokens
功能:获取或设置 InterfaceDecl 节点的父接口声明中的 & 操作符的词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是
&词法单元序列时,抛出异常。
prop superTypes
public mut prop superTypes: ArrayList<TypeNode>
功能:获取或设置 InterfaceDecl 节点的父接口。
prop upperBound
public mut prop upperBound: Token
功能:获取或设置 <: 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
<:操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 InterfaceDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 InterfaceDecl 对象。
参数:
- inputs: Tokens - 将要构造 InterfaceDecl 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 InterfaceDecl 节点时,抛出异常。
class IsExpr
public class IsExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示一个类型检查表达式。
一个 IsExpr 表达式:e is T,类型为 Bool。其中 e 可以是任何类型的表达式,T 可以是任何类型。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 IsExpr 节点中的表达式节点。
类型:Expr
prop keyword
public mut prop keyword: Token
功能:获取或设置 IsExpr 节点中的 is 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
is操作符时,抛出异常。
prop shiftType
public mut prop shiftType: TypeNode
功能:获取或设置 IsExpr 节点中的目标类型。
类型:TypeNode
init()
public init()
功能:构造一个默认的 IsExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 IsExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 IsExpr 节点时,抛出异常。
class JumpExpr
public class JumpExpr <: Expr {
public init()
public init(kind: Tokens)
}
功能:表示循环表达式的循环体中的 break 和 continue。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取或设置关键字。
类型:Token
init()
public init()
功能:构造一个默认的 JumpExpr 对象。
init(Tokens)
public init(kind: Tokens)
功能:构造一个 JumpExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 JumpExpr 节点时,抛出异常。
class LambdaExpr
public class LambdaExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 Lambda 表达式,是一个匿名的函数。
一个 LambdaExpr 节点有两种形式,一种是有形参的,例如 {a: Int64 => e1; e2 },另一种是无形参的,例如 { => e1; e2 }。
父类型:
prop doubleArrow
public mut prop doubleArrow: Token
功能:获取或设置 LambdaExpr 中的 =>。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
=>操作符时,抛出异常。
prop funcParams
public mut prop funcParams: ArrayList<FuncParam>
功能:获取或设置 LambdaExpr 中的参数列表。
prop lBrace
public mut prop lBrace: Token
功能:获取或设置 LambdaExpr 中的 "{"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "{" 时,抛出异常。
prop nodes
public mut prop nodes: ArrayList<Node>
功能:获取或设置 LambdaExpr 中的表达式或声明节点。
prop rBrace
public mut prop rBrace: Token
功能:获取或设置 LambdaExpr 中的 "}"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "}" 时,抛出异常。
init()
public init()
功能:构造一个默认的 LambdaExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 LambdaExpr 对象。
参数:
- inputs: Tokens - 将要构造 LambdaExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 LambdaExpr 节点时,抛出异常。
class LetPatternExpr
public class LetPatternExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 let 声明的解构匹配节点。
一个 LetPatternExpr 节点:if (let Some(v) <- x) 中的 let Some(v) <- x。
父类型:
prop backArrow
public mut prop backArrow: Token
功能:获取或设置 LetPatternExpr 节点中 <- 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
<-操作符时,抛出异常。
prop expr
public mut prop expr: Expr
功能:获取或设置 LetPatternExpr 节点中 <- 操作符之后的表达式。
类型:Expr
prop keyword
public mut prop keyword: Token
功能:获取或设置 LetPatternExpr 节点中 let 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
let关键字时,抛出异常。
prop pattern
public mut prop pattern: Pattern
功能:获取或设置 LetPatternExpr 节点中 let 之后的 pattern。
类型:Pattern
init()
public init()
功能:构造一个默认的 LetPatternExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 LetPatternExpr 对象。
参数:
- inputs: Tokens - 将要构造 LetPatternExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 LetPatternExpr 节点时,抛出异常。
class LitConstExpr
public class LitConstExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示一个常量表达式节点。
一个 LitConstExpr 表达式:"abc",123 等。
父类型:
prop literal
public mut prop literal: Token
功能:获取或设置 LitConstExpr 节点中的字面量。
类型:Token
init()
public init()
功能:构造一个默认的 LitConstExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 LitConstExpr 对象。
参数:
- inputs: Tokens - 将要构造 LitConstExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ParenExpr 节点时,抛出异常。
class MacroDecl
public class MacroDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个宏定义节点。
一个 MacroDecl 节点:public macro M(input: Tokens): Tokens {...}。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 MacroDecl 节点的函数体。
类型:Block
prop colon
public mut prop colon: Token
功能:获取或设置 MacroDecl 节点的冒号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是冒号时,抛出异常。
prop declType
public mut prop declType: TypeNode
功能:获取或设置 MacroDecl 节点的函数返回类型。
类型:TypeNode
异常:
- ASTException - 当 MacroDecl 节点的函数返回类型是一个缺省值时,抛出异常。
prop funcParams
public mut prop funcParams: ArrayList<FuncParam>
功能:获取或设置 MacroDecl 节点的参数。
prop lParen
public mut prop lParen: Token
功能:获取或设置 MacroDecl 节点的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 MacroDecl 节点的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 MacroDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 MacroDecl 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 MacroDecl 节点时,抛出异常。
class MacroExpandDecl
public class MacroExpandDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示宏调用节点。
一个 MacroExpandDecl 节点: @M class A {}。
父类型:
prop fullIdentifier
public mut prop fullIdentifier: Token
功能:获取或设置宏调用节点的完整标识符。
类型:Token
prop lParen
public mut prop lParen: Token
功能:获取或设置 MacroExpandDecl 宏调用的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop lSquare
public mut prop lSquare: Token
功能:获取或设置 MacroExpandDecl 属性宏调用的 "["。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "[" 时,抛出异常。
prop macroAttrs
public mut prop macroAttrs: Tokens
功能:获取或设置 MacroExpandDecl 属性宏调用的输入。
类型:Tokens
prop macroInputDecl
public mut prop macroInputDecl: Decl
功能:获取或设置 MacroExpandDecl 中的声明节点。
类型:Decl
异常:
- ASTException - 当 MacroExpandDecl 节点中没有声明节点时,抛出异常。
prop macroInputs
public mut prop macroInputs: Tokens
功能:获取或设置 MacroExpandDecl 宏调用的输入。
类型:Tokens
prop rParen
public mut prop rParen: Token
功能:获取或设置 MacroExpandDecl 宏调用的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop rSquare
public mut prop rSquare: Token
功能:获取或设置 MacroExpandDecl 属性宏调用的 "]"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "]" 时,抛出异常。
init()
public init()
功能:构造一个默认的 MacroExpandDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 MacroExpandDecl 对象。
参数:
- inputs: Tokens - 将要构造 MacroExpandDecl 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 MacroExpandDecl 节点时,抛出异常。
class MacroExpandExpr
public class MacroExpandExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示宏调用节点。
一个 MacroExpandExpr 节点: @M (a is Int64)。
父类型:
prop at
public mut prop at: Token
功能:获取或设置 MacroExpandExpr 节点中的 @ 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
@操作符时,抛出异常。
prop identifier
public mut prop identifier: Token
功能:获取或设置宏调用节点的标识符。
类型:Token
prop lParen
public mut prop lParen: Token
功能:获取或设置 MacroExpandExpr 宏调用的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop lSquare
public mut prop lSquare: Token
功能:获取或设置 MacroExpandExpr 属性宏调用的 "["。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "[" 时,抛出异常。
prop macroAttrs
public mut prop macroAttrs: Tokens
功能:获取或设置 MacroExpandExpr 属性宏调用的输入。
类型:Tokens
prop macroInputs
public mut prop macroInputs: Tokens
功能:获取或设置 MacroExpandExpr 宏调用的输入。
类型:Tokens
prop rParen
public mut prop rParen: Token
功能:获取或设置 MacroExpandExpr 宏调用的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop rSquare
public mut prop rSquare: Token
功能:获取或设置 MacroExpandExpr 属性宏调用的 "]"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "]" 时,抛出异常。
init()
public init()
功能:构造一个默认的 MacroExpandExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 MacroExpandExpr 对象。
参数:
- inputs: Tokens - 将要构造 MacroExpandExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 MacroExpandExpr 节点时,抛出异常。
class MacroExpandParam
public class MacroExpandParam <: FuncParam {
public init()
}
功能:表示宏调用节点。
一个 MacroExpandParam 节点: func foo (@M a: Int64) 中的 @M a: Int64。
父类型:
prop fullIdentifier
public mut prop fullIdentifier: Token
功能:获取或设置宏调用节点的完整标识符。
类型:Token
prop lParen
public mut prop lParen: Token
功能:获取或设置 MacroExpandParam 宏调用的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop lSquare
public mut prop lSquare: Token
功能:获取或设置 MacroExpandParam 属性宏调用的 "["。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "[" 时,抛出异常。
prop macroAttrs
public mut prop macroAttrs: Tokens
功能:获取或设置 MacroExpandParam 属性宏调用的输入。
类型:Tokens
prop macroInputDecl
public mut prop macroInputDecl: Decl
功能:获取或设置 MacroExpandParam 中的声明节点。
类型:Decl
异常:
- ASTException - 当 MacroExpandParam 节点中没有声明节点时,抛出异常。
prop macroInputs
public mut prop macroInputs: Tokens
功能:获取或设置 MacroExpandParam 宏调用的输入。
类型:Tokens
prop rParen
public mut prop rParen: Token
功能:获取或设置 MacroExpandParam 宏调用的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop rSquare
public mut prop rSquare: Token
功能:获取或设置 MacroExpandParam 属性宏调用的 "]"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "]" 时,抛出异常。
init()
public init()
功能:构造一个默认的 MacroExpandParam 对象。
class MacroMessage
public class MacroMessage
功能:记录内层宏发送的信息。
func getBool(String)
public func getBool(key: String): Bool
功能:获取对应 key 值的 Bool 类型信息。
参数:
- key: String - 用于检索的关键字的名字。
返回值:
异常:
func getInt64(String)
public func getInt64(key: String): Int64
功能:获取对应 key 值的 Int64 类型信息。
参数:
- key: String - 用于检索的关键字的名字。
返回值:
异常:
func getString(String)
public func getString(key: String): String
功能:获取对应 key 值的 String 类型信息。
参数:
- key: String - 用于检索的关键字的名字。
返回值:
异常:
func getTokens(String)
public func getTokens(key: String): Tokens
功能:获取对应 key 值的 Tokens 类型信息。
参数:
- key: String - 用于检索的关键字的名字。
返回值:
异常:
func hasItem(String)
public func hasItem(key: String): Bool
功能:检查是否有 key 值对应的相关信息。
参数:
- key: String - 用于检索的关键字名字。
返回值:
- Bool - 若存在 key 值对应的相关信息,返回 true;反之,返回 false。
class MainDecl
public class MainDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个 main 函数定义节点。
一个 MainDecl 节点:main() {}。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 MainDecl 节点的函数体。
类型:Block
prop colon
public mut prop colon: Token
功能:获取或设置 MainDecl 节点的冒号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是冒号时,抛出异常。
prop declType
public mut prop declType: TypeNode
功能:获取或设置 MainDecl 节点的函数返回类型。
类型:TypeNode
异常:
- ASTException - 当 MainDecl 节点的函数返回类型是一个缺省值时,抛出异常。
prop funcParams
public mut prop funcParams: ArrayList<FuncParam>
功能:获取或设置 MainDecl 节点的函数参数。
prop lParen
public mut prop lParen: Token
功能:获取或设置 MainDecl 节点的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 MainDecl 节点的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 MainDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 MainDecl 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 MainDecl 节点时,抛出异常。
class MatchCase
public class MatchCase <: Node {
public init()
}
功能:表示 match 表达式中的一个 case 节点。
一个 MatchCase 节点:case failScore where score > 0 => 0。
说明:
父类型:
prop arrow
public mut prop arrow: Token
功能:获取或设置 MatchCase 中的 => 操作符的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
=>操作符时,抛出异常。
prop bitOrs
public mut prop bitOrs: Tokens
功能:获取或设置 MatchCase 中的 | 操作符的词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是
|词法单元序列时,抛出异常。
prop block
public mut prop block: Block
功能:获取或设置 MatchCase 中的一系列声明或表达式节点。
类型:Block
prop expr
public mut prop expr: Expr
功能:获取或设置 MatchCase 中位于 case 后的表达式节点。
类型:Expr
异常:
- ASTException - 当 MatchCase 节点中不存在表达式节点时,抛出异常。
prop keywordC
public mut prop keywordC: Token
功能:获取或设置 MatchCase 内的 case 关键字的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
case关键字时,抛出异常。
prop keywordW
public mut prop keywordW: Token
功能:获取或设置 MatchCase 中可选的关键字 where 的词法单元,可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
where关键字时,抛出异常。
prop patternGuard
public mut prop patternGuard: Expr
功能:获取或设置 MatchCase 中可选的 pattern guard 表达式节点。
类型:Expr
异常:
- ASTException - 当 MatchCase 节点中不存在 pattern guard 表达式时,抛出异常。
prop patterns
public mut prop patterns: ArrayList<Pattern>
功能:获取或设置 MatchCase 中位于 case 后的 pattern 列表。
init()
public init()
功能:构造一个默认的 MatchCase 对象。
class MatchExpr
public class MatchExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示模式匹配表达式实现模式匹配。
模式匹配表达式分为带 selector 的 match 表达式和不带 selector 的 match 表达式。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取或设置 MatchExpr 节点中 match 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
matcch关键字时,抛出异常。
prop lBrace
public mut prop lBrace: Token
功能:获取或设置 MatchExpr 之后的 "{"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "{" 时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 MatchExpr 之后的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop matchCases
public mut prop matchCases: ArrayList<MatchCase>
功能:获取或设置 MatchExpr 内的 matchCase, matchCase 以关键字 case 开头,后跟一个或者多个由 Pattern 或 Expr节点,具体见 MatchCase。
prop rBrace
public mut prop rBrace: Token
功能:获取或设置 MatchExpr 之后的 "}"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "}" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 MatchExpr 之后的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop selector
public mut prop selector: Expr
功能:获取或设置关键字 match 之后的 Expr。
类型:Expr
异常:
- ASTException - 当该表达式是一个不带 selector 的
match表达式时,抛出异常。
init()
public init()
功能:构造一个默认的 MatchExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 MatchExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 MatchExpr 节点时,抛出异常。
class MemberAccess
public class MemberAccess <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示成员访问表达式。
可以用于访问 class、interface、struct 等类型的成员。一个 MemberAccess 节点的形式为 T.a,T 为成员访问表达式的主体,a 表示成员的名字。
父类型:
prop baseExpr
public mut prop baseExpr: Expr
功能:获取或设置 MemberAccess 节点的成员访问表达式主体。
类型:Expr
prop commas
public mut prop commas: Tokens
功能:获取或设置 MemberAccess 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop dot
public mut prop dot: Token
功能:获取或设置 MemberAccess 节点中的 "."。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "." 词法单元类型时,抛出异常。
prop field
public mut prop field: Token
功能:获取或设置 MemberAccess 节点成员的名字。
类型:Token
prop lAngle
public mut prop lAngle: Token
功能:获取或设置 MemberAccess 节点中的左尖括号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是左尖括号时,抛出异常。
prop rAngle
public mut prop rAngle: Token
功能:获取或设置 MemberAccess 节点中的右尖括号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是右尖括号时,抛出异常。
prop typeArguments
public mut prop typeArguments: ArrayList<TypeNode>
功能:获取或设置 MemberAccess 节点中的实例化类型。
init()
public init()
功能:构造一个默认的 MemberAccess 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 MemberAccess 对象。
参数:
- inputs: Tokens - 将要构造 MemberAccess 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 MemberAccess 节点时,抛出异常。
class Modifier
public class Modifier <: Node {
public init()
public init(keyword: Token)
}
功能:表示该定义具备某些特性,通常放在定义处的最前端。
一个 Modifier 节点:public func foo() 中的 public。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取或设置 Modifier 节点中的修饰符词法单元。
类型:Token
init()
public init()
功能:构造一个默认的 Modifier 对象。
init(Token)
public init(keyword: Token)
功能:构造一个 Modifier 对象。
参数:
class Node
abstract sealed class Node <: ToTokens
功能:所有仓颉语法树节点的父类。
该类提供了所有数据类型通用的操作接口。
父类型:
prop beginPos
public mut prop beginPos: Position
功能:获取或设置当前节点的起始的位置信息。
类型:Position
prop endPos
public mut prop endPos: Position
功能:获取或设置当前节点的终止的位置信息。
类型:Position
func dump()
public func dump(): Unit
功能:将当前语法树节点转化为树形结构的形态并进行打印。
语法树节点的树形结构将按照以下形式进行输出:
-字符串:表示当前节点的公共属性, 如-keyword,-identifier。- 节点属性后紧跟该节点的具体类型, 如
-declType: PrimitiveType表示节点类型是一个 PrimitiveType 节点。 - 每个类型使用大括号表示类型的作用区间。
语法树输出的详细格式请参见语法树节点打印。
func toTokens()
public func toTokens(): Tokens
功能:将语法树节点转化为 Tokens 类型。
返回值:
func traverse(Visitor)
public func traverse(v: Visitor): Unit
功能:遍历当前语法树节点及其子节点。若提前终止遍历子节点的行为,可重写 visit 函数并调用 breakTraverse 函数提前终止遍历行为,请参见自定义访问函数遍历 AST 对象示例。
参数:
class OptionalExpr
public class OptionalExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示一个带有问号操作符的表达式节点。
一个 OptionalExpr 节点:a?.b, a?(b), a?[b] 中的 a?。
父类型:
prop baseExpr
public mut prop baseExpr: Expr
功能:获取或设置 OptionalExpr 的表达式节点。
类型:Expr
prop quest
public mut prop quest: Token
功能:获取或设置 OptionalExpr 中的问号操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是问号操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 OptionalExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 OptionalExpr 对象。
参数:
- inputs: Tokens - 将要构造 OptionalExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 OptionalExpr 节点时,抛出异常。
class PackageHeader
public class PackageHeader <: Node {
public init()
public init(inputs: Tokens)
}
功能:表示包声明节点。
一个 PackageHeader 节点: package define 或者 macro package define。
说明:
包声明以关键字
package或macro package开头,后面紧跟包名,且包声明必须在源文件的首行。
父类型:
prop accessible
public mut prop accessible: Token
功能:获取或设置 PackageHeader 节点中的访问性修饰符的词法单元,可能为 ILLEGAL 的词法单元。
类型:Token
prop keywordM
public mut prop keywordM: Token
功能:获取或设置 PackageHeader 节点中的 macro 关键字的词法单元(M 为关键字首字母,下同),可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
macro关键字时,抛出异常。
prop keywordP
public mut prop keywordP: Token
功能:获取或设置 PackageHeader 节点中的 package 关键字的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
package关键字时,抛出异常。
prop prefixPaths
public mut prop prefixPaths: Tokens
功能:获取或设置 PackageHeader 节点中完整包名的前缀部分的词法单元序列,可能为空。如 package a.b.c 中的 a 和 b。
类型:Tokens
prop prefixDots
public mut prop prefixDots: Tokens
功能:获取或设置 PackageHeader 节点中完整包名中用于分隔每层子包的词法单元序列,可能为空。如 package a.b.c 中的两个 "."。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "." 词法单元序列时,抛出异常。
prop packageIdentifier
public mut prop packageIdentifier: Token
功能:获取或设置 PackageHeader 节点中当前包的名字,如果当前包为 root 包,即为完整包名,若当前包为子包,则为最后一个 "." 后的名字。
类型:Token
init()
public init()
功能:构造一个默认的 PackageHeader 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 PackageHeader 对象。
参数:
- inputs: Tokens - 将要构造 PackageHeader 类型的词法单元集合 (Tokens) 序列。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 PackageHeader 节点时,抛出异常。
class ParenExpr
public class ParenExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示一个括号表达式节点,是指使用圆括号括起来的表达式。
一个 ParenExpr 节点:(1 + 2)。
父类型:
prop lParen
public mut prop lParen: Token
功能:获取或设置 ParenExpr 节点中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop parenthesizedExpr
public mut prop parenthesizedExpr: Expr
功能:获取或设置 ParenExpr 节点中由圆括号括起来的子表达式。
类型:Expr
prop rParen
public mut prop rParen: Token
功能:获取或设置 ParenExpr 节点中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 ParenExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ParenExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ParenExpr 节点时,抛出异常。
class ParenType
public class ParenType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示括号类型节点。
例如 var a: (Int64) 中的 (Int64)。
父类型:
prop lParen
public mut prop lParen: Token
功能:获取或设置 ParenType 节点中的 "(" 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop parenthesizedType
public mut prop parenthesizedType: TypeNode
功能:获取或设置 ParenType 节点中括起来的类型,如 (Int64) 中的 Int64。
类型:TypeNode
prop rParen
public mut prop rParen: Token
功能:获取或设置 ParenType 节点中的 ")" 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 ParenType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ParenType 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ParenType 节点时,抛出异常。
class Pattern
public open class Pattern <: Node
功能:所有模式匹配节点的父类,继承自 Node 节点。
父类型:
class PrefixType
public class PrefixType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示带问号的前缀类型节点。
例如 var a : ?A 中的 ?A。
父类型:
prop baseType
public mut prop baseType: TypeNode
功能:获取或设置 PrefixType 节点中的类型节点,如 var a: ?A 中的 A。
类型:TypeNode
prop prefixOps
public mut prop prefixOps: Tokens
功能:获取或设置 PrefixType 节点中前缀操作符集合。
类型:Tokens
init()
public init()
功能:构造一个默认的 PrefixType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 PrefixType 对象。
参数:
- inputs: Tokens - 将要构造 PrefixType 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 PrefixType 节点时,抛出异常。
class PrimaryCtorDecl
public class PrimaryCtorDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个主构造函数节点。
主构造函数节点由修饰符,主构造函数名,形参列表和主构造函数体构成。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 PrimaryCtorDecl 节点的主构造函数体。
类型:Block
prop funcParams
public mut prop funcParams: ArrayList<FuncParam>
功能:获取或设置 PrimaryCtorDecl 节点的参数。
prop lParen
public mut prop lParen: Token
功能:获取或设置 PrimaryCtorDecl 节点的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 PrimaryCtorDecl 节点的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 PrimaryCtorDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 PrimaryCtorDecl 对象。
参数:
- inputs: Tokens - 将要构造 PrimaryCtorDecl 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 PrimaryCtorDecl 节点时,抛出异常。
func isConst()
public func isConst(): Bool
功能:判断是否是一个 Const 类型的节点。
返回值:
- Bool - 当前节点为
Const类型的节点时,返回 true;反之,返回 false。
class PrimitiveType
public class PrimitiveType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示一个基本类型节点。
例如数值类型,Rune 类型,布尔类型等。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取或设置构造 PrimitiveType 类型的关键字,如 Int8。
类型:Token
init()
public init()
功能:构造一个默认的 PrimitiveType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 PrimitiveType 对象。
参数:
- inputs: Tokens - 将要构造 PrimitiveType 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 PrimitiveType 节点时,抛出异常。
class PrimitiveTypeExpr
public class PrimitiveTypeExpr <: Expr {
public init()
public init(kind: Tokens)
}
功能:表示基本类型表达式节点。
PrimitiveTypeExpr 节点:编译器内置的基本类型作为表达式出现在节点中。如 Int64.toSting() 中的 Int64。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取或设置 PrimitiveTypeExpr 中的基本类型关键字。
类型:Token
init()
public init()
功能:构造一个默认的 PrimitiveTypeExpr 对象。
init(Tokens)
public init(kind: Tokens)
功能:构造一个 PrimitiveTypeExpr 对象。
参数:
- kind: Tokens - 将要构造 PrimitiveTypeExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 PrimitiveTypeExpr 节点时,抛出异常。
class Program
public class Program <: Node {
public init()
public init(inputs: Tokens)
}
功能:表示一个仓颉源码文件节点。
一个仓颉源码文件节点主要包括包定义节点,包导入节点和 TopLevel 作用域内的所有声明节点。
说明:
任何一个仓颉源码文件都可以被解析为一个 Program 类型。
父类型:
prop decls
public mut prop decls: ArrayList<Decl>
功能:获取或设置仓颉源码文件中 TopLevel 作用域内定义的声明节点列表。
prop importLists
public mut prop importLists: ArrayList<ImportList>
功能:获取或设置仓颉源码文件中包导入节点 ImportList 的列表。
类型:ArrayList<ImportList>
prop packageHeader
public mut prop packageHeader: PackageHeader
功能:获取或设置仓颉源码文件中包的声明节点 PackageHeader。
init()
public init()
功能:构造一个默认的 Program 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 Program 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为一个文件节点时,抛出异常。
class PropDecl
public class PropDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个属性定义节点。
一个 PropDecl 节点:prop X: Int64 { get() { 0 } }。
父类型:
prop colon
public mut prop colon: Token
功能:获取或设置 PropDecl 节点的冒号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是冒号时,抛出异常。
prop declType
public mut prop declType : TypeNode
功能:获取或设置 PropDecl 节点的返回类型。
类型:TypeNode
prop getter
public mut prop getter: FuncDecl
功能:获取或设置 PropDecl 节点的 getter 函数。
类型:FuncDecl
异常:
- ASTException - 当 PropDecl 节点不存在 getter 函数时,抛出异常。
prop lBrace
public mut prop lBrace: Token
功能:获取或设置 PropDecl 节点的 "{"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "{" 时,抛出异常。
prop rBrace
public mut prop rBrace: Token
功能:获取或设置 PropDecl 节点的 "}"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "}" 时,抛出异常。
prop setter
public mut prop setter: FuncDecl
功能:获取或设置 PropDecl 节点的 setter 函数。
类型:FuncDecl
异常:
- ASTException - 当 PropDecl 节点不存在 setter 函数时,抛出异常。
init()
public init()
功能:构造一个默认的 PropDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 PropDecl 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 PropDecl 节点时,抛出异常。
class QualifiedType
public class QualifiedType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示一个用户自定义成员类型。
例如 var a : T.a 中的 T.a, 其中 T 是包名,a 是从 T 包中导入的类型。
父类型:
prop baseType
public mut prop baseType: TypeNode
功能:获取或设置 QualifiedType 节点的成员访问类型主体,如 var a : T.a 中的 T。
类型:TypeNode
prop commas
public mut prop commas: Tokens
功能:获取或设置 QualifiedType 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop dot
public mut prop dot: Token
功能:获取或设置 QualifiedType 节点中的 "." 。
类型:Token
异常:
- ASTException - 当设置的 Tokens 不是 "." 词法单元时,抛出异常。
prop identifier
public mut prop identifier: Token
功能:获取或设置 QualifiedType 节点成员的标识符,如 var a : T.a 中的 a。
类型:Token
prop lAngle
public mut prop lAngle: Token
功能:获取或设置 QualifiedType 节点中的左尖括号词法单元,可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是左尖括号时,抛出异常。
prop rAngle
public mut prop rAngle: Token
功能:获取或设置 QualifiedType 节点中的右尖括号词法单元,可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是右尖括号时,抛出异常。
prop typeArguments
public mut prop typeArguments: ArrayList<TypeNode>
功能:获取或设置 QualifiedType 节点中的实例化类型的列表,如 T.a<Int32> 中的 Int32,列表可能为空。
init()
public init()
功能:构造一个默认的 QualifiedType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 QualifiedType 对象。
参数:
- inputs: Tokens - 将要构造 QualifiedType 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 QualifiedType 节点时,抛出异常。
class QuoteExpr
public class QuoteExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 quote 表达式节点。
一个 QuoteExpr 节点: quote(var ident = 0)。
父类型:
prop exprs
public mut prop exprs: ArrayList<Expr>
功能:获取或设置 QuoteExpr 中由 () 括起的内部引用表达式节点。
prop keyword
public mut prop keyword: Token
功能:获取或设置 QuoteExpr 的 quote 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
quote关键字时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 QuoteExpr 中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 QuoteExpr 中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 QuoteExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 QuoteExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 QuoteExpr 节点。
class QuoteToken
public class QuoteToken <: Expr
功能:表示 quote 表达式节点内任意合法的 token。
父类型:
prop tokens
public mut prop tokens: Tokens
功能:获取 QuoteToken 内的 Tokens。
类型:Tokens
class RangeExpr
public class RangeExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示包含区间操作符的表达式。
RangeExpr 节点:存在两种 Range 操作符:.. 和 ..=,分别用于创建左闭右开和左闭右闭的 Range 实例。它们的使用方式分别为 start..end:step 和 start..=end:step。
父类型:
prop colon
public mut prop colon: Token
功能:获取或设置 RangeExpr 中的 ":" 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ":" 操作符时,抛出异常。
prop end
public mut prop end: Expr
功能:获取或设置 RangeExpr 中的终止值。
类型:Expr
异常:
- ASTException - 终止表达式省略。只有在 Range<Int64> 类型的实例用在下标操作符
[]为空的场景。
prop op
public mut prop op: Token
功能:获取或设置 RangeExpr 中的 Range 的操作符。
类型:Token
prop start
public mut prop start: Expr
功能:获取或设置 RangeExpr 中的起始值。
类型:Expr
异常:
- ASTException - 起始表达式省略。只有在 Range<Int64> 类型的实例用在下标操作符
[]为空的场景。
prop step
public mut prop step: Expr
功能:获取或设置 RangeExpr 中序列中前后两个元素之间的差值。
类型:Expr
异常:
- ASTException - 当 RangeExpr 中未设置序列前后两个元素之间的差值时,抛出异常。
init()
public init()
功能:构造一个默认的 RangeExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 RangeExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 RangeExpr 节点时,抛出异常。
class RefExpr
public class RefExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示引用一个声明的表达式节点。
一个 RefExpr 节点:var b = a + 1 中的 a 是一个 RefExpr。
父类型:
prop commas
public mut prop commas: Tokens
功能:获取或设置 RefExpr 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop identifier
public mut prop identifier: Token
功能:获取或设置 RefExpr 节点中的自定义类型的标识符。
类型:Token
prop lAngle
public mut prop lAngle: Token
功能:获取或设置 RefExpr 节点中的左尖括号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是左尖括号时,抛出异常。
prop rAngle
public mut prop rAngle: Token
功能:获取或设置 RefExpr 节点中的右尖括号。
类型:Token
异常:
- ASTException - 当设置的 Token 不是右尖括号时,抛出异常。
prop typeArguments
public mut prop typeArguments: ArrayList<TypeNode>
功能:获取或设置 RefExpr 节点中的实例化类型。
init()
public init()
功能:构造一个默认的 RefExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 RefExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 RefExpr 节点时,抛出异常。
class RefType
public class RefType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示一个非基础类型节点。
例如用户通过 class、struct、enum 等定义的自定义类型,以及 Array、String 等内置类型都可以使用 RefType 表示。例如 var a : A 中的 A。
父类型:
prop commas
public mut prop commas: Tokens
功能:获取或设置 RefType 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop identifier
public mut prop identifier: Token
功能:获取或设置构造 RefType 类型的关键字,如 var a : A = A() 中的 A。
类型:Token
prop lAngle
public mut prop lAngle: Token
功能:获取或设置 RefType 节点中的左尖括号词法单元,可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是左尖括号时,抛出异常。
prop rAngle
public mut prop rAngle: Token
功能:获取或设置 RefType 节点中的右尖括号词法单元,可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是右尖括号时,抛出异常。
prop typeArguments
public mut prop typeArguments: ArrayList<TypeNode>
功能:获取或设置 RefType 节点中的实例化类型的列表,可能为空,如 var a : Array<Int32> 中的 Int32。
init()
public init()
功能:构造一个默认的 RefType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 RefType 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 RefType 节点时,抛出异常。
class ReturnExpr
public class ReturnExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 return 表达式节点。
一个 ReturnExpr 节点:return 1。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 ReturnExpr 节点中的表达式节点。
类型:Expr
异常:
- ASTException - 当 ReturnExpr 节点没有表达式时,抛出异常。
prop keyword
public mut prop keyword: Token
功能:获取或设置 ReturnExpr 节点中的关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
return关键字时,抛出异常。
init()
public init()
功能:构造一个默认的 ReturnExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ReturnExpr 对象。
参数:
- inputs: Tokens - 将要构造 ReturnExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ReturnExpr 节点时,抛出异常。
class SpawnExpr
public class SpawnExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 Spawn 表达式。
一个 SpawnExpr 节点由 spawn 关键字和一个不包含形参的闭包组成,例如:spawn { add(1, 2) }。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取或设置 SpawnExpr 中的 spawn 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
spawn关键字时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 SpawnExpr 中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop lambdaExpr
public mut prop lambdaExpr: LambdaExpr
功能:获取或设置 SpawnExpr 中的不含形参的闭包。
类型:LambdaExpr
prop rParen
public mut prop rParen: Token
功能:获取或设置 SpawnExpr 中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop threadContext
public mut prop threadContext: Expr
功能:获取或设置 SpawnExpr 中的线程上下文环境表达式。
类型:Expr
异常:
- ASTException - 当 SpawnExpr 中不含有上下文表达式时,抛出异常。
init()
public init()
功能:构造一个默认的 SpawnExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 SpawnExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 SpawnExpr 节点时,抛出异常。
class StructDecl
public class StructDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示一个 Struct 节点。
Struct 的定义使用 struct 关键字,定义依次为:可缺省的修饰符、struct 关键字、struct 名、可选的类型参数、是否指定父接口、可选的泛型约束、struct 体的定义。
父类型:
prop body
public mut prop body: Body
功能:获取或设置 StructDecl 节点的类体。
类型:Body
prop superTypeBitAnds
public mut prop superTypeBitAnds: Tokens
功能:获取或设置 StructDecl 节点的父接口声明中的 & 操作符的词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是
&词法单元序列时,抛出异常。
prop superTypes
public mut prop superTypes: ArrayList<TypeNode>
功能:获取或设置 StructDecl 节点的父接口。
prop upperBound
public mut prop upperBound: Token
功能:获取或设置 <: 操作符。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
<:操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 StructDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 StructDecl 对象。
参数:
- inputs: Tokens - 将要构造 StructDecl 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 StructDecl 节点时,抛出异常。
class SubscriptExpr
public class SubscriptExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示索引访问表达式。
SubscriptExpr 节点:用于那些支持索引访问的类型(包括 Array 类型和 Tuple 类型)通过下标来访问其具体位置的元素,如 arr[0]。
父类型:
prop baseExpr
public mut prop baseExpr: Expr
功能:获取或设置 SubscriptExpr 中的表达式。
类型:Expr
prop indexList
public mut prop indexList: ArrayList<Expr>
功能:获取或设置 SubscriptExpr 中的索引表达式序列。
prop lSquare
public mut prop lSquare: Token
功能:获取或设置 SubscriptExpr 中的 "["。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "[" 时,抛出异常。
prop rSquare
public mut prop rSquare: Token
功能:获取或设置 SubscriptExpr 中的 "]"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "]" 时,抛出异常。
init()
public init()
功能:构造一个默认的 SubscriptExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 SubscriptExpr 对象。
参数:
- inputs: Tokens - 将要构造 SubscriptExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 SubscriptExpr 节点时,抛出异常。
class SynchronizedExpr
public class SynchronizedExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 synchronized 表达式。
一个 SynchronizedExpr 节点由 synchronized 关键字和 StructuredMutex 对以及后面的代码块组成, 例如 synchronized(m) { foo() }。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 SynchronizedExpr 修饰的代码块。
类型:Block
prop keyword
public mut prop keyword: Token
功能:获取或设置 SynchronizedExpr 中的 synchronized 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
synchronized关键字时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 SynchronizedExpr 中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 SynchronizedExpr 中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop structuredMutex
public mut prop structuredMutex: Expr
功能:获取或设置 SynchronizedExpr 中的 StructuredMutex 的对象。
类型:Expr
init()
public init()
功能:构造一个默认的 SynchronizedExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 SynchronizedExpr 对象。
参数:
- inputs: Tokens - 将要构造 SynchronizedExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 SynchronizedExpr 节点时,抛出异常。
class ThisType
public class ThisType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示 This 类型节点。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取或设置 ThisType 节点关键字 This 的词法单元。
类型:Token
init()
public init()
功能:构造一个默认的 ThisType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ThisType 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ThisType 节点时,抛出异常。
class ThrowExpr
public class ThrowExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 throw 表达式节点。
一个 ThrowExpr 节点:throw Exception()。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 ThrowExpr 节点中的表达式节点。
类型:Expr
prop keyword
public mut prop keyword: Token
功能:获取或设置 ThrowExpr 节点中的关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
throw关键字时,抛出异常。
init()
public init()
功能:构造一个默认的 ThrowExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 ThrowExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 ThrowExpr 节点时,抛出异常。
class Tokens
public open class Tokens <: ToString & Iterable<Token> & ToBytes {
public init()
public init(tokArray: Array<Token>)
public init(tokArrayList: ArrayList<Token>)
}
功能:对 Token 序列进行封装的类型。
父类型:
prop size
public open prop size: Int64
类型:Int64
init()
public init()
功能:构造一个默认的 Tokens 对象。
init(Array<Token>)
public init(tokArray: Array<Token>)
功能:构造一个 Tokens 对象。
参数:
init(ArrayList<Token>)
public init(tokArrayList: ArrayList<Token>)
功能:构造一个 Tokens 对象。
参数:
func append(Node)
public func append(node: Node): Tokens
功能:将当前的 Tokens 与传入节点所转换得到的 Tokens 进行拼接。
参数:
返回值:
func append(Token)
public open func append(token: Token): Tokens
功能:将当前的 Tokens 与传入的 Token 进行拼接。
参数:
返回值:
func append(Tokens)
public open func append(tokens: Tokens): Tokens
功能:在当前的 Tokens 后追加传入的 Tokens 进行拼接(该接口性能较其他拼接函数表现更好)。
参数:
返回值:
func concat(Tokens)
public func concat(tokens: Tokens): Tokens
功能:将当前的 Tokens 与传入的 Tokens 进行拼接,返回新的 Tokens 实例。
参数:
返回值:
func dump()
public func dump(): Unit
功能:将 Tokens 内所有 Token 的信息打印出来。
func get(Int64)
public open func get(index: Int64): Token
功能:通过索引值获取 Token 元素。
参数:
- index: Int64 - 待索引的数值。
返回值:
异常:
- IndexOutOfBoundsException - 当
index无效时,抛出异常。
func iterator()
public func iterator(): TokensIterator
功能:获取 Tokens 对象中的一个迭代器对象。
返回值:
- TokensIterator - Tokens 对象的迭代器对象。
func remove(Int64)
public func remove(index: Int64): Tokens
功能:删除指定位置的 Token 对象。
参数:
返回值:
func toBytes()
public func toBytes(): Array<UInt8>
功能:Tokens 类型的序列化。
返回值:
func toString()
public func toString(): String
operator func +(Token)
public operator func +(r: Token): Tokens
功能:使用当前 Tokens 与另一个 Token 相加以获取新的 Tokens 实例。
参数:
返回值:
operator func +(Tokens)
public operator func +(r: Tokens): Tokens
功能:使用当前 Tokens 与 Tokens 相加以获取新的 Tokens 实例。
参数:
返回值:
operator func [](Int64)
public operator func [](index: Int64): Token
功能:操作符重载,通过索引值获取对应 Token。
参数:
- index: Int64 - 待索引的数值。
返回值:
异常:
- IndexOutOfBoundsException - 当
index无效时,抛出异常。
operator func [](Range<Int64>)
public open operator func [](range: Range<Int64>): Tokens
功能:操作符重载,通过 range 获取对应 Tokens 切片。
参数:
返回值:
异常:
- IllegalArgumentException - 当
range.step不等于 1 时,抛出异常。 - IndexOutOfBoundsException - 当 range 无效时,抛出异常。
class TokensIterator
public class TokensIterator <: Iterator<Token> {
public init(tokens: Tokens)
}
功能:实现 Tokens 的迭代器功能。
父类型:
init(Tokens)
public init(tokens: Tokens)
功能:构造一个 TokensIterator 对象。
参数:
func iterator()
public func iterator(): Iterator<Token>
功能:获取当前迭代器实例。
返回值:
func next()
public func next(): Option<Token>
功能:获取迭代器中的下一个值。
返回值:
func peek()
public func peek(): Option<Token>
功能:获取迭代器中的当前值。
返回值:
func seeing(TokenKind)
public func seeing(kind: TokenKind): Bool
功能:判断当前节点的 Token 类型是否是传入的类型。
参数:
返回值:
class TrailingClosureExpr
public class TrailingClosureExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示尾随 Lambda 节点。
一个 TrailingClosureExpr 节点将 lambda 表达式放在函数调用的尾部,括号外面,如 f(a){ i => i * i }。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 TrailingClosureExpr 中的表达式。
类型:Expr
prop lambdaExpr
public mut prop lambdaExpr: LambdaExpr
功能:获取或设置 TrailingClosureExpr 中的尾随 lambda。
类型:LambdaExpr
init()
public init()
功能:构造一个默认的 TrailingClosureExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TrailingClosureExpr 对象。
参数:
- inputs: Tokens - 将要构造 TrailingClosureExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TrailingClosureExpr 节点。
class TryExpr
public class TryExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 try 表达式节点。
try 表达式包括三个部分:try 块,catch 块和 finally 块。
父类型:
prop catchBlocks
public mut prop catchBlocks: ArrayList<Block>
功能:获取或设置 TryExpr 中的 Catch 块。
prop catchPatterns
public mut prop catchPatterns: ArrayList<Pattern>
功能:获取或设置 TryExpr 中通过模式匹配的方式匹配待捕获的异常序列。
prop finallyBlock
public mut prop finallyBlock: Block
功能:获取或设置 TryExpr 中的关键字 Finally 块。
类型:Block
异常:
- ASTException - 当 TryExpr 节点无
Finally块节点时,抛出异常。
prop keywordF
public mut prop keywordF: Token
功能:获取或设置 TryExpr 中的 finally 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
finally关键字时,抛出异常。
prop keywordT
public mut prop keywordT: Token
功能:获取或设置 TryExpr 中的 try 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
try关键字时,抛出异常。
prop keywordsC
public mut prop keywordsC: Tokens
功能:获取或设置 TryExpr 中的关键字 catch。
类型:Tokens
异常:
- ASTException - 当设置的 Token 不是
catch关键字时,抛出异常。
prop resourceSpec
public mut prop resourceSpec: ArrayList<VarDecl>
功能:获取或设置 TryExpr 中 Try-with-resources 类型表达式的实例化对象序列。
prop tryBlock
public mut prop tryBlock: Block
功能:获取或设置 TryExpr 中由表达式与声明组成的块。
类型:Block
init()
public init()
功能:构造一个默认的 TryExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TryExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TryExpr 节点时,抛出异常。
class TupleLiteral
public class TupleLiteral <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示元组字面量节点。
TupleLiteral 节点:使用格式 (expr1, expr2, ... , exprN) 表示,每个 expr 是一个表达式。
父类型:
prop elements
public mut prop elements: ArrayList<Expr>
功能:获取或设置 TupleLiteral 中的表达式列表。
prop lParen
public mut prop lParen: Token
功能:获取或设置 TupleLiteral 中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 TupleLiteral 中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 TupleLiteral 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TupleLiteral 对象。
参数:
- inputs: Tokens - 将要构造 TupleLiteral 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TupleLiteral 节点时,抛出异常。
class TuplePattern
public class TuplePattern <: Pattern {
public init()
public init(inputs: Tokens)
}
功能:表示 Tuple 模式节点。
用于 tuple 值的匹配,如 case ("Bob", age) => 1 中的 ("Bob", age)。
父类型:
prop commas
public mut prop commas: Tokens
功能:获取或设置 TuplePattern 节点中的 "," 词法单元序列,可能为空。
类型:Tokens
异常:
- ASTException - 当设置的 Tokens 不是 "," 词法单元序列时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 TuplePattern 节点中的 "(" 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop patterns
public mut prop patterns: ArrayList<Pattern>
功能:获取或设置 TuplePattern 节点中的一组 Pattern 节点。
prop rParen
public mut prop rParen: Token
功能:获取或设置 TuplePattern 节点中的 ")" 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 TuplePattern 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TuplePattern 对象。
参数:
- inputs: Tokens - 将要构造 TuplePattern 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TuplePattern 节点时,抛出异常。
class TupleType
public class TupleType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示元组类型节点。
例如 var a : (Int64, Int32) 中的 (Int64, Int32)。
父类型:
prop lParen
public mut prop lParen: Token
功能:获取或设置 TupleType 节点中的 "(" 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 TupleType 节点中的 ")" 词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop types
public mut prop types: ArrayList<TypeNode>
功能:获取或设置 TupleType 节点中的类型节点列表。
init()
public init()
功能:构造一个默认的 TupleType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TupleType 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TupleType 节点时,抛出异常。
class TypeAliasDecl
public class TypeAliasDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示类型别名节点。
一个 TypeAliasDecl 节点: type Point2D = Float64。
说明:
该节点中
type作为关键字,紧跟任意的合法标识符,其后的type是任意的 top-level 可见的类型,标识符和type之间使用=进行连接。
父类型:
prop aliasType
public mut prop aliasType: TypeNode
功能:获取或设置将要别名的类型。
类型:TypeNode
prop assign
public mut prop assign: Token
功能:获取或设置标识符和 type 之间的 =。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
=时,抛出异常。
init()
public init()
功能:构造一个默认的 TypeAliasDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TypeAliasDecl 对象。
参数:
- inputs: Tokens - 将要构造 TypeAliasDecl 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TypeAliasDecl 节点时,抛出异常。
class TypeConvExpr
public class TypeConvExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示类型转换表达式。
用于实现若干数值类型间的转换。一个 TypeConvExpr 节点:Int8(32)。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 TypeConvExpr 中进行类型转化的原始表达式。
类型:Expr
prop lParen
public mut prop lParen: Token
功能:获取或设置 TypeConvExpr 中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 TypeConvExpr 中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop targetType
public mut prop targetType: PrimitiveType
功能:获取或设置 TypeConvExpr 中将要转换到的目标类型。
init()
public init()
功能:构造一个默认的 TypeConvExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TypeConvExpr 对象。
参数:
- inputs: Tokens - 将要构造 TypeConvExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TypeConvExpr 节点时,抛出异常。
class TypeNode
public open class TypeNode <: Node
功能:所有类型节点的父类,继承自 Node。
父类型:
prop typeParameterName
public mut prop typeParameterName: Token
功能:获取或设置类型节点的参数,如:(p1:Int64, p2:Int64) 中的 p1 和 p2,可能为 ILLEGAL 的词法单元。
类型:Token
prop colon
public mut prop colon: Token
功能:获取或设置 TypeNode 节点中的操作符 ":",可能为 ILLEGAL 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ":" 操作符时,抛出异常。
class TypePattern
public class TypePattern <: Pattern {
public init()
public init(inputs: Tokens)
}
功能:表示类型模式节点。
用于判断一个值的运行时类型是否是某个类型的子类型,如 case b: Base => 0 中的 b: Base。
父类型:
prop colon
public mut prop colon: Token
功能:获取或设置 TypePattern 节点中的 ":" 操作符的词法单元节点。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ":" 操作符时,抛出异常。
prop pattern
public mut prop pattern: Pattern
功能:获取或设置 TypePattern 节点中的模式节点。
类型:Pattern
prop patternType
public mut prop patternType: TypeNode
功能:获取或设置 TypePattern 节点中的待匹配的模式类型节点。
类型:TypeNode
init()
public init()
功能:构造一个默认的 TypePattern 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 TypePattern 对象。
参数:
- inputs: Tokens - 将要构造 TypePattern 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 TypePattern 节点时,抛出异常。
class UnaryExpr
public class UnaryExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示一个一元操作表达式节点。
父类型:
prop expr
public mut prop expr: Expr
功能:获取或设置 UnaryExpr 节点中的操作数。
类型:Expr
prop op
public mut prop op: Token
功能:获取或设置 UnaryExpr 节点中的一元操作符。
类型:Token
init()
public init()
功能:构造一个默认的 UnaryExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 UnaryExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 UnaryExpr 节点时,抛出异常。
class VArrayExpr
public class VArrayExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 VArray 的实例节点。
一个 VArrayExpr 节点:let arr: VArray<Int64, $5> = VArray<Int64, $5>({ i => i }) 中的 VArray<Int64, $5>({ i => i })。
父类型:
prop arguments
public mut prop arguments: ArrayList<Argument>
功能:获取或设置 VArrayExpr 中的中的初始化参数序列。
prop lParen
public mut prop lParen: Token
功能:获取或设置 VArrayExpr 中的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 VArrayExpr 中的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
prop vArrayType
public mut prop vArrayType: VArrayType
功能:获取或设置 VArrayExpr 的 VArray 类型节点。
类型:VArrayType
init()
public init()
功能:构造一个默认的 VArrayExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 VArrayExpr 对象。
参数:
- inputs: Tokens - 将要构造 VArrayExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 VArrayExpr 节点时,抛出异常。
class VArrayType
public class VArrayType <: TypeNode {
public init()
public init(inputs: Tokens)
}
功能:表示 VArray 类型节点。
使用泛型 VArray<T, size: Int64> 表示 VArray 类型。
父类型:
prop dollar
public mut prop dollar: Token
功能:获取或设置 VArrayType 节点中的操作符 $ 的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
$词法单元时,抛出异常。
prop elementTy
public mut prop elementTy: TypeNode
功能:获取或设置 VArrayType 节点中的类型变元节点,如 VArray<Int16, $0> 中的 Int16。
类型:TypeNode
prop keyword
public mut prop keyword: Token
功能:获取或设置 VArrayType 节点的关键字 VArray 的词法单元。
类型:Token
prop lAngle
public mut prop lAngle: Token
功能:获取或设置 VArrayType 节点左尖括号的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是左尖括号时,抛出异常。
prop rAngle
public mut prop rAngle: Token
功能:获取或设置 VArrayType 节点右尖括号的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是右尖括号时,抛出异常。
prop size
public mut prop size: Token
功能:获取或设置 VArrayType 节点中类型长度的词法单元。
类型:Token
init()
public init()
功能:构造一个默认的 VArrayType 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 VArrayType 对象。
参数:
- inputs: Tokens - 将要构造 VArrayType 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 VArrayType 节点时,抛出异常。
class VarDecl
public class VarDecl <: Decl {
public init()
public init(inputs: Tokens)
}
功能:表示变量定义节点。
一个 VarDecl 节点: var a: String,var b: Int64 = 1。
说明:
变量的定义主要包括如下几个部分:修饰符、关键字、patternsMaybeIrrefutable、变量类型和变量初始值。
父类型:
prop assign
public mut prop assign: Token
功能:获取或设置 VarDecl 节点中的赋值操作符的位置信息。
类型:Token
异常:
- ASTException - 当设置的 Token 不是赋值操作符时,抛出异常。
prop colon
public mut prop colon: Token
功能:获取或设置 VarDecl 节点中的冒号位置信息。
类型:Token
异常:
- ASTException - 当设置的 Token 不是冒号时,抛出异常。
prop declType
public mut prop declType: TypeNode
功能:获取或设置 VarDecl 节点的变量类型。
类型:TypeNode
异常:
- ASTException - 当 VarDecl 节点没有声明变量类型时,抛出异常。
prop expr
public mut prop expr: Expr
功能:获取或设置 VarDecl 节点的变量初始化节点。
类型:Expr
异常:
- ASTException - 当 VarDecl 节点没有对变量进行初始化时,抛出异常。
prop pattern
public mut prop pattern: Pattern
功能:获取或设置 VarDecl 节点的 pattern 节点。
类型:Pattern
异常:
- ASTException - 当 VarDecl 节点没有声明 pattern 节点时,抛出异常。
init()
public init()
功能:构造一个默认的 VarDecl 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 VarDecl 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 VarDecl 节点时,抛出异常。
func isConst()
public func isConst(): Bool
功能:判断是否是一个 Const 类型的节点。
返回值:
- Bool - 是一个
Const类型的节点返回 true;反之,返回 false。
class VarOrEnumPattern
public class VarOrEnumPattern <: Pattern {
public init()
public init(identifier: Token)
}
功能:表示当模式的标识符为 Enum 构造器时的节点。
例如 case RED 中的 RED 为 Enum 构造器。
父类型:
prop identifier
public mut prop identifier: Token
功能:获取或设置 VarOrEnumPattern 节点中的标识符的词法单元。
类型:Token
init()
public init()
功能:构造一个默认的 VarOrEnumPattern 对象。
init(Tokens)
public init(identifier: Token)
功能:构造一个 VarOrEnumPattern 对象。
参数:
- identifier: Token - 将要构造 VarOrEnumPattern 类型的词法单元。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 VarOrEnumPattern 节点时,抛出异常。
class VarPattern
public class VarPattern <: Pattern {
public init()
public init(identifier: Token)
}
功能:表示绑定模式节点。
使用一个合法的标识符表示,如 for (i in 1..10) 中的 i。
父类型:
prop identifier
public mut prop identifier: Token
功能:获取或设置 VarPattern 节点中的标识符符的词法单元。
类型:Token
init()
public init()
功能:构造一个默认的 VarPattern 对象。
init(Tokens)
public init(identifier: Token)
功能:构造一个 VarPattern 对象。
参数:
- identifier: Token - 将要构造 VarPattern 类型的词法单元。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 VarPattern 节点时,抛出异常。
class Visitor
public abstract class Visitor
功能:一个抽象类,其内部默认定义了访问不同类型 AST 节点访问(visit)函数。
说明:
visit函数搭配traverse一起使用,可实现对节点的访问和修改, 所有visit函数都有默认为空的实现,可以按需实现需要的visit方法。- 该类需要被继承使用,并允许子类重新定义访问函数。
func breakTraverse()
public func breakTraverse(): Unit
功能:用于重写 visit 函数中,通过调用该函数来终止继续遍历子节点的行为。
class WhileExpr
public class WhileExpr <: Expr {
public init()
public init(inputs: Tokens)
}
功能:表示 while 表达式。
while 是关键字,while 之后是一个小括号,小括号内可以是一个表达式或者一个 let 声明的解构匹配,接着是一个 Block 节点。
父类型:
prop block
public mut prop block: Block
功能:获取或设置 WhileExpr 中的块节点。
类型:Block
prop condition
public mut prop condition: Expr
功能:获取或设置关键字 WhileExpr 中的条件表达式。
类型:Expr
prop keyword
public mut prop keyword: Token
功能:获取或设置 WhileExpr 节点中 while 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是
while关键字时,抛出异常。
prop lParen
public mut prop lParen: Token
功能:获取或设置 WhileExpr 中 while 关键字之后的 "("。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "(" 时,抛出异常。
prop rParen
public mut prop rParen: Token
功能:获取或设置 WhileExpr 中 while 关键字之后的 ")"。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 ")" 时,抛出异常。
init()
public init()
功能:构造一个默认的 WhileExpr 对象。
init(Tokens)
public init(inputs: Tokens)
功能:构造一个 WhileExpr 对象。
参数:
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 WhileExpr 节点时,抛出异常。
class WildcardExpr
public class WildcardExpr <: Expr {
public init()
public init(keyword: Tokens)
}
功能:表示通配符表达式节点。
父类型:
prop keyword
public mut prop keyword: Token
功能:获取 WildcardExpr 的 "_" 关键字。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "_" 关键字时,抛出异常。
init()
public init()
功能:构造一个默认的 WildcardExpr 对象。
init(Tokens)
public init(keyword: Tokens)
功能:构造一个 WildcardExpr 对象。
参数:
- keyword: Tokens - 将要构造 WildcardExpr 类型的词法单元集合 (Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 WildcardExpr 节点时,抛出异常。
class WildcardPattern
public class WildcardPattern <: Pattern {
public init()
public init(keyword: Tokens)
}
功能:表示通配符模式节点。
使用下划线 "_" 表示,可以匹配任意值。
父类型:
prop wildcard
public mut prop wildcard: Token
功能:获取或设置 WildcardPattern 节点中的 "_" 操作符的词法单元。
类型:Token
异常:
- ASTException - 当设置的 Token 不是 "_" 操作符时,抛出异常。
init()
public init()
功能:构造一个默认的 WildcardPattern 对象。
init(Tokens)
public init(keyword: Tokens)
功能:构造一个 WildcardPattern 对象。
参数:
- keyword: Tokens - 将要构造 WildcardPattern 类型的词法单元集合(Tokens)。
异常:
- ASTException - 当输入的 Tokens 类型无法构造为 WildcardPattern 节点时,抛出异常。
枚举
enum DiagReportLevel
public enum DiagReportLevel {
ERROR|
WARNING
}
功能:表示报错接口的信息等级,支持 ERROR 和 WARNING 两种等级。
ERROR
ERROR
功能:构造一个表示 ERROR 的枚举实例。
WARNING
WARNING
功能:构造一个表示 WARNING 的枚举实例。
func level()
public func level(): Int32
功能:返回枚举值对应的整型。
返回值:
- Int32 - 枚举值对应的整型。
ERROR返回 0,WARNING返回 1。
enum ImportKind
public enum ImportKind <: ToString {
Single | Alias | All | Multi
}
功能:表示导入语句的类型。
父类型:
Single
Single
功能:表示单导入,如 import a.b。
Alias
Alias
功能:表示别名导入,如 import a.b as c。
All
All
功能:表示全导入,如 import a.b.*。
Multi
Multi
功能:表示多导入,如 import a.{b, c, d}。
func toString()
public func toString(): String
功能:将 ImportKind 类型转化为字符串类型表示。
返回值:
- String - ImportKind 转换后的字符串值。
enum TokenKind
public enum TokenKind <: ToString {
DOT| /* "." */
COMMA| /* "," */
LPAREN| /* "(" */
RPAREN| /* ")" */
LSQUARE| /* "[" */
RSQUARE| /* "]" */
LCURL| /* "{" */
RCURL| /* "}" */
EXP| /* "**" */
MUL| /* "*" */
MOD| /* "%" */
DIV| /* "/" */
ADD| /* "+" */
SUB| /* "-" */
INCR| /* "++" */
DECR| /* "--" */
AND| /* "&&" */
OR| /* "||" */
COALESCING| /* "??" */
PIPELINE| /* "|>" */
COMPOSITION| /* "~>" */
NOT| /* "!" */
BITAND| /* "&" */
BITOR| /* "|" */
BITXOR| /* "^" */
BITNOT| /* "~" */
LSHIFT| /* "<<" */
RSHIFT| /* ">>" */
COLON| /* ":" */
SEMI| /* ";" */
ASSIGN| /* "=" */
ADD_ASSIGN| /* "+=" */
SUB_ASSIGN| /* "-=" */
MUL_ASSIGN| /* "*=" */
EXP_ASSIGN| /* "**=" */
DIV_ASSIGN| /* "/=" */
MOD_ASSIGN| /* "%=" */
AND_ASSIGN| /* "&&=" */
OR_ASSIGN| /* "||=" */
BITAND_ASSIGN| /* "&=" */
BITOR_ASSIGN| /* "|=" */
BITXOR_ASSIGN| /* "^=" */
LSHIFT_ASSIGN| /* "<<=" */
RSHIFT_ASSIGN| /* ">>=" */
ARROW| /* "->" */
BACKARROW| /* "<-" */
DOUBLE_ARROW| /* "=>" */
RANGEOP| /* ".." */
CLOSEDRANGEOP| /* "..=" */
ELLIPSIS| /* "..." */
HASH| /* "#" */
AT| /* "@" */
QUEST| /* "?" */
LT| /* "<" */
GT| /* ">" */
LE| /* "<=" */
GE| /* ">=" */
IS| /* "is" */
AS| /* "as" */
NOTEQ| /* "!=" */
EQUAL| /* "==" */
WILDCARD| /* "_" */
INT8| /* "Int8" */
INT16| /* "Int16" */
INT32| /* "Int32" */
INT64| /* "Int64" */
INTNATIVE| /* "IntNative" */
UINT8| /* "UInt8" */
UINT16| /* "UInt16" */
UINT32| /* "UInt32" */
UINT64| /* "UInt64" */
UINTNATIVE| /* "UIntNative" */
FLOAT16| /* "Float16" */
FLOAT32| /* "Float32" */
FLOAT64| /* "Float64" */
RUNE| /* "Rune" */
BOOLEAN| /* "Bool" */
NOTHING| /* "Nothing" */
UNIT| /* "Unit" */
STRUCT| /* "struct" */
ENUM| /* "enum" */
VARRAY| /* "VArray" */
THISTYPE| /* "This" */
PACKAGE| /* "package" */
IMPORT| /* "import" */
CLASS| /* "class" */
INTERFACE| /* "interface" */
FUNC| /* "func" */
MACRO| /* "macro" */
QUOTE| /* "quote" */
DOLLAR| /* "$" */
LET| /* "let" */
VAR| /* "var" */
CONST| /* "const" */
TYPE| /* "type" */
INIT| /* "init" */
THIS| /* "this" */
SUPER| /* "super" */
IF| /* "if" */
ELSE| /* "else" */
CASE| /* "case" */
TRY| /* "try" */
CATCH| /* "catch" */
FINALLY| /* "finally" */
FOR| /* "for" */
DO| /* "do" */
WHILE| /* "while" */
THROW| /* "throw" */
RETURN| /* "return" */
CONTINUE| /* "continue" */
BREAK| /* "break" */
IN| /* "in" */
NOT_IN| /* "!in" */
MATCH| /* "match" */
WHERE| /* "where" */
EXTEND| /* "extend" */
WITH| /* "with" */
PROP| /* "prop" */
STATIC| /* "static" */
PUBLIC| /* "public" */
PRIVATE| /* "private" */
INTERNAL| /* "internal" */
PROTECTED| /* "protected" */
OVERRIDE| /* "override" */
REDEF| /* "redef" */
ABSTRACT| /* "abstract" */
SEALED| /* "sealed" */
OPEN| /* "open" */
FOREIGN| /* "foreign" */
INOUT| /* "inout" */
MUT| /* "mut" */
UNSAFE| /* "unsafe" */
OPERATOR| /* "operator" */
SPAWN| /* "spawn" */
SYNCHRONIZED| /* "synchronized" */
UPPERBOUND| /* "<:" */
MAIN| /* "main" */
IDENTIFIER| /* "x" */
PACKAGE_IDENTIFIER| /* e.g. "x-y" */
INTEGER_LITERAL| /* e.g. "1" */
RUNE_BYTE_LITERAL| /* e.g. "b'x'" */
FLOAT_LITERAL| /* e.g. "'1.0'" */
COMMENT| /* e.g. "/*xx*/" */
NL| /* newline */
END| /* end of file */
SENTINEL| /* ";" */
RUNE_LITERAL| /* e.g. "r'x'" */
STRING_LITERAL| /* e.g. ""xx"" */
SINGLE_QUOTED_STRING_LITERAL|
/* e.g. "'xx'" */
JSTRING_LITERAL| /* e.g. "J"xx"" */
MULTILINE_STRING| /* e.g. """"aaa"""" */
MULTILINE_RAW_STRING| /* e.g. "#"aaa"#" */
BOOL_LITERAL| /* "true" or "false" */
UNIT_LITERAL| /* "()" */
DOLLAR_IDENTIFIER| /* e.g. "$x" */
ANNOTATION| /* e.g. "@When" */
AT_EXCL| /* e.g. "@!" */
ILLEGAL|
...
}
功能:表示仓颉编译内部所有的词法结构,包括符号、关键字、标识符、换行等。
父类型:
ABSTRACT
ABSTRACT
功能:构造一个表示 abstract 的枚举实例。
ADD
ADD
功能:构造一个表示 + 的枚举实例。
ADD_ASSIGN
ADD_ASSIGN
功能:构造一个表示 += 的枚举实例。
AND
AND
功能:构造一个表示 && 的枚举实例。
AND_ASSIGN
AND_ASSIGN
功能:构造一个表示 &&= 的枚举实例。
ANNOTATION
ANNOTATION
功能:构造一个表示注解的枚举实例。
ARROW
ARROW
功能:构造一个表示 -> 的枚举实例。
AS
AS
功能:构造一个表示 as 的枚举实例。
ASSIGN
ASSIGN
功能:构造一个表示 = 的枚举实例。
AT
AT
功能:构造一个表示 @ 的枚举实例。
AT_EXCL
AT_EXCL
功能:构造一个表示 @! 的枚举实例。
BACKARROW
BACKARROW
功能:构造一个表示 <- 的枚举实例。
BITAND
BITAND
功能:构造一个表示 & 的枚举实例。
BITAND_ASSIGN
BITAND_ASSIGN
功能:构造一个表示 &= 的枚举实例。
BITNOT
BITNOT
功能:构造一个表示 ~ 的枚举实例。
BITOR
BITOR
功能:构造一个表示 | 的枚举实例。
BITOR_ASSIGN
BITOR_ASSIGN
功能:构造一个表示 |= 的枚举实例。
BITXOR
BITXOR
功能:构造一个表示 ^ 的枚举实例。
BITXOR_ASSIGN
BITXOR_ASSIGN
功能:构造一个表示 ^= 的枚举实例。
BOOLEAN
BOOLEAN
功能:构造一个表示 bool 的枚举实例。
BOOL_LITERAL
BOOL_LITERAL
功能:构造一个表示布尔类型字面量的枚举实例。
BREAK
BREAK
功能:构造一个表示 break 的枚举实例。
CASE
CASE
功能:构造一个表示 case 的枚举实例。
CATCH
CATCH
功能:构造一个表示 catch 的枚举实例。
CLASS
CLASS
功能:构造一个表示 class 的枚举实例。
CLOSEDRANGEOP
CLOSEDRANGEOP
功能:构造一个表示 ..= 的枚举实例。
COALESCING
COALESCING
功能:构造一个表示 ?? 的枚举实例。
COLON
COLON
功能:构造一个表示 : 的枚举实例。
COMMA
COMMA
功能:构造一个表示 , 的枚举实例。
COMMENT
COMMENT
功能:构造一个表示注释的枚举实例。
COMPOSITION
COMPOSITION
功能:构造一个表示 ~> 的枚举实例。
CONST
CONST
功能:构造一个表示 const 的枚举实例。
CONTINUE
CONTINUE
功能:构造一个表示 continue 的枚举实例。
DECR
DECR
功能:构造一个表示 -- 的枚举实例。
DIV
DIV
功能:构造一个表示 / 的枚举实例。
DIV_ASSIGN
DIV_ASSIGN
功能:构造一个表示 /= 的枚举实例。
DO
DO
功能:构造一个表示 do 的枚举实例。
DOLLAR
DOLLAR
功能:构造一个表示 $ 的枚举实例。
DOLLAR_IDENTIFIER
DOLLAR_IDENTIFIER
功能:构造一个表示插值字符串的枚举实例。
DOT
DOT
功能:构造一个表示 . 的枚举实例。
DOUBLE_ARROW
DOUBLE_ARROW
功能:构造一个表示 => 的枚举实例。
ELLIPSIS
ELLIPSIS
功能:构造一个表示 ... 的枚举实例。
ELSE
ELSE
功能:构造一个表示 else 的枚举实例。
END
END
功能:构造一个表示 EOF 的枚举实例。
ENUM
ENUM
功能:构造一个表示 enum 的枚举实例。
EQUAL
EQUAL
功能:构造一个表示 == 的枚举实例。
EXP
EXP
功能:构造一个表示 ** 的枚举实例。
EXP_ASSIGN
EXP_ASSIGN
功能:构造一个表示 **= 的枚举实例。
EXTEND
EXTEND
功能:构造一个表示 extend 的枚举实例。
FINALLY
FINALLY
功能:构造一个表示 finally 的枚举实例。
FLOAT16
FLOAT16
功能:构造一个表示 float16 的枚举实例。
FLOAT32
FLOAT32
功能:构造一个表示 float32 的枚举实例。
FLOAT64
FLOAT64
功能:构造一个表示 float64 的枚举实例。
FLOAT_LITERAL
FLOAT_LITERAL
功能:构造一个表示浮点字面量的枚举实例。
FOR
FOR
功能:构造一个表示 for 的枚举实例。
FOREIGN
FOREIGN
功能:构造一个表示 foreign 的枚举实例。
FUNC
FUNC
功能:构造一个表示 func 的枚举实例。
GE
GE
功能:构造一个表示 >= 的枚举实例。
GT
GT
功能:构造一个表示 > 的枚举实例。
HASH
HASH
功能:构造一个表示 # 的枚举实例。
IDENTIFIER
IDENTIFIER
功能:构造一个表示标识符的枚举实例。
PACKAGE_IDENTIFIER
PACKAGE_IDENTIFIER
功能:构造一个表示包标识符的枚举实例。
IF
IF
功能:构造一个表示 if 的枚举实例。
ILLEGAL
ILLEGAL
功能:构造一个表示非法的枚举实例。
IMPORT
IMPORT
功能:构造一个表示 import 的枚举实例。
IN
IN
功能:构造一个表示 in 的枚举实例。
INCR
INCR
功能:构造一个表示 ++ 的枚举实例。
INIT
INIT
功能:构造一个表示 init 的枚举实例。
INOUT
INOUT
功能:构造一个表示 inout 的枚举实例。
INT16
INT16
功能:构造一个表示 int16 的枚举实例。
INT32
INT32
功能:构造一个表示 int32 的枚举实例。
INT64
INT64
功能:构造一个表示 int64 的枚举实例。
INT8
INT8
功能:构造一个表示 int8 的枚举实例。
INTEGER_LITERAL
INTEGER_LITERAL
功能:构造一个表示整型字面量的枚举实例。
INTERFACE
INTERFACE
功能:构造一个表示 interface 的枚举实例。
INTERNAL
INTERNAL
功能:构造一个表示 internal 的枚举实例。
INTNATIVE
INTNATIVE
功能:构造一个表示 intnative 的枚举实例。
IS
IS
功能:构造一个表示 is 的枚举实例。
JSTRING_LITERAL
JSTRING_LITERAL
功能:构造一个表示 JavaSTRING字面量 的枚举实例。
LCURL
LCURL
功能:构造一个表示 { 的枚举实例。
LE
LE
功能:构造一个表示 <= 的枚举实例。
LET
LET
功能:构造一个表示 let 的枚举实例。
LPAREN
LPAREN
功能:构造一个表示 ( 的枚举实例。
LSHIFT
LSHIFT
功能:构造一个表示 << 的枚举实例。
LSHIFT_ASSIGN
LSHIFT_ASSIGN
功能:构造一个表示 <<= 的枚举实例。
LSQUARE
LSQUARE
功能:构造一个表示 [ 的枚举实例。
LT
LT
功能:构造一个表示 < 的枚举实例。
MACRO
MACRO
功能:构造一个表示 macro 的枚举实例。
MAIN
MAIN
功能:构造一个表示 main 的枚举实例。
MATCH
MATCH
功能:构造一个表示 match 的枚举实例。
MOD
MOD
功能:构造一个表示 % 的枚举实例。
MOD_ASSIGN
MOD_ASSIGN
功能:构造一个表示 %= 的枚举实例。
MUL
MUL
功能:构造一个表示 * 的枚举实例。
MULTILINE_RAW_STRING
MULTILINE_RAW_STRING
功能:构造一个表示多行原始字符串字面量的枚举实例。
MULTILINE_STRING
MULTILINE_STRING
功能:构造一个表示多行字符串字面量的枚举实例。
MUL_ASSIGN
MUL_ASSIGN
功能:构造一个表示 *= 的枚举实例。
MUT
MUT
功能:构造一个表示 mut 的枚举实例。
NL
NL
功能:构造一个表示换行符的枚举实例。
NOT
NOT
功能:构造一个表示 ! 的枚举实例。
NOTEQ
NOTEQ
功能:构造一个表示 != 的枚举实例。
NOTHING
NOTHING
功能:构造一个表示 nothing 的枚举实例。
NOT_IN
NOT_IN
功能:构造一个表示 !in 的枚举实例。
OPEN
OPEN
功能:构造一个表示 open 的枚举实例。
OPERATOR
OPERATOR
功能:构造一个表示 operator 的枚举实例。
OR
OR
功能:构造一个表示 || 的枚举实例。
OR_ASSIGN
OR_ASSIGN
功能:构造一个表示 ||= 的枚举实例。
OVERRIDE
OVERRIDE
功能:构造一个表示 override 的枚举实例。
PACKAGE
PACKAGE
功能:构造一个表示 package 的枚举实例。
PIPELINE
PIPELINE
功能:构造一个表示 |> 的枚举实例。
PRIVATE
PRIVATE
功能:构造一个表示 private 的枚举实例。
PROP
PROP
功能:构造一个表示 prop 的枚举实例。
PROTECTED
PROTECTED
功能:构造一个表示 protected 的枚举实例。
PUBLIC
PUBLIC
功能:构造一个表示 public 的枚举实例。
QUEST
QUEST
功能:构造一个表示 ? 的枚举实例。
QUOTE
QUOTE
功能:构造一个表示 quote 的枚举实例。
RANGEOP
RANGEOP
功能:构造一个表示 .. 的枚举实例。
RCURL
RCURL
功能:构造一个表示 } 的枚举实例。
REDEF
REDEF
功能:构造一个表示 redef 的枚举实例。
RETURN
RETURN
功能:构造一个表示 return 的枚举实例。
RPAREN
RPAREN
功能:构造一个表示 ) 的枚举实例。
RSHIFT
RSHIFT
功能:构造一个表示 >> 的枚举实例。
RSHIFT_ASSIGN
RSHIFT_ASSIGN
功能:构造一个表示 >>= 的枚举实例。
RSQUARE
RSQUARE
功能:构造一个表示 ] 的枚举实例。
RUNE
RUNE
功能:构造一个表示 Rune 的枚举实例。
RUNE_BYTE_LITERAL
RUNE_BYTE_LITERAL
功能:构造一个表示字符字节字面量的枚举实例。
RUNE_LITERAL
RUNE_LITERAL
功能:构造一个表示字符字面量的枚举实例。
SEALED
SEALED
功能:构造一个表示 sealed 的枚举实例。
SEMI
SEMI
功能:构造一个表示 ; 的枚举实例。
SENTINEL
SENTINEL
功能:构造一个表示 ; 的枚举实例。
SINGLE_QUOTED_STRING_LITERAL
SINGLE_QUOTED_STRING_LITERAL
功能:构造一个表示单引号字符串字面量的枚举实例。
SPAWN
SPAWN
功能:构造一个表示 spawn 的枚举实例。
STATIC
STATIC
功能:构造一个表示 static 的枚举实例。
STRING_LITERAL
STRING_LITERAL
功能:构造一个表示双引号字符串字面量的枚举实例。
STRUCT
STRUCT
功能:构造一个表示 struct 的枚举实例。
SUB
SUB
功能:构造一个表示 - 的枚举实例。
SUB_ASSIGN
SUB_ASSIGN
功能:构造一个表示 -= 的枚举实例。
SUPER
SUPER
功能:构造一个表示 super 的枚举实例。
SYNCHRONIZED
SYNCHRONIZED
功能:构造一个表示 synchronized 的枚举实例。
THIS
THIS
功能:构造一个表示 this 的枚举实例。
THISTYPE
THISTYPE
功能:构造一个表示 This 的枚举实例。
THROW
THROW
功能:构造一个表示 throw 的枚举实例。
TRY
TRY
功能:构造一个表示 try 的枚举实例。
TYPE
TYPE
功能:构造一个表示 type 的枚举实例。
UINT16
UINT16
功能:构造一个表示 uint16 的枚举实例。
UINT32
UINT32
功能:构造一个表示 uint32 的枚举实例。
UINT64
UINT64
功能:构造一个表示 uint64 的枚举实例。
UINT8
UINT8
功能:构造一个表示 uint8 的枚举实例。
UINTNATIVE
UINTNATIVE
功能:构造一个表示 uintnative 的枚举实例。
UNIT
UNIT
功能:构造一个表示 unit 的枚举实例。
UNIT_LITERAL
UNIT_LITERAL
功能:构造一个表示 unit 字面量的枚举实例。
UNSAFE
UNSAFE
功能:构造一个表示 unsafe 的枚举实例。
UPPERBOUND
UPPERBOUND
功能:构造一个表示 <: 的枚举实例。
VAR
VAR
功能:构造一个表示 var 的枚举实例。
VARRAY
VARRAY
功能:构造一个表示 varray 的枚举实例。
WHERE
WHERE
功能:构造一个表示 where 的枚举实例。
WHILE
WHILE
功能:构造一个表示 while 的枚举实例。
WILDCARD
WILDCARD
功能:构造一个表示 _ 的枚举实例。
WITH
WITH
功能:构造一个表示 with 的枚举实例。
func !=(TokenKind)
public operator func !=(right: TokenKind): Bool
功能:重载不等号操作符,用于比较两个 TokenKind 是否相等。
返回值:
- Bool - 布尔类型。
func ==(TokenKind)
public operator func ==(right: TokenKind): Bool
功能:重载等号操作符,用于比较两个 TokenKind 是否相等。
返回值:
- Bool - 布尔类型。
func toString()
public func toString(): String
功能:将 TokenKind 类型转化为字符串类型表示。
返回值:
结构体
struct Position
public struct Position <: ToBytes {
public let column: Int32
public let fileID: UInt32
public let line: Int32
public init()
public init(fileID: UInt32, line: Int32, column: Int32)
}
功能:表示位置信息的数据结构,包含文件ID,行号和列号。
父类型:
let column
public let column: Int32
功能:获取列号信息。
类型:Int32
let fileID
public let fileID: UInt32
功能:获取文件 ID 信息。
类型:UInt32
let line
public let line: Int32
功能:获取行号信息。
类型:Int32
init()
public init()
功能:构造一个默认的 Position 实例,其中 fileID、line、column 成员变量均为 0。
init(UInt32, Int32, Int32)
public init(fileID: UInt32, line: Int32, column: Int32)
功能:构造一个 Position 实例。
参数:
func dump()
public func dump(): Unit
功能:将 Position 的信息打印出来。
func isEmpty()
public func isEmpty(): Bool
功能:判断行号和列号是否同时为 0。
返回值:
- Bool - 当行号和列号为
0时返回 true。
func toBytes()
public func toBytes(): Array<UInt8>
功能:Position 类型的序列化。
返回值:
operator func !=(Position)
public operator func !=(r: Position): Bool
功能:比较两个 Position 实例是否不等。
参数:
- r: Position - 与当前位置比较的另一个位置实例。
返回值:
operator func ==(Position)
public operator func ==(r: Position): Bool
功能:比较两个 Position 实例是否相等。
参数:
- r: Position - 与当前位置比较的另一个位置实例。
返回值:
struct Token
public struct Token <: ToBytes {
public let kind: TokenKind
public let pos: Position
public let value: String
public var delimiterNum: UInt16 = 1
public init()
public init(kind: TokenKind)
public init(kind: TokenKind, value: String)
}
功能:词法单元类型。
词法单元是构成仓颉源码的最小单元,一组合法的词法单元列表经过语法解析后可生成一个语法树节点。
父类型:
let kind
public let kind: TokenKind
功能:词法单元的类型。词法单元类型有关键字、标识符、运算符、常量值等,具体见 TokenKind 章节。
类型:TokenKind
let pos
public let pos: Position
功能:词法单元在源码中的位置信息。
类型:Position
let value
public let value: String
功能:词法单元的字面量值。
类型:String
var delimiterNum
public var delimiterNum: UInt16 = 1
功能:多行字符串的 '#' 符号个数。
类型:UInt16
init()
public init()
功能:构造一个默认的 Token 对象,其中 TokenKind 类型为 ILLEGAL,value 为空字符串,Position 成员变量均为 0。
init(TokenKind)
public init(kind: TokenKind)
功能:根据词法单元类型,构造一个默认的 Token 对象。
参数:
- kind: TokenKind - 构建词法单元的类型。
init(TokenKind, String)
public init(kind: TokenKind, value: String)
功能:根据词法单元类型 kind 和词法单元值 value,构造一个 Token 对象。
参数:
异常:
- IllegalArgumentException - 当输入的
kind与value不匹配时,抛出异常点。
func addPosition(UInt32, Int32, Int32)
public func addPosition(fileID: UInt32, line: Int32, colum: Int32): Token
功能:补充词法单元的位置信息。
参数:
返回值:
func dump()
public func dump(): Unit
功能:将 Token 的信息打印出来。
func toBytes()
public func toBytes(): Array<UInt8>
功能:Token 类型的序列化。
返回值:
operator func !=(Token)
public operator func !=(r: Token): Bool
功能:判断两个 Token 对象是否不相等。
参数:
返回值:
- Bool - 两个词法单元的种类
ID、值、位置不相同时,返回 true。
operator func +(Token)
public operator func +(r: Token): Tokens
功能:使用当前 Token 添加一个 Token 以获取新的 Tokens。
参数:
返回值:
operator func +(Tokens)
public operator func +(r: Tokens): Tokens
功能:使用当前 Token 添加一个 Tokens 以获取新的 Tokens。
参数:
返回值:
operator func ==(Token)
public operator func ==(r: Token): Bool
功能:判断两个 Token 对象是否相等。
参数:
返回值:
- Bool - 两个词法单元的种类
ID、值、位置相同时,返回 true。
异常类
class ASTException
public class ASTException <: Exception {
public init()
public init(message: String)
}
功能:ast 库的异常类,在 ast 库调用过程中发生异常时使用。
父类型:
init()
public init()
功能:构造一个默认的 ASTException 对象。
init(String)
public init(message: String)
功能:根据异常信息构造一个 ASTException 对象。
参数:
- message: String - 异常信息。
class MacroContextException
public class MacroContextException <: Exception {
public init()
public init(message: String)
}
功能:ast库的上下文宏异常类,在上下文宏的相关接口中发生异常时使用。
父类型:
init()
public init()
功能:构造一个默认的 MacroContextException 对象。
init(String)
public init(message: String)
功能:根据异常信息构造一个 MacroContextException 对象。
参数:
- message: String - 异常信息。
class ParseASTException
public class ParseASTException <: Exception {
public init()
public init(message: String)
}
功能:ast 库的解析异常类,在节点解析过程中发生异常时使用。
父类型:
init()
public init()
功能:构造一个默认的 ParseASTException 对象。
init(String)
public init(message: String)
功能:根据异常信息构造一个 ParseASTException 对象。
参数:
- message: String - 异常信息。
Macro With Context
宏定义如下:
// macro_definition.cj
macro package macro_definition
import std.ast.*
public macro Outter(input: Tokens): Tokens {
return input
}
public macro Inner(input: Tokens): Tokens {
assertParentContext("Outter")
return input
}
宏调用如下:
// macro_call.cj
package macro_calling
import macro_definition.*
main() {
@Outter var a = 0
@Inner var b = 0 // error: The macro call 'Inner' should with the surround code contains a call 'Outter'.
}
编译命令如下:
# 先编译宏定义文件
cjc macro_definition.cj --compile-macro
# 编译使用宏的文件
cjc macro_call.cj -o demo
如上代码所示,Inner 宏在定义时使用了 assertParentContext 函数用于检查其在调用阶段是否位于 Outter 宏中,在代码示例的宏调用场景下,由于 Outter 和 Inner 在调用时不存在这样的嵌套关系,因此编译器将报告一个错误。
宏定义如下:
// macro_definition.cj
macro package macro_definition
import std.ast.*
public macro Outter(input: Tokens): Tokens {
let messages = getChildMessages("Inner")
for (m in messages) {
let value1 = m.getString("key1") // get value: "value1"
let value2 = m.getString("key2") // get value: "value2"
println("value1: ${value1} value2: ${value2}")
}
return input
}
public macro Inner(input: Tokens): Tokens {
assertParentContext("Outter")
setItem("key1", "value1")
setItem("key2", "value2")
return input
}
宏调用如下:
// macro_call.cj
import std.ast.*
import macro_definition.*
main() {
@Outter(
@Inner var cnt = 0
)
println(cnt)
}
编译命令如下:
# 先编译宏定义文件
cjc macro_definition.cj --compile-macro
# 编译使用宏的文件
cjc macro_call.cj -o demo
编译阶段输出:
value1: value1 value2: value2
在上面的代码中,内层宏 Inner 通过 setItem 向外层宏发送信息;Outter 宏通过 getChildMessages 函数接收到 Inner 发送的一组信息对象(Outter 中可以调用多次 Inner);最后通过该信息对象的 getString 函数接收对应的值。
语法树节点打印
仓颉 ast 包提供了丰富的语法树节点用于表示仓颉源码。由于节点种类丰富、不同节点间属性不同,使用过程可能会发生混淆不清的情况,为此我们为每个 AST 节点实现了 dump 函数方便实时查看语法树节点的整体结构,避免重复查看该手册带来的困扰。
示例:
import std.ast.*
main() {
let input = quote(var demo: Int64 = 1) // 假设当前代码所在行数为:3
let varDecl = parseDecl(input)
varDecl.dump()
}
运行结果:
VarDecl {
-keyword: Token {
value: "var"
kind: VAR
pos: 3: 23
}
-identifier: Token {
value: "demo"
kind: IDENTIFIER
pos: 3: 27
}
-declType: PrimitiveType {
-keyword: Token {
value: "Int64"
kind: INT64
pos: 3: 33
}
}
-assign: Token {
value: "="
kind: ASSIGN
pos: 3: 39
}
-expr: LitConstExpr {
-literal: Token {
value: "1"
kind: INTEGER_LITERAL
pos: 3: 41
}
}
}
操作 AST 对象示例
获取 ClassDecl 类型的节点后,可以对该节点进行增、删、改、查等操作。代码如下所示:
import std.ast.*
main() {
let input: Tokens = quote(
class Data {
var a: Int32
init(a_: Int32) {
a = a_
}
}
)
let decl = parseDecl(input) // 获取一个 Decl 声明节点
var classDecl = match (decl as ClassDecl) { // decl 的具体类型为 ClassDecl, 将其进行类型转化。
case Some(v) => v
case None => throw Exception()
}
var identifier = classDecl.identifier
// 为该节点增加一个成员函数用于获取a的值
var funcdecl = FuncDecl(quote(func getValue() {a}))
classDecl.body.decls.add(funcdecl)
println("Identifier value is ${identifier.value}")
println("ClassDecl body size is ${classDecl.body.decls.size}")
0
}
运行结果:
Identifier value is Data
ClassDecl body size is 3
将仓颉源码解析为 AST 对象示例
如下有一个类 Data:
class Data {
var a: Int32
init(a_: Int32) {
a = a_
}
}
利用解析函数将上述代码解析为一个 Decl 对象,代码如下所示:
import std.ast.*
main() {
let input: Tokens = quote(
class Data {
var a: Int32
init(a_: Int32) {
a = a_
}
}
)
let decl = parseDecl(input) // 获取一个 Decl 声明节点
var classDecl = match (decl as ClassDecl) { // decl 的具体类型为 ClassDecl, 将其进行类型转化。
case Some(v) => v
case None => throw Exception()
}
classDecl.dump()
}
运行结果:
ClassDecl {
-keyword: Token {
value: "class"
kind: CLASS
pos: 5: 9
}
-identifier: Token {
value: "Data"
kind: IDENTIFIER
pos: 5: 15
}
-body: Body {
-decls: 0, VarDecl {
-keyword: Token {
value: "var"
kind: VAR
pos: 6: 13
}
-identifier: Token {
value: "a"
kind: IDENTIFIER
pos: 6: 17
}
-declType: PrimitiveType {
-keyword: Token {
value: "Int32"
kind: INT32
pos: 6: 20
}
}
}
-decls: 1, FuncDecl {
-keyword: Token {
value: "init"
kind: INIT
pos: 7: 13
}
-identifier: Token {
value: "init"
kind: IDENTIFIER
pos: 7: 13
}
-funcParams: 0, FuncParam {
-identifier: Token {
value: "a_"
kind: IDENTIFIER
pos: 7: 18
}
-colon: Token {
value: ":"
kind: COLON
pos: 7: 20
}
-paramType: PrimitiveType {
-keyword: Token {
value: "Int32"
kind: INT32
pos: 7: 22
}
}
}
-block: Block {
-nodes: 0, AssignExpr {
-leftExpr: RefExpr {
-identifier: Token {
value: "a"
kind: IDENTIFIER
pos: 8: 17
}
}
-assign: Token {
value: "="
kind: ASSIGN
pos: 8: 19
}
-rightExpr: RefExpr {
-identifier: Token {
value: "a_"
kind: IDENTIFIER
pos: 8: 21
}
}
}
}
}
}
}
自定义报错接口
仓颉 ast 包提供了自定义报错接口 diagReport。方便定义宏的用户,在解析传入 Tokens 时,对错误 Tokens 内容进行自定义报错。
自定义报错接口提供同原生编译器报错一样的输出格式,允许用户报 WARNING 和 ERROR 两类错误提示信息。
正确使用示例
宏定义如下:
// macro_definition.cj
macro package macro_definition
import std.ast.*
public macro testDef(input: Tokens): Tokens {
for (i in 0..input.size) {
if (input[i].kind == IDENTIFIER) {
diagReport(DiagReportLevel.ERROR, input[i..(i + 1)], "This expression is not allowed to contain identifier", "Here is the illegal identifier")
}
}
return input
}
宏调用如下:
// macro_call.cj
package macro_calling
import std.ast.*
import macro_definition.*
main(): Int64 {
let a = @testDef(1)
let b = @testDef(a)
let c = @testDef(1 + a)
return 0
}
编译命令如下:
# 先编译宏定义文件
cjc macro_definition.cj --compile-macro
# 编译使用宏的文件
cjc macro_call.cj -o demo
报错提示信息如下:
error: This expression is not allowed to contain identifier
==> call.cj:9:22:
|
9 | let b = @testDef(a)
| ^ Here is the illegal identifier
|
error: This expression is not allowed to contain identifier
==> call.cj:10:26:
|
10 | let c = @testDef(1 + a)
| ^ Here is the illegal identifier
|
2 errors generated, 2 errors printed.
非宏展开过程中调用示例
import std.ast.*
func A(input: Tokens) {
diagReport(DiagReportLevel.ERROR, input, "Message", "Hint") // 该调用处在普通函数 A 中,diagReport 实际不会执行任何操作
}
main() {
let tokens = quote(var a = 0)
A(tokens)
}
自定义访问函数遍历 AST 对象示例
定义访问变量声明节点的行为:继承 Visitor 并重写访问函数,找到未定义变量,将其变量词法单元存起来。
import std.ast.*
class MyVisitor <: Visitor {
public var uninitializedVars = Tokens() // 存储变量词法单元
override public func visit(varDecl: VarDecl) {
try {
varDecl.expr
} catch (e: ASTException) {
uninitializedVars.append(varDecl.identifier)
}
breakTraverse() // 不会继续遍历 varDecl 的子节点
return
}
}
main(): Int64 {
let input = quote(
var a : Int64
)
let varDecl = parseDecl(input)
let visitor = MyVisitor() // MyVisitor中定义了对 varDecl 节点的处理
varDecl.traverse(visitor) // 实现对 varDecl 节点的处理
println("Uninitialized VarDecl size is ${visitor.uninitializedVars.size}")
0
}
运行结果:
Uninitialized VarDecl size is 1
std.binary
功能介绍
当前 binary 包提供了如下功能:
- 仓颉数据类型和二进制字节序列间的互相转换接口,分为大端序和小端序两种转换类型。
- 仓颉数据类型自身大小端序转换的接口。
说明:
- 一般来说,多字节对象被存储为连续的字节序列。存储器或数字通信链路中,字节的排列顺序称为端序(Endianness)。端序又称字节顺序或者尾序。
- 字节有两种排列方式:将将一个多位数的低位存储在内存的低地址端,高位存储在内存的高地址端,称为小端序(Little-endian);反之称为大端序(Big-endian)。
API 列表
接口
| 接口名 | 功能 |
|---|---|
| BigEndianOrder<T> | 大端序字节序列转换接口。 |
| LittleEndianOrder<T> | 小端序字节序列转换接口。 |
| SwapEndianOrder<T> | 反转字节顺序接口。 |
接口
interface BigEndianOrder<T>
public interface BigEndianOrder<T> {
func writeBigEndian(buffer: Array<Byte>): Int64
static func readBigEndian(buffer: Array<Byte>): T
}
功能:大端序字节序列转换接口。
static func readBigEndian(Array<Byte>)
static func readBigEndian(buffer: Array<Byte>): T
功能:从字节数组中以大端序的方式读取一个 T 值。
参数:
返回值:
- T - T 值。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 T 值时,抛出异常。
func writeBigEndian(Array<Byte>)
func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 T 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 T 值时,抛出异常。
extend Bool <: BigEndianOrder<Bool>
extend Bool <: BigEndianOrder<Bool>
功能:为 Bool 扩展 BigEndianOrder 接口,以实现将 Bool 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Bool
功能:从字节数组中以大端序的方式读取一个 Bool 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Bool 值时,抛出异常。
示例:
import std.binary.*
main() {
let buffer: Array<Byte> = [0x1]
let n = Bool.readBigEndian(buffer)
println(n)
}
运行结果:
true
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Bool 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Bool 值时,抛出异常。
示例:
import std.binary.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = true.writeBigEndian(buffer)
println(n == 1)
println(buffer[0] == 0x01u8)
}
运行结果:
true
true
extend Float16 <: BigEndianOrder<Float16>
extend Float16 <: BigEndianOrder<Float16>
功能:为 Float16 扩展 BigEndianOrder 接口,以实现将 Float16 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Float16
功能:从字节数组中以大端序的方式读取一个 Float16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Float16 值时,抛出异常。
示例:
import std.binary.*
main() {
/* 12.5的IEEE 754表示为0x4A40 */
let buffer: Array<Byte> = [0x4A, 0x40]
let n = Float16.readBigEndian(buffer)
println(n == 12.5)
}
运行结果:
true
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Float16 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Float16 值时,抛出异常。
示例:
import std.binary.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let len = 12.5f16.writeBigEndian(buffer)
println(len)
/* 0x4A的十进制表示为74,0x40的十进制表示为64 */
println(buffer[0..len])
}
运行结果:
2
[74, 64]
extend Float32 <: BigEndianOrder<Float32>
extend Float32 <: BigEndianOrder<Float32>
功能:为 Float32 扩展 BigEndianOrder 接口,以实现将 Float32 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Float32
功能:从字节数组中以大端序的方式读取一个 Float32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Float32 值时,抛出异常。
示例:
import std.binary.*
main() {
let buffer: Array<Byte> = [0x41, 0x48, 0x00, 0x00]
let n = Float32.readBigEndian(buffer)
println(n)
}
运行结果:
12.500000
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Float32 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Float32 值时,抛出异常。
示例:
import std.binary.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let len = 12.5f32.writeBigEndian(buffer)
println(len)
/* 12.5的IEEE 754的单精度浮点表示为 0x4148 ,0x41的十进制表示为65,0x48的十进制表示为72 */
println(buffer[0..len])
}
运行结果:
4
[65, 72, 0, 0]
extend Float64 <: BigEndianOrder<Float64>
extend Float64 <: BigEndianOrder<Float64>
功能:为 Float64 扩展 BigEndianOrder 接口,以实现将 Float64 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Float64
功能:从字节数组中以大端序的方式读取一个 Float64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Float64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
let n = Float64.readBigEndian(buffer)
@Assert(n, 12.5)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Float64 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Float64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 12.5f64.writeBigEndian(buffer)
@Assert(n, 8)
@Assert(buffer[..n] == [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
}
extend Int16 <: BigEndianOrder<Int16>
extend Int16 <: BigEndianOrder<Int16>
功能:为 Int16 扩展 BigEndianOrder 接口,以实现将 Int16 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Int16
功能:从字节数组中以大端序的方式读取一个 Int16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12, 0x34]
let n = Int16.readBigEndian(buffer)
@Assert(n, 0x1234)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Int16 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234i16.writeBigEndian(buffer)
@Assert(n, 2)
@Assert(buffer[..n] == [0x12, 0x34])
}
extend Int32 <: BigEndianOrder<Int32>
extend Int32 <: BigEndianOrder<Int32>
功能:为 Int32 扩展 BigEndianOrder 接口,以实现将 Int32 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Int32
功能:从字节数组中以大端序的方式读取一个 Int32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12, 0x34, 0x56, 0x78]
let n = Int32.readBigEndian(buffer)
@Assert(n, 0x12345678)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Int32 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
var buffer: Array<Byte> = Array<Byte>(8, repeat: 0)
let n = 0x12345678i32.
writeBigEndian(buffer)
@Assert(n, 4)
@Assert(buffer[..n] == [0x12u8, 0x34u8, 0x56u8, 0x78u8])
}
extend Int64 <: BigEndianOrder<Int64>
extend Int64 <: BigEndianOrder<Int64>
功能:为 Int64 扩展 BigEndianOrder 接口,以实现将 Int64 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Int64
功能:从字节数组中以大端序的方式读取一个 Int64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]
let n = Int64.readBigEndian(buffer)
@Assert(n, 0x1234567890123456)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Int64 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234567890123456i64.writeBigEndian(buffer)
@Assert(n, 8)
@Assert(buffer[..n] == [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56])
}
extend Int8 <: BigEndianOrder<Int8>
extend Int8 <: BigEndianOrder<Int8>
功能:为 Int8 扩展 BigEndianOrder 接口,以实现将 Int8 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): Int8
功能:从字节数组中以大端序的方式读取一个 Int8 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12]
let n = Int8.readBigEndian(buffer)
@Assert(n, 0x12)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 Int8 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x12i8.writeBigEndian(buffer)
@Assert(n, 1)
@Assert(buffer[..n] == [0x12])
}
extend UInt16 <: BigEndianOrder<UInt16>
extend UInt16 <: BigEndianOrder<UInt16>
功能:为 UInt16 扩展 BigEndianOrder 接口,以实现将 UInt16 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): UInt16
功能:从字节数组中以大端序的方式读取一个 UInt16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12, 0x34]
let n = UInt16.readBigEndian(buffer)
@Assert(n, 0x1234)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 UInt16 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234u16.writeBigEndian(buffer)
@Assert(n, 2)
@Assert(buffer[..n] == [0x12, 0x34])
}
extend UInt32 <: BigEndianOrder<UInt32>
extend UInt32 <: BigEndianOrder<UInt32>
功能:为 UInt32 扩展 BigEndianOrder 接口,以实现将 UInt32 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): UInt32
功能:从字节数组中以大端序的方式读取一个 UInt32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12, 0x34, 0x56, 0x78]
let n = UInt32.readBigEndian(buffer)
@Assert(n, 0x12345678)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 UInt32 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x12345678u32.writeBigEndian(buffer)
@Assert(n, 4)
@Assert(buffer[..n] == [0x12, 0x34, 0x56, 0x78])
}
extend UInt64 <: BigEndianOrder<UInt64>
extend UInt64 <: BigEndianOrder<UInt64>
功能:为 UInt64 扩展 BigEndianOrder 接口,以实现将 UInt64 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): UInt64
功能:从字节数组中以大端序的方式读取一个 UInt64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]
let n = UInt64.readBigEndian(buffer)
@Assert(n, 0x1234567890123456)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 UInt64 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234567890123456u64.writeBigEndian(buffer)
@Assert(n, 8)
@Assert(buffer[..n] == [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56])
}
extend UInt8 <: BigEndianOrder<UInt8>
extend UInt8 <: BigEndianOrder<UInt8>
功能:为 UInt8 扩展 BigEndianOrder 接口,以实现将 UInt8 值和大端序字节序列的转换。
父类型:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): UInt8
功能:从字节数组中以大端序的方式读取一个 UInt8 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12]
let n = UInt8.readBigEndian(buffer)
@Assert(n, 0x12)
}
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:将 UInt8 值以大端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x12u8.writeBigEndian(buffer)
@Assert(n, 1)
@Assert(buffer[..n] == [0x12])
}
interface LittleEndianOrder<T>
public interface LittleEndianOrder<T> {
func writeLittleEndian(buffer: Array<Byte>): Int64
static func readLittleEndian(buffer: Array<Byte>): T
}
功能:小端序字节序列转换接口。
static func readLittleEndian(Array<Byte>)
static func readLittleEndian(buffer: Array<Byte>): T
功能:从字节数组中以小端序的方式读取一个 T 值。
参数:
返回值:
- T - T 值。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 T 值时,抛出异常。
func writeLittleEndian(Array<Byte>)
func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 T 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 T 值时,抛出异常。
extend Bool <: LittleEndianOrder<Bool>
extend Bool <: LittleEndianOrder<Bool>
功能:为 Bool 扩展 LittleEndianOrder 接口,以实现将 Bool 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Bool
功能:从字节数组中以小端序的方式读取一个 Bool 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Bool 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x1]
let n = Bool.readLittleEndian(buffer)
@Assert(n, true)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Bool 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Bool 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = true.writeLittleEndian(buffer)
@Assert(n, 1)
@Assert(buffer[..n] == [0x01])
}
extend Float16 <: LittleEndianOrder<Float16>
extend Float16 <: LittleEndianOrder<Float16>
功能:为 Float16 扩展 LittleEndianOrder 接口,以实现将 Float16 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Float16
功能:从字节数组中以小端序的方式读取一个 Float16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Float16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x40, 0x4A]
let n = Float16.readLittleEndian(buffer)
@Assert(n, 12.5)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Float16 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Float16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 12.5f16.writeLittleEndian(buffer)
@Assert(n, 2)
@Assert(buffer[..n] == [0x40, 0x4A])
}
extend Float32 <: LittleEndianOrder<Float32>
extend Float32 <: LittleEndianOrder<Float32>
功能:为 Float32 扩展 LittleEndianOrder 接口,以实现将 Float32 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Float32
功能:从字节数组中以小端序的方式读取一个 Float32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Float32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x00, 0x00, 0x48, 0x41]
let n = Float32.readLittleEndian(buffer)
@Assert(n, 12.5)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Float32 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Float32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 12.5f32.writeLittleEndian(buffer)
@Assert(n, 4)
@Assert(buffer[..n] == [0x00, 0x00, 0x48, 0x41])
}
extend Float64 <: LittleEndianOrder<Float64>
extend Float64 <: LittleEndianOrder<Float64>
功能:为 Float64 扩展 LittleEndianOrder 接口,以实现将 Float64 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Float64
功能:从字节数组中以小端序的方式读取一个 Float64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Float64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
let n = Float64.readLittleEndian(buffer)
@Assert(n, 12.5)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Float64 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Float64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 12.5f64.writeLittleEndian(buffer)
@Assert(n, 8)
@Assert(buffer[..n] == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40])
}
extend Int16 <: LittleEndianOrder<Int16>
extend Int16 <: LittleEndianOrder<Int16>
功能:为 Int16 扩展 LittleEndianOrder 接口,以实现将 Int16 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Int16
功能:从字节数组中以小端序的方式读取一个 Int16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x34, 0x12]
let n = Int16.readLittleEndian(buffer)
@Assert(n, 0x1234i16)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Int16 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234i16.writeLittleEndian(buffer)
@Assert(n, 2)
@Assert(buffer[..n] == [0x34, 0x12])
}
extend Int32 <: LittleEndianOrder<Int32>
extend Int32 <: LittleEndianOrder<Int32>
功能:为 Int32 扩展 LittleEndianOrder 接口,以实现将 Int32 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Int32
功能:从字节数组中以小端序的方式读取一个 Int32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x78, 0x56, 0x34, 0x12]
let n = Int32.readLittleEndian(buffer)
@Assert(n, 0x12345678)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Int32 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x12345678i32.writeLittleEndian(buffer)
@Assert(n, 4)
@Assert(buffer[..n] == [0x78, 0x56, 0x34, 0x12])
}
extend Int64 <: LittleEndianOrder<Int64>
extend Int64 <: LittleEndianOrder<Int64>
功能:为 Int64 扩展 LittleEndianOrder 接口,以实现将 Int64 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Int64
功能:从字节数组中以小端序的方式读取一个 Int64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]
let n = Int64.readLittleEndian(buffer)
@Assert(n, 0x1234567890123456)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Int64 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234567890123456i64.writeLittleEndian(buffer)
@Assert(n, 8)
@Assert(buffer[..n] == [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12])
}
extend Int8 <: LittleEndianOrder<Int8>
extend Int8 <: LittleEndianOrder<Int8>
功能:为 Int8 扩展 LittleEndianOrder 接口,以实现将 Int8 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): Int8
功能:从字节数组中以小端序的方式读取一个 Int8 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 Int8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12]
let n = Int8.readLittleEndian(buffer)
@Assert(n, 0x12)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 Int8 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 Int8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x12i8.writeLittleEndian(buffer)
@Assert(n, 1)
@Assert(buffer[..n] == [0x12])
}
extend UInt16 <: LittleEndianOrder<UInt16>
extend UInt16 <: LittleEndianOrder<UInt16>
功能:为 UInt16 扩展 LittleEndianOrder 接口,以实现将 UInt16 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): UInt16
功能:从字节数组中以小端序的方式读取一个 UInt16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x34, 0x12]
let n = UInt16.readLittleEndian(buffer)
@Assert(n, 0x1234u16)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 UInt16 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt16 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234u16.writeLittleEndian(buffer)
@Assert(n, 2)
@Assert(buffer[..n] == [0x34, 0x12])
}
extend UInt32 <: LittleEndianOrder<UInt32>
extend UInt32 <: LittleEndianOrder<UInt32>
功能:为 UInt32 扩展 LittleEndianOrder 接口,以实现将 UInt32 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): UInt32
功能:从字节数组中以小端序的方式读取一个 UInt32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x78, 0x56, 0x34, 0x12]
let n = UInt32.readLittleEndian(buffer)
@Assert(n, 0x12345678)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 UInt32 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt32 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x12345678u32.writeLittleEndian(buffer)
@Assert(n, 4)
@Assert(buffer[..n] == [0x78, 0x56, 0x34, 0x12])
}
extend UInt64 <: LittleEndianOrder<UInt64>
extend UInt64 <: LittleEndianOrder<UInt64>
功能:为 UInt64 扩展 LittleEndianOrder 接口,以实现将 UInt64 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): UInt64
功能:从字节数组中以小端序的方式读取一个 UInt64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]
let n = UInt64.readLittleEndian(buffer)
@Assert(n, 0x1234567890123456)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 UInt64 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt64 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x1234567890123456u64.writeLittleEndian(buffer)
@Assert(n, 8)
@Assert(buffer[..n] == [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12])
}
extend UInt8 <: LittleEndianOrder<UInt8>
extend UInt8 <: LittleEndianOrder<UInt8>
功能:为 UInt8 扩展 LittleEndianOrder 接口,以实现将 UInt8 值和小端序字节序列的转换。
父类型:
static func readLittleEndian(Array<Byte>)
public static func readLittleEndian(buffer: Array<Byte>): UInt8
功能:从字节数组中以小端序的方式读取一个 UInt8 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 UInt8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer: Array<Byte> = [0x12]
let n = UInt8.readLittleEndian(buffer)
@Assert(n, 0x12)
}
func writeLittleEndian(Array<Byte>)
public func writeLittleEndian(buffer: Array<Byte>): Int64
功能:将 UInt8 值以小端序的方式写入字节数组中。
参数:
返回值:
- Int64 - 写入的数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 太小,不足以存储 UInt8 值时,抛出异常。
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let buffer = Array<Byte>(8, repeat: 0)
let n = 0x12u8.writeLittleEndian(buffer)
@Assert(n, 1)
@Assert(buffer[..n] == [0x12])
}
interface SwapEndianOrder<T>
public interface SwapEndianOrder<T> {
func swapBytes(): T
}
功能:反转字节顺序接口。
func swapBytes()
func swapBytes(): T
功能:反转 T 值的字节顺序。
返回值:
- T - T 值。
extend Int16 <: SwapEndianOrder<Int16>
extend Int16 <: SwapEndianOrder<Int16>
功能:为 Int16 扩展 SwapEndianOrder 接口,以实现将 Int16 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): Int16
功能:反转 Int16 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x1234i16
let m = n.swapBytes()
@Assert(m, 0x3412)
}
extend Int32 <: SwapEndianOrder<Int32>
extend Int32 <: SwapEndianOrder<Int32>
功能:为 Int32 扩展 SwapEndianOrder 接口,以实现将 Int32 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): Int32
功能:反转 Int32 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x12345678i32
let m = n.swapBytes()
@Assert(m, 0x78563412)
}
extend Int64 <: SwapEndianOrder<Int64>
extend Int64 <: SwapEndianOrder<Int64>
功能:为 Int64 扩展 SwapEndianOrder 接口,以实现将 Int64 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): Int64
功能:反转 Int64 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x1234567890123456i64
let m = n.swapBytes()
@Assert(m, 0x5634129078563412)
}
extend Int8 <: SwapEndianOrder<Int8>
extend Int8 <: SwapEndianOrder<Int8>
功能:为 Int8 扩展 SwapEndianOrder 接口,以实现将 Int8 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): Int8
功能:反转 Int8 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x12i8
let m = n.swapBytes()
@Assert(m, 0x12)
}
extend UInt16 <: SwapEndianOrder<UInt16>
extend UInt16 <: SwapEndianOrder<UInt16>
功能:为 UInt16 扩展 SwapEndianOrder 接口,以实现将 UInt16 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): UInt16
功能:反转 UInt16 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x1234u16
let m = n.swapBytes()
@Assert(m, 0x3412)
}
extend UInt32 <: SwapEndianOrder<UInt32>
extend UInt32 <: SwapEndianOrder<UInt32>
功能:为 UInt32 扩展 SwapEndianOrder 接口,以实现将 UInt32 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): UInt32
功能:反转 UInt32 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x12345678u32
let m = n.swapBytes()
@Assert(m, 0x78563412)
}
extend UInt64 <: SwapEndianOrder<UInt64>
extend UInt64 <: SwapEndianOrder<UInt64>
功能:为 UInt64 扩展 SwapEndianOrder 接口,以实现将 UInt64 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): UInt64
功能:反转 UInt64 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x1234567890123456u64
let m = n.swapBytes()
@Assert(m, 0x5634129078563412)
}
extend UInt8 <: SwapEndianOrder<UInt8>
extend UInt8 <: SwapEndianOrder<UInt8>
功能:为 UInt8 扩展 SwapEndianOrder 接口,以实现将 UInt8 值的字节顺序反转。
父类型:
func swapBytes()
public func swapBytes(): UInt8
功能:反转 UInt8 值的字节顺序。
返回值:
示例:
import std.binary.*
import std.unittest.*
import std.unittest.testmacro.*
main() {
let n = 0x12u8
let m = n.swapBytes()
@Assert(m, 0x12)
}
std.collection
功能介绍
collection 包提供了常见数据结构的高效实现、相关抽象的接口的定义以及在集合类型中常用的函数功能。
本包实现了以下常用的数据结构:
-
ArrayDeque:基于数组实现的双端循环队列,支持在集合的两端进行元素的插入和删除操作。可以使用 addFirst() 和 addLast() 方法在头部和尾部插入元素,使用 removeFirst() 和 removeLast() 方法从集合的头部和尾部删除元素。
-
ArrayList:变长的连续数组,在需要存储不确定数量的数据,或者需要根据运行时的条件动态调整数组大小时使用 ArrayList。使用 ArrayList 可能会导致内存分配和释放的开销增加,因此需要谨慎使用。
-
ArrayQueue:基于数组实现的循环队列,只允许在尾部插入元素,在头部删除元素。
-
ArrayStack:基于数组实现的栈数据结构。特点是先进后出,只能在顶部进行数据的插入和删除。
-
LinkedList:链表结构, LinkedList 的优点是它可以动态地添加或删除元素,而不需要移动其他元素。这使得它在需要频繁添加或删除元素的情况下非常有用。它还可以轻松地进行修改或删除操作,并且可以在列表中存储多个元素。 LinkedList 的缺点是它需要额外的内存来存储每个元素的引用,这可能会导致内存浪费。
-
HashMap:哈希表,它存储键值对,并且可以根据键快速访问值。在需要使用映射关系并且需要快速查找时使用。
-
HashSet:基于哈希表实现的集合数据结构,它可以用于快速检索和删除元素,具有高效的插入、删除和查找操作。
-
TreeMap:基于红黑树实现的有序映射表。通常情况下,当需要将元素按照自然顺序或者自定义顺序进行排序时,可以使用TreeMap。
-
TreeSet:基于 TreeMap 实现的有序集合。能自动排序元素,可用于存储不重复且需排序的数据。
collection 包提供的集合类型都不支持并发安全,并发安全的集合请参见 collection.concurrent 包。
API 列表
函数
接口
| 接口名 | 功能 |
|---|---|
| Deque<T> | 双端队列是一种具有队列和栈特性的数据结构,它允许在两端进行插入和删除操作。 |
| EquatableCollection<T> | 定义了可以进行比较的集合类型。 |
| List<T> | 提供了对索引友好的列表操作。 |
| Map<K, V> | 提供了一种将键映射到值的方式。 |
| MapEntryView<K, V> | 键值对集合中的某个Key的视图 |
| OrderedMap<K, V> | 有序映射 |
| OrderedSet<T> | 有序集合 |
| Queue<T> | 队列数据结构,它遵循先进先出(First In First Out, FIFO)原则。 |
| ReadOnlyList<T> | 定义了对列表的只读操作。 |
| ReadOnlyMap<K, V> | 只读映射 |
| ReadOnlySet<K, V> | 只读集合 |
| Set<T> | 不包含重复元素的集合。 |
| Stack<T> | 栈数据结构接口,具有后进先出(Last In First Out,LIFO)的特点。 |
类
| 类名 | 功能 |
|---|---|
| ArrayDeque<T> | 根据可调整大小的循环数组实现的双端队列。 |
| ArrayList<T> | 提供可变长度的数组的功能。 |
| ArrayQueue<T> | 基于数组实现的循环队列数据结构。 |
| ArrayStack<T> | 基于数组实现的栈Stack 数据结构。 |
| HashMapIterator<K, V> where K <: Hashable & Equatable<K> | 此类主要实现 HashMap 的迭代器功能。 |
| HashMap<K, V> where K <: Hashable & Equatable<K> | Map<K, V> 接口的哈希表实现。 |
| HashSet<T> where T <: Hashable & Equatable<T> | 基于 HashMap<K, V> 实现的 Set<T> 接口的实例。 |
| LinkedListNode<T> | LinkedList<T> 上的节点。 |
| LinkedList<T> | 实现双向链表的数据结构。 |
| TreeMap<K, V> where K <: Comparable<K> | 基于平衡二叉搜索树实现的 Map<K, V> 接口实例。 |
| TreeSet<T> where T <: Comparable<T> | 基于 TreeMap<K, V> 实现的 Set<T> 接口的实例。 |
异常类
| 异常类名 | 功能 |
|---|---|
| ConcurrentModificationException | 并发修改异常类。 |
函数
func all<T>((T) -> Bool)
public func all<T>(predicate: (T) -> Bool): (Iterable<T>) -> Bool
功能:判断迭代器所有元素是否都满足条件。
参数:
- predicate: (T) -> Bool - 给定的条件。
返回值:
func any<T>((T) -> Bool)
public func any<T>(predicate: (T) -> Bool): (Iterable<T>) -> Bool
功能:判断迭代器是否存在任意一个满足条件的元素。
参数:
- predicate: (T) -> Bool - 给定的条件。
返回值:
func at<T>(Int64)
public func at<T>(n: Int64): (Iterable<T>) -> Option<T>
功能:获取迭代器指定位置的元素。
参数:
- n: Int64 - 给定的个数。
返回值:
func collectArrayList<T>(Iterable<T>)
public func collectArrayList<T>(it: Iterable<T>): ArrayList<T>
功能:将一个迭代器转换成 ArrayList 类型。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
func collectArray<T>(Iterable<T>)
public func collectArray<T>(it: Iterable<T>): Array<T>
功能:将一个迭代器转换成 Array 类型。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Array<T> - 返回一个数组。
func collectHashMap<K, V>(Iterable<(K, V)>) where K <: Hashable & Equatable<K>
public func collectHashMap<K, V>(it: Iterable<(K, V)>): HashMap<K, V> where K <: Hashable & Equatable<K>
功能:将一个迭代器转换成 HashMap 类型。
参数:
- it: Iterable<(K, V)> - 给定的迭代器。
返回值:
func collectHashSet<T>(Iterable<T>) where T <: Hashable & Equatable<T>
public func collectHashSet<T>(it: Iterable<T>): HashSet<T> where T <: Hashable & Equatable<T>
功能:将一个迭代器转换成 HashSet 类型。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
func collectString<T>(String) where T <: ToString
public func collectString<T>(delimiter!: String = ""): (Iterable<T>) -> String where T <: ToString
功能:将一个对应元素实现了 ToString 接口的迭代器转换成 String 类型。
参数:
- delimiter!: String - 字符串拼接分隔符。
返回值:
func concat<T>(Iterable<T>)
public func concat<T>(other: Iterable<T>): (Iterable<T>) -> Iterator<T>
功能:串联两个迭代器。
参数:
- other: Iterable<T> - 要串联在后面的迭代器。
返回值:
func contains<T>(T) where T <: Equatable<T>
public func contains<T>(element: T): (Iterable<T>) -> Bool where T <: Equatable<T>
功能:遍历所有元素,判断是否包含指定元素并返回该元素。
参数:
- element: T - 要查找的元素。
返回值:
func count<T>(Iterable<T>)
public func count<T>(it: Iterable<T>): Int64
功能:统计迭代器包含元素数量。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Int64 - 返回迭代器包含元素数量。
func enumerate<T>(Iterable<T>)
public func enumerate<T>(it: Iterable<T>): Iterator<(Int64, T)>
功能:用于获取带索引的迭代器。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
func filter<T>((T) -> Bool)
public func filter<T>(predicate: (T) -> Bool): (Iterable<T>) -> Iterator<T>
功能:筛选出满足条件的元素。
参数:
- predicate: (T) -> Bool - 给定的条件。
返回值:
func filterMap<T, R>((T) -> ?R)
public func filterMap<T, R>(transform: (T)-> ?R): (Iterable<T>) ->Iterator<R>
功能:同时进行筛选操作和映射操作,返回一个新的迭代器。
参数:
- transform: (T) -> ?R - 给定的映射函数。函数返回值为 Some 对应 filter 的 predicate 为 true,反之表示 false。
返回值:
func first<T>(Iterable<T>)
public func first<T>(it: Iterable<T>): Option<T>
功能:获取头部元素。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Option<T> - 返回头部元素,若为空则返回 None。
func flatMap<T, R>( (T) -> Iterable<R>)
public func flatMap<T, R>(transform: (T) -> Iterable<R>): (Iterable<T>) -> Iterator<R>
功能:创建一个带 flatten 功能的映射。
参数:
- transform: (T) -> Iterable<R> - 给定的映射函数。
返回值:
func flatten<T, R>(Iterable<T>) where T <: Iterable<R>
public func flatten<T, R>(it: Iterable<T>): Iterator<R> where T <: Iterable<R>
功能:将嵌套的迭代器展开一层。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Iterator<R> - 返回展开一层后的迭代器。
func fold<T, R>(R, (R, T) -> R)
public func fold<T, R>(initial: R, operation: (R, T) -> R): (Iterable<T>) -> R
功能:使用指定初始值,从左向右计算。
参数:
- initial: R - 给定的 R 类型的初始值。
- operation: (R, T) -> R - 给定的计算函数。
返回值:
- (Iterable<T>) -> R - 返回一个折叠函数。
func forEach<T>((T) -> Unit)
public func forEach<T>(action: (T) -> Unit): (Iterable<T>) -> Unit
功能:遍历所有元素,指定给定的操作。
参数:
- action: (T) -> Unit - 给定的操作函数。
返回值:
func inspect<T>((T) -> Unit)
public func inspect<T>(action: (T)->Unit): (Iterable<T>) ->Iterator<T>
功能:迭代器每次调用 next() 对当前元素执行额外操作(不会消耗迭代器中元素)。
参数:
- action: (T) -> Unit - 给定的操作函数。
返回值:
func isEmpty<T>(Iterable<T>)
public func isEmpty<T>(it: Iterable<T>): Bool
功能:判断迭代器是否为空。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Bool - 返回迭代器是否为空。
func last<T>(Iterable<T>)
public func last<T>(it: Iterable<T>): Option<T>
功能:获取尾部元素。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Option<T> - 返回尾部元素,若为空则返回 None。
func map<T, R>((T) -> R)
public func map<T, R>(transform: (T) -> R): (Iterable<T>) -> Iterator<R>
功能:创建一个映射。
参数:
- transform: (T) ->R - 给定的映射函数。
返回值:
func max<T>(Iterable<T>) where T <: Comparable<T>
public func max<T>(it: Iterable<T>): Option<T> where T <: Comparable<T>
功能:筛选最大的元素。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Option<T> - 返回最大的元素,若为空则返回 None。
func min<T>(Iterable<T>) where T <: Comparable<T>
public func min<T>(it: Iterable<T>): Option<T> where T <: Comparable<T>
功能:筛选最小的元素。
参数:
- it: Iterable<T> - 给定的迭代器。
返回值:
- Option<T> - 返回最小的元素,若为空则返回 None。
func none<T>((T) -> Bool)
public func none<T>(predicate: (T) -> Bool): (Iterable<T>) -> Bool
功能:判断迭代器中所有元素是否都不满足条件。
参数:
- predicate: (T) -> Bool - 给定的条件。
返回值:
func reduce<T>((T, T) -> T)
public func reduce<T>(operation: (T, T) -> T): (Iterable<T>) -> Option<T>
功能:使用第一个元素作为初始值,从左向右计算。
参数:
- operation: (T, T) -> T - 给定的操作函数。
返回值:
func skip<T>(Int64)
public func skip<T>(count: Int64): (Iterable<T>) -> Iterator<T>
功能:从迭代器跳过特定个数。
当 count 小于 0 时,抛出异常。当 count 等于 0 时,相当没有跳过任何元素,返回原迭代器。当 count 大于0并且count小于迭代器的大小时,跳过 count 个元素后,返回含有剩下的元素的新迭代器。当 count 大于等于迭代器的大小时,跳过所有元素,返回空迭代器。
参数:
- count: Int64 - 要跳过的个数。
返回值:
异常:
- IllegalArgumentException - 当 count < 0 时,抛出异常。
func step<T>(Int64)
public func step<T>(count: Int64): (Iterable<T>) -> Iterator<T>
功能:迭代器每次调用 next() 跳过特定个数。
当 count 小于等于 0 时,抛出异常。当 count 大于 0 时,每次调用 next() 跳过 count 次,直到迭代器为空。
参数:
- count: Int64 - 每次调用 next() 要跳过的个数。
返回值:
异常:
- IllegalArgumentException - 当 count <= 0 时,抛出异常。
func take<T>(Int64)
public func take<T>(count: Int64): (Iterable<T>) -> Iterator<T>
功能:从迭代器取出特定个数。
当 count 小于 0 时,抛出异常。当 count 等于 0 时,不取元素,返回空迭代器。当 count 大于 0 小于迭代器的大小时,取前 count 个元素,返回新迭代器。当 count 大于等于迭代器的大小时,取所有元素,返回原迭代器。
参数:
- count: Int64 - 要取出的个数。
返回值:
异常:
- IllegalArgumentException - 当 count < 0 时,抛出异常。
func zip<T, R>(Iterable<R>)
public func zip<T, R>(other: Iterable<R>): (Iterable<T>) -> Iterator<(T, R)>
功能:将两个迭代器合并成一个(长度取决于短的那个迭代器)。
参数:
- other: Iterable<R> - 要合并的其中一个迭代器。
返回值:
接口
interface Deque<T>
public interface Deque<T> <: Collection<T> {
prop first: ?T
prop last: ?T
func addFirst(element: T): Unit
func addLast(element: T): Unit
func removeFirst(): ?T
func removeLast(): ?T
}
功能:Deque(double-ended queue)是一种具有队列和栈特性的数据结构,允许从两端插入和删除元素。Deque 接口的主要功能包括:
- 插入操作:可以在双端队列的前端或后端插入元素。使用 addFirst 方法在双端队列头部插入元素,使用 addLast 在双端队列尾部插入元素。
- 访问操作:可以访问双端队列的前端或后端的元素,而不进行删除操作。使用 first 访问头部元素,使用 last 访问尾部元素。
- 删除操作:可以在双端队列的前端或后端删除元素。使用 removeFirst 删除头部元素并返回其值,使用 removeLast 删除尾部元素并返回其值。
- 其他集合类型支持的操作,比如元素数量、判空、迭代器操作。
父类型:
- Collection<T>
prop first
prop first: ?T
功能:访问双端队列头部元素,该操作不会删除头部元素。
返回值:
- Option<T> - Option 封装的头部元素的值,如果双端队列为空,返回None。
prop last
prop last: ?T
功能:访问双端队列尾部元素,该操作不会删除尾部元素。
返回值:
- Option<T> - Option 封装的尾部元素的值,如果双端队列为空,返回None。
func addFirst(T)
func addFirst(element: T): Unit
功能:在双端队列头部插入指定的元素。
参数:
- element: T - 被添加到双端队列中的元素。
func addLast(T)
func addLast(element: T): Unit
功能:在双端队列尾部插入指定的元素。
参数:
- element: T - 被添加到双端队列中的元素。
func removeFirst()
func removeFirst(): ?T
功能:删除双端队列中的头部元素并返回这个元素的值。
返回值:
- ?T - Option 封装的被删除的元素的值,如果双端队列为空,返回None。
func removeLast()
func removeLast(): ?T
功能:删除双端队列中的尾部元素并返回这个元素的值。
返回值:
- ?T - Option 封装的被删除的元素的值,如果双端队列为空,返回None。
interface EquatableCollection<T>
public interface EquatableCollection<T> <: Collection<T> {
func contains(element: T): Bool
func contains(all!: Collection<T>): Bool
}
功能:定义了可以进行比较的集合类型。
父类型:
- Collection<T>
func contains(T)
func contains(element: T): Bool
功能:判断 Keys 是否包含指定元素。
参数:
- element: T - 指定元素,待判断 Keys 是否包含该元素。
返回值:
- Bool - 包含返回 true,否则返回 false。
func contains(Collection<T>)
func contains(all!: Collection<T>): Bool
功能:判断 Keys 是否包含指定集合的所有元素。
参数:
- all!: Collection<T> - 待判断的集合 all。
返回值:
- Bool - 包含则返回 true,否则返回 false。
interface List<T>
public interface List<T> <: ReadOnlyList<T> {
func add(element: T): Unit
func add(all!: Collection<T>): Unit
func add(element: T, at!: Int64): Unit
func add(all!: Collection<T>, at!: Int64): Unit
func remove(at!: Int64): T
func remove(range: Range<Int64>): Unit
func removeIf(predicate: (T) -> Bool): Unit
func clear(): Unit
operator func [](index: Int64, value!: T): Unit
}
功能:定义了只提供对索引友好操作的列表类型。
父类型:
- ReadOnlyList<T>
func add(T)
func add(element: T): Unit
功能:将指定的元素附加到此列表的末尾。
参数:
- element: T - 插入的元素,类型为 T。
func add(Collection<T>)
func add(all!: Collection<T>): Unit
功能:将指定集合中的所有元素附加到此列表的末尾。
参数:
- all!: Collection<T> - 需要插入的元素的集合。
func add(T, Int64)
func add(element: T, at!: Int64): Unit
功能:在此列表中的指定位置插入指定元素。
参数:
- element: T - 要插入的 T 类型元素。
- at!: Int64 - 插入元素的目标索引。
func add(Collection<T>, Int64)
func add(all!: Collection<T>, at!: Int64): Unit
功能:从指定位置开始,将指定集合中的所有元素插入此列表。
参数:
- all!: Collection<T> - 要插入的 T 类型元素集合。
- at!: Int64 - 插入集合的目标索引。
func clear()
func clear(): Unit
功能:从此列表中删除所有元素。
func remove(Int64)
func remove(at!: Int64): T
功能:删除此列表中指定位置的元素。
参数:
- at!: Int64 - 被删除元素的索引。
返回值:
- T - 被移除的元素。
func remove(Range<Int64>)
func remove(range: Range<Int64>): Unit
功能:删除此列表中 Range 范围所包含的所有元素。
参数:
func removeIf((T) -> Bool)
func removeIf(predicate: (T) -> Bool): Unit
功能:删除此列表中满足给定 lambda 表达式或函数的所有元素。
参数:
- predicate: (T) ->Bool - 传递判断删除的条件。
operator func [](Int64, T)
operator func [](index: Int64, value!: T): Unit
功能:操作符重载 - set,通过下标运算符用指定的元素替换此列表中指定位置的元素。
参数:
- index: Int64 - 要设置的索引值。
- value!: T - 要设置的 T 类型的值。
interface Map<K, V>
public interface Map<K, V> <: ReadOnlyMap<K, V> {
func add(key: K, value: V): ?V
func add(all!: Collection<(K, V)>): Unit
func addIfAbsent(key: K, value: V): ?V
func clear(): Unit
func entryView(k: K): MapEntryView<K, V>
func remove(key: K): Option<V>
func remove(all!: Collection<K>): Unit
func removeIf(predicate: (K, V) -> Bool): Unit
func replace(key: K, value: V): ?V
operator func [](key: K, value!: V): Unit
}
功能:Map 接口提供了一种将键映射到值的方式。它允许我们使用键来查找值,因此可以用于存储和操作键值对。
Map 不能包含重复的key,每个key最多只能映射到一个value。
父类型:
- ReadOnlyMap<K, V>
func add(K, V)
func add(key: K, value: V): ?V
功能:将传入的键值对放入该 Map 中。对于 Map 中已有的键,该键映射的值将被新值替换。
参数:
- key: K - 要放置的键。
- value: V - 要分配的值。
返回值:
- ?V - 如果赋值之前 key 存在,返回旧值,否则返回 None。
func add(Collection<(K, V)>)
func add(all!: Collection<(K, V)>): Unit
功能:将新的键值对放入 Map 中。对于 Map 中已有的键,该键映射的值将被新值替换。
参数:
- all!: Collection<(K, V)> - 需要放入到 Map 中的键值对集合。
func addIfAbsent(K, V)
func addIfAbsent(key: K, value: V): ?V
功能:如果 key 不在当前 Map 中,添加指定键值对 key-value。否则不做修改。
参数:
- key: K - 待添加键值对的键。
- value: V - 待添加键值对的值。
返回值:
- ?V - 如果调用该函数时当前 Map 中已有指定的 key,返回该 key 对应的旧值,否则返回 None。
func clear()
func clear(): Unit
功能:清除所有键值对。
func entryView(K)
func entryView(k: K): MapEntryView<K, V>
功能:获取键 k 对应的视图。
参数:
- k: K - 待获取其视图的键。
返回值:
- MapEntryView<K, V> - 键 k 对应的视图。
func remove(K)
func remove(key: K): Option<V>
功能:从此 Map 中删除指定键的映射(如果存在)。
参数:
- key: K - 传入要删除的 key。
返回值:
func remove(Collection<K>)
func remove(all!: Collection<K>): Unit
功能:从此映射中删除指定集合的映射(如果存在)。
参数:
- all!: Collection<K> - 传入要删除的集合。
func removeIf((K, V) -> Bool)
func removeIf(predicate: (K, V) -> Bool): Unit
功能:传入 lambda 表达式,如果满足条件,则删除对应的键值对。
参数:
- predicate: (K, V) ->Bool - 传递一个 lambda 表达式进行判断。
func replace(K, V)
func replace(key: K, value: V): ?V
功能:如果当前 Map 中已有指定 key,将其值修改为 value。否则不做修改。
参数:
- key: K - 待修改键值对的键。
- value: V - 待修改键值对的新值。
返回值:
- ?V - 如果当前 Map 中已有指定 key,返回其旧值。否则返回 None。
operator func [](K, V)
operator func [](key: K, value!: V): Unit
功能:运算符重载集合,如果键存在,新 value 覆盖旧 value,如果键不存在,添加此键值对。
参数:
- key: K - 需要进行设置的键。
- value!: V - 传递要设置的值。
interface MapEntryView<K, V>
public interface MapEntryView<K, V> {
public prop key: K
public mut prop value: ?V
}
功能:提供映射中的某个 key 对应的视图。
prop key
public prop key: K
功能:返回视图中的 key,如果视图的 key 不在原始映射中,则返回一个该 key 的空视图。
类型:K
prop value
public mut prop value: ?V
功能:读取或修改视图对应原始映射的 value。
设置非空的 value 时,如果该视图的 value 不存在,则在该视图对应的原始映射中新增元素。
设置为 None 时,则会删除当前 Entry,删除完之后仍然能继续使用该视图。
类型:Option(V)
interface OrderedMap<K, V>
public interface OrderedMap<K, V> <: Map<K, V> {
public prop first: ?(K, V)
public prop last: ?(K, V)
public func removeFirst(): ?(K, V)
public func removeLast(): ?(K, V)
public func backward(mark: K, inclusive!: Bool): Iterator<(K, V)>
public func forward(mark: K, inclusive!: Bool): Iterator<(K, V)>
}
功能:OrderedMap 接口提供了一种将键映射到值的方式。它允许我们使用键来查找值,因此可以用于存储和操作键值对。
在 OrderedMap 接口的实例中,其内部的元素是有序的。
父类型:
- Map<K, V>
prop first
public prop first: ?(K, V)
功能:获取 OrderedMap 第一个元素。
类型:Option<(K, V)>
prop last
public prop last: ?(K, V)
功能:获取 OrderedMap 最后一个元素。
类型:Option<(K, V)>
func removeFirst()
public func removeFirst(): ?(K, V)
功能:删除 OrderedMap 的第一个元素。
返回值:
- ?(K, V) - 如果当前 OrderedMap 不为空,返回 Option 封装的被删除的键值对,否则返回
None。
func removeLast()
public func removeLast(): ?(K, V)
功能:删除 OrderedMap 的最后一个元素。
返回值:
- ?(K, V) - 如果当前 OrderedMap 不为空,返回 Option 封装的被删除的键值对,否则返回
None。
func backward(K, Bool)
public func backward(mark: K, inclusive!: Bool): Iterator<(K, V)>
功能:获取从第一个键小于等于 mark 的节点按降序遍历到 first 的迭代器。如果该节点的键等于 mark ,那么根据 inclusive! 确定是否包含该键对应的节点。
参数:
- mark: K - 用于确定从哪里开始的键。
- inclusive!: Bool - 当 mark 是迭代器的首个元素的 key 时,指定是否包含 mark 作为起始点。
返回值:
- Iterator<(K, V)> - 迭代器。
func forward(K, Bool)
public func forward(mark: K, inclusive!: Bool): Iterator<(K, V)>
功能:获取从第一个键大于等于 mark 的节点按升序遍历到 last 结束的一个迭代器。如果该节点的键等于 mark ,那么根据 inclusive! 确定是否包含该键对应的节点。
参数:
- mark: K - 用于确定从哪里开始的键。
- inclusive!: Bool - 当 mark 是迭代器的首个元素的 key 时,指定是否包含 mark 作为起始点。
返回值:
- Iterator<(K, V)> - 迭代器。
interface OrderedSet<T>
public interface OrderedSet<T> <: Set<T> {
public prop first: ?T
public prop last: ?T
public func removeFirst(): ?T
public func removeLast(): ?T
public func backward(mark: T, inclusive!: Bool): Iterator<T>
public func forward(mark: T, inclusive!: Bool): Iterator<T>
}
功能:OrderedSet 接口提供了一组集合的相关操作,允许我们以可读写的方式操作内部元素。
在 OrderedSet 接口的实例中,其内部的元素是有序的。
父类型:
- Set<T>
prop first
public prop first: ?T
功能:获取 OrderedSet 第一个元素。
类型:Option<T>
prop last
public prop last: ?T
功能:获取 OrderedSet 最后一个元素。
类型:Option<T>
func removeFirst()
public func removeFirst(): ?T
功能:删除 OrderedSet 的第一个元素。
返回值:
- ?T - 如果当前 OrderedSet 不为空,返回 Option 封装的被删除的元素,否则返回
None。
func removeLast()
public func removeLast(): ?T
功能:删除 OrderedSet 的最后一个元素。
返回值:
- ?T - 如果当前 OrderedSet 不为空,返回 Option 封装的被删除的元素,否则返回
None。
func backward(T, Bool)
public func backward(mark: T, inclusive!: Bool): Iterator<T>
功能:获取从第一个元素小于等于 mark 的节点按降序遍历到 first 的迭代器。如果该节点的元素等于 mark ,那么根据 inclusive! 确定是否包含该元素对应的节点。
参数:
- mark: T - 用于确定从哪里开始的元素。
- inclusive!: Bool - 当 mark 是迭代器的首个元素时,指定是否包含 mark 作为起始点。
返回值:
- Iterator<T> - 迭代器。
func forward(T, Bool)
public func forward(mark: T, inclusive!: Bool): Iterator<T>
功能:获取从第一个元素大于等于 mark 的节点按升序遍历到 last 结束的一个迭代器。如果该节点的元素等于 mark ,那么根据 inclusive! 确定是否包含该元素对应的节点。
参数:
- mark: T - 用于确定从哪里开始的元素。
- inclusive!: Bool - 当 mark 是迭代器的首个元素时,指定是否包含 mark 作为起始点。
返回值:
- Iterator<T> - 迭代器。
interface Queue<T>
public interface Queue<T> <: Collection<T> {
func add(element: T): Unit
func peek(): ?T
func remove(): ?T
}
功能:队列数据结构,它遵循先进先出(First In First Out, FIFO)原则。Queue 的主要功能包括:
- 添加元素:将指定的元素添加到队列的尾部。
- 访问操作:可以访问队列的前端元素,而不进行删除操作。
- 删除操作:可以删除队列的前端元素。
- 其他集合类型支持的操作,比如元素数量、判空、迭代器操作。
父类型:
- Collection<T>
func add(T)
func add(element: T): Unit
功能:在队列尾部插入指定的元素。
参数:
- element: T - 被添加到队列中的元素。
func peek()
func peek(): ?T
功能:访问双端队列头部元素,该操作不会删除头部元素。
返回值:
- ?T - Option 封装的头部元素的值,如果双端队列为空,返回
None。
func remove()
func remove(): ?T
功能:删除队列中的头部元素并返回这个元素的值。
返回值:
- ?T - Option 封装的被删除的元素的值,如果队列为空,返回
None。
interface ReadOnlyList<T>
public interface ReadOnlyList<T> <: Collection<T> {
prop first: ?T
prop last: ?T
func get(index: Int64): ?T
operator func [](index: Int64): T
}
功能:定义了只读列表。
父类型:
- Collection<T>
prop first
prop first: ?T
功能:返回此列表中的第一个元素,如果没有则返回 None。
类型:Option<T>
prop last
prop last: ?T
功能:返回此列表中的最后一个元素,如果没有则返回 None。
类型:Option<T>
func get(Int64)
func get(index: Int64): ?T
功能:返回此列表中指定位置的元素。
参数:
- index: Int64 - 要返回的元素的索引。
返回值:
- ?T - 返回指定位置的元素,如果 index 大小小于 0 或者大于等于此列表中的元素数量,返回 None。
operator func [](Int64)
operator func [](index: Int64): T
功能:操作符重载 - get。
参数:
- index: Int64 - 表示 get 接口的索引。
返回值:
- T - 索引位置的元素的值。
interface ReadOnlyMap<K, V>
public interface ReadOnlyMap<K, V> <: Collection<(K, V)> {
func get(key: K): ?V
func contains(key: K): Bool
func contains(all!: Collection<K>): Bool
func keys(): EquatableCollection<K>
func values(): Collection<V>
operator func [](key: K): V
}
功能:ReadOnlyMap 接口提供了一种将键映射到值的方式。它允许我们使用键来查找值,因此可以用于存储键值对。
ReadOnlyMap不能包含重复的 key,每个 key 最多只能映射到一个 value。
父类型:
- Collection<(K, V)>
func get(K)
func get(key: K): ?V
功能:根据 key 得到 ReadOnlyMap 中映射的值。
参数:
- key: K - 传递 key,获取 value。
返回值:
- ?V - ReadOnlyMap 中与 Key 对应的值。
func contains(K)
func contains(key: K): Bool
功能:判断是否包含指定键的映射。
参数:
- key: K - 传递要判断的 key。
返回值:
- Bool - 如果存在,则返回 true;否则,返回 false。
func contains(Collection<K>)
func contains(all!: Collection<K>): Bool
功能:判断是否包含指定集合键的映射。
参数:
- all!: Collection<K> - 传递待判断的 的集合。
返回值:
- Bool - 如果存在,则返回 true;否则,返回 false。
func keys()
func keys(): EquatableCollection<K>
功能:返回 ReadOnlyMap 中所有的 key,并将所有 key 存储在一个 EquatableCollection<K> 容器中。
返回值:
- EquatableCollection<K> - 保存所有返回的 key。
func values()
func values(): Collection<V>
功能:返回 ReadOnlyMap 中所有的 value,并将所有 value 存储在一个 Collection<V> 容器中。
返回值:
- Collection<V> - 保存所有返回的 value。
operator func [](K)
operator func [](key: K): V
功能:运算符重载集合,如果键存在,返回键对应的值,如果不存在,抛出异常。
参数:
- key: K - 需要进行查找的键。
返回值:
- V - 与键对应的值。
interface ReadOnlySet<T>
public interface ReadOnlySet<T> <: Collection<T> {
func contains(element: T): Bool
func contains(all!: Collection<T>): Bool
func subsetOf(other: ReadOnlySet<T>): Bool
}
功能:ReadOnlySet 接口提供了一组集合的相关操作,允许我们以只读方式操作内部元素。
父类型:
- Collection<T>
func contains(T)
func contains(element: T): Bool
功能:如果该集合包含指定元素,则返回 true。
参数:
- element: T - 需要判断的元素。
返回值:
- Bool - 如果包含,则返回 true;否则,返回 false。
func contains(Collection<T>)
func contains(all!: Collection<T>): Bool
功能:检查该集合是否包含其他集合。
参数:
- all!: Collection<T> - 其他集合。
返回值:
- Bool - 如果该集合包含指定集合,则返回 true;否则,返回 false。
func subsetOf(ReadOnlySet<T>)
func subsetOf(other: ReadOnlySet<T>): Bool
功能:检查该集合是否为其他集合的子集。
参数:
- other: ReadOnlySet<T> - 其他集合。
返回值:
- Bool - 果该集合是指定集合的子集,则返回 true;否则,返回 false。
interface Set<T>
public interface Set<T> <: ReadOnlySet<T> {
func add(element: T): Bool
func add(all!: Collection<T>): Unit
func remove(element: T): Bool
func remove(all!: Collection<T>): Unit
func removeIf(predicate: (T) -> Bool): Unit
func clear(): Unit
func retain(all!: Set<T>): Unit
}
功能:Set 接口提供了一组集合的相关操作,允许我们以可读写的方式操作内部元素。
Set 接口不规定内部的实现方式,在 Set 接口的实例中,其内部的元素通常是无序的,不能通过索引访问,也不能保证元素的插入顺序。
父类型:
- ReadOnlySet<T>
func add(T)
func add(element: T): Bool
功能:添加元素操作。如果元素已经存在,则不会添加它。
参数:
- element: T - 要添加的元素。
返回值:
- Bool - 如果添加成功,则返回 true;否则,返回 false。
func add(Collection<T>)
func add(all!: Collection<T>): Unit
功能:添加 Collection 中的所有元素至此 Set 中,如果元素存在,则不添加。
参数:
- all!: Collection<T> - 需要被添加的元素的集合。
func remove(T)
func remove(element: T): Bool
功能:从该集合中移除指定元素(如果存在)。
参数:
- element: T - 要删除的元素。
返回值:
- Bool - 集合中存在指定的元素并且删除成功返回
true,否则返回false。
func remove(Collection<T>)
func remove(all!: Collection<T>): Unit
功能:移除此 Set 中那些也包含在指定 Collection 中的所有元素。
参数:
- all!: Collection<T> - 传入 Collection<T>。
func removeIf((T) -> Bool)
func removeIf(predicate: (T) -> Bool): Unit
功能:传入 lambda 表达式,如果满足 true 条件,则删除对应的元素。
参数:
- predicate: (T) ->Bool - 传入一个 lambda 表达式进行判断。
func clear()
func clear(): Unit
功能:清除所有键值对。
func retain(Set<T>)
func retain(all!: Set<T>): Unit
参数:
- all!: Set<T> - 要保存的元素集合。
interface Stack<T>
public interface Stack<T> <: Collection<T> {
func add(element: T): Unit
func peek(): ?T
func remove(): ?T
}
功能:Stack(栈)是一种数据结构,具有后进先出(Last In First Out,LIFO)的特点。可以在一端(称为栈顶)进行插入和删除操作,而另一端(称为栈底)则不允许进行操作。
栈的基本操作包括入栈(add)、出栈(remove)、查看栈顶元素(peek)。
父类型:
- Collection<T>
func add(T)
func add(element: T): Unit
功能:向栈中添加元素。
参数:
- element: T - 将被放到栈顶的元素。
func peek()
func peek(): ?T
功能:查看栈顶元素,该操作不会删除栈顶元素。
返回值:
- ?T - 栈顶元素,如果栈为空,返回
None。
func remove()
func remove(): ?T
功能:删除并返回栈顶的元素。
返回值:
- ?T - 被删除的栈顶元素,如果栈为空,返回
None。
类
class ArrayDeque<T>
public class ArrayDeque<T> <: Deque<T> {
public init()
public init(capacity: Int64)
}
功能:ArrayDeque 是双端队列(deque)实现类,可以在双端队列的两端进行元素的插入和删除操作。ArrayDeque 是根据可调整大小的数组实现的,其容量会在插入元素的过程中不断地增长,默认每次扩容 50% 大小。ArrayDeque 的实现采用了循环队列的方式,在没有扩容的情况下,其插入、删除、查看等操作的时间复杂度为 O(1)。
父类型:
- Deque<T>
prop capacity
public prop capacity: Int64
功能:获取此双端队列的容量。
类型:Int64
prop first
public prop first: ?T
功能:获取双端队列的头部元素。如果双端队列为空,返回 None。
类型:Option<T>
prop last
public prop last: ?T
功能:获取双端队列的尾部元素。如果双端队列为空,返回 None。
类型:Option<T>
prop size
public prop size: Int64
功能:返回此双端队列中的元素个数。
类型:Int64
init()
public init()
功能:构造一个空的双端队列,其容量大小为默认值 8。
init(Int64)
public init(capacity: Int64)
功能:构造一个具有指定容量的双端队列,当 capacity 小于默认容量 8 时,构造的 ArrayDeque 初始容量为 8 。
参数:
- capacity: Int64 - 指定的初始容量。
异常:
- IllegalArgumentException - 如果参数的大小小于 0 则抛出异常。
func addFirst(T)
public func addFirst(element: T): Unit
功能:在此双端队列头部插入元素。
参数:
- element: T - 被插入到此双端队列的元素。
func addLast(T)
public func addLast(element: T): Unit
功能:在此双端队列尾部插入元素。
参数:
- element: T - 被插入到此双端队列的元素。
func clear()
public func clear(): Unit
功能:清空此双端队列中的所有元素。
func iterator()
public func iterator(): Iterator<T>
功能:获取此双端队列中元素的迭代器,其顺序为从前到后的顺序。
返回值:
- Iterator<T> - 元素的迭代器。
func isEmpty()
public func isEmpty(): Bool
功能:判断此双端队列是否为空。
返回值:
- Bool - 如果为空,则返回
true,否则,返回false。
func removeFirst()
public func removeFirst(): ?T
功能:删除双端队列中的头部元素并返回该值,如果此双端队列为空,返回 None。
返回值:
- ?T - 被删除的头部元素。
func removeLast()
public func removeLast(): ?T
功能:删除双端队列中的尾部元素并返回该值,如果此双端队列为空,返回 None。
返回值:
- ?T - 被删除的尾部元素。
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:增加此双端队列的容量。
将双端队列扩容 additional 大小,当 additional 小于等于零时,不发生扩容;当此双端队列剩余容量大于等于 additional 时,不发生扩容;当此双端队列剩余容量小于 additional 时,取(原始容量的1.5倍向下取整)与(additional + 已使用容量)两个值中的最大值进行扩容。
参数:
- additional: Int64 - 将要扩容的大小。
func toArray()
public func toArray(): Array<T>
功能:返回一个数组,其包含此双端队列中的所有元素,且顺序为从前到后的顺序。
返回值:
- Array<T> - T 类型数组。
extend<T> ArrayDeque<T> <: ToString where T <: ToString
extend<T> ArrayDeque<T> <: ToString where T <: ToString
功能:为 ArrayDeque<T> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:获取当前ArrayDeque<T>实例的字符串表示。
该字符串包含双端队列内每个元素的字符串表示,其顺序为从前到后的顺序,形如:"[elem1, elem2, elem3]"。
返回值:
- String - 转换得到的字符串。
class ArrayList<T>
public class ArrayList<T> <: List<T> {
public init()
public init(capacity: Int64)
public init(size: Int64, initElement: (Int64) -> T)
public init(elements: Collection<T>)
}
功能:提供可变长度的数组的功能。
ArrayList 是一种线性的动态数组,与 Array 不同,它可以根据需要自动调整大小,并且在创建时不需要指定大小。
说明:
当向动态数组中添加元素时,如果数组已满,则会重新分配更大的内存空间,并将原有的元素复制到新的内存空间中。
动态数组的优点是可以节省内存空间,并且可以根据需要自动调整大小,因此非常适合需要频繁添加或删除元素的情况。但是,动态数组的缺点是在重新分配内存空间时可能会导致性能下降,因此在使用动态数组时需要考虑这一点。
父类型:
- List<T>
prop size
public prop size: Int64
功能:返回此 ArrayList 中的元素个数。
类型:Int64
prop capacity
public prop capacity: Int64
功能:返回此 ArrayList 的容量大小。
类型:Int64
prop first
public prop first: ?T
功能:返回此 ArrayList 中的第一个元素,如果没有则返回 None。
类型:Option<T>
prop last
public prop last: ?T
功能:返回此 ArrayList 中的最后一个元素,如果没有则返回 None。
类型:Option<T>
init()
public init()
功能:构造一个初始容量大小为默认值16的ArrayList。
init(Collection<T>)
public init(elements: Collection<T>)
功能:构造一个包含指定集合中所有元素的 ArrayList。这些元素按照集合的迭代器返回的顺序排列。
参数:
- elements: Collection<T> - 传入集合。
init(Int64)
public init(capacity: Int64)
功能:构造一个初始容量为指定大小的 ArrayList。
参数:
- capacity: Int64 - 指定的初始容量大小。
异常:
- IllegalArgumentException - 如果参数的大小小于 0 则抛出异常。
init(Int64, (Int64) -> T)
public init(size: Int64, initElement: (Int64) -> T)
功能:构造具有指定初始元素个数和指定规则函数的 ArrayList。该构造函数根据参数 size 设置 ArrayList 的容量。
参数:
异常:
- IllegalArgumentException - 如果 size 小于 0 则抛出异常。
static func of(Array<T>)
public static func of(elements: Array<T>): ArrayList<T>
功能:构造一个包含指定数组中所有元素的 ArrayList。
参数:
- elements: Array<T> - 传入数组。
返回值:
- ArrayList<T> - 元素为 T 类型的 ArrayList。
func add(T)
public func add(element: T): Unit
功能:将指定的元素附加到此 ArrayList 的末尾。
参数:
- element: T - 插入的元素,类型为 T。
示例:
使用示例见 ArrayList 的 add 函数。
func add(Collection<T>)
public func add(all!: Collection<T>): Unit
功能:将指定集合中的所有元素附加到此 ArrayList 的末尾。
函数会按照迭代器顺序遍历入参中的集合,并且将所有元素插入到此 ArrayList 的尾部。
参数:
- all!: Collection<T> - 需要插入的元素的集合。
func add(T, Int64)
public func add(element: T, at!: Int64): Unit
功能:在此 ArrayList 中的指定位置插入指定元素。
参数:
- element: T - 要插入的 T 类型元素。
- at!: Int64 - 插入元素的目标索引。
异常:
- IndexOutOfBoundsException - 当 at 超出范围时,抛出异常。
示例:
使用示例见 ArrayList 的 add 函数。
func add(Collection<T>, Int64)
public func add(all!: Collection<T>, at!: Int64): Unit
功能:从指定位置开始,将指定集合中的所有元素插入此 ArrayList。
函数会按照迭代器顺序遍历入参中的集合,并且将所有元素插入到指定位置,原先在指定位置及其后的元素会后移。
参数:
- all!: Collection<T> - 要插入的 T 类型元素集合。
- at!: Int64 - 插入集合的目标索引。
异常:
- IndexOutOfBoundsException - 当 at 超出范围时,抛出异常。
示例:
使用示例见 ArrayList 的 add 函数。
func clear()
public func clear(): Unit
功能:从此 ArrayList 中删除所有元素。
示例:
使用示例见 ArrayList 的 remove/clear/slice 函数。
func clone()
public func clone(): ArrayList<T>
功能:返回此 ArrayList 实例的拷贝(浅拷贝)。
返回值:
func get(Int64)
public func get(index: Int64): ?T
功能:返回此 ArrayList 中指定位置的元素。
参数:
- index: Int64 - 要返回的元素的索引。
返回值:
- ?T - 返回指定位置的元素,如果 index 大小小于 0 或者大于等于 ArrayList 中的元素数量,返回 None。
示例:
使用示例见 ArrayList 的 get/set 函数。
func getRawArray()
public unsafe func getRawArray(): Array<T>
功能:返回 ArrayList 的原始数据。
注意:
这是一个 unsafe 的接口,使用处需要在 unsafe 上下文中。
原始数据是指 ArrayList 底层实现的数组,其大小大于等于 ArrayList 中的元素数量,且索引大于等于 ArrayList 大小的位置中可能包含有未初始化的元素,对其进行访问可能会产生未定义的行为。
返回值:
func isEmpty()
public func isEmpty(): Bool
功能:判断 ArrayList 是否为空。
返回值:
- Bool - 如果为空,则返回
true,否则,返回false。
func iterator()
public func iterator(): Iterator<T>
功能:返回此 ArrayList 中元素的迭代器。
返回值:
func remove(Int64)
public func remove(at!: Int64): T
功能:删除此 ArrayList 中指定位置的元素。
参数:
- at!: Int64 - 被删除元素的索引。
返回值:
- T - 被移除的元素。
异常:
- IndexOutOfBoundsException - 当 at 超出范围时,抛出异常。
示例:
使用示例见 ArrayList 的 remove/clear/slice 函数。
func remove(Range<Int64>)
public func remove(range: Range<Int64>): Unit
功能:删除此 ArrayList 中 Range 范围所包含的所有元素。
注意:
如果参数 range 是使用 Range 构造函数构造的 Range 实例,hasEnd 为 false 时,end 值不生效,且不受构造时传入的 isClosed 的值的影响,数组切片取到原数组最后一个元素。
参数:
异常:
- IllegalArgumentException - 当 range 的 step 不等于 1 时抛出异常。
- IndexOutOfBoundsException - 当 range 的 start 或 end 小于 0,或 end 大于 Array 的长度时抛出。
func removeIf((T) -> Bool)
public func removeIf(predicate: (T) -> Bool): Unit
功能:删除此 ArrayList 中满足给定 lambda 表达式或函数的所有元素。
参数:
- predicate: (T) ->Bool - 传递判断删除的条件。
异常:
- ConcurrentModificationException - 当
predicate中增删或者修改 ArrayList 内元素时,抛出异常。
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:增加此 ArrayList 实例的容量。
将 ArrayList 扩容 additional 大小,当 additional 小于等于零时,不发生扩容;当 ArrayList 剩余容量大于等于 additional 时,不发生扩容;当 ArrayList 剩余容量小于 additional 时,取(原始容量的1.5倍向下取整)与(additional + 已使用容量)两个值中的最大值进行扩容。
参数:
- additional: Int64 - 将要扩容的大小。
异常:
- OverflowException - 当additional + 已使用容量超过Int64.Max时,抛出异常。
func reverse()
public func reverse(): Unit
功能:反转此 ArrayList 中元素的顺序。
func slice(Range<Int64>)
public func slice(range: Range<Int64>): ArrayList<T>
功能:以传入参数 range 作为索引,返回索引对应的 ArrayList<T>。
注意:
如果参数 range 是使用 Range 构造函数构造的 Range 实例,有如下行为:
- start 的值就是构造函数传入的值本身,不受构造时传入的 hasStart 的值的影响。
- hasEnd 为 false 时,end 值不生效,且不受构造时传入的 isClosed 的值的影响,该数组切片取到原数组最后一个元素。
参数:
返回值:
- ArrayList<T> - 切片所得的数组。
异常:
- IllegalArgumentException - 当 range.step 不等于 1 时,抛出异常。
- IndexOutOfBoundsException - 当 range 无效时,抛出异常。
示例:
使用示例见 ArrayList 的 remove/clear/slice 函数。
func sortBy((T, T) -> Ordering) (deprecated)
public func sortBy(comparator!: (T, T) -> Ordering): Unit
功能:对数组中的元素进行非稳定排序。
通过传入的比较函数,根据其返回值 Ordering 类型的结果,可对数组进行自定义排序comparator: (t1: T, t2: T) -> Ordering,如果 comparator 的返回值为 Ordering.GT,排序后 t1 在 t2后;如果 comparator 的返回值为 Ordering.LT,排序后 t1 在t2 前;如果 comparator 的返回值为 Ordering.EQ,且为稳定排序,那么 t1 在 t2 之前; 如果 comparator 的返回值为 Ordering.EQ,且为不稳定排序,那么 t1,t2 顺序不确定。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
func sortBy(Bool, (T, T) -> Ordering) (deprecated)
public func sortBy(stable!: Bool, comparator!: (T, T) -> Ordering): Unit
功能:对数组中的元素进行排序。
通过传入的比较函数,根据其返回值 Ordering 类型的结果,可对数组进行自定义排序comparator: (t1: T, t2: T) -> Ordering,如果 comparator 的返回值为 Ordering.GT,排序后 t1 在 t2后;如果 comparator 的返回值为 Ordering.LT,排序后 t1 在t2 前;如果 comparator 的返回值为 Ordering.EQ,且为稳定排序,那么 t1 在 t2 之前; 如果 comparator 的返回值为 Ordering.EQ,且为不稳定排序,那么 t1,t2 顺序不确定。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
func toArray()
public func toArray(): Array<T>
功能:返回一个数组,其中包含此列表中按正确顺序排列的所有元素。
返回值:
- Array<T> - T 类型数组。
operator func [](Int64)
public operator func [](index: Int64): T
功能:操作符重载 - get。
参数:
- index: Int64 - 表示 get 接口的索引。
返回值:
- T - 索引位置的元素的值。
异常:
- IndexOutOfBoundsException - 当 index 超出范围时,抛出异常。
operator func [](Int64, T)
public operator func [](index: Int64, value!: T): Unit
功能:操作符重载,通过下标运算符用指定的元素替换此列表中指定位置的元素。
参数:
- index: Int64 - 要设置的索引值。
- value!: T - 要设置的 T 类型的值。
异常:
- IndexOutOfBoundsException - 当 index 超出范围时,抛出异常。
operator func [](Range<Int64>)
public operator func [](range: Range<Int64>): ArrayList<T>
功能:运算符重载 - 切片。
注意:
参数:
返回值:
- ArrayList<T> - 切片所得的数组。
异常:
- IllegalArgumentException - 当 range.step 不等于 1 时,抛出异常。
- IndexOutOfBoundsException - 当 range 无效时,抛出异常。
extend<T> ArrayList<T> <: Equatable<ArrayList<T>> where T <: Equatable<T>
extend<T> ArrayList<T> <: Equatable<ArrayList<T>> where T <: Equatable<T>
功能:为 ArrayList<T> 类型扩展 Equatable<ArrayList<T>> 接口,支持判等操作。
父类型:
operator func ==(ArrayList<T>)
public operator func ==(that: ArrayList<T>): Bool
功能:判断当前实例与参数指向的 ArrayList 实例是否相等。
两个数组相等指的是两者对应位置的元素分别相等。
参数:
- that: ArrayList<T> - 被比较的对象。
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
operator func !=(ArrayList<T>)
public operator func !=(that: ArrayList<T>): Bool
功能:判断当前实例与参数指向的 ArrayList 实例是否不等。
参数:
- that: ArrayList<T> - 被比较的对象。
返回值:
- Bool - 如果不等,则返回 true,否则返回 false。
func contains(T)
public func contains(element: T): Bool
功能:判断当前数组中是否含有指定元素 element。
参数:
- element: T - 待寻找的元素。
返回值:
- Bool - 如果数组中包含指定元素,返回 true,否则返回 false。
extend<T> ArrayList<T> <: SortExtension where T <: Comparable<T> (deprecated)
extend<T> ArrayList<T> where T <: Comparable<T>
功能:为 ArrayList<T> 扩展 SortExtension 接口,支持数组排序。
注意:
未来版本即将废弃。
父类型:
func sort() (deprecated)
public func sort(): Unit
功能:将当前数组内元素以升序的方式非稳定排序。
注意:
未来版本即将废弃,使用 sort 替代。
func sort(Bool) (deprecated)
public func sort(stable!: Bool): Unit
功能:将当前数组内元素以升序的方式排序。
参数:
- stable!: Bool - 是否使用稳定排序。
注意:
未来版本即将废弃,使用 sort 替代。
func sortDescending() (deprecated)
public func sortDescending(): Unit
功能:将当前数组内元素以降序的方式非稳定排序。
注意:
未来版本即将废弃,使用 sort 替代。
func sortDescending(Bool) (deprecated)
public func sortDescending(stable!: Bool): Unit
功能:将当前数组内元素以降序的方式排序。
参数:
- stable!: Bool - 是否使用稳定排序。
注意:
未来版本即将废弃,使用 sort 替代。
extend<T> ArrayList<T> <: ToString where T <: ToString
extend<T> ArrayList<T> <: ToString where T <: ToString
功能:为 ArrayList<T> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将当前数组转换为字符串。
该字符串包含数组内每个元素的字符串表示,形如:"[elem1, elem2, elem3]"。
返回值:
- String - 转换得到的字符串。
class ArrayQueue<T>
public class ArrayQueue<T> <: Queue<T> {
public init()
public init(capacity: Int64)
}
功能:基于数组实现的循环队列数据结构。
父类型:
- Queue<T>
prop capacity
public prop capacity: Int64
功能:获取此队列的容量。
类型:Int64
prop size
public prop size: Int64
功能:返回此队列中的元素个数。
类型:Int64
init()
public init()
功能:构造一个空的队列,其容量大小为默认值 8。
init(Int64)
public init(capacity: Int64)
功能:构造一个具有指定容量的队列,当 capacity 小于默认容量 8 时,构造的 ArrayQueue 初始容量为 8 。
参数:
- capacity: Int64 - 指定的初始容量。
异常:
- IllegalArgumentException - 如果参数的大小小于 0 则抛出异常。
func add(T)
public func add(element: T): Unit
功能:在此队列尾部插入元素。
参数:
- element: T - 被插入到此双端队列的元素。
func clear()
public func clear(): Unit
功能:清空此队列中的所有元素。
func iterator()
public func iterator(): Iterator<T>
功能:获取此队列中元素的迭代器,其顺序为从前到后的顺序。
返回值:
- Iterator<T> - 元素的迭代器。
func isEmpty()
public func isEmpty(): Bool
功能:判断此队列是否为空。
返回值:
- Bool - 如果为空,则返回
true,否则,返回false。
func peek()
public func peek():?T
功能:查看此队列头部元素。此操作不会删除元素。
返回值:
- ?T - 队列的头部元素,如果队列为空,返回
None。
func remove()
public func remove(): ?T
功能:删除队列中的头部元素并返回该值,如果此队列为空,返回 None。
返回值:
- ?T - 被删除的头部元素。
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:增加此队列的容量。
将队列扩容 additional 大小,当 additional 小于等于零时,不发生扩容;当此队列剩余容量大于等于 additional 时,不发生扩容;当此队列剩余容量小于 additional 时,取(原始容量的 1.5 倍向下取整)与(additional + 已使用容量)两个值中的最大值进行扩容。
参数:
- additional: Int64 - 将要扩容的大小。
func toArray()
public func toArray(): Array<T>
功能:返回一个数组,其包含此队列中的所有元素,且顺序为从前到后的顺序。
返回值:
- Array<T> - T 类型数组。
extend<T> ArrayQueue<T> <: ToString where T <: ToString
extend<T> ArrayQueue<T> <: ToString where T <: ToString
功能:为 ArrayQueue<T> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:获取当前ArrayQueue<T>实例的字符串表示。
该字符串包含双端队列内每个元素的字符串表示,其顺序为从前到后的顺序,形如:"[elem1, elem2, elem3]"。
返回值:
- String - 转换得到的字符串。
class ArrayStack<T>
public class ArrayStack<T> <: Stack<T> {
public init(capacity: Int64)
public init()
}
功能:ArrayStack 是一种基于数组 Array 实现的栈 Stack 数据结构。ArrayStack 的实现方式是使用一个数组来存储栈中的元素,同时使用一个指针来指向栈顶元素的位置。
ArrayStack 只支持后进先出(Last In First Out,LIFO),只能在头部进行插入删除操作,并且 ArrayStack 会根据实际需要进行扩容。
父类型:
- Stack<T>
prop capacity
public prop capacity: Int64
功能:栈的容量大小。
类型:Int64
prop size
public prop size: Int64
功能:栈中元素的数量。
类型:Int64
func init()
public init()
功能:构造一个空的 ArrayStack,其初始容量为 8 。
func init(Int64)
public init(capacity: Int64)
功能:构造一个空的 ArrayStack,其初始容量为指定的值。当 capacity 小于默认容量 8 时,构造的 ArrayStack 初始容量为 8 。
参数:
- capacity: Int64 - 初始容量大小。
异常:
- IllegalArgumentException - 当入参为负数时,抛出此异常。
func add(T)
public func add(element: T): Unit
功能:在栈顶添加元素。
参数:
- element: T - 添加的元素。
func clear()
public func clear(): Unit
功能:清空当前的 ArrayStack。
func isEmpty()
public func isEmpty(): Bool
功能:判断此 ArrayStack 是否为空。
返回值:
- Bool - 如果为空,返回 true,否则返回 false。
func iterator()
public func iterator(): Iterator<T>
功能:返回此 ArrayStack 中元素的迭代器,其顺序为出栈的顺序。
返回值:
- Iterator<T> - 栈中元素的迭代器。
func peek()
public func peek(): ?T
功能:获取栈顶的元素,该操作不会做出栈操作,只查看栈顶的元素。当栈为空时,返回 None。
返回值:
- ?T - 栈顶的元素。
func remove()
public func remove(): ?T
功能:出栈操作,删除栈顶的元素并且返回这个元素。当栈为空时,返回 None。
返回值:
- ?T - 被删除的栈顶元素。
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:为当前 ArrayStack 预留出相应的空间。当 additional 小于等于零时,不发生扩容;如果当前剩余空间大小大于等于 additional,不进行扩容操作,否则当前 ArrayStack 会扩容至 size + additional 大小。
参数:
- additional: Int64 - 预留的剩余容量大小。
func toArray()
public func toArray(): Array<T>
功能:返回一个数组,其中元素为栈中的元素,顺序为栈的出栈顺序。
返回值:
- Array<T> - T 类型数组。
extend<T> ArrayStack<T> <: ToString where T <: ToString
extend<T> ArrayStack<T> <: ToString where T <: ToString
功能:为 ArrayStack 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:获取当前 ArrayStack<T> 实例的字符串表示。
该字符串包含栈内每个元素的字符串表示,其顺序为从后到前的顺序。形如:"[elem1, elem2, elem3]"。
返回值:
- String - 当前栈的字符串表示。
class HashMapIterator<K, V> where K <: Hashable & Equatable<K>
public class HashMapIterator<K, V> <: Iterator<(K, V)> where K <: Hashable & Equatable<K> {
public init(map: HashMap<K, V>)
}
功能:此类主要实现 HashMap 的迭代器功能。
父类型:
- Iterator<(K, V)>
init(HashMap<K, V>)
public init(map: HashMap<K, V>)
功能:创建 HashMapIterator<K, V> 实例。
参数:
func next()
public func next(): ?(K, V)
功能:返回迭代器中的下一个元素。
返回值:
- ?(K, V) - 迭代器中的下一个元素,用 Option 封装。
异常:
- ConcurrentModificationException - 当函数检测到不同步的并发修改,抛出异常。
func remove()
public func remove(): Option<(K, V)>
功能:删除此 HashMap 迭代器的 next 函数返回的元素,此函数只能在 next 函数调用时调用一次。
返回值:
- Option<(K, V)> - 返回被删除的元素。
异常:
- ConcurrentModificationException - 当函数检测到不同步的并发修改,抛出异常。
class HashMap<K, V> where K <: Hashable & Equatable<K>
public class HashMap<K, V> <: Map<K, V> where K <: Hashable & Equatable<K> {
public init()
public init(elements: Array<(K, V)>)
public init(elements: Collection<(K, V)>)
public init(capacity: Int64)
public init(size: Int64, initElement: (Int64) -> (K, V))
}
功能:Map 接口的哈希表实现。
哈希表是一种常用的数据结构,它可以用来快速地查找、插入和删除数据。哈希表的基本原理是将数据映射到一个数组中,这个数组称为哈希表。每个数据元素都有一个对应的哈希值,这个哈希值可以用来确定该元素在哈希表中的位置。
哈希表的特点是快速的查找、插入和删除操作,时间复杂度通常是O(1)。由于哈希表底层的数组大小是动态的,所以哈希表不能保证元素的顺序不可变。
父类型:
- Map<K, V>
prop capacity
public prop capacity: Int64
功能:返回 HashMap 的容量。
返回值:
prop size
public prop size: Int64
功能:返回键值对的个数。
类型:Int64
init()
public init()
功能:构造一个具有默认初始容量为16和默认负载因子为空的 HashMap。
init(Array<(K, V)>)
public init(elements: Array<(K, V)>)
功能:通过传入的键值对数组构造一个 HashMap。
该构造函数根据传入数组的 size 设置 HashMap 的容量。由于HashMap 内部不允许键重复,当 Array 中存在重复的键时,按照迭代器顺序,出现在后面的键值对将会覆盖前面的键值对。
参数:
init(Collection<(K, V)>)
public init(elements: Collection<(K, V)>)
功能:通过传入的键值对集合构造一个 HashMap。
该构造函数根据传入集合 elements 的 size 设置 HashMap 的容量。由于HashMap 内部不允许键重复,当 Array 中存在重复的键时,按照迭代器顺序,出现在后面的键值对将会覆盖前面的键值对。
参数:
- elements: Collection<(K, V)> - 初始化该 HashMap 的键值对集合。
init(Int64)
public init(capacity: Int64)
功能:构造一个带有传入容量大小的 HashMap。
参数:
- capacity: Int64 - 初始化容量大小。
异常:
- IllegalArgumentException - 如果 capacity 小于 0 则抛出异常。
init(Int64, (Int64) -> (K, V))
public init(size: Int64, initElement: (Int64) -> (K, V))
功能:通过传入的元素个数 size 和函数规则来构造 HashMap。
构造出的 HashMap 的容量受 size 大小影响。由于HashMap 内部不允许键重复,当函数 initElement 生成相同的键时,后构造的键值对将会覆盖之前出现的键值对。
参数:
异常:
- IllegalArgumentException - 如果 size 小于 0 则抛出异常。
func add(K, V)
public func add(key: K, value: V): Option<V>
功能:将键值对放入 HashMap 中。
对于 HashMap 中已有的键,该键的值将被新值替换,并且返回旧的值。
参数:
- key: K - 要放置的键。
- value: V - 要分配的值。
返回值:
示例:
使用示例见 HashMap 的 get/add/contains 函数。
func add(Collection<(K, V)>)
public func add(all!: Collection<(K, V)>): Unit
功能:按照 elements 的迭代器顺序将新的键值对集合放入 HashMap 中。
对于 HashMap 中已有的键,该键的值将被新值替换。
参数:
- all!: Collection<(K, V)> - 需要添加进 HashMap 的键值对集合。
示例:
使用示例见 HashMap 的 add/remove/clear 函数。
func addIfAbsent(K, V)
func addIfAbsent(key: K, value: V): ?V
功能:如果 key 不在当前 HashMap 中,添加指定键值对 key-value。否则不做修改。
参数:
- key: K - 待添加键值对的键。
- value: V - 待添加键值对的值。
返回值:
- ?V - 如果调用该函数时当前 HashMap 中已有指定的 key,返回该 key 对应的旧值,否则返回 None。
func clear()
public func clear(): Unit
功能:清除所有键值对。
示例:
使用示例见 HashMap 的 add/remove/clear 函数。
func clone()
public func clone(): HashMap<K, V>
功能:克隆 HashMap。
返回值:
func contains(K)
public func contains(key: K): Bool
功能:判断是否包含指定键的映射。
参数:
- key: K - 传递要判断的 key。
返回值:
- Bool - 如果存在,则返回 true;否则,返回 false。
示例:
使用示例见 HashMap 的 get/add/contains 函数。
func contains(Collection<K>)
public func contains(all!: Collection<K>): Bool
功能:判断是否包含指定集合中所有键的映射。
参数:
- all!: Collection<K> - 键传递待判断的 keys。
返回值:
- Bool - 如果都包含,则返回 true;否则,返回 false。
func entryView(K)
public func entryView(key: K): MapEntryView<K, V>
功能:如果不包含特定键,返回一个空的引用视图。如果包含特定键,则返回该键对应的元素的引用视图。
参数:
- key: K - 要添加的键值对的键。
返回值:
- MapEntryView<K, V> - 一个引用视图。
func get(K)
public func get(key: K): ?V
功能:返回指定键映射到的值,如果 HashMap 不包含指定键的映射,则返回 Option<V>.None。
参数:
- key: K - 传入的键。
返回值:
- ?V - 键对应的值。用 Option 封装。
示例:
使用示例见 HashMap 的 get/add/contains 函数。
func isEmpty()
public func isEmpty(): Bool
功能:判断 HashMap 是否为空,如果是,则返回 true;否则,返回 false。
返回值:
func iterator()
public func iterator(): HashMapIterator<K, V>
功能:返回 HashMap 的迭代器。
返回值:
- HashMapIterator<K, V> - 返回 HashMap 的迭代器。
func keys()
public func keys(): EquatableCollection<K>
功能:返回 HashMap 中所有的 key,并将所有 key 存储在一个 Keys 容器中。
返回值:
- EquatableCollection<K> - 保存所有返回的 key。
func remove(Collection<K>)
public func remove(all!: Collection<K>): Unit
功能:从此 HashMap 中删除指定集合中键的映射(如果存在)。
参数:
- all!: Collection<K> - 传入要删除的键的集合。
func remove(K)
public func remove(key: K): Option<V>
功能:从此 HashMap 中删除指定键的映射(如果存在)。
参数:
- key: K - 传入要删除的 key。
返回值:
示例:
使用示例见 HashMap 的 add/remove/clear 函数。
func removeIf((K, V) -> Bool)
public func removeIf(predicate: (K, V) -> Bool): Unit
功能:传入 lambda 表达式,如果满足条件,则删除对应的键值对。
该函数会遍历整个HashMap,所以满足 predicate(K, V) == true 的键值对都会被删除。
参数:
- predicate: (K, V) ->Bool - 传递一个 lambda 表达式进行判断。
异常:
- ConcurrentModificationException - 当
predicate中增删或者修改 HashMap 内键值对时,抛出异常。
func replace(K, V)
func replace(key: K, value: V): ?V
功能:如果当前 HashMap 中已有指定 key,将其值修改为 value。否则不做修改。
参数:
- key: K - 待修改键值对的键。
- value: V - 待修改键值对的新值。
返回值:
- ?V - 如果当前 HashMap 中已有指定 key,返回其旧值。否则返回 None。
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:扩容当前的HashMap。
将 HashMap 扩容 additional 大小,当 additional 小于等于零时,不发生扩容;当 HashMap 剩余容量大于等于 additional 时,不发生扩容;当 HashMap 剩余容量小于 additional 时,取(原始容量的1.5倍向下取整)与(additional + 已使用容量)中的最大值进行扩容。
参数:
- additional: Int64 - 将要扩容的大小。
异常:
- OverflowException - 当additional + 已使用容量超过Int64.Max时,抛出异常。
func toArray()
public func toArray(): Array<(K, V)>
功能:构造一个包含 HashMap 内键值对的数组,并返回。
返回值:
- Array<(K, V)> - 包含容器内所有键值对的数组。
func values()
public func values(): Collection<V>
功能:返回 HashMap 中包含的值,并将所有的 value 存储在一个 Values 容器中。
返回值:
- Collection<V> - 保存所有返回的 value。
operator func [](K, V)
public operator func [](key: K, value!: V): Unit
功能:运算符重载 add 方法,如果键存在,新 value 覆盖旧 value,如果键不存在,添加此键值对。
参数:
- key: K - 传递值进行判断。
- value!: V - 传递要设置的值。
operator func [](K)
public operator func [](key: K): V
功能:运算符重载 get 方法,如果键存在,返回键对应的值。
参数:
- key: K - 传递值进行判断。
返回值:
- V - 与键对应的值。
异常:
- NoneValueException - 如果该 HashMap 不存在该键,抛此异常。
extend<K, V> HashMap<K, V> <: Equatable<HashMap<K, V>> where V <: Equatable<V>
extend<K, V> HashMap<K, V> <: Equatable<HashMap<K, V>> where V <: Equatable<V>
功能:为 HashMap<K, V> 类型扩展 Equatable<HashMap<K, V>> 接口,支持判等操作。
父类型:
operator func ==(HashMap<K, V>)
public operator func ==(right: HashMap<K, V>): Bool
功能:判断当前实例与参数指向的 HashMap<K, V> 实例是否相等。
两个 HashMap<K, V> 相等指的是其中包含的键值对完全相等。
参数:
- right: HashMap<K, V> - 被比较的对象。
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
operator func !=(HashMap<K, V>)
public operator func !=(right: HashMap<K, V>): Bool
功能:判断当前实例与参数指向的 HashMap<K, V> 实例是否不等。
参数:
- right: HashMap<K, V> - 被比较的对象。
返回值:
- Bool - 如果不等,则返回 true,否则返回 false。
extend<K, V> HashMap<K, V> <: ToString where V <: ToString, K <: ToString
extend<K, V> HashMap<K, V> <: ToString where V <: ToString, K <: ToString
功能:为 HashMap<K, V> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将当前 HashMap<K, V> 实例转换为字符串。
该字符串包含 HashMap<K, V> 内每个键值对的字符串表示,形如:"[(k1, v1), (k2, v2), (k3, v3)]"。
返回值:
- String - 转换得到的字符串。
class HashSet<T> where T <: Hashable & Equatable<T>
public class HashSet<T> <: Set<T> where T <: Hashable & Equatable<T> {
public init()
public init(elements: Collection<T>)
public init(elements: Array<T>)
public init(capacity: Int64)
public init(size: Int64, initElement: (Int64) -> T)
}
HashSet中的元素是无序的,不允许有重复元素。当我们向HashSet中添加元素时,HashSet会根据元素的哈希值来确定该元素在哈希表中的位置。
提示:
HashSet 是基于 HashMap 实现的,因此 HashSet 的容量、内存布局、时间性能等都和 HashMap 相同。
父类型:
- Set<T>
prop size
public prop size: Int64
功能:返回此 HashSet 的元素个数。
类型:Int64
init(Int64, (Int64) -> T)
public init(size: Int64, initElement: (Int64) -> T)
功能:通过传入的函数元素个数 size 和函数规则来构造 HashSet。构造出的 HashSet 的容量受 size 大小影响。
参数:
异常:
- IllegalArgumentException - 如果 size 小于 0,抛出异常。
init()
public init()
功能:构造一个空的 HashSet ,初始容量为 16 。
init(Array<T>)
public init(elements: Array<T>)
功能:使用传入的数组构造 HashSet。该构造函数根据传入数组 elements 的 size 设置 HashSet 的容量。
参数:
init(Collection<T>)
public init(elements: Collection<T>)
功能:使用传入的集合构造 HashSet。该构造函数根据传入集合 elements 的 size 设置 HashSet 的容量。
参数:
- elements: Collection<T> - 初始化 HashSet 的集合。
init(Int64)
public init(capacity: Int64)
功能:使用传入的容量构造一个 HashSet。
参数:
- capacity: Int64 - 初始化容量大小。
异常:
- IllegalArgumentException - 如果 capacity 小于 0,抛出异常。
func add(T)
public func add(element: T): Bool
功能:将指定的元素添加到 HashSet 中, 若添加的元素在 HashSet 中存在, 则添加失败。
参数:
- element: T - 指定的元素。
返回值:
- Bool - 如果添加成功,则返回 true;否则,返回 false。
示例:
使用示例见 HashSet 的 add/iterator/remove 函数。
func add(Collection<T>)
public func add(all!: Collection<T>): Unit
功能:添加 Collection 中的所有元素至此 HashSet 中,如果元素存在,则不添加。
参数:
- all!: Collection<T> - 需要被添加的元素的集合。
prop capacity
public prop capacity: Int64
功能:返回此 HashSet 的内部数组容量大小。
注意:
容量大小不一定等于 HashSet 的 size。
返回值:
func clear()
public func clear(): Unit
功能:从此 HashSet 中移除所有元素。
func clone()
public func clone(): HashSet<T>
功能:克隆 HashSet。
返回值:
func contains(T)
public func contains(element: T): Bool
功能:判断 HashSet 是否包含指定元素。
参数:
- element: T - 指定的元素。
返回值:
- Bool - 如果包含指定元素,则返回 true;否则,返回 false。
func contains(Collection<T>)
public func contains(all!: Collection<T>): Bool
功能:判断 HashSet 是否包含指定 Collection 中的所有元素。
参数:
- all!: Collection<T> - 指定的元素集合。
返回值:
- Bool - 如果此 HashSet 包含 Collection 中的所有元素,则返回 true;否则,返回 false。
func isEmpty()
public func isEmpty(): Bool
功能:判断 HashSet 是否为空。
返回值:
- Bool - 如果为空,则返回 true;否则,返回 false。
func iterator()
public func iterator(): Iterator<T>
功能:返回此 HashSet 的迭代器。
返回值:
示例:
使用示例见 HashSet 的 add/iterator/remove 函数。
func remove(T)
public func remove(element: T): Bool
功能:如果指定元素存在于此 HashSet 中,则将其移除。
参数:
- element: T - 需要被移除的元素。
返回值:
- Bool - true,表示移除成功;false,表示移除失败。
示例:
使用示例见 HashSet 的 add/iterator/remove 函数。
func remove(Collection<T>)
public func remove(all!: Collection<T>): Unit
功能:移除此 HashSet 中那些也包含在指定 Collection 中的所有元素。
参数:
- all!: Collection<T> - 需要从此 HashSet 中移除的元素的集合。
func removeIf((T) -> Bool)
public func removeIf(predicate: (T) -> Bool): Unit
功能:传入 lambda 表达式,如果满足 true 条件,则删除对应的元素。
参数:
- predicate: (T) ->Bool - 是否删除元素的判断条件。
异常:
- ConcurrentModificationException - 当
predicate中增删或者修改 HashSet 内元素时,抛出异常。
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:将 HashSet 扩容 additional 大小,当 additional 小于等于零时,不发生扩容;当 HashSet 剩余容量大于等于 additional 时,不发生扩容;当 HashSet 剩余容量小于 additional 时,取(原始容量的1.5倍向下取整)与(additional + 已使用容量)中的最大值进行扩容。
参数:
- additional: Int64 - 将要扩容的大小。
异常:
- OverflowException - 当additional + 已使用容量超过Int64.Max时,抛出异常。
func retain(Set<T>)
public func retain(all!: Set<T>): Unit
参数:
func subsetOf(ReadOnlySet<T>)
public func subsetOf(other: ReadOnlySet<T>): Bool
功能:检查该集合是否为其他 ReadOnlySet 的子集。
参数:
- other: ReadOnlySet<T> - 传入集合,此函数将判断当前集合是否为 other 的子集。
返回值:
- Bool - 如果该 Set 是指定 ReadOnlySet 的子集,则返回 true;否则返回 false。
func toArray()
public func toArray(): Array<T>
功能:返回一个包含容器内所有元素的数组。
返回值:
- Array<T> - T 类型数组。
operator func &(ReadOnlySet<T>)
public operator func &(other: ReadOnlySet<T>): HashSet<T>
功能:返回包含两个集合交集的元素的新集合。
参数:
- other: ReadOnlySet<T> - 传入集合。
返回值:
- HashSet<T> - T 类型集合。
operator func |(ReadOnlySet<T>)
public operator func |(other: ReadOnlySet<T>): HashSet<T>
功能:返回包含两个集合并集的元素的新集合。
参数:
- other: ReadOnlySet<T> - 传入集合。
返回值:
- HashSet<T> - T 类型集合。
operator func -(ReadOnlySet<T>)
public operator func -(other: ReadOnlySet<T>): HashSet<T>
功能:返回包含两个集合差集的元素的新集合。
参数:
- other: ReadOnlySet<T> - 传入集合。
返回值:
- HashSet<T> - T 类型集合。
extend<T> HashSet<T> <: Equatable<HashSet<T>>
extend<T> HashSet<T> <: Equatable<HashSet<T>>
功能:为 HashSet<T> 类型扩展 Equatable<HashSet<T>> 接口,支持判等操作。
父类型:
operator func ==(HashSet<T>)
public operator func ==(that: HashSet<T>): Bool
功能:判断当前实例与参数指向的 HashSet<T> 实例是否相等。
两个 HashSet<T> 相等指的是其中包含的元素完全相等。
参数:
- that: HashSet<T> - 被比较的对象。
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
operator func !=(HashSet<T>)
public operator func !=(that: HashSet<T>): Bool
功能:判断当前实例与参数指向的 HashSet<T> 实例是否不等。
参数:
- that: HashSet<T> - 被比较的对象。
返回值:
- Bool - 如果不等,则返回 true,否则返回 false。
extend<T> HashSet<T> <: ToString where T <: ToString
extend<T> HashSet<T> <: ToString where T <: ToString
功能:为 HashSet<T> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将当前 HashSet<T> 实例转换为字符串。
该字符串包含 HashSet<T> 内每个元素的字符串表示,形如:"[elem1, elem2, elem3]"。
返回值:
- String - 转换得到的字符串。
class LinkedListNode<T>
public class LinkedListNode<T>
功能:LinkedListNode 是 LinkedList 上的节点。
可以通过 LinkedListNode 对 LinkedList 进行前向后向遍历操作,也可以访问和修改元素的值。
LinkedListNode 只能通过对应 LinkedList 的 'nodeAt'、'firstNode'、'lastNode' 获得,当 LinkedList 删除掉对应的节点时,会造成一个悬空的节点,对悬空的节点进行任何操作都会抛 'IllegalStateException' 异常。
prop next
public prop next: Option<LinkedListNode<T>>
功能:获取当前节点的下一个节点,如果没有则返回 None。
类型:Option<LinkedListNode<T>>
异常:
- IllegalStateException - 如果该节点不属于任何链表实例,抛此异常。
prop prev
public prop prev: Option<LinkedListNode<T>>
功能:获取当前节点的前一个节点,如果没有则返回 None。
类型:Option<LinkedListNode<T>>
异常:
- IllegalStateException - 如果该节点不属于任何链表实例,抛此异常。
prop value
public mut prop value: T
功能:获取或者修改元素的值。
类型:T
异常:
- IllegalStateException - 如果该节点不属于任何链表实例,抛此异常。
class LinkedList<T>
public class LinkedList<T> <: Collection<T> {
public init()
public init(elements: Collection<T>)
public init(elements: Array<T>)
public init(size: Int64, initElement: (Int64)-> T)
}
功能:实现双向链表的数据结构。
双向链表是一种常见的数据结构,它由一系列节点组成,每个节点都包含两个指针,一个指向前一个节点,另一个指向后一个节点。这种结构允许在任何一个节点上进行双向遍历,即可以从头节点开始向后遍历,也可以从尾节点开始向前遍历。
LinkedList 不支持并发操作,并且对集合中元素的修改不会使迭代器失效,只有在添加和删除元素的时候会使迭代器失效。
父类型:
- Collection<T>
prop first
public prop first: ?T
功能:链表中第一个元素的值,如果是空链表则返回 None。
类型:?T
prop firstNode
public prop firstNode: ?LinkedListNode<T>
功能:获取链表中的第一个元素的节点。
类型:?LinkedListNode<T>
prop last
public prop last: ?T
功能:链表中最后一个元素的值,如果是空链表则返回 None。
类型:?T
prop lastNode
public prop lastNode: ?LinkedListNode<T>
功能:获取链表中的最后一个元素的节点。
类型:?LinkedListNode<T>
prop size
public prop size: Int64
功能:链表中的元素数量。
类型:Int64
init
public init()
功能:构造一个空的链表。
init(Array<T>)
public init(elements: Array<T>)
功能:按照数组的遍历顺序构造一个包含指定集合元素的 LinkedList 实例。
参数:
- elements: Array<T> - 将要放入此链表中的元素数组。
init(Collection<T>)
public init(elements: Collection<T>)
功能:按照集合迭代器返回元素的顺序构造一个包含指定集合元素的链表。
参数:
- elements: Collection<T> - 将要放入此链表中的元素集合。
init(Int64, (Int64)-> T)
public init(size: Int64, initElement: (Int64)-> T)
功能:创建一个包含 size 个元素,且第 n 个元素满足 (Int64)-> T 条件的链表。
参数:
异常:
- IllegalArgumentException - 如果指定的链表长度小于 0 则抛此异常。
func addAfter(LinkedListNode<T>,T)
public func addAfter(node: LinkedListNode<T>, element: T): LinkedListNode<T>
功能:在链表中指定节点的后面插入一个元素,并且返回该元素的节点。
参数:
- node: LinkedListNode<T> - 指定的节点。
- element: T - 要添加到链表中的元素。
返回值:
- LinkedListNode<T> - 指向被插入元素的节点。
异常:
- IllegalArgumentException - 如果指定的节点不属于该链表,则抛此异常。
func addBefore(LinkedListNode<T>,T)
public func addBefore(node: LinkedListNode<T>, element: T): LinkedListNode<T>
功能:在链表中指定节点的前面插入一个元素,并且返回该元素的节点。
参数:
- node: LinkedListNode<T> - 指定的节点。
- element: T - 要添加到链表中的元素。
返回值:
- LinkedListNode<T> - 指向被插入元素的节点。
异常:
- IllegalArgumentException - 如果指定的节点不属于该链表,则抛此异常。
func addFirst(T)
public func addFirst(element: T): LinkedListNode<T>
功能:在链表的头部位置插入一个元素,并且返回该元素的节点。
参数:
- element: T - 要添加到链表中的元素。
返回值:
- LinkedListNode<T> - 指向该元素的节点。
func addLast(T)
public func addLast(element: T): LinkedListNode<T>
功能:在链表的尾部位置添加一个元素,并且返回该元素的节点。
参数:
- element: T - 要添加到链表中的元素。
返回值:
- LinkedListNode<T> - 指向该元素的节点。
func backward(LinkedListNode<T>)
public func backward(mark: LinkedListNode<T>): Iterator<T>
功能:获取一个从 mark 节点开始,到所对应链表的头部节点的所有元素的迭代器。
参数:
- mark: LinkedListNode<T> - 开始的元素节点。
返回值:
- Iterator<T> - 对应元素的迭代器。
异常:
- IllegalStateException - 如果该节点不属于任何链表实例,抛此异常。
func clear()
public func clear(): Unit
功能:删除链表中的所有元素。
func forward(LinkedListNode<T>)
public func forward(mark: LinkedListNode<T>): Iterator<T>
功能:获取一个从 mark 节点开始,到所对应链表的尾部节点的所有元素的迭代器。
参数:
- mark: LinkedListNode<T> - 开始的元素节点。
返回值:
- Iterator<T> - 对应元素的迭代器。
异常:
- IllegalStateException - 如果该节点不属于任何链表实例,抛此异常。
func isEmpty()
public func isEmpty(): Bool
功能:返回此链表是否为空链表的判断。
返回值:
- Bool - 如果此链表中不包含任何元素,返回 true。
func iterator()
public func iterator(): Iterator<T>
功能:返回当前集合中元素的迭代器,其顺序是从链表的第一个节点到链表的最后一个节点。
返回值:
- Iterator<T> - 当前集合中元素的迭代器。
func nodeAt(Int64)
public func nodeAt(index: Int64): Option<LinkedListNode<T>>
功能:获取链表中的第 index 个元素的节点,编号从 0 开始。
该函数的时间复杂度为 O(n)。
参数:
- index: Int64 - 指定获取第 index 个元素的节点。
返回值:
- Option<LinkedListNode<T>> - 编号为 index 的节点,如果没有则返回 None。
func removeFirst()
public func removeFirst() : ?T
功能:移除链表的第一个元素,并返回该元素的值。
返回值:
- ?T - 被删除的元素的值,若链表为空则返回 None。
func removeLast()
public func removeLast() : ?T
功能:移除链表的最后一个元素,并返回该元素的值。
返回值:
- ?T - 被删除的元素的值,若链表为空则返回 None。
func remove(LinkedListNode<T>)
public func remove(node: LinkedListNode<T>): T
功能:删除链表中指定节点。
参数:
- node: LinkedListNode<T> - 要被删除的节点。
返回值:
- T - 被删除的节点的值。
异常:
- IllegalArgumentException - 如果指定的节点不属于该链表,则抛此异常。
func removeIf((T)-> Bool)
public func removeIf(predicate: (T)-> Bool): Unit
功能:删除此链表中满足给定 lambda 表达式或函数的所有元素。
参数:
- predicate: (T) ->Bool - 对于要删除的元素,返回值为 true。
异常:
- ConcurrentModificationException - 当
predicate中增删或者修改 LinkedList 内节点时,抛出异常。
func reverse()
public func reverse(): Unit
功能:反转此链表中的元素顺序。
func splitOff(LinkedListNode<T>)
public func splitOff(node: LinkedListNode<T>): LinkedList<T>
功能:从指定的节点 node 开始,将链表分割为两个链表,如果分割成功,node 不在当前的链表内,而是作为首个节点存在于新的链表内部。
参数:
- node: LinkedListNode<T> - 要分割的位置。
返回值:
- LinkedList<T> - 原链表分割后新产生的链表。
异常:
- IllegalArgumentException - 如果指定的节点不属于该链表,则抛此异常。
func toArray()
public func toArray(): Array<T>
功能:返回一个数组,数组包含该链表中的所有元素,并且顺序与链表的顺序相同。
返回值:
- Array<T> - T 类型数组。
extend<T> LinkedList<T> <: Equatable<LinkedList<T>> where T <: Equatable<T>
extend<T> LinkedList<T> <: Equatable<LinkedList<T>> where T <: Equatable<T>
功能:为 LinkedList<T> 类型扩展 Equatable<LinkedList<T>> 接口,支持判等操作。
父类型:
- Equatable<LinkedList<T>>
operator func ==(LinkedList<T>)
public operator func ==(right: LinkedList<T>): Bool
功能:判断当前实例与参数指向的 LinkedList<T> 实例是否相等。
两个 LinkedList<T> 相等指的是其中包含的元素完全相等。
参数:
- right: LinkedList<T> - 被比较的对象。
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
operator func !=(LinkedList<T>)
public operator func !=(right: LinkedList<T>): Bool
功能:判断当前实例与参数指向的 LinkedList<T> 实例是否不等。
参数:
- right: LinkedList<T> - 被比较的对象。
返回值:
- Bool - 如果不等,则返回 true,否则返回 false。
extend<T> LinkedList<T> <: ToString where T <: ToString
extend<T> LinkedList<T> <: ToString where T <: ToString
功能:为 LinkedList<T> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将当前 LinkedList<T> 实例转换为字符串。
该字符串包含 LinkedList<T> 内每个元素的字符串表示,形如:"[elem1, elem2, elem3]"。
返回值:
- String - 转换得到的字符串。
class TreeMap<K, V> where K <: Comparable<K>
public class TreeMap<K, V> <: OrderedMap<K, V> where K <: Comparable<K> {
public init()
public init(elements: Collection<(K, V)>)
public init(elements: Array<(K,V)>)
public init(size: Int64, initElement: (Int64) -> (K, V))
}
功能:基于平衡二叉搜索树实现的 OrderedMap 接口实例。
这个类的主要目的是提供一个有序的 key-value 存储结构,它可以快速地插入、删除、查找元素。
TreeMap 可以用于任何需要有序键值对存储的场景,例如数据库、缓存、查找表等。
父类型:
- OrderedMap<K, V>
prop first
public prop first: ?(K, V)
功能:获取 TreeMap 的第一个元素。
返回值:
prop last
public prop last: ?(K, V)
功能:获取 TreeMap 的最后一个元素。
返回值:
prop size
public prop size: Int64
功能:返回键值的个数。
类型:Int64
init()
public init()
功能:构造一个空的 TreeMap。
init(Array<(K,V)>)
public init(elements: Array<(K,V)>)
功能:通过传入的键值对数组构造一个 TreeMap。
按照 elements 的先后顺序将元素插入到 TreeMap 内,由于 TreeMap 中不允许出现相同的键,如果 elements 中有相同的键时,后出现的键值对将会覆盖先出现的键值对。
参数:
init(Collection<(K, V)>)
public init(elements: Collection<(K, V)>)
功能:通过传入的键值对集合构造一个 TreeMap。
按照 elements 的迭代器顺序将元素插入到 TreeMap 内,由于 TreeMap 中不允许出现相同的键,如果 elements 中有相同的键时,后出现(迭代器顺序)的键值对将会覆盖先出现的键值对。
参数:
- elements: Collection<(K, V)> - 初始化该 TreeMap 的键值对集合。
init(Int64, (Int64) -> (K, V))
public init(size: Int64, initElement: (Int64) -> (K, V))
功能:通过传入的元素个数 size 和函数规则来构造 TreeMap。
参数:
异常:
- IllegalArgumentException - 如果 size 小于 0 则抛出异常。
func add(K, V)
public func add(key: K, value: V): Option<V>
功能:将新的键值对放入 TreeMap 中。对于 TreeMap 中已有的键,该键的值将被新值替换。
参数:
- key: K - 要放置的键。
- value: V - 要分配的值。
返回值:
func add(Collection<(K, V)>)
public func add(all!: Collection<(K, V)>): Unit
功能:将新的键值对集合放入 TreeMap 中。对于 TreeMap 中已有的键,该键的值将被新值替换。
参数:
- all!: Collection<(K, V)> - 需要添加进 TreeMap 的键值对集合。
func backward(K, Bool)
public func backward(mark: K, inclusive!: Bool = true): Iterator<(K, V)>
功能:获取从第一个键小于等于 mark 的节点按降序遍历到 first 的迭代器。如果该节点的键等于 mark ,那么根据 inclusive! 确定是否包含该键对应的节点。
参数:
- mark: K - 用于确定从哪里开始的键。
- inclusive!: Bool - 当
mark是迭代器的首个元素的 key 时,指定是否包含 mark 作为起始点,默认为true。
返回值:
- Iterator<(K, V)> - 对应元素的迭代器。
func clear()
public func clear(): Unit
功能:清除所有键值对。
func clone()
public func clone(): TreeMap<K, V>
功能:克隆 TreeMap。
返回值:
func contains(K)
public func contains(key: K): Bool
功能:判断是否包含指定键的映射。
参数:
- key: K - 传递要判断的 key。
返回值:
- Bool - 如果存在,则返回 true;否则,返回 false。
func contains(Collection<K>)
public func contains(all!: Collection<K>): Bool
功能:判断是否包含指定集合键的映射。
参数:
- all!: Collection<K> - 键的集合。
返回值:
- Bool - 如果存在,则返回 true;否则,返回 false。
func entryView(K)
public func entryView(k: K): MapEntryView<K, V>
功能:如果不包含特定键,返回一个空的引用视图。如果包含特定键,则返回该键对应的元素的引用视图。
参数:
- k: K - 要添加的键值对的键。
返回值:
- MapEntryView<K, V> - 一个引用视图。
func forward(K, Bool)
public func forward(mark: K, inclusive!: Bool = true): Iterator<(K, V)>
功能:获取从第一个键大于等于 mark 的节点按升序遍历到 last 结束的一个迭代器。如果该节点的键等于 mark ,那么根据 inclusive! 确定是否包含该键对应的节点。
参数:
- mark: K - 用于确定从哪里开始的键。
- inclusive!: Bool - 当
mark是迭代器的首个元素的 key 时,指定是否包含 mark 作为起始点,默认为true。
返回值:
- Iterator<(K, V)> - 对应元素的迭代器。
func get(K)
public func get(key: K): ?V
功能:返回指定键映射的值。
参数:
- key: K - 指定的键。
返回值:
func isEmpty()
public func isEmpty(): Bool
功能:判断 TreeMap 是否为空。
返回值:
- Bool - 如果为空,返回 true,否则返回 false。
func iterator()
public func iterator(): Iterator<(K, V)>
功能:返回 TreeMap 的迭代器,迭代器按 Key 值从小到大的顺序迭代。
返回值:
func keys()
public func keys(): EquatableCollection<K>
功能:返回 TreeMap 中所有的 key,并将所有 key 存储在一个容器中。
返回值:
- EquatableCollection<K> - 包含所有键的集合。
func removeFirst()
public func removeFirst(): ?(K, V)
功能:删除 TreeMap 的第一个元素。
返回值:
func removeLast()
public func removeLast(): ?(K, V)
功能:删除 TreeMap 的最后一个元素。
返回值:
func remove(K)
public func remove(key: K): Option<V>
功能:从此映射中删除指定键的映射(如果存在)。
参数:
- key: K - 传入要删除的 key。
返回值:
func remove(Collection<K>)
public func remove(all!: Collection<K>): Unit
功能:从此映射中删除指定集合的映射(如果存在)。
参数:
- all!: Collection<K> - 传入要删除的键的集合。
func removeIf((K, V) -> Bool)
public func removeIf(predicate: (K, V) -> Bool): Unit
功能:传入 lambda 表达式,如果满足条件,则删除对应的键值。
参数:
- predicate: (K, V) ->Bool - 传递一个 lambda 表达式进行判断。
异常:
- ConcurrentModificationException - 当
predicate中增删或者修改 TreeMap 内键值对时,抛出异常。
func values()
public func values(): Collection<V>
功能:返回 TreeMap 中包含的值,并将所有的 value 存储在一个容器中。
返回值:
- Collection<V> - 包含所有值的集合。
operator func [](K, V)
public operator func [](key: K, value!: V): Unit
功能:运算符重载集合,如果键存在,新 value 覆盖旧 value,如果键不存在,添加此键值对。
参数:
- key: K - 传递值进行判断。
- value!: V - 传递要设置的值。
operator func [](K)
public operator func [](key: K): V
功能:运算符重载集合,如果键存在,返回键对应的值。
参数:
- key: K - 传递值进行判断。
返回值:
- V - 与键对应的值。
异常:
- NoneValueException - 如果该 HashMap 不存在该键,抛出异常。
extend<K, V> TreeMap<K, V> <: Equatable<TreeMap<K, V>> where V <: Equatable<V>
extend<K, V> TreeMap<K, V> <: Equatable<TreeMap<K, V>> where V <: Equatable<V>
功能:为 TreeMap<K, V> 类型扩展 Equatable<TreeMap<K, V>> 接口,支持判等操作。
父类型:
operator func ==(TreeMap<K, V>)
public operator func ==(right: TreeMap<K, V>): Bool
功能:判断当前实例与参数指向的 TreeMap<K, V> 实例是否相等。
两个 TreeMap<K, V> 相等指的是其中包含的键值对完全相等。
参数:
- right: TreeMap<K, V> - 被比较的对象。
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
operator func !=(TreeMap<K, V>)
public operator func !=(right: TreeMap<K, V>): Bool
功能:判断当前实例与参数指向的 TreeMap<K, V> 实例是否不等。
参数:
- right: TreeMap<K, V> - 被比较的对象。
返回值:
- Bool - 如果不等,则返回 true,否则返回 false。
extend<K, V> TreeMap<K, V> <: ToString where V <: ToString, K <: ToString & Comparable<K>
extend<K, V> TreeMap<K, V> <: ToString where V <: ToString, K <: ToString & Comparable<K>
功能:为 TreeMap<K, V> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将当前 TreeMap<K, V> 实例转换为字符串。
该字符串包含 TreeMap<K, V> 内每个键值对的字符串表示,形如:"[(k1, v1), (k2, v2), (k3, v3)]"。
返回值:
- String - 转换得到的字符串。
class TreeSet<T> where T <: Comparable<T>
public class TreeSet<T> <: OrderedSet<T> where T <: Comparable<T> {
public init()
public init(elements: Collection<T>)
public init(size: Int64, initElement: (Int64) -> T)
}
这个类的主要目的是提供一个有序的元素存储结构,它可以快速地插入、删除、查找元素。
TreeSet 可以用于任何需要有序元素存储的场景,例如数据库、缓存、查找表等。
父类型:
- OrderedSet<T>
prop first
public prop first: ?T
功能:获取 TreeSet 的第一个元素。
类型:?T - 如果存在第一个元素,用 Option 封装该元素并返回;否则返回 Option<T>.None。
prop last
public prop last: ?T
功能:获取 TreeSet 的最后一个元素。
类型:?T - 如果存在最后一个元素,用 Option 封装该元素并返回;否则返回 Option<T>.None。
prop size
public prop size: Int64
功能:返回元素的个数。
类型:Int64
init()
public init()
功能:构造一个空的 TreeSet。
init(Collection<T>)
public init(elements: Collection<T>)
功能:通过传入的元素集合构造一个 TreeSet。
按照 elements 的迭代器顺序将元素插入到 TreeSet 内,由于 TreeSet 中不允许出现相同的元素,如果 elements 中有多个相同的元素时,TreeSet 只会保留一个元素。
参数:
- elements: Collection<T> - 初始化该 TreeSet 的元素集合。
init(Int64, (Int64) -> T)
public init(size: Int64, initElement: (Int64) -> T)
功能:通过传入的元素个数 size 和函数规则来构造 TreeSet。
参数:
异常:
- IllegalArgumentException - 如果 size 小于 0 则抛出异常。
static func of(Array<T>)
public static func of(elements: Array<T>): TreeSet<T>
功能:构造一个包含指定数组中所有元素的 TreeSet。
按照 elements 的先后顺序将元素插入到 TreeSet 内,由于 TreeSet 中不允许出现相同的元素,如果 elements 中有多个相同的元素时,TreeSet 只会保留一个元素。
参数:
- elements: Array<T> - 传入数组。
返回值:
func add(T)
public func add(element: T): Bool
功能:将新的元素放入 TreeSet 中。若添加的元素在 TreeSet 中存在, 则添加失败。
参数:
- element: T - 指定的元素。
返回值:
- Bool - 如果添加成功,则返回 true;否则,返回 false。
func add(Collection<T>)
public func add(all!: Collection<T>): Unit
功能:添加 Collection 中的所有元素至此 TreeSet 中,如果元素存在,则不添加。
参数:
- all!: Collection<T> - 需要被添加的元素的集合。
func backward(T, Bool)
public func backward(mark: T, inclusive!: Bool = true): Iterator<T>
功能:获取从第一个键小于等于 mark 的节点按降序遍历到 first 的迭代器。如果该节点的键等于 mark ,那么根据 inclusive! 确定是否包含该键对应的节点。
参数:
- mark: T - 用于确定从哪里开始的元素。
- inclusive!: Bool - 当
mark是迭代器的首个元素时,指定是否包含 mark 作为起始点,默认为true。
返回值:
- Iterator<T> - 对应元素的迭代器。
func clear()
public func clear(): Unit
功能:清除所有元素。
func clone()
public func clone(): TreeSet<T>
功能:克隆 TreeSet。
返回值:
func contains(T)
public func contains(element: T): Bool
功能:判断是否包含指定元素。
参数:
- element: T - 指定的元素。
返回值:
- Bool - 如果包含指定元素,则返回 true;否则,返回 false。
func contains(Collection<T>)
public func contains(all!: Collection<T>): Bool
功能:判断 TreeSet 是否包含指定 Collection 中的所有元素。
参数:
- all!: Collection<T> - 指定的元素集合。
返回值:
- Bool - 如果此 TreeSet 包含 Collection 中的所有元素,则返回 true;否则,返回 false。
func forward(T, Bool)
public func forward(mark: T, inclusive!: Bool = true): Iterator<T>
功能:获取从第一个元素大于等于 mark 的节点按升序遍历到 last 结束的一个迭代器。如果该节点的元素等于 mark ,那么根据 inclusive! 确定是否包含该元素对应的节点。
参数:
- mark: T - 用于确定从哪里开始的元素。
- inclusive!: Bool - 当
mark是迭代器的首个元素时,指定是否包含 mark 作为起始点,默认为true。
返回值:
- Iterator<T> - 对应元素的迭代器。
func isEmpty()
public func isEmpty(): Bool
功能:判断 TreeSet 是否为空。
返回值:
- Bool - 如果为空,返回 true,否则返回 false。
func iterator()
public func iterator(): Iterator<T>
功能:返回 TreeSet 的迭代器,迭代器按元素值从小到大的顺序迭代。
返回值:
func removeFirst()
public func removeFirst(): ?T
功能:删除 TreeSet 的第一个元素。
返回值:
func removeLast()
public func removeLast(): ?T
功能:删除 TreeSet 的最后一个元素。
返回值:
func remove(T)
public func remove(element: T): Bool
功能:如果指定元素存在于此 TreeSet 中,则将其移除。
参数:
- element: T - 需要被移除的元素。
返回值:
- Bool - true,表示移除成功;false,表示移除失败。
func remove(Collection<T>)
public func remove(all!: Collection<T>): Unit
功能:移除此 TreeSet 中那些也包含在指定 Collection 中的所有元素。
参数:
- all!: Collection<T> - 需要从此TreeSet 中移除的元素的集合。
func removeIf((T) -> Bool)
public func removeIf(predicate: (T) -> Bool): Unit
功能:传入 lambda 表达式,如果满足 true 条件,则删除对应的元素。
参数:
- predicate: (T) ->Bool - 是否删除元素的判断条件。
异常:
- ConcurrentModificationException - 当
predicate中增删或者修改 TreeSet 内元素时,抛出异常。
func retain(Set<T>)
public func retain(all!: Set<T>): Unit
功能:从此 TreeSet 中保留 Set 中的元素,其他元素将被移除。
参数:
func subsetOf(ReadOnlySet<T>)
public func subsetOf(other: ReadOnlySet<T>): Bool
功能:检查该集合是否为其他 ReadOnlySet 的子集。
参数:
- other: ReadOnlySet<T> - 传入集合,此函数将判断当前集合是否为 other 的子集。
返回值:
- Bool - 如果该 TreeSet 是指定 ReadOnlySet 的子集,则返回 true;否则返回 false。
func toArray()
public func toArray(): Array<T>
功能:返回一个包含容器内所有元素的数组。
返回值:
- Array<T> - T 类型数组。
operator func &(ReadOnlySet<T>)
public operator func &(other: ReadOnlySet<T>): TreeSet<T>
功能:返回包含两个集合交集的元素的新集合。
参数:
- other: ReadOnlySet<T> - 传入集合。
返回值:
- TreeSet<T> - T 类型集合。
operator func |(ReadOnlySet<T>)
public operator func |(other: ReadOnlySet<T>): TreeSet<T>
功能:返回包含两个集合并集的元素的新集合。
参数:
- other: ReadOnlySet<T> - 传入集合。
返回值:
- TreeSet<T> - T 类型集合。
operator func -(ReadOnlySet<T>)
public operator func -(other: ReadOnlySet<T>): TreeSet<T>
功能:返回包含两个集合差集的元素的新集合。
参数:
- other: ReadOnlySet<T> - 传入集合。
返回值:
- TreeSet<T> - T 类型集合。
extend<T> TreeSet<T> <: Equatable<TreeSet<T>>
extend<T> TreeSet<T> <: Equatable<TreeSet<T>>
功能:为 TreeSet<T> 类型扩展 Equatable<TreeSet<T>> 接口,支持判等操作。
父类型:
operator func ==(TreeSet<T>)
public operator func ==(that: TreeSet<T>): Bool
功能:判断当前实例与参数指向的 TreeSet<T> 实例是否相等。
两个 TreeSet<T> 相等指的是其中包含的元素完全相等。
参数:
- that: TreeSet<T> - 被比较的对象。
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
operator func !=(TreeSet<T>)
public operator func !=(that: TreeSet<T>): Bool
功能:判断当前实例与参数指向的 TreeSet<T> 实例是否不等。
参数:
- that: TreeSet<T> - 被比较的对象。
返回值:
- Bool - 如果不等,则返回 true,否则返回 false。
extend<T> TreeSet<T> <: ToString where T <: ToString
extend<T> TreeSet<T> <: ToString where T <: ToString
功能:为 TreeSet<T> 扩展 ToString 接口,支持转字符串操作。
父类型:
func toString()
public func toString(): String
功能:将当前 TreeSet<T> 实例转换为字符串。
该字符串包含 TreeSet<T> 内每个元素的字符串表示,形如:"[elem1, elem2, elem3]"。
返回值:
- String - 转换得到的字符串。
异常
class ConcurrentModificationException
public class ConcurrentModificationException <: Exception {
public init()
public init(message: String)
}
功能:并发修改异常类。当函数检测到不同步的并发修改,抛出异常。
由于 collection 包提供的容器类都不支持并发修改,因此在执行某些操作时,会抛出 ConcurrentModificationException。
典型的抛出异常场景有:
- 使用 for-in 遍历一个容器过程中对容器进行修改时(HashMapIterator的remove() 方法除外)。
- 在使用声明周期较短的类型,如 MapEntryView 时,如果其所在的容器内容被修改,也会抛出异常。
父类型:
init()
public init()
功能:构造一个不带异常信息的实例。
init(String)
public init(message: String)
功能:根据异常信息构造异常实例。
参数:
- message: String - 异常信息。
ArrayList 的 add 函数
ArrayList 中添加元素的方法如下:
import std.collection.*
main() {
var list: ArrayList<Int64> = ArrayList<Int64>(10) // 创建一个容量为 10 的 ArrayList
var arr: Array<Int64> = [1, 2, 3]
list.add(all: arr) // list: [1, 2, 3]
list[1] = 120 // list: [1, 120, 3]
var b = list.get(2)
print("b=${b.getOrThrow()},")
list.add(12, at: 1) // list: [1, 12, 120, 3]
var c = list.get(2)
print("c=${c.getOrThrow()},")
var arr1: Array<Int64> = [1,2,3]
list.add(all: arr1, at: 1) // list: [1, 1, 2, 3, 12, 120, 3]
var d = list.get(2)
print("d=${d.getOrThrow()}")
return 0
}
运行结果:
b=3,c=120,d=2
ArrayList 的 get/set 函数
此用例展示了如何使用 get 方法获取 ArrayList 中对应索引的值,以及如何修改值。
代码如下:
import std.collection.*
main() {
var list = ArrayList<Int64>([97, 100]) // list: [97, 100]
// 修改值
list[1] = 120 // list: [97, 120]
// 获取值
var b = list.get(1)
print("b=${b.getOrThrow()}")
return 0
}
运行结果:
b=120
ArrayList 的 remove/clear/slice 函数
此用例展示了 ArrayList 的 remove/clear/slice 函数的使用方法。
代码如下:
import std.collection.*
main() {
var list: ArrayList<Int64> = ArrayList<Int64>([97, 100, 99]) // Function call syntactic sugar of variable-length
list.remove(at: 1) // list: [97, 99]
var b = list.get(1)
print("b=${b.getOrThrow()},")
list.clear()
list.add(11) // list: [97, 99, 11]
var arr: Array<Int64> = [1, 2, 3]
list.add(all: arr, at: 0) // list: [1, 2, 3, 97, 99]
var g = list.get(0)
print("g=${g.getOrThrow()},")
let r: Range<Int64> = 1..=2 : 1
var sublist: ArrayList<Int64> = list.slice(r) // sublist: [2, 3]
var m = sublist.get(0)
print("m=${m.getOrThrow()}")
return 0
}
运行结果:
b=99,g=1,m=2
HashMap 的 get/add/contains 函数
此用例展示了 HashMap 的基本使用方法。
代码如下:
import std.collection.*
main() {
var map: HashMap<String, Int64> = HashMap<String, Int64>()
map.add("a", 99) // map : [("a", 99)]
map.add("b", 100) // map : [("a", 99), ("b", 100)]
var a = map.get("a")
var bool = map.contains("a")
print("a=${a.getOrThrow()} ")
print("bool=${bool.toString()}")
return 0
}
运行结果:
a=99 bool=true
HashMap 的 add/remove/clear 函数
此用例展示了 HashMap 的基本使用方法。
代码如下:
import std.collection.*
main() {
var map: HashMap<String, Int64> = HashMap<String, Int64>()
var arr: Array<(String, Int64)> = [("d", 11), ("e", 12)]
map.add("a", 13)
print("a=${map.get("a").getOrThrow()} ")
map.add(all: arr) // map : [("d", 11), ("e", 12)]
var d = map.get("d")
print("d=${d.getOrThrow()} ")
map.remove("d") // map : [("e", 12)]
var bool = map.contains("d")
print("bool=${bool.toString()} ")
map.clear() // map: []
var bool1 = map.contains("e")
print("bool1=${bool1.toString()}")
return 0
}
运行结果:
a=13 d=11 bool=false bool1=false
HashSet 的 add/iterator/remove 函数
此用例展示了 HashSet 的基本使用方法。
代码如下:
import std.collection.*
/* 测试 */
main() {
var set: HashSet<String> = HashSet<String>() // set: []
set.add("apple") // set: ["apple"]
set.add("banana") // set: ["apple", "banana"], not in order
set.add("orange") // set: ["apple", "banana", "orange"], not in order
set.add("peach") // set: ["apple", "banana", "orange", "peach"], not in order
var itset = set.iterator()
while(true) {
var value = itset.next()
match(value) {
case Some(v) =>
if (!set.contains(v)) {
print("Operation failed")
return 1
} else { println(v) }
case None => break
}
}
set.remove("apple") // set: ["banana", "orange", "peach"], not in order
println(set)
return 0
}
由于 Set 中的顺序不是固定的,因此运行结果可能如下:
apple
banana
orange
peach
[banana, orange, peach]
TreeSet 的 add/iterator/remove 函数
此用例展示了 TreeSet 的基本使用方法。
代码如下:
import std.collection.*
/* 测试 */
main() {
var set: TreeSet<String> = TreeSet<String>()
set.add("peach")
set.add("banana")
set.add("apple")
set.add("orange")
var itset = set.iterator()
for (e in itset) {
println(e)
}
set.remove("banana")
println(set)
return 0
}
运行结果:
apple
banana
orange
peach
[apple, orange, peach]
迭代器操作函数
此用例展示了迭代器操作函数结合 pipeline 表达式的使用方法。
代码如下:
import std.collection.*
main() {
let arr = [-1, 2, 3, 4, 5, 6, 7, 8, 9]
arr |> filter{a: Int64 => a > 0} |> // filter -1
step<Int64>(2) |> // [2, 4, 6, 8]
skip<Int64>(2) |> // [6, 8]
forEach<Int64>(println)
let str = arr |> filter{a: Int64 => a % 2 == 1} |> collectString<Int64>(delimiter: ">")
println(str)
println(arr |> contains(6_i64))
return 0
}
运行结果:
6
8
3>5>7>9
true
std.collection.concurrent
功能介绍
collection.concurrent 包提供了并发安全的集合类型实现。
本包实现了以下几种并发安全的集合类型:
-
ArrayBlockingQueue:以数组的形式实现的具有固定大小的有界队列。
-
ConcurrentHashMap:线程安全的哈希表实现,支持高并发的读写操作。
-
ConcurrentLinkedQueue:一种线程安全的队列数据结构,特点是在添加元素时,如果当前的尾部 Block 已满,那么会创建一个新的 Block,而不是阻塞等待。这样可以保证在多线程环境下,队列的操作不会因为阻塞而导致线程的阻塞,从而提高了程序的性能。
-
LinkedBlockingQueue:一种阻塞队列,它支持在队列为空时阻塞获取元素的操作,以及在队列已满时阻塞添加元素的操作。
API 列表
类型别名
| 类型别名 | 功能 |
|---|---|
| BlockingQueue<E> (deprecated) | LinkedBlockingQueue 的别名。 |
| NonBlockingQueue<E> (deprecated) | ConcurrentLinkedQueue 的别名。 |
接口
| 接口名 | 功能 |
|---|---|
| ConcurrentMap<K, V> | 保证线程安全和操作原子性的 Map 接口定义。 |
类
| 类名 | 功能 |
|---|---|
| ArrayBlockingQueue<E> | 基于数组实现的 Blocking Queue 数据结构及相关操作函数。 |
| ConcurrentHashMapIterator<K, V> where K <: Hashable & Equatable<K> | 此类主要实现 Concurrent HashMap 的迭代器功能。 |
| ConcurrentHashMap<K, V> where K <: Hashable & Equatable<K> | 此类用于实现并发场景下线程安全的哈希表 ConcurrentHashMap 数据结构及相关操作函数。 |
| ConcurrentLinkedQueue<E> | 提供一个线程安全的队列,可以在多线程环境下安全地进行元素的添加和删除操作。 |
| LinkedBlockingQueue<E> | 实现是带阻塞机制并支持用户指定容量上界的并发队列。 |
类型别名
type BlockingQueue<E> (deprecated)
public type BlockingQueue<E> = LinkedBlockingQueue<E>
功能:LinkedBlockingQueue<E> 的别名。
注意:
未来版本即将废弃,使用 LinkedBlockingQueue<E> 替代。
type NonBlockingQueue<E> (deprecated)
public type NonBlockingQueue<E> = ConcurrentLinkedQueue<E>
功能:ConcurrentLinkedQueue<E> 的别名。
注意:
未来版本即将废弃,使用 ConcurrentLinkedQueue<E> 替代。
接口
interface ConcurrentMap<K, V>
public interface ConcurrentMap<K, V> {
func add(key: K, value: V): ?V
func addIfAbsent(key: K, value: V): ?V
func entryView(key: K, fn: (MapEntryView<K, V>) -> Unit): ?V
func get(key: K): ?V
func contains(key: K): Bool
func put(key: K, value: V): ?V
func putIfAbsent(key: K, value: V): ?V
func remove(key: K): ?V
func remove(key: K, predicate: (V) -> Bool): ?V
func replace(key: K, value: V): ?V
func replace(key: K, eval: (V) -> V): ?V
func replace(key: K, predicate: (V) -> Bool, eval: (V) -> V): ?V
operator func [](key: K): V
operator func [](key: K, value!: V): Unit
}
功能:保证线程安全和操作原子性的 Map 接口定义。
ConcurrentMap 接口中声明了并发场景下线程安全的 Map 必须保证原子性的方法,我们希望定义的线程安全 Map 类都能实现 ConcurrentMap 接口。例如我们在该包中定义的 ConcurrentHashMap 就实现了 ConcurrentMap 接口,并提供了 ConcurrentMap 中所声明方法的保证原子性的实现。
ConcurrentMap 接口中声明了并发 Map 在并发场景下需要保证原子性的方法。
并发 Map 为“键”到“值”的映射,其中 K 为键的类型,V 为值的类型。
func add(K, V)
func add(key: K, value: V): ?V
功能:将指定的值 value 与此 Map 中指定的键 key 关联。如果 Map 中已经包含键 key 的关联,则旧值将被替换;如果 Map 中不包含键 key 的关联,则添加键 key 与值 value 的关联。
参数:
- key: K - 要放置的键。
- value: V - 要关联的值。
返回值:
- ?V - 如果赋值之前 key 存在,则返回旧的值 Some(V);当赋值前 key 不存在时,返回 None。
func addIfAbsent(K, V)
func addIfAbsent(key: K, value: V): ?V
功能:当此 Map 中不存在键 key 时,在 Map 中添加指定的值 value 与指定的键 key 的关联。如果 Map 已经包含键 key,则不执行赋值操作。
参数:
- key: K - 要放置的键。
- value: V - 要分配的值。
返回值:
- ?V - 如果赋值之前 key 存在,则返回当前 key 对应的值 Some(V),且不执行赋值操作;当赋值前 key 不存在时,返回 None。
func contains(K)
func contains(key: K): Bool
功能:判断 Map 中是否包含指定键 key 的关联。
参数:
- key: K - 传递要判断的 key。
返回值:
- Bool - 当 key 存在时返回 true;当 key 不存在时返回 false。
func entryView(K, (MapEntryView<K, V>) -> Unit)
func entryView(key: K, fn: (MapEntryView<K, V>) -> Unit): ?V
功能:根据指定键 key 获取当前映射中相应的键值对视图 entryView,并调用函数 fn 对该键值对进行增、删、改操作,并返回最终映射中键 key 对应的值。
如果当前映射中不包含键 key,则将获取一个空视图 entryView,如果将其 value 置为非 None 值,则将在当前映射中增加 key-value 键值对。
如果当前映射中包含键 key,则将获取 key-value 的视图,如果将 value 置为 None,则相当于从当前映射中删除该键值对;如果将 value 置为新的非 None 值,则相当于修改当前映射中键 key 对应的值。
参数:
- key: K - 待获取其相应视图的键。
- fn: (MapEntryView<K, V>) -> Unit - 对指定视图进行的自定义操作,可用于对映射中键值对进行增、删、改操作。
返回值:
- ?V - 函数 fn 调用结束后当前映射中键 key 对应的值,如果 key 不存在,返回 None。
func get(K)
func get(key: K): ?V
功能:返回 Map 中键 key 所关联的值。
参数:
- key: K - 传递 key,获取 value。
返回值:
- ?V - 当 key 存在时,返回其关联的值 Some(V);当 key 不存在时,返回 None。
func put(K, V) (deprecated)
func put(key: K, value: V): ?V
功能:将指定的值 value 与此 Map 中指定的键 key 关联。如果 Map 中已经包含键 key 的关联,则旧值将被替换;如果 Map 中不包含键 key 的关联,则添加键 key 与值 value 的关联。
注意:
未来版本即将废弃,使用 add(K, V) 替代。
参数:
- key: K - 要放置的键。
- value: V - 要关联的值。
返回值:
- ?V - 如果赋值之前 key 存在,则返回旧的值 Some(V);当赋值前 key 不存在时,返回 None。
func putIfAbsent(K, V) (deprecated)
func putIfAbsent(key: K, value: V): ?V
功能:当此 Map 中不存在键 key 时,在 Map 中添加指定的值 value 与指定的键 key 的关联。如果 Map 已经包含键 key,则不执行赋值操作。
注意:
未来版本即将废弃,使用 addIfAbsent(K, V) 替代。
参数:
- key: K - 要放置的键。
- value: V - 要分配的值。
返回值:
- ?V - 如果赋值之前 key 存在,则返回当前 key 对应的值 Some(V),且不执行赋值操作;当赋值前 key 不存在时,返回 None。
func remove(K)
func remove(key: K): ?V
功能:从此映射中删除指定键 key 的映射(如果存在)。
参数:
- key: K - 传入要删除的 key。
返回值:
- ?V - 如果移除之前 key 存在,则返回 key 对应的值 Some(V);当移除时 key 不存在时,返回 None。
func remove(K, (V) -> Bool) (deprecated)
func remove(key: K, predicate: (V) -> Bool): ?V
功能:如果 Map 中存在键 key 且 key 所关联的值 v 满足条件 predicate,则从 Map 中删除 key 的关联。
注意:
未来版本即将废弃,使用 entryView(K, (MapEntryView<K, V>) -> Unit) 替代。
参数:
- key: K - 传入要删除的 key。
- predicate: (V) ->Bool - 传递一个 lambda 表达式进行判断。
返回值:
func replace(K, (V) -> Bool, (V) -> V) (deprecated)
func replace(key: K, predicate: (V) -> Bool, eval: (V) -> V): ?V
功能:如果 Map 中存在键 key(假设其关联的值为 v),且 v 满足条件 predicate,则将 Map 中键 key 关联的值替换为 eval(v) 的计算结果;如果 Map 中不存在键 key,或者存在键 key 但关联的值不满足 predicate,则不对 Map 做任何修改。
注意:
未来版本即将废弃,使用 entryView(K, (MapEntryView<K, V>) -> Unit) 替代。
参数:
- key: K - 传入要替换所关联值的键。
- predicate: (V) ->Bool - 传递一个 lambda 表达式进行判断。
- eval: (V) ->V - 传入计算用于替换的新值的函数。
返回值:
- ?V - 如果 key 存在,则返回 key 对应的旧值 Some(V);当 key 不存在时,或者 key 关联的值不满足 predicate 时,返回 None。
func replace(K, (V) -> V) (deprecated)
func replace(key: K, eval: (V) -> V): ?V
功能:如果 Map 中存在键 key(假设其关联的值为 v),则将 Map 中键 key 关联的值替换为 eval(v) 的计算结果;如果 Map 中不存在键 key,则不对 Map 做任何修改。
注意:
未来版本即将废弃,使用 entryView(K, (MapEntryView<K, V>) -> Unit) 替代。
参数:
- key: K - 传入要替换所关联值的键。
- eval: (V) ->V - 传入计算用于替换的新值的函数。
返回值:
- ?V - 如果 key 存在,则返回 key 对应的旧值 Some(V);当 key 不存在时,返回 None。
func replace(K, V)
func replace(key: K, value: V): ?V
功能:如果 Map 中存在 key,则将 Map 中键 key 关联的值替换为 value;如果 Map 中不存在 key,则不对 Map 做任何修改。
参数:
- key: K - 传入要替换所关联值的键。
- value: V - 传入要替换成的新值。
返回值:
- ?V - 如果 key 存在,则返回 key 对应的旧值 Some(V);当 key 不存在时,返回 None。
operator func [](K)
operator func [](key: K): V
功能:根据指定键 key 获取值。如果键 key 存在,返回对应的值;如果不存在,抛出异常。
参数:
- key: K - 待获取其值的键。
返回值:
- V - 键 key 对应的值。
异常:
- NoneValueException - 当前映射中不存在键 key。
operator func [](K, V)
operator func [](key: K, value!: V): Unit
功能:设置指定键 key 的值为 value。如果键 key 存在,新 value 覆盖旧 value;如果键不存在,添加此键值对。
参数:
- key: K - 待设置其值的键。
- value!: V - 待设置的值。
类
class ArrayBlockingQueue<E>
public class ArrayBlockingQueue<E> {
public let capacity: Int64
public init(capacity: Int64)
public init(capacity: Int64, elements: Collection<E>)
}
功能:基于数组实现的 Blocking Queue 数据结构及相关操作函数。
ArrayBlockingQueue 是带阻塞机制且需要用户指定容量上界的并发队列。
prop size
public prop size: Int64
功能:返回此 ArrayBlockingQueue 的元素个数。
注意:
此方法不保证并发场景下的原子性,建议在环境中没有其他线程并发地修改 ArrayBlockingQueue 时调用。
类型:Int64
let capacity
public let capacity: Int64
功能:此 ArrayBlockingQueue 的容量。
类型:Int64
init(Int64)
public init(capacity: Int64)
功能:构造一个带有传入容量大小的 ArrayBlockingQueue。
参数:
- capacity: Int64 - 初始化容量大小。
异常:
- IllegalArgumentException - 如果 capacity 小于等于 0 则抛出异常。
init(Int64, Collection<E>) (deprecated)
public init(capacity: Int64, elements: Collection<E>)
功能:构造一个带有传入容量大小,并带有传入迭代器的 ArrayBlockingQueue。
注意:
未来版本即将废弃,同等功能替代写法为:创建空队列,再将 elements 中元素依次添加到队列中。
参数:
- capacity: Int64 - 初始化容量大小。
- elements: Collection<E> - 初始化迭代器元素。
异常:
- IllegalArgumentException - 如果 capacity 小于等于 0 或小于迭代器元素 elements 的 size 则抛出异常。
func add(E)
public func add(element: E): Unit
功能:阻塞的入队操作,将元素添加到队列尾部。如果队列已满,则阻塞等待。
参数:
- element: E - 要添加的元素。
示例:
import std.collection.concurrent.*
main() {
var blockArr: ArrayBlockingQueue<Int64> = ArrayBlockingQueue<Int64>(2)
blockArr.add(10)
println(blockArr.peek())
}
运行结果:
Some(10)
func add(E, Duration)
public func add(element: E, timeout: Duration): Bool
功能:阻塞的入队操作,将元素添加到队列尾部,如果队列满了,将等待指定的时间。如果 timeout 为负,则会立即执行入队操作并且返回操作结果。
参数:
- element: E - 要添加的元素。
- timeout: Duration - 等待时间。
返回值:
- Bool - 成功添加元素返回 true,超出等待时间还未成功添加元素返回 false。
示例:
import std.collection.concurrent.*
import std.sync.*
import std.time.*
main() {
let blockArr: ArrayBlockingQueue<Int64> = ArrayBlockingQueue<Int64>(2)
/* 创建新线程,填满阻塞队列,休眠 1 秒后移除阻塞队列队首元素 */
spawn {
=>
blockArr.add(0)
blockArr.add(1)
sleep(1000 * Duration.millisecond)
println("New thread moves out of blocked queue head element.")
blockArr.remove()
}
/* 主线程立即让出执行权,唤醒后阻塞的添加 */
sleep(-1 * Duration.millisecond)
println("The main thread is woken up.")
let isSuccess: Bool = blockArr.add(2, 2000 * Duration.millisecond)
println(isSuccess)
}
运行结果:
The main thread is woken up.
New thread moves out of blocked queue head element.
true
func dequeue() (deprecated)
public func dequeue(): E
功能:阻塞的出队操作,获得队首元素并删除。
注意:
未来版本即将废弃,使用 remove() 替代。
返回值:
- E - 返回队首元素。
func dequeue(Duration) (deprecated)
public func dequeue(timeout: Duration): Option<E>
功能:阻塞的出队操作,获得队首元素并删除,如果队列为空,将等待指定的时间。如果 timeout 为负,则会立即执行出队操作并且返回操作结果。
注意:
未来版本即将废弃,使用 remove(Duration) 替代。
参数:
- timeout: Duration - 等待时间。
返回值:
- Option<E> - 返回队首元素。如果超出等待时间还未成功获取队首元素,则返回 None。
func enqueue(E) (deprecated)
public func enqueue(element: E): Unit
功能:阻塞的入队操作,将元素添加到队列尾部。
注意:
未来版本即将废弃,使用 add(E) 替代。
参数:
- element: E - 要添加的元素。
func enqueue(E, Duration) (deprecated)
public func enqueue(element: E, timeout: Duration): Bool
功能:阻塞的入队操作,将元素添加到队列尾部,如果队列满了,将等待指定的时间。如果 timeout 为负,则会立即执行入队操作并且返回操作结果。
注意:
未来版本即将废弃,使用 add(E, Duration) 替代。
参数:
- element: E - 要添加的元素。
- timeout: Duration - 等待时间。
返回值:
- Bool - 成功添加元素返回 true,超出等待时间还未成功添加元素返回 false。
func head() (deprecated)
public func head(): Option<E>
功能:获取队首元素。
该函数是非阻塞的。
注意:
未来版本即将废弃,使用 peek() 替代。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
func peek()
public func peek(): Option<E>
功能:非阻塞的获取队首元素。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
示例:
import std.collection.concurrent.*
main() {
let blockArr: ArrayBlockingQueue<Int64> = ArrayBlockingQueue<Int64>(2)
blockArr.add(2)
blockArr.add(3)
println(blockArr.peek())
}
运行结果:
Some(2)
func remove()
public func remove(): E
功能:阻塞的出队操作,获得队首元素并删除。如果队列为空,则阻塞等待。
返回值:
- E - 返回队首元素。
示例:
import std.collection.concurrent.*
main() {
let blockArr: ArrayBlockingQueue<Int64> = ArrayBlockingQueue<Int64>(2)
blockArr.add(2)
blockArr.add(3)
println(blockArr.remove())
println(blockArr.size)
}
运行结果:
2
1
func remove(Duration)
public func remove(timeout: Duration): Option<E>
功能:阻塞的出队操作,获得队首元素并删除,如果队列为空,将等待指定的时间。如果 timeout 为负,则会立即执行出队操作并且返回操作结果。
参数:
- timeout: Duration - 等待时间。
返回值:
- Option<E> - 返回队首元素。如果超出等待时间还未成功获取队首元素,则返回 None。
示例:
import std.collection.concurrent.*
import std.sync.*
import std.time.*
main() {
let blockArr: ArrayBlockingQueue<Int64> = ArrayBlockingQueue<Int64>(2)
/* 创建新线程,休眠 1 秒后向队列添加元素 */
spawn {
=>
sleep(1000 * Duration.millisecond)
println("This new thread adds new elements to the queue.")
blockArr.add(3)
}
/* 主线程立即让出执行权,唤醒后阻塞的取出队首元素 */
sleep(-1 * Duration.millisecond)
println("The main thread is woken up.")
let num: Option<Int64> = blockArr.remove(2000 * Duration.millisecond)
println(num)
}
运行结果:
The main thread is woken up.
This new thread adds new elements to the queue.
Some(3)
func tryAdd(E)
public func tryAdd(element: E): Bool
功能:非阻塞的入队操作,将元素添加到队列尾部。
参数:
- element: E - 要添加的元素。
返回值:
- Bool - 成功添加返回 true;如果队列满了,添加失败返回 false。
示例:
import std.collection.concurrent.*
main() {
let blockArr: ArrayBlockingQueue<Int64> = ArrayBlockingQueue<Int64>(2)
blockArr.tryAdd(2)
blockArr.tryAdd(3)
println(blockArr.size)
}
运行结果:
2
func tryDequeue() (deprecated)
public func tryDequeue(): Option<E>
功能:非阻塞的出队操作,获得队首元素并删除。
注意:
未来版本即将废弃,使用 tryRemove() 替代。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
func tryEnqueue(E) (deprecated)
public func tryEnqueue(element: E): Bool
功能:非阻塞的入队操作,将元素添加到队列尾部。
注意:
未来版本即将废弃,使用 tryAdd(E) 替代。
参数:
- element: E - 要添加的元素。
返回值:
- Bool - 成功添加返回 true;如果队列满了,添加失败返回 false。
func tryRemove()
public func tryRemove(): Option<E>
功能:非阻塞的出队操作,获得队首元素并删除。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
示例:
import std.collection.concurrent.*
main() {
let blockArr: ArrayBlockingQueue<Int64> = ArrayBlockingQueue<Int64>(2)
blockArr.tryAdd(2)
println(blockArr.tryRemove())
println(blockArr.tryRemove())
}
运行结果:
Some(2)
None
class ConcurrentHashMap<K, V> where K <: Hashable & Equatable<K>
public class ConcurrentHashMap<K, V> <: ConcurrentMap<K, V> & Collection<(K, V)> where K <: Hashable & Equatable<K> {
public init(concurrencyLevel!: Int64 = 16)
public init(capacity: Int64, concurrencyLevel!: Int64 = 16)
public init(elements: Collection<(K, V)>, concurrencyLevel!: Int64 = 16)
public init(size: Int64, initElement: (Int64) -> (K, V), concurrencyLevel!: Int64 = 16)
}
功能:此类用于实现并发场景下线程安全的哈希表 ConcurrentHashMap 数据结构及相关操作函数。
当 ConcurrentHashMap 中出现键值对数量大于“桶”数量的情况时,会进行“扩容”。
构造函数中的参数 concurrencyLevel 表示“并发度”,即:最多允许多少个线程并发修改 ConcurrentHashMap。查询键值对的操作是非阻塞的,不受所指定的并发度 concurrencyLevel 的限制。参数 concurrencyLevel 默认等于 16。它只影响 ConcurrentHashMap 在并发场景下的性能,不影响功能。
注意:
如果用户传入的 concurrencyLevel 小于 16,则并发度会被设置为 16。
concurrencyLevel 并非越大越好,更大的 concurrencyLevel 会导致更大的内存开销(甚至可能导致 out of memory 异常),用户需要在内存开销和运行效率之间进行平衡。
父类型:
- ConcurrentMap<K, V>
- Collection<(K, V)>
示例:
使用示例见 ConcurrentHashMap 使用示例。
prop size
public prop size: Int64
功能:返回键值的个数。
注意:
此方法不保证并发场景下的原子性,建议在环境中没有其他线程并发地修改 ConcurrentHashMap 时调用。
类型:Int64
init(Collection<(K, V)>, Int64)
public init(elements: Collection<(K, V)>, concurrencyLevel!: Int64 = 16)
功能:构造一个带有传入迭代器和指定并发度的 ConcurrentHashMap。该构造函数根据传入迭代器元素 elements 的 size 设置 ConcurrentHashMap 的容量。
参数:
- elements: Collection<(K, V)> - 初始化迭代器元素。
- concurrencyLevel!: Int64 - 用户指定的并发度。
init(Int64)
public init(concurrencyLevel!: Int64 = 16)
功能:构造一个具有默认初始容量(16)和指定并发度(默认等于 16)的 ConcurrentHashMap。
参数:
- concurrencyLevel!: Int64 - 用户指定的并发度。
init(Int64, (Int64) -> (K, V), Int64)
public init(size: Int64, initElement: (Int64) -> (K, V), concurrencyLevel!: Int64 = 16)
功能:构造具有传入大小和初始化函数元素以及指定并发度的 ConcurrentHashMap。该构造函数根据参数 size 设置 ConcurrentHashMap 的容量。
参数:
- size: Int64 - 初始化函数元素的大小。
- initElement: (Int64) -> (K, V) - 初始化函数元素。
- concurrencyLevel!: Int64 - 用户指定并发度。
异常:
- IllegalArgumentException - 如果 size 小于 0 则抛出异常。
init(Int64, Int64)
public init(capacity: Int64, concurrencyLevel!: Int64 = 16)
功能:构造一个带有传入容量大小和指定并发度(默认等于 16)的 ConcurrentHashMap。
参数:
异常:
- IllegalArgumentException - 如果 capacity 小于 0 则抛出异常。
func add(K, V)
public func add(key: K, value: V): ?V
功能:将指定的值 value 与此 ConcurrentHashMap中指定的键 key 关联。如果 ConcurrentHashMap 中已经包含键 key 的关联,则旧值将被替换;如果 ConcurrentHashMap 中不包含键 key 的关联,则添加键 key 与值 value 的关联。
参数:
- key: K - 要放置的键。
- value: V - 要关联的值。
返回值:
- ?V - 如果赋值之前 key 存在,则返回旧的值 Some(V);当赋值前 key 不存在时,返回 None。
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(3, {value => (value, value)})
let oldValue = map.add(2, 3)
println(oldValue)
let newValue = map.add(3, 3)
println(newValue)
let iter = ConcurrentHashMapIterator<Int64, Int64>(map)
while (true) {
match (iter.next()) {
case Some(i) => println("(${i[0]},${i[1]})")
case None => break
}
}
}
运行结果:
Some(2)
None
(0,0)
(1,1)
(2,3)
(3,3)
func addIfAbsent(K, V)
public func addIfAbsent(key: K, value: V): ?V
功能:当此 ConcurrentHashMap中不存在键 key 时,在 ConcurrentHashMap 中添加指定的值 value 与指定的键 key 的关联。如果 ConcurrentHashMap 已经包含键 key,则不执行赋值操作。
参数:
- key: K - 要放置的键。
- value: V - 要分配的值。
返回值:
- ?V - 如果赋值之前 key 存在,则返回当前 key 对应的值 Some(V),且不执行赋值操作;当赋值前 key 不存在时,返回 None。
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(3, {value => (value, value)})
let oldValue = map.addIfAbsent(2, 3)
println(oldValue)
let newValue = map.addIfAbsent(3, 3)
println(newValue)
let iter = ConcurrentHashMapIterator<Int64, Int64>(map)
while (true) {
match (iter.next()) {
case Some(i) => println("(${i[0]},${i[1]})")
case None => break
}
}
}
运行结果:
Some(2)
None
(0,0)
(1,1)
(2,2)
(3,3)
func contains(K)
public func contains(key: K): Bool
功能:判断此映射中是否包含指定键 key 的映射。
参数:
- key: K - 传递要判断的 key。
返回值:
- Bool - 是否包含指定键 key 的映射,包含为true,不包含为false。
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(3, {value => (value, value)})
map.add(3, 3)
println(map.contains(3))
println(map.contains(6))
}
运行结果:
true
false
func entryView(K, (MapEntryView<K, V>) -> Unit)
public func entryView(key: K, fn: (MapEntryView<K, V>) -> Unit): ?V
功能:根据指定键 key 获取当前映射中相应的键值对视图 entryView,并调用函数 fn 对该键值对进行增、删、改操作,并返回最终映射中键 key 对应的值。
如果当前映射中不包含键 key,则将获取一个空视图 entryView,如果将其 value 置为非 None 值,则将在当前映射中增加 key-value 键值对。
如果当前映射中包含键 key,则将获取 key-value 的视图,如果将 value 置为 None,则相当于从当前映射中删除该键值对;如果将 value 置为新的非 None 值,则相当于修改当前映射中键 key 对应的值。
注意参数 fn 中不能并发调用函数 entryView、remove、replace,如:
map.entryView(1) { _ =>
let f = spawn {
map.entryView(17) { _ => () }
}
f.get()
}
说明:
该操作具有原子性。
回调 fn 调用过程中对 key-value 键值对的修改不会即时更新到当前映射中,等到 entryView 函数调用结束再将修改整体更新到当前映射中。
参数:
- key: K - 待获取其相应视图的键。
- fn: (MapEntryView<K, V>) -> Unit - 对指定视图进行的自定义操作,可用于对映射中键值对进行增、删、改操作。
返回值:
- ?V - 函数 fn 调用结束后当前映射中键 key 对应的值,如果 key 不存在,返回 None。
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(2, {value => (value, value)})
map.add(2, 2)
/* 当前映射不包含 key 为 3 的键值对,对 entryView.value 设置新值 7,等价于添加新的键值对 (3,7) */
let num1 = map.entryView(3, {view => view.value = 7})
println(num1)
/* 当前映射包含 key 为 2 的键值对,对 entryView.value 设置新值 6,等价更新 key 为 1 的值为 6 */
let num2 = map.entryView(1, {view => view.value = 6})
println(num2)
/* 当前映射包含 key 为 0 的键值对,对 entryView.value 设置新值 None,等价删除 key 为 0 的键值对 */
let num3 = map.entryView(0, {view => view.value = None})
println(num3)
let iter = ConcurrentHashMapIterator<Int64, Int64>(map)
while (true) {
match (iter.next()) {
case Some(i) => println("(${i[0]},${i[1]})")
case None => break
}
}
}
运行结果:
Some(7)
Some(6)
None
(1,6)
(2,2)
(3,7)
func get(K)
public func get(key: K): ?V
功能:返回此映射中键 key 所关联的值。
参数:
- key: K - 传递 key,获取 value。
返回值:
- ?V - 此映射中键 key 所关联的值。
func isEmpty()
public func isEmpty(): Bool
功能:判断 ConcurrentHashMap 是否为空。
注意:
此方法不保证并发场景下的原子性,建议在环境中没有其他线程并发地修改 ConcurrentHashMap 时调用。
返回值:
- Bool - 如果是,则返回 true,否则,返回 false。
func iterator()
public func iterator(): ConcurrentHashMapIterator<K, V>
功能:获取 ConcurrentHashMap 的迭代器。
返回值:
- ConcurrentHashMapIterator<K, V> - ConcurrentHashMap 的迭代器
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(3, {value => (value, value)})
let iter = map.iterator()
while (true) {
match (iter.next()) {
case Some(i) => println("(${i[0]},${i[1]})")
case None => break
}
}
}
运行结果:
(0,0)
(1,1)
(2,2)
func put(K, V) (deprecated)
public func put(key: K, value: V): ?V
功能:将指定的值 value 与此 ConcurrentHashMap中指定的键 key 关联。如果 ConcurrentHashMap 中已经包含键 key 的关联,则旧值将被替换;如果 ConcurrentHashMap 中不包含键 key 的关联,则添加键 key 与值 value 的关联。
注意:
未来版本即将废弃,使用 add(K, V) 替代。
参数:
- key: K - 要放置的键。
- value: V - 要关联的值。
返回值:
- ?V- 如果赋值之前 key 存在,则返回旧的值 Some(V);当赋值前 key 不存在时,返回 None。
func putIfAbsent(K, V) (deprecated)
public func putIfAbsent(key: K, value: V): ?V
功能:当此 ConcurrentHashMap中不存在键 key 时,在 ConcurrentHashMap 中添加指定的值 value 与指定的键 key 的关联。如果 ConcurrentHashMap 已经包含键 key,则不执行赋值操作。
注意:
未来版本即将废弃,使用 addIfAbsent(K, V) 替代。
参数:
- key: K - 要放置的键。
- value: V - 要分配的值。
返回值:
- ?V - 如果赋值之前 key 存在,则返回当前 key 对应的值 Some(V),且不执行赋值操作;当赋值前 key 不存在时,返回 None。
func remove((K, (V) -> Bool)) (deprecated)
public func remove(key: K, predicate: (V) -> Bool): ?V
功能:如果此映射中存在键 key 且 key 所映射的值 v 满足条件 predicate,则从此映射中删除 key 的映射。
注意:
未来版本即将废弃,使用 entryView(K, (MapEntryView<K, V>) -> Unit) 替代。
参数:
- key: K - 传入要删除的 key。
- predicate: (V) ->Bool - 传递一个 lambda 表达式进行判断。
返回值:
- ?V - 如果映射中存在 key,则返回 key 对应的旧值;当映射中不存在 key 时,或者 key 关联的值不满足 predicate 时,返回 None。
func remove(K)
public func remove(key: K): ?V
功能:从此映射中删除指定键 key 的映射(如果存在)。
参数:
- key: K - 传入要删除的 key。
返回值:
- ?V - 如果移除之前 key 存在,则返回 key 对应的值 Some(V);当移除时 key 不存在时,返回 None。
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(3, {value => (value, value)})
let num = map.remove(0)
println(num)
let iter = map.iterator()
while (true) {
match (iter.next()) {
case Some(i) => println("(${i[0]},${i[1]})")
case None => break
}
}
}
运行结果:
Some(0)
(1,1)
(2,2)
func replace(K, (V) -> Bool, (V) -> V) (deprecated)
public func replace(key: K, predicate: (V) -> Bool, eval: (V) -> V): ?V
功能:如果 ConcurrentHashMap 中存在键 key(假设其关联的值为 v),且 v 满足条件 predicate,则将 ConcurrentHashMap 中键 key 关联的值替换为 eval(v) 的计算结果;如果 ConcurrentHashMap 中不存在键 key,或者存在键 key 但关联的值不满足 predicate,则不对 ConcurrentHashMap 做任何修改。
注意:
未来版本即将废弃,使用 entryView(K, (MapEntryView<K, V>) -> Unit) 替代。
参数:
- key: K - 传入要替换所关联值的键。
- predicate: (V) ->Bool - 传递一个 lambda 表达式进行判断。
- eval: (V) ->V - 传入计算用于替换的新值的函数。
返回值:
- ?V - 如果 key 存在,则返回 key 对应的旧值 Some(V);当 key 不存在时,或者 key 关联的值不满足 predicate 时,返回 None。
func replace(K, (V) -> V) (deprecated)
public func replace(key: K, eval: (V) -> V): ?V
功能:如果 ConcurrentHashMap 中存在键 key(假设其关联的值为 v),则将 ConcurrentHashMap 中键 key 关联的值替换为 eval(v) 的计算结果;如果 ConcurrentHashMap中不存在键 key,则不对 ConcurrentHashMap 做任何修改。
注意:
未来版本即将废弃,使用 entryView(K, (MapEntryView<K, V>) -> Unit) 替代。
参数:
- key: K - 传入要替换所关联值的键。
- eval: (V) ->V - 传入计算用于替换的新值的函数。
返回值:
- ?V - 如果 key 存在,则返回 key 对应的旧值 Some(V);当 key 不存在时,返回 None。
func replace(K, V)
public func replace(key: K, value: V): ?V
功能:如果 ConcurrentHashMap 中存在 key,则将 ConcurrentHashMap 中键 key 关联的值替换为 value;如果 ConcurrentHashMap 中不存在 key,则不对 ConcurrentHashMap 做任何修改。
参数:
- key: K - 传入要替换所关联值的键。
- value: V - 传入要替换成的新值。
返回值:
- ?V - 如果 key 存在,则返回 key 对应的旧值 Some(V);当 key 不存在时,返回 None。
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(3, {value => (value, value)})
let num = map.replace(0, 2)
println(num)
let iter = map.iterator()
while (true) {
match (iter.next()) {
case Some(i) => println("(${i[0]},${i[1]})")
case None => break
}
}
}
运行结果:
Some(0)
(0,2)
(1,1)
(2,2)
operator func [](K)
public operator func [](key: K): V
功能:运算符重载集合,如果键存在,返回键对应的值;如果不存在,抛出异常。
参数:
- key: K - 传递值进行判断。
返回值:
- V - 与键对应的值。
异常:
- NoneValueException - 关联中不存在键 key。
operator func [](K, V)
public operator func [](key: K, value!: V): Unit
功能:运算符重载集合,如果键 key 存在,新 value 覆盖旧 value;如果键不存在,添加此键值对。
参数:
- key: K - 传递值进行判断。
- value!: V - 传递要设置的值。
class ConcurrentHashMapIterator<K, V> where K <: Hashable & Equatable<K>
public class ConcurrentHashMapIterator<K, V> <: Iterator<(K, V)> where K <: Hashable & Equatable<K> {
public init(cmap: ConcurrentHashMap<K, V>)
}
功能:此类主要实现 ConcurrentHashMap 的迭代器功能。
注意:
这里定义的 ConcurrentHashMap 迭代器:
- 不保证迭代结果为并发 HashMap 某一时刻的 “快照”,建议在环境中没有其他线程并发地修改 ConcurrentHashMap 时调用;
- 迭代器在迭代过程中,不保证可以感知环境线程对目标 ConcurrentHashMap 的修改。
父类型:
- Iterator<(K, V)>
init(ConcurrentHashMap<K, V>)
public init(cmap: ConcurrentHashMap<K, V>)
功能:创建 ConcurrentHashMapIterator<K, V> 实例。
参数:
- cmap: ConcurrentHashMap<K, V> - 待获取其迭代器的 ConcurrentHashMap<K, V> 实例。
func next()
public func next(): Option<(K, V)>
功能:返回迭代中的下一个元素。
返回值:
示例:
import std.collection.concurrent.*
main() {
let map: ConcurrentHashMap<Int64, Int64> = ConcurrentHashMap<Int64, Int64>(3, {value => (value, value)})
let iter = ConcurrentHashMapIterator<Int64, Int64>(map)
while (true) {
match (iter.next()) {
case Some(i) => println("(${i[0]},${i[1]})")
case None => break
}
}
}
运行结果:
(0,0)
(1,1)
(2,2)
class ConcurrentLinkedQueue<E>
public class ConcurrentLinkedQueue<E> <: Collection<E> {
public init()
public init(elements: Collection<E>)
}
功能:提供一个线程安全的队列,可以在多线程环境下安全地进行元素的添加和删除操作。
非阻塞队列的目的是为了解决多线程环境下的同步问题,使得多个线程可以并发地进行队列的操作,而不会出现数据冲突或者死锁的问题。
非阻塞队列在多线程编程中非常常见,它可以用于任何需要线程安全队列的场景,例如生产者消费者模型、任务调度、线程池等。
父类型:
- Collection<E>
使用示例:
使用示例见 ConcurrentLinkedQueue 使用示例。
prop size
public prop size: Int64
功能:获取此 ConcurrentLinkedQueue 的元素个数。
注意:
此方法不保证并发场景下的原子性,建议在环境中没有其他线程并发地修改 ConcurrentLinkedQueue 时调用。
类型:Int64
init()
public init()
功能:构造一个默认的 ConcurrentLinkedQueue 实例。
init(Collection<E>) (deprecated)
public init(elements: Collection<E>)
功能:根据 Collection<E> 实例构造一个 ConcurrentLinkedQueue 实例。
注意:
未来版本即将废弃,如需实现等效功能,可先创建空队列,再依次将 Collection 中元素添加到队列中。
参数:
- elements: Collection<E> - 将该容器中元素放入新构造的 ConcurrentLinkedQueue
func add(E)
public func add(element: E): Bool
功能:非阻塞的入队操作,将元素添加到队列尾部。
注意:
该函数不会返回 false。
参数:
- element: E - 要添加的元素。
返回值:
- Bool - 成功添加元素则返回 true。
func dequeue() (deprecated)
public func dequeue(): Option<E>
功能:获取并删除队首元素。
注意:
未来版本即将废弃,使用 remove() 替代。
返回值:
- Option<E> - 成功删除则返回队首元素,队列为空则返回 None。
func enqueue(E) (deprecated)
public func enqueue(element: E): Bool
功能:非阻塞的入队操作,将元素添加到队列尾部。
注意:
- 该函数不会返回 false。
- 未来版本即将废弃,使用 add(E) 替代。
参数:
- element: E - 要添加的元素。
返回值:
- Bool - 成功添加元素则返回 true。
func head() (deprecated)
public func head(): Option<E>
功能:获取队首元素,不会删除该元素。
注意:
未来版本即将废弃,使用 peek() 替代。
返回值:
- Option<E> - 成功获取则返回队首元素,队列为空则返回 None。
func isEmpty()
public func isEmpty(): Bool
功能:判断当前队列是否为空。
返回值:
- Bool - 当前队列为空返回 true,否则返回 false。
func iterator()
public func iterator(): Iterator<E>
功能:获取当前队列的迭代器,用于遍历当前队列。
说明:
遍历操作不会删除队列中的元素。 遍历操作不保证原子性,如果有其他线程并发修改当前队列,不保遍历得到的元素是当前队列某一时刻的静态切片。
返回值:
- Iterator<E> - 当前队列的迭代器。
func peek()
public func peek(): Option<E>
功能:获取队首元素,不会删除该元素。
返回值:
- Option<E> - 成功获取则返回队首元素,队列为空则返回 None。
func remove()
public func remove(): Option<E>
功能:获取并删除队首元素。
返回值:
- Option<E> - 成功删除则返回队首元素,队列为空则返回 None。
func toArray()
public func toArray(): Array<E>
功能:将当前队列中所有元素按顺序存入数组,先入队的元素在数组下标较小的位置。
说明:
该操作不会删除队列中的元素。 该操作不保证原子性,如果有其他线程并发修改当前队列,不保证该操作得到的数组是当前队列某一时刻的静态切片。
返回值:
- Array<E> - 得到的数组,里面的元素为当前队列中的元素。
class LinkedBlockingQueue<E>
public class LinkedBlockingQueue<E> {
public let capacity: Int64
public init()
public init(capacity: Int64)
public init(capacity: Int64, elements: Array<E>)
public init(capacity: Int64, elements: Collection<E>)
}
功能:实现是带阻塞机制并支持用户指定容量上界的并发队列。
阻塞队列的特点是,当队列满时,尝试向队列中添加元素的线程会被阻塞,直到队列有空余位置;当队列空时,尝试从队列中获取元素的线程会被阻塞,直到队列有可取元素。
let capacity
public let capacity: Int64
功能:返回此 LinkedBlockingQueue 的容量。
类型:Int64
prop size
public prop size: Int64
功能:返回此 LinkedBlockingQueue 的元素个数。
注意:
此方法不保证并发场景下的原子性,建议在环境中没有其他线程并发地修改 LinkedBlockingQueue 时调用。
类型:Int64
init()
public init()
功能:构造一个具有默认初始容量(Int64.Max)的 LinkedBlockingQueue。
init(Int64)
public init(capacity: Int64)
功能:构造一个带有传入容量大小的 LinkedBlockingQueue。
参数:
- capacity: Int64 - 初始化容量大小。
异常:
- IllegalArgumentException - 如果 capacity 小于等于 0 则抛出异常。
init(Int64, Array<E>) (deprecated)
public init(capacity: Int64, elements: Array<E>)
功能:构造一个带有传入容量大小,并带有传入数组元素的 LinkedBlockingQueue。
注意:
未来版本即将废弃,如需实现等效功能,可先创建空队列,再依次将数组中的元素添加到队列中。
参数:
异常:
- IllegalArgumentException - 如果 capacity 小于等于 0 或小于数组元素elements 的 size 则抛出异常。
init(Int64, Collection<E>) (deprecated)
public init(capacity: Int64, elements: Collection<E>)
功能:构造一个带有传入容量大小,并带有传入迭代器的 LinkedBlockingQueue。
注意:
未来版本即将废弃,如需实现等效功能,可先创建空队列,再依次将 Collection 中的元素添加到队列中。
参数:
- capacity: Int64 - 初始化容量大小。
- elements: Collection<E> - 初始化迭代器元素。
异常:
- IllegalArgumentException - 如果 capacity 小于等于 0 或小于迭代器元素elements 的 size 则抛出异常。
func add(E)
public func add(element: E): Unit
功能:阻塞的入队操作,将元素添加到队列尾部。如果队列已满,则阻塞等待。
参数:
- element: E - 要添加的元素。
示例:
import std.collection.concurrent.*
main() {
var blockArr: LinkedBlockingQueue<Int64> = LinkedBlockingQueue<Int64>(2)
blockArr.add(10)
println(blockArr.peek())
}
运行结果:
Some(10)
func add(E, Duration)
public func add(element: E, timeout: Duration): Bool
功能:阻塞的入队操作,将元素添加到队列尾部,如果队列满了,将等待指定的时间。如果 timeout 为负,则会立即执行入队操作并且返回操作结果。
参数:
- element: E - 要添加的元素。
- timeout: Duration - 等待时间。
返回值:
- Bool - 成功添加元素返回 true。超出等待时间还未成功添加元素返回 false。
示例:
import std.collection.concurrent.*
import std.sync.*
import std.time.*
main() {
let blockArr: LinkedBlockingQueue<Int64> = LinkedBlockingQueue<Int64>(2)
/* 创建新线程,填满阻塞队列,休眠 1 秒后移除阻塞队列队首元素 */
spawn {
=>
blockArr.add(0)
blockArr.add(1)
sleep(1000 * Duration.millisecond)
println("New thread moves out of blocked queue head element.")
blockArr.remove()
}
/* 主线程立即让出执行权,唤醒后阻塞的添加 */
sleep(-1 * Duration.millisecond)
println("The main thread is woken up.")
let isSuccess: Bool = blockArr.add(2, 2000 * Duration.millisecond)
println(isSuccess)
}
运行结果:
The main thread is woken up.
New thread moves out of blocked queue head element.
true
func dequeue() (deprecated)
public func dequeue(): E
功能:阻塞的出队操作,获得队首元素并删除。
注意:
未来版本即将废弃,使用 remove() 替代。
返回值:
- E - 返回队首元素。
func dequeue(Duration) (deprecated)
public func dequeue(timeout: Duration): Option<E>
功能:阻塞的出队操作,获得队首元素并删除。如果队列为空,将等待指定的时间。如果 timeout 为负,则会立即执行出队操作并且返回操作结果。
注意:
未来版本即将废弃,使用 remove(Duration) 替代。
参数:
- timeout: Duration - 等待时间。
返回值:
- Option<E> - 返回队首元素。如果超出等待时间还未成功获取队首元素,则返回 None。
func enqueue(E) (deprecated)
public func enqueue(element: E): Unit
功能:阻塞的入队操作,将元素添加到队列尾部。
注意:
未来版本即将废弃,使用 add(E) 替代。
参数:
- element: E - 要添加的元素。
func enqueue(E, Duration) (deprecated)
public func enqueue(element: E, timeout: Duration): Bool
功能:阻塞的入队操作,将元素添加到队列尾部,如果队列满了,将等待指定的时间。如果 timeout 为负,则会立即执行入队操作并且返回操作结果。
注意:
未来版本即将废弃,使用 add(E, Duration) 替代。
参数:
- element: E - 要添加的元素。
- timeout: Duration - 等待时间。
返回值:
- Bool - 成功添加元素返回 true。超出等待时间还未成功添加元素返回 false。
func head() (deprecated)
public func head(): Option<E>
功能:获取队首元素。
注意:
- 该函数是非阻塞的。
- 未来版本即将废弃,使用 peek() 替代。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
func peek()
public func peek(): Option<E>
功能:获取队首元素。
注意:
该函数是非阻塞的。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
示例:
import std.collection.concurrent.*
main() {
let blockArr: LinkedBlockingQueue<Int64> = LinkedBlockingQueue<Int64>(2)
blockArr.add(2)
blockArr.add(3)
println(blockArr.peek())
}
运行结果:
Some(2)
func remove()
public func remove(): E
功能:阻塞的出队操作,获得队首元素并删除。
返回值:
- E - 返回队首元素。
示例:
import std.collection.concurrent.*
main() {
let blockArr: LinkedBlockingQueue<Int64> = LinkedBlockingQueue<Int64>(2)
blockArr.add(2)
blockArr.add(3)
println(blockArr.remove())
println(blockArr.size)
}
运行结果:
2
1
func remove(Duration)
public func remove(timeout: Duration): Option<E>
功能:阻塞的出队操作,获得队首元素并删除。如果队列为空,将等待指定的时间。如果 timeout 为负,则会立即执行出队操作并且返回操作结果。
参数:
- timeout: Duration - 等待时间。
返回值:
- Option<E> - 返回队首元素。如果超出等待时间还未成功获取队首元素,则返回 None。
示例:
import std.collection.concurrent.*
import std.sync.*
import std.time.*
main() {
let blockArr: LinkedBlockingQueue<Int64> = LinkedBlockingQueue<Int64>(2)
/* 创建新线程,休眠 1 秒后向队列添加元素 */
spawn {
=>
sleep(1000 * Duration.millisecond)
println("This new thread adds new elements to the queue.")
blockArr.add(3)
}
/* 主线程立即让出执行权,唤醒后阻塞的取出队首元素 */
sleep(-1 * Duration.millisecond)
println("The main thread is woken up.")
let num: Option<Int64> = blockArr.remove(2000 * Duration.millisecond)
println(num)
}
运行结果:
The main thread is woken up.
This new thread adds new elements to the queue.
Some(3)
func tryAdd(E)
public func tryAdd(element: E): Bool
功能:非阻塞的入队操作,将元素添加到队列尾部。
参数:
- element: E - 要添加的元素。
返回值:
- Bool - 成功添加返回 true;如果队列满了,添加失败返回 false。
示例:
import std.collection.concurrent.*
main() {
let blockArr: LinkedBlockingQueue<Int64> = LinkedBlockingQueue<Int64>(2)
blockArr.tryAdd(2)
blockArr.tryAdd(3)
println(blockArr.size)
}
运行结果:
2
func tryDequeue() (deprecated)
public func tryDequeue(): Option<E>
功能:非阻塞的出队操作,获得队首元素并删除。
注意:
未来版本即将废弃,使用 tryRemove() 替代。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
func tryEnqueue(E) (deprecated)
public func tryEnqueue(element: E): Bool
功能:非阻塞的入队操作,将元素添加到队列尾部。
注意:
未来版本即将废弃,使用 tryAdd(E) 替代。
参数:
- element: E - 要添加的元素。
返回值:
- Bool - 成功添加返回 true;如果队列满了,添加失败返回 false。
func tryRemove()
public func tryRemove(): Option<E>
功能:非阻塞的出队操作,获得队首元素并删除。
返回值:
- Option<E> - 返回队首元素,队列为空时返回 None。
示例:
import std.collection.concurrent.*
main() {
let blockArr: LinkedBlockingQueue<Int64> = LinkedBlockingQueue<Int64>(2)
blockArr.tryAdd(3)
println(blockArr.tryRemove())
println(blockArr.tryRemove())
}
运行结果:
Some(3)
None
ConcurrentHashMap 使用示例
示例:
import std.collection.*
import std.collection.concurrent.*
import std.sync.*
main() {
let threads = 8
let M = 1024
let cmap = ConcurrentHashMap<Int64, Int64>(concurrencyLevel: 64)
let jobs = Array<Future<Unit>>(threads, repeat: unsafe { zeroValue<Future<Unit>>() })
for (t in 0..threads) {
jobs[t] = spawn {
for (i in t..M : threads) {
cmap.put(i, i + 3)
}
}
}
for (t in 0..threads) {
jobs[t].get()
}
println("Size after put: ${cmap.size}")
for (t in 0..threads) {
jobs[t] = spawn {
for (i in t..M : threads) {
cmap.remove(i, {v => v % 2 == 0})
}
}
}
for (t in 0..threads) {
jobs[t].get()
}
println("Size after remove first: ${cmap.size}")
for (t in 0..threads) {
jobs[t] = spawn {
for (i in t..M : threads) {
cmap.remove(i)
}
}
}
for (t in 0..threads) {
jobs[t].get()
}
println("Size after remove second: ${cmap.size}")
}
运行结果:
Size after put: 1024
Size after remove first: 512
Size after remove second: 0
ConcurrentLinkedQueue 使用示例
示例:
import std.collection.*
import std.collection.concurrent.*
import std.sync.*
main() {
let threads = 8
let total: Int64 = 128
let bq = ConcurrentLinkedQueue<Int64>(Array<Int64>(total, {i => i}))
println("Total ${bq.size} after init")
let jobs = Array<Future<Unit>>(threads, repeat: unsafe { zeroValue<Future<Unit>>() })
for (t in 0..threads) {
jobs[t] = spawn {
for (i in t..total : threads) {
bq.dequeue()
}
}
}
for (t in 0..threads) {
jobs[t].get()
}
println("Total ${bq.size} after dequeue")
}
运行结果:
Total 128 after init
Total 0 after dequeue
std.console(deprecated)
注意:
未来版本即将废弃不再使用,可使用 env 包替代。
功能介绍
console 包提供和标准输入、标准输出、标准错误进行交互的方法。
本包提供 Console 类,用于获取这三个标准流。
- ConsoleReader 封装了标准输入流的相关功能,可以通过相关的
read方法从标准输入中读取数据。 - ConsoleWriter 封装了标准输出、标准错误流的相关功能,ConsoleWriter 封装了一系列的
write方法,提供了向标准输出、标准错误写入数据的能力。
标准输入(stdin)、标准输出(stdout)和标准错误(stderr)是计算机操作系统中常见的三个流。
标准输入是程序从用户获取输入数据的流,通常是键盘输入。标准输出是程序向用户输出结果的流,通常是屏幕输出。标准错误是程序在发生错误时输出错误信息的流,通常也是屏幕输出。
在 Unix/Linux 系统中,标准输入、标准输出和标准错误分别对应文件描述符 0、1 和 2。程序可以使用这些文件描述符来读取和写入数据。例如,可以使用重定向符号将标准输出重定向到文件中,或将标准错误输出重定向到另一个程序的标准输入中。
API 列表
类
| 类名 | 功能 |
|---|---|
| Console | 提供标准输入、标准输出和标准错误 Stream 的获取接口。 |
| ConsoleReader | 提供从标准输入读取字符或者字符串的功能。 |
| ConsoleWriter | 提供向标准输出或者标准错误流写入字符或者字符串的功能。 |
类
class Console (deprecated)
public class Console
功能:此类提供标准输入、标准输出和标准错误流的获取接口。
注意:
未来版本即将废弃,使用 env 包中相应函数替代。
static prop stdErr
public static prop stdErr: ConsoleWriter
功能:该成员属性为 ConsoleWriter 类型,它提供标准错误的获取功能。
static prop stdIn
public static prop stdIn: ConsoleReader
功能:该成员属性为 ConsoleReader 类型,它提供标准输入的获取功能。
static prop stdOut
public static prop stdOut: ConsoleWriter
功能:该成员属性为 ConsoleWriter 类型,它提供标准输出的获取功能。
class ConsoleReader (deprecated)
public class ConsoleReader <: InputStream
功能:提供从控制台读出数据并转换成字符或字符串的功能。
该类型无法构造实例,只能通过 Console.stdIn 获取实例。
读操作是同步的,内部设有缓存区来保存控制台输入的内容,当到达控制台输入流的结尾时,控制台读取函数将返回None。
ConsoleReader 只有一个实例,所有方法共享同一个缓存区,相关read方法返回None的情形有:
- 将标准输入重定向到文件时,读取到文件结尾EOF。
- Linux 环境,按下
Ctrl+D。 - Windows 环境,按下
Ctrl+Z后加回车。
注意:
未来版本即将废弃,使用 ConsoleReader 替代。
父类型:
func read()
public func read(): ?Rune
功能:从标准输入中读取下一个字符。
返回值:
异常:
- IllegalArgumentException:当输入不符合
UTF-8编码的字符串时,抛此异常。
func read(Array<Byte>)
public func read(arr: Array<Byte>): Int64
功能:从标准输入中读取并放入 arr 中。
注意:
该函数存在风险,可能读取出来的结果恰好把
UTF-8 code point从中截断,如果发生截断,将导致该 Array<Byte> 转换成字符串的结果不正确或抛出异常。
参数:
返回值:
- Int64 - 返回读取到的字节长度。
func readToEnd()
public func readToEnd(): ?String
功能:从标准输入中读取所有字符。
直到读取到文件结束符 EOF,或者在 Linux 上键入 Ctrl+D 或在 Windows 上键入 Ctrl+Z + 回车结束。读取到字符,返回 ?String,否则返回 None。读取失败时会返回 None,该接口不会抛出异常,即使输入不符合 UTF-8 编码的字符串,也会构造出一个 String 并返回,其行为等同于 String.fromUtf8Uncheck(Array<Byte>)。
返回值:
func readUntil((Rune) -> Bool)
public func readUntil(predicate: (Rune) -> Bool): ?String
功能:从标准输入中读取数据直到读取到的字符满足predicate条件结束。
满足 predicate: (Rune) -> Bool 条件的字符包含在结果中,读取失败时会返回None。
参数:
- predicate: (Rune) ->Bool - 终止读取的条件。
返回值:
func readUntil(Rune)
public func readUntil(ch: Rune): ?String
功能:从标准输入中读取数据直到读取到字符 ch 结束。
ch包含在结果中,如果读取到文件结束符 EOF,将返回读取到的所有信息,读取失败时会返回 None。
参数:
- ch: Rune - 终止字符。
返回值:
func readln()
public func readln(): ?String
功能:从标准输入中读取一行字符串。
读取到字符,返回 ?String,结果不包含末尾换行符。该接口不会抛出异常,即使输入不符合UTF-8编码的字符串,也会构造出一个 String 并返回,其行为等同于 String.fromUtf8Uncheck(Array<Byte>)。
返回值:
- ?String - 读取到的行数据,读取失败返回
None。
class ConsoleWriter (deprecated)
public class ConsoleWriter <: OutputStream
功能:此类提供保证线程安全的标准输出功能。
每次 write 调用写到控制台的结果是完整的,不同的 write 函数调用的结果不会混合到一起。 该类型无法构造实例,只能通过 Console.stdOut 获取标准输出实例或者 Console.stdErr 获取标准错误的实例。
注意:
未来版本即将废弃,使用 ConsoleWriter 替代。
父类型:
func flush()
public func flush(): Unit
功能:刷新输出流。
func write(Array<Byte>)
public func write(buffer: Array<Byte>): Unit
功能:指定的将字节数组 buffer 写入标准输出或标准错误流中。
参数:
func write(Bool)
public func write(v: Bool): Unit
功能:将指定的布尔值的文本表示形式写入标准输出或标准错误流中。
参数:
- v: Bool - 要写入的值。
func write(Float16)
public func write(v: Float16): Unit
功能:将指定的 16 位浮点数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Float16 - 要写入的值。
func write(Float32)
public func write(v: Float32): Unit
功能:将指定的 32 位浮点数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Float32 - 要写入的值。
func write(Float64)
public func write(v: Float64): Unit
功能:将指定的 64 位浮点数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Float64 - 要写入的值。
func write(Int16)
public func write(v: Int16): Unit
功能:将指定的 16 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int16 - 要写入的值。
func write(Int32)
public func write(v: Int32): Unit
功能:将指定的 32 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int32 - 要写入的值。
func write(Int64)
public func write(v: Int64): Unit
功能:将指定的 64 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int64 - 要写入的值。
func write(Int8)
public func write(v: Int8): Unit
功能:将指定的 8 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int8 - 要写入的值。
func write(Rune)
public func write(v: Rune): Unit
功能:将指定的 Rune 的 Unicode 字符值写入标准输出或标准错误流中。
参数:
- v: Rune - 要写入的值。
func write(String)
public func write(v: String): Unit
功能:将指定的字符串值写入标准输出或标准错误流中。
参数:
- v: String - 要写入的值。
func write(UInt16)
public func write(v: UInt16): Unit
功能:将指定的 16 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt16 - 要写入的值。
func write(UInt32)
public func write(v: UInt32): Unit
功能:将指定的 32 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt32 - 要写入的值。
func write(UInt64)
public func write(v: UInt64): Unit
功能:将指定的 64 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt64 - 要写入的值。
func write(UInt8)
public func write(v: UInt8): Unit
功能:将指定的 8 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt8 - 要写入的值。
func write<T>(T) where T <: ToString
public func write<T>(v: T): Unit where T <: ToString
功能:将实现了 ToString 接口的数据类型写入标准输出或标准错误流中。
参数:
- v: T - 要被写入的 ToString 类型的实例。
func writeln(Array<Byte>)
public func writeln(buffer: Array<Byte>): Unit
功能:指定的将字节数组 buffer (后跟换行符)写入标准输出或标准错误流中。
参数:
func writeln(Bool)
public func writeln(v: Bool): Unit
功能:将指定的布尔值的文本表示形式(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Bool - 要写入的值。
func writeln(Float16)
public func writeln(v: Float16): Unit
功能:将指定的 16 位浮点数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Float16 - 要写入的值。
func writeln(Float32)
public func writeln(v: Float32): Unit
功能:将指定的 32 位浮点数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Float32 - 要写入的值。
func writeln(Float64)
public func writeln(v: Float64): Unit
功能:将指定的 64 位浮点数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Float64 - 要写入的值。
func writeln(Int16)
public func writeln(v: Int16): Unit
功能:将指定的 16 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int16 - 要写入的值。
func writeln(Int32)
public func writeln(v: Int32): Unit
功能:将指定的 32 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int32 - 要写入的值。
func writeln(Int64)
public func writeln(v: Int64): Unit
功能:将指定的 64 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int64 - 要写入的值。
func writeln(Int8)
public func writeln(v: Int8): Unit
功能:将指定的 8 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int8 - 要写入的值。
func writeln(Rune)
public func writeln(v: Rune): Unit
功能:将指定的 Unicode 字符值(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Rune - 要写入的值。
func writeln(String)
public func writeln(v: String): Unit
功能:将指定的字符串值(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: String - 要写入的值。
func writeln(UInt16)
public func writeln(v: UInt16): Unit
功能:将指定的 16 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: UInt16 - 要写入的值。
func writeln(UInt32)
public func writeln(v: UInt32): Unit
功能:将指定的 32 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。 参数:
- v: UInt32 - 要写入的值。
func writeln(UInt64)
public func writeln(v: UInt64): Unit
功能:将指定的 64 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: UInt64 - 要写入的值。
func writeln(UInt8)
public func writeln(v: UInt8): Unit
功能:将指定的 8 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: UInt8 - 要写入的值。
func writeln<T>(T) where T <: ToString
public func writeln<T>(v: T): Unit where T <: ToString
功能:将实现了 ToString 接口的数据类型转换成的字符串(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: T - 要写入的值。
Console 示例
下面是 Console 示例,示例中接收用户输入的两条信息,并将这些信息通过标准输出原样返回给用户。
示例:
import std.console.*
main() {
Console.stdOut.write("请输入信息1:")
var c = Console.stdIn.readln() // 输入:你好,请问今天星期几?
var r = c.getOrThrow()
Console.stdOut.writeln("输入的信息1为:" + r)
Console.stdOut.write("请输入信息2:")
c = Console.stdIn.readln() // 输入:你好,请问今天几号?
r = c.getOrThrow()
Console.stdOut.writeln("输入的信息2为:" + r)
return
}
运行结果:
请输入信息1:你好,请问今天星期几?
输入的信息1为:你好,请问今天星期几?
请输入信息2:你好,请问今天几号?
输入的信息2为:你好,请问今天几号?
std.convert
功能介绍
convert 包提供从字符串转到特定类型的 Convert 系列函数。
例如字符串 "true" 到布尔类型 true 的转换以及字符串 "123" 到整数类型 123 的转换等。
convert 包提供格式化能力,主要为将仓颉类型实例转换为格式化字符串。
定义了接口 Formattable,用于规定统一的格式化方法,并为 Int8、Int16 等一系列仓颉类型实现了该接口,用户也可以自行为其他类型实现该接口以获取格式化功能。
将仓颉类型转换为字符串时,可根据格式化参数规定字符串格式,如宽度、对齐方式等。(在 Formattable 接口定义的方法中,格式化参数将作为函数入参。)
格式化参数的详细语法说明如下:
format_spec := [flags][width][.precision][specifier]
flags := '-' | '+' | '#' | '0'
width := integer
precision := integer
specifier := 'b' | 'B' | 'o' | 'O' | 'x' | 'X' | 'e' | 'E' | 'g' | 'G'
参数 flags:
-
'-' 适用于 Int,UInt,Rune 和 Float,表示左对齐。
代码如下:
import std.convert.* main() { var c : Int32 = -20 print("\"${c.format("-10")}\"") }运行结果:
"-20 " -
'+' 适用于 Int,UInt 和 Float,如果数值为正数则打出 '+' 符号,如果数值为负数则忽略。
代码如下:
import std.convert.* main() { var c: Int32 = 20 print("\"${c.format("+10")}\"") }运行结果:
" +20" -
'#' 是针对进制打印的,对于二进制打印会补充一个 '0b' 或者 '0B',对于八进制打印会补充一个 '0o' 或者 '0O',对于十六进制会补充 '0x' 或者 '0X'。
代码如下:
import std.convert.* main() { var c: Int32 = 1 print("\"${c.format("#10x")}\"") }运行结果:
" 0x1" -
'0' 适用于 Int,UInt 和 Float,在空位补充 0。
代码如下:
import std.convert.* main() { var c: Int32 = -20 print("\"${c.format("010")}\"") }运行结果:
"-000000020"
参数 width 宽度:
-
宽度为正整数,适用于 Int,UInt,Rune 和 Float,宽度前有负号则表示左对齐,没有负号则是右对齐,如果数值小于数值本身的长度,不会发生截断。 如果前缀有
+或-符号会占用一个字符位,如果前缀有0x或0o等会占用两个字符位。代码如下:
import std.convert.* main() { var c: Int32 = 20 println("\"${c.format("1")}\"") println("\"${c.format("+4")}\"") }运行结果:
"20" " +20"
参数 precision 精度:
-
精度为正整数,适用于 Int,UInt 和 Float。 对于浮点数表示小数点后的有效数字位数,如果不指定,那么则打印六位小数,如果小于数值本身有效数字的长度,那就四舍五入,如果大于就补全,补全的不一定是 0。
-
对于整数类型,不指定或者指定的数字小于数值本身的长度,则无效果,如果大于数值本身的长度,则在前面补全'0'。
代码如下:
import std.convert.* main() { var e: Float32 = 1234.1 println("\"${e.format("20.20")}\"") var c: Int32 = -20 println("\"${c.format("10.8")}\"") }运行结果:
"1234.09997558593750000000" " -00000020"
参数 specifier:
-
'b' | 'B' | 'o' | 'O' | 'x' | 'X' 适用于 Int 和 UInt 类型。
'b' | 'B' : 表示二进制格式打印
'o' | 'O' : 表示八进制格式打印
'x' | 'X' : 表示十六进制格式打印
代码如下:
import std.convert.* main() { var a = 20 println("\"${a.format("b")}\"") println("\"${a.format("o")}\"") println("\"${a.format("x")}\"") println("\"${a.format("X")}\"") println("\"${a.format("#X")}\"") }运行结果:
"10100" "24" "14" "14" "0X14" -
'e' | 'E' | 'g' | 'G' 适用于 Float 类型。
'e' | 'E' : 科学计数法,小写和大写
'g' | 'G' : general,用十进制或者科学计数法表示,会选择精简的表示方式进行打印
代码如下:
import std.convert.* main() { var f: Float32 = 1234.1 var c: Float32 = 123412341234.1 println("\"${f.format("20.2e")}\"") println("\"${f.format("20G")}\"") println("\"${c.format("20G")}\"") println("\"${f.format("20")}\"") println("\"${c.format("20")}\"") }运行结果:
" 1.23e+03" " 1234.1" " 1.23412E+11" " 1234.099976" " 123412340736.000000"
API 列表
接口
| 接口名 | 功能 |
|---|---|
| Formattable | 该接口定义了格式化函数,即根据格式化参数将指定类型实例转换为对应格式的字符串。 |
| Parsable<T> | 将字符串解析为特定类型的接口。 |
| RadixConvertible<T> | 将指定字符串解析为特定类型的接口。 |
接口
interface Formattable
public interface Formattable {
func format(fmt: String): String
}
功能:该接口定义了格式化函数,即根据格式化参数将指定类型实例转换为对应格式的字符串。
格式化参数相关的说明请参见 convert 包中的功能介绍。
其他类型可通过实现该接口提供格式化功能。
func format(String)
func format(fmt: String): String
功能:根据格式化参数将当前实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
- String - 将当前实例格式化后得到的字符串。
extend Float16 <: Formattable
extend Float16 <: Formattable
功能:为 Float16 扩展 Formattable 接口,以实现将 Float16 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Float16 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Float32 <: Formattable
extend Float32 <: Formattable
功能:为 Float32 扩展 Formattable 接口,以实现将 Float32 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Float32 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Float64 <: Formattable
extend Float64 <: Formattable
功能:为 Float64 扩展 Formattable 接口,以实现将 Float64 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Float64 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Int16 <: Formattable
extend Int16 <: Formattable
功能:为 Int16 扩展 Formattable 接口,以实现将 Int16 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Int16 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Int32 <: Formattable
extend Int32 <: Formattable
功能:为 Int32 扩展 Formattable 接口,以实现将 Int32 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Int32 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Int64 <: Formattable
extend Int64 <: Formattable
功能:为 Int64 扩展 Formattable 接口,以实现将 Int64 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Int64 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Int8 <: Formattable
extend Int8 <: Formattable
功能:为 Int8 扩展 Formattable 接口,以实现将 Int8 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Int8 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Rune <: Formattable
extend Rune <: Formattable
功能:为 Rune 扩展 Formattable 接口,以实现将 Rune 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Rune 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend UInt16 <: Formattable
extend UInt16 <: Formattable
功能:为 UInt16 扩展 Formattable 接口,以实现将 UInt16 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 UInt16 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend UInt32 <: Formattable
extend UInt32 <: Formattable
功能:为 UInt32 扩展 Formattable 接口,以实现将 UInt32 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 UInt32 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend UInt64 <: Formattable
extend UInt64 <: Formattable
功能:为 UInt64 扩展 Formattable 接口,以实现将 UInt64 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 UInt64 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend UInt8 <: Formattable
extend UInt8 <: Formattable
功能:为 UInt8 扩展 Formattable 接口,以实现将 UInt8 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 UInt8 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
interface Parsable<T>
public interface Parsable<T> {
static func parse(value: String): T
static func tryParse(value: String): Option<T>
}
功能:本接口提供了统一的方法,以支持将字符串解析为特定类型。
本接口提供了 parse 和 tryParse 两套方法,parse 方法将在解析失败时抛出异常,tryParse 方法将返回值用 Option 包裹,解析失败时将返回 None。 本包内已经为 Bool,Rune,Float16,Int64 等基础类型实现该接口,可用于将字符串转换为这些类型。
static func parse(String)
static func parse(value: String): T
功能:从字符串中解析特定类型。
参数:
- value: String - 待解析的字符串。
返回值:
- T - 转换后的值。
static func tryParse(String)
static func tryParse(value: String): Option<T>
功能:从字符串中解析特定类型。
参数:
- value: String - 待解析的字符串。
返回值:
extend Bool <: Parsable<Bool>
extend Bool <: Parsable<Bool>
功能:此扩展主要用于实现将 Bool 类型字面量的字符串转换为 Bool 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Bool
功能:将 Bool 类型字面量的字符串转换为 Bool 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空或转换失败时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Bool>
功能:将 Bool 类型字面量的字符串转换为 Option<Bool> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Float16 <: Parsable<Float16>
extend Float16 <: Parsable<Float16>
功能:此扩展主要用于实现将 Float16 类型字面量的字符串转换为 Float16 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Float16
功能:将 Float16 类型字面量的字符串转换为 Float16 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串不符合浮点数语法时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Float16>
功能:将 Float16 类型字面量的字符串转换为 Option<Float16> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Float32 <: Parsable<Float32>
extend Float32 <: Parsable<Float32>
功能:此扩展主要用于实现将 Float32 类型字面量的字符串转换为 Float32 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Float32
功能:将 Float32 类型字面量的字符串转换为 Float32 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串不符合浮点数语法时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Float32>
功能:将 Float32 类型字面量的字符串转换为 Option<Float32> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Float64 <: Parsable<Float64>
extend Float64 <: Parsable<Float64>
功能:此扩展主要用于实现将 Float64 类型字面量的字符串转换为 Float64 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Float64
功能:将 Float64 类型字面量的字符串转换为 Float64 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串不符合浮点数语法时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Float64>
功能:将 Float64 类型字面量的字符串转换为 Option<Float64> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Int16 <: Parsable<Int16>
extend Int16 <: Parsable<Int16>
功能:此扩展主要用于实现将 Int16 类型字面量的字符串转换为 Int16 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Int16
功能:将 Int16 类型字面量的字符串转换为 Int16 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+,转换失败,或转换后超出 Int16 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Int16>
功能:将 Int16 类型字面量的字符串转换为 Option<Int16> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Int32 <: Parsable<Int32>
extend Int32 <: Parsable<Int32>
功能:此扩展主要用于实现将 Int32 类型字面量的字符串转换为 Int32 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Int32
功能:将 Int32 类型字面量的字符串转换为 Int32 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+,转换失败,或转换后超出 Int32 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Int32>
功能:将 Int32 类型字面量的字符串转换为 Option<Int32> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Int64 <: Parsable<Int64>
extend Int64 <: Parsable<Int64>
功能:此扩展主要用于实现将 Int64 类型字面量的字符串转换为 Int64 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Int64
功能:将 Int64 类型字面量的字符串转换为 Int64 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+,转换失败,或转换后超出 Int64 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Int64>
功能:将 Int64 类型字面量的字符串转换为 Option<Int64> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Int8 <: Parsable<Int8>
extend Int8 <: Parsable<Int8>
功能:此扩展主要用于实现将 Int8 类型字面量的字符串转换为 Int8 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Int8
功能:将 Int8 类型字面量的字符串转换为 Int8 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+,转换失败,或转换后超出 Int8 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Int8>
功能:将 Int8 类型字面量的字符串转换为 Option<Int8> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend Rune <: Parsable<Rune>
extend Rune <: Parsable<Rune>
功能:此扩展主要用于实现将 Rune 类型字面量的字符串转换为 Rune 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): Rune
功能:将 Rune 类型字面量的字符串转换为 Rune 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,或转换失败时,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<Rune>
功能:将 Rune 类型字面量的字符串转换为 Option<Rune> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend UInt16 <: Parsable<UInt16>
extend UInt16 <: Parsable<UInt16>
功能:此扩展主要用于实现将 UInt16 类型字面量的字符串转换为 UInt16 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): UInt16
功能:将 UInt16 类型字面量的字符串转换为 UInt16 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+或-,转换失败,或转换后超出 UInt16 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<UInt16>
功能:将 UInt16 类型字面量的字符串转换为 Option<UInt16> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend UInt32 <: Parsable<UInt32>
extend UInt32 <: Parsable<UInt32>
功能:此扩展主要用于实现将 UInt32 类型字面量的字符串转换为 UInt32 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): UInt32
功能:将 UInt32 类型字面量的字符串转换为 UInt32 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+或-,转换失败,或转换后超出 UInt32 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<UInt32>
功能:将 UInt32 类型字面量的字符串转换为 Option<UInt32> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend UInt64 <: Parsable<UInt64>
extend UInt64 <: Parsable<UInt64>
功能:此扩展主要用于实现将 UInt64 类型字面量的字符串转换为 UInt64 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): UInt64
功能:将 UInt64 类型字面量的字符串转换为 UInt64 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+或-,转换失败,或转换后超出 UInt64 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<UInt64>
功能:将 UInt64 类型字面量的字符串转换为 Option<UInt64> 值。
参数:
- data: String - 要转换的字符串。
返回值:
extend UInt8 <: Parsable<UInt8>
extend UInt8 <: Parsable<UInt8>
功能:此扩展主要用于实现将 UInt8 类型字面量的字符串转换为 UInt8 值的相关操作函数。
父类型:
static func parse(String)
public static func parse(data: String): UInt8
功能:将 UInt8 类型字面量的字符串转换为 UInt8 值。
参数:
- data: String - 要转换的字符串。
返回值:
异常:
- IllegalArgumentException - 当字符串为空,首位为
+或-,转换失败,或转换后超出 UInt8 范围,或字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String)
public static func tryParse(data: String): Option<UInt8>
功能:将 UInt8 类型字面量的字符串转换为 Option<UInt8> 值。
参数:
- data: String - 要转换的字符串。
返回值:
interface RadixConvertible<T>
public interface RadixConvertible<T> {
static func parse(value: String, radix!: Int): T
static func tryParse(value: String, radix!: Int): Option<T>
func toString(radix!: Int): String
}
功能:本接口提供了统一的方法,以支持将指定进制的字符串解析为特定类型。
进制将以参数指定,不按字符串前缀指定,进制表示范围必须在 2-36 之间,否则会抛异常,超过十进制的表示按大或者小写英文字母序表示,即 10 个数字 + 26 个英文字母 = 36 进制,Int 系列的字符串可以以 +、- 开头,如果不以这两个符号开头则处理成 +,UInt 系列的字符串可以以 + 开头,如果以 - 开头会抛出异常。返回指定进制形式字符串,超过十进制的表示按小写英文字母序表示,即 10 个数字 + 26 个小写英文字母 = 36 进制。
本接口提供了 parse 和 tryParse 两套方法,parse 方法将在解析失败时抛出异常,tryParse 方法将返回值用 Option 包裹,解析失败时将返回 None。 本包内已经为Int64,UInt64 等基础类型实现该接口,可用于将字符串转换为这些类型。
static func parse(String, Int)
static func parse(value: String, radix!: Int): T
功能:从指定进制字符串中解析特定类型。
参数:
返回值:
- T - 转换后的值。
static func tryParse(String, Int)
static func tryParse(value: String, radix!: Int): Option<T>
功能:从指定进制字符串中解析特定类型。
参数:
返回值:
func toString(Int)
func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
extend Int8 <: RadixConvertible<Int8>
extend Int8 <: RadixConvertible<Int8>
功能:此扩展主要用于实现将 Int8 类型字面量的字符串转换为 Int8 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): Int8
功能:将 Int8 类型字面量的字符串转换为 Int8 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空,进制超出范围,转换后超出 Int8 范围或字符串中含有无效的 UTF-8 字符,转换失败时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<Int8>
功能:将 Int8 类型字面量的字符串转换为 Option<Int8> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
extend Int16 <: RadixConvertible<Int16>
extend Int16 <: RadixConvertible<Int16>
功能:此扩展主要用于实现将 Int16 类型字面量的字符串转换为 Int16 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): Int16
功能:将 Int16 类型字面量的字符串转换为 Int16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空、进制超出范围、转换后超出 Int16 范围、字符串中含有无效的 UTF-8 字符、转换失败时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<Int16>
功能:将 Int16 类型字面量的字符串转换为 Option<Int16> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
extend Int32 <: RadixConvertible<Int32>
extend Int32 <: RadixConvertible<Int32>
功能:此扩展主要用于实现将 Int32 类型字面量的字符串转换为 Int32 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): Int32
功能:将 Int32 类型字面量的字符串转换为 Int32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空、进制超出范围、转换后超出 Int32 范围、字符串中含有无效的 UTF-8 字符、转换失败时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<Int32>
功能:将 Int32 类型字面量的字符串转换为 Option<Int32> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
extend Int64 <: RadixConvertible<Int64>
extend Int64 <: RadixConvertible<Int64>
功能:此扩展主要用于实现将 Int64 类型字面量的字符串转换为 Int64 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): Int64
功能:将 Int64 类型字面量的字符串转换为 Int64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空、进制超出范围、转换后超出 Int64 范围、字符串中含有无效的 UTF-8 字符、转换失败时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<Int64>
功能:将 Int64 类型字面量的字符串转换为 Option<Int64> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
extend UInt8 <: RadixConvertible<UInt8>
extend UInt8 <: RadixConvertible<UInt8>
功能:此扩展主要用于实现将 UInt8 类型字面量的字符串转换为 UInt8 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): UInt8
功能:将 UInt8 类型字面量的字符串转换为 UInt8 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空、进制超出范围、首位为
-、转换后超出 UInt8 范围、字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<UInt8>
功能:将 UInt8 类型字面量的字符串转换为 Option<UInt8> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
extend UInt16 <: RadixConvertible<UInt16>
extend UInt16 <: RadixConvertible<UInt16>
功能:此扩展主要用于实现将 UInt16 类型字面量的字符串转换为 UInt16 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): UInt16
功能:将 UInt16 类型字面量的字符串转换为 UInt16 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空、进制超出范围、首位为
-、转换后超出 UInt16 范围、字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<UInt16>
功能:将 UInt16 类型字面量的字符串转换为 Option<UInt16> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
extend UInt32 <: RadixConvertible<UInt32>
extend UInt32 <: RadixConvertible<UInt32>
功能:此扩展主要用于实现将 UInt32 类型字面量的字符串转换为 UInt32 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): UInt32
功能:将 UInt32 类型字面量的字符串转换为 UInt32 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空、进制超出范围、首位为
-、转换后超出 UInt32 范围、字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<UInt32>
功能:将 UInt32 类型字面量的字符串转换为 Option<UInt32> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
extend UInt64 <: RadixConvertible<UInt64>
extend UInt64 <: RadixConvertible<UInt64>
功能:此扩展主要用于实现将 UInt64 类型字面量的字符串转换为 UInt64 值的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): UInt64
功能:将 UInt64 类型字面量的字符串转换为 UInt64 值。
参数:
返回值:
异常:
- IllegalArgumentException - 当字符串为空、进制超出范围、首位为
-、转换后超出 UInt64 范围、字符串中含有无效的 UTF-8 字符时,抛出异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): Option<UInt64>
功能:将 UInt64 类型字面量的字符串转换为 Option<UInt64> 值。
参数:
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:返回指定进制形式字符串。
参数:
- radix!: Int - 指定的进制。
返回值:
- String - 指定进制形式字符串。
异常:
- IllegalArgumentException - 当进制不合规时,抛出异常。
convert 包使用示例
format 使用示例
格式化整型
下面是格式化整型示例。
示例:
import std.convert.*
main(): Int64 {
var a: Int32 = -20
var res1 = a.format("-10")
var res2 = a.format("+10")
var res3 = (-20).format("10")
var res4 = a.format("-")
println("\"${res1}\"")
println("\"${res2}\"")
println("\"${res3}\"")
println("\"${res4}\"")
return 0
}
运行结果:
"-20 "
" -20"
" -20"
"-20"
格式化浮点型
下面是格式化浮点型示例。
示例:
import std.convert.*
main(): Int64 {
var a: Float16 = -0.34
var b: Float32 = .34
var c: Float64 = 3_0.3__4_
var d: Float64 = 20.00
/* 左对齐 */
var res1 = a.format("-20")
/* 右对齐 */
var res2 = b.format("+20")
/* 右对齐 */
var res3 = c.format("10")
/* 左对齐 */
var res4 = d.format("-10")
/* 正常输出 */
var res5 = d.format("-")
println("\"${res1}\"")
println("\"${res2}\"")
println("\"${res3}\"")
println("\"${res4}\"")
println("\"${res5}\"")
return 0
}
运行结果:
"-0.340088 "
" +0.340000"
" 30.340000"
"20.000000 "
"20.000000"
格式化字符型
下面是格式化字符型示例。
示例:
import std.convert.*
main(): Int64 {
var a: Rune = 'a'
var b: Rune = '-'
/* 左对齐 */
var res1 = a.format("-10")
/* 左对齐 */
var res2 = b.format("-10")
/* 右对齐 */
var res3 = a.format("10")
/* 右对齐 */
var res4 = b.format("10")
println("\"${res1}\"")
println("\"${res2}\"")
println("\"${res3}\"")
println("\"${res4}\"")
return 0
}
运行结果:
"a "
"- "
" a"
" -"
convert 使用示例
示例:
import std.convert.*
main(): Int64 {
var strBool_parse: String = "true"
var strBool_tryParse: String = "false"
var strChar_parse: String = "'a'"
var strChar_tryParse: String = "'\\u{00e2}'"
var strInt8_parse: String = "-128"
var strInt8_tryParse: String = "127"
var strInt16_parse: String = "-32768"
var strInt16_tryParse: String = "32767"
var strInt32_parse: String = "-2147483648"
var strInt32_tryParse: String = "2147483647"
var strInt64_parse: String = "-9223372036854775808"
var strInt64_tryParse: String = "9223372036854775807"
var strFloat16_parse: String = "-65504.0"
var strFloat16_tryParse: String = "65504.0"
var strFloat32_parse: String = "-3.14159"
var strFloat32_tryParse: String = "3.14159"
var strFloat64_parse: String = "-3.1415926"
var strFloat64_tryParse: String = "3.1415926"
var strUInt8_parse: String = "255"
var strUInt8_tryParse: String = "255"
var strUInt16_parse: String = "65535"
var strUInt16_tryParse: String = "65535"
var strUInt32_parse: String = "4294967295"
var strUInt32_tryParse: String = "4294967295"
var strUInt64_parse: String = "18446744073709551615"
var strUInt64_tryParse: String = "18446744073709551615"
println("After the conversion of parse, \"true\" became ${Bool.parse(strBool_parse)}")
println("After the conversion of tryParse, \"false\" became ${Bool.tryParse(strBool_tryParse)}")
println("After the conversion of parse, \"'a'\" became ${Rune.parse(strChar_parse)}")
println("After the conversion of tryParse, \"'\\u{00e2}'\" became ${Rune.tryParse(strChar_tryParse)}")
println("After the conversion of parse, \"-128\" became ${Int8.parse(strInt8_parse)}")
println("After the conversion of tryParse, \"127\" became ${Int8.tryParse(strInt8_tryParse)}")
println("After the conversion of parse, \"-32768\" became ${Int16.parse(strInt16_parse)}")
println("After the conversion of tryParse, \"32767\" became ${Int16.tryParse(strInt16_tryParse)}")
println("After the conversion of parse, \"-2147483648\" became ${Int32.parse(strInt32_parse)}")
println("After the conversion of tryParse, \"2147483647\" became ${Int32.tryParse(strInt32_tryParse)}")
println("After the conversion of parse, \"-9223372036854775808\" became ${Int64.parse(strInt64_parse)}")
println("After the conversion of tryParse, \"9223372036854775807\" became ${Int64.tryParse(strInt64_tryParse)}")
println("After the conversion of parse, \"-65504.0\" became ${Float16.parse(strFloat16_parse)}")
println("After the conversion of tryParse, \"65504.0\" became ${Float16.tryParse(strFloat16_tryParse)}")
println("After the conversion of parse, \"-3.14159\" became ${Float32.parse(strFloat32_parse)}")
println("After the conversion of tryParse, \"3.14159\" became ${Float32.tryParse(strFloat32_tryParse)}")
println("After the conversion of parse, \"-3.1415926\" became ${Float64.parse(strFloat64_parse)}")
println("After the conversion of tryParse, \"3.1415926\" became ${Float64.tryParse(strFloat64_tryParse)}")
println("After the conversion of parse, \"255\" became ${UInt8.parse(strUInt8_parse)}")
println("After the conversion of tryParse, \"255\" became ${UInt8.tryParse(strUInt8_tryParse)}")
println("After the conversion of parse, \"65535\" became ${UInt16.parse(strUInt16_parse)}")
println("After the conversion of tryParse, \"65535\" became ${UInt16.tryParse(strUInt16_tryParse)}")
println("After the conversion of parse, \"4294967295\" became ${UInt32.parse(strUInt32_parse)}")
println("After the conversion of tryParse, \"4294967295\" became ${UInt32.tryParse(strUInt32_tryParse)}")
println("After the conversion of parse, \"18446744073709551615\" became ${UInt64.parse(strUInt64_parse)}")
println("After the conversion of tryParse, \"18446744073709551615\" became ${UInt64.tryParse(strUInt64_tryParse)}")
return 0
}
运行结果:
After the conversion of parse, "true" became true
After the conversion of tryParse, "false" became Some(false)
After the conversion of parse, "'a'" became a
After the conversion of tryParse, "'\u{00e2}'" became Some(â)
After the conversion of parse, "-128" became -128
After the conversion of tryParse, "127" became Some(127)
After the conversion of parse, "-32768" became -32768
After the conversion of tryParse, "32767" became Some(32767)
After the conversion of parse, "-2147483648" became -2147483648
After the conversion of tryParse, "2147483647" became Some(2147483647)
After the conversion of parse, "-9223372036854775808" became -9223372036854775808
After the conversion of tryParse, "9223372036854775807" became Some(9223372036854775807)
After the conversion of parse, "-65504.0" became -65504.000000
After the conversion of tryParse, "65504.0" became Some(65504.000000)
After the conversion of parse, "-3.14159" became -3.141590
After the conversion of tryParse, "3.14159" became Some(3.141590)
After the conversion of parse, "-3.1415926" became -3.141593
After the conversion of tryParse, "3.1415926" became Some(3.141593)
After the conversion of parse, "255" became 255
After the conversion of tryParse, "255" became Some(255)
After the conversion of parse, "65535" became 65535
After the conversion of tryParse, "65535" became Some(65535)
After the conversion of parse, "4294967295" became 4294967295
After the conversion of tryParse, "4294967295" became Some(4294967295)
After the conversion of parse, "18446744073709551615" became 18446744073709551615
After the conversion of tryParse, "18446744073709551615" became Some(18446744073709551615)
std.crypto.cipher
功能介绍
std.crypto.cipher 包提供对称加解密通用接口。
API 列表
接口
| 接口名 | 功能 |
|---|---|
| BlockCipher | 此接口是分组加解密算法的通用接口。 |
接口
interface BlockCipher
public interface BlockCipher {
prop blockSize: Int64
prop algorithm: String
func encrypt(input: Array<Byte>): Array<Byte>
func decrypt(input: Array<Byte>): Array<Byte>
func encrypt(input: Array<Byte>, to!: Array<Byte>): Int64
func decrypt(input: Array<Byte>, to!: Array<Byte>): Int64
}
功能:分组加解密算法接口,继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
prop algorithm
prop algorithm: String
功能:获取分组加解密算法的算法名称。
类型:String
prop blockSize
prop blockSize: Int64
功能:分组块长度,单位字节。
类型:Int64
func encrypt(Array<Byte>)
func encrypt(input: Array<Byte>): Array<Byte>
功能:提供加密函数。
参数:
返回值:
func decrypt(Array<Byte>)
func decrypt(input: Array<Byte>): Array<Byte>
功能:提供解密函数。
参数:
返回值:
func encrypt(Array<Byte>, Array<Byte>)
func encrypt(input: Array<Byte>, to!: Array<Byte>): Int64
功能:提供加密函数。
参数:
返回值:
- Int64 - 输出长度。
func decrypt(Array<Byte>, Array<Byte>)
func decrypt(input: Array<Byte>, to!: Array<Byte>): Int64
功能:提供解密函数。
参数:
返回值:
- Int64 - 输出长度。
std.crypto.digest
功能介绍
std.crypto.digest 包提供常用摘要算法的通用接口,包括 MD5、SHA1、SHA224、SHA256、SHA384、SHA512、HMAC、SM3 等。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| digest<T>(T, Array<Byte>) where T <: Digest | 提供 digest 泛型函数,实现用指定的摘要算法进行摘要运算。 |
| digest<T>(T, String) where T <: Digest (deprecated) | 提供 digest 泛型函数,实现用指定的摘要算法进行摘要运算。 |
| digest<T>(T, InputStream) where T <: Digest | 提供 digest 泛型函数,实现用指定的摘要算法对 InputStream 里的数据进行摘要运算。 |
接口
| 接口名 | 功能 |
|---|---|
| Digest | 此接口是摘要算法的通用接口。 |
函数
func digest<T>(T, Array<Byte>) where T <: Digest
public func digest<T>(algorithm: T, data: Array<Byte>): Array<Byte> where T <: Digest
功能:提供 digest 泛型函数,实现用指定的摘要算法进行摘要运算。
参数:
返回值:
示例:
import std.crypto.digest.*
main() {
let data: Array<Byte> = [1, 2, 3, 4, 5]
let mydigest = MyDigest()
let digestBytes = digest<MyDigest>(mydigest, data)
println(digestBytes)
}
// 自定义 Digest
class MyDigest <: Digest {
public prop size: Int64 {
get() { 0 }
}
public prop blockSize: Int64 {
get() { 0 }
}
public prop algorithm: String {
get() { "" }
}
public func write(buffer: Array<Byte>): Unit { println("buffer = ${buffer}") }
public func finish(to!: Array<Byte>): Unit { println("to = ${to}") }
public func finish(): Array<Byte> { [3,2,1] }
public func reset(): Unit {}
}
运行结果:
buffer = [1, 2, 3, 4, 5]
[3, 2, 1]
func digest<T>(T, String) where T <: Digest (deprecated)
public func digest<T>(algorithm: T, data: String): Array<Byte> where T <: Digest
功能:提供 digest 泛型函数,实现用指定的摘要算法进行摘要运算。
注意:
未来版本即将废弃不再使用,可使用 digest<T>(T, Array<Byte>) where T <: Digest 替代。
参数:
- algorithm: T - 具体的摘要算法。
- data: String - 待进行摘要运算的数据。
返回值:
func digest<T>(T, InputStream) where T <: Digest
public func digest<T>(algorithm: T, input: InputStream): Array<Byte> where T <: Digest
功能:提供 digest 泛型函数,实现用指定的摘要算法对 InputStream 里的数据进行摘要运算。
参数:
- algorithm: T - 具体的摘要算法。
- input: InputStream - 待进行摘要运算的 InputStream。
返回值:
示例:
import std.crypto.digest.*
import std.io.*
main() {
/* 将原始的字节数组 data 转换为一个输入流 BufferedInputStream */
let data: Array<Byte> = [1, 2, 3, 4, 5]
let byteBuffer = ByteBuffer(data)
let bufferedInputStream = BufferedInputStream(byteBuffer)
let mydigest = MyDigest()
let digestBytes = digest<MyDigest>(mydigest, bufferedInputStream)
println(digestBytes)
}
// 自定义 Digest
class MyDigest <: Digest {
public prop size: Int64 {
get() { 0 }
}
public prop blockSize: Int64 {
get() { 2 }
}
public prop algorithm: String {
get() { "" }
}
public func write(buffer: Array<Byte>): Unit { println("buffer = ${buffer}") }
public func finish(to!: Array<Byte>): Unit { println("to = ${to}") }
public func finish(): Array<Byte> { [3,2,1] }
public func reset(): Unit {}
}
运行结果:
buffer = [1, 2]
buffer = [3, 4]
buffer = [5]
[3, 2, 1]
接口
interface Digest
public interface Digest {
prop size: Int64
prop blockSize: Int64
prop algorithm: String
func write(buffer: Array<Byte>): Unit
func finish(to!: Array<Byte>): Unit
func finish(): Array<Byte>
func reset(): Unit
}
功能:摘要算法接口,继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
prop algorithm
prop algorithm: String
功能:获取摘要算法的算法名称。
类型:String
prop blockSize
prop blockSize: Int64
功能:返回 Block 块长度,单位字节。
类型:Int64
prop size
prop size: Int64
功能:返回生成的摘要信息长度,单位字节。
类型:Int64
func finish()
func finish(): Array<Byte>
功能:返回生成的 digest 值。
返回值:
func finish(Array<Byte>)
func finish(to!: Array<Byte>): Unit
功能:获取生成的信息摘要值,注意调用 finish 后不可以再进行摘要计算,如重新计算需要 reset 重置上下文。
参数:
func reset()
func reset(): Unit
功能:重置 digest 对象到初始状态。
func write(Array<Byte>)
func write(buffer: Array<Byte>): Unit
功能:使用给定的 buffer 更新 digest 对象。
std.database.sql
功能介绍
database.sql 包提供仓颉访问数据库的接口。
本包提供 SQL/CLI 的通用接口,配合数据库驱动 Driver 完成对数据库的各项操作。
注意:
当前仅支持 SQL/CLI 接口。
SQL 数据类型和仓颉数据类型对应表如下:
| SQL | CDBC/Cangjie | SqlDataType | 说明 |
|---|---|---|---|
RUNE | String | SqlChar | - |
VARCHAR | String | SqlVarchar | - |
CLOB | io.InputStream | SqlClob | - |
BINARY | Array<Byte> | SqlBinary | - |
VARBINARY | Array<Byte> | SqlVarBinary | - |
BLOB | io.InputStream | SqlBlob | - |
NUMERIC | Decimal | SqlDecimal | - |
DECIMAL | Decimal | SqlDecimal | - |
BOOLEAN | Bool | SqlBool | - |
TINYINT | Int8 | SqlByte | - |
SMALLINT | Int16 | SqlSmallInt | - |
INTEGER | Int32 | SqlInteger | - |
BIGINT | Int64 | SqlBigInt | - |
REAL | Float32 | SqlReal | - |
DOUBLE | Float64 | SqlDouble | - |
DATE | time.DateTime | SqlDate | 值支持 YEAR,MONTH,DAY。 |
TIME | time.DateTime | SqlTime | 值支持 HOUR,MINUTE,SECOND(不包括 TIME ZONE)。 |
TIMETZ | time.DateTime | SqlTimeTz | 值支持 HOUR,MINUTE,SECOND(包括 TIME ZONE)。 |
TIMESTAMP | time.DateTime | SqlTimestamp | 值支持 YEAR,MONTH,DAY,HOUR,MINUTE,SECOND,TIME ZONE。 |
INTERVAL | time.Duration | SqlInterval | 年-月间隔或者日-时间隔。 |
API列表
接口
| 接口名 | 功能 |
|---|---|
| ColumnInfo | 执行 Select/Query 语句返回结果的列信息。 |
| Connection | 数据库连接接口。 |
| Datasource | 数据源接口。 |
| Driver | 数据库驱动接口。 |
| QueryResult | 执行 Select 语句产生的结果接口。 |
| SqlDbType (deprecated) | 所有 sql 数据类型的父类。 |
| SqlNullableDbType (deprecated) | 允许 null 值的 sql 数据类型父类。 |
| Statement | sql 语句预执行接口。 |
| Transaction | 定义数据库事务的核心行为。 |
| UpdateResult | 执行 Insert、Update、Delete 语句产生的结果接口。 |
类
| 类名 | 功能 |
|---|---|
| DriverManager | 支持运行时根据驱动名获取数据库驱动实例。 |
| PooledDatasource | 数据库连接池类,提供数据库连接池能力。 |
| SqlOption | 预定义的 sql 选项名称和值。 |
| SqlBigInt (deprecated) | 大整数,对应仓颉 Int64 类型。 |
| SqlBinary (deprecated) | 定长二进制字符串,对应仓颉 Array<Byte> 类型。 |
| SqlBlob (deprecated) | 变长超大二进制字符串(BINARY LARGE OBJECT),对应仓颉 InputStream 类型。 |
| SqlBool (deprecated) | 布尔类型,对应仓颉 Bool 类型。 |
| SqlByte (deprecated) | 字节,对应仓颉 Int8 类型。 |
| SqlChar (deprecated) | 定长字符串,对应仓颉 String 类型。 |
| SqlClob (deprecated) | 变长超大字符串(RUNE LARGE OBJECT),对应仓颉 InputStream 类型。 |
| SqlDate (deprecated) | 日期,仅年月日有效,对应仓颉 DateTime 类型。 |
| SqlDecimal (deprecated) | 高精度数,对应仓颉 Decimal 类型。 |
| SqlDouble (deprecated) | 双精度数,对应仓颉 Float64 类型。 |
| SqlInteger (deprecated) | 中整数,对应仓颉 Int32 类型。 |
| SqlInterval (deprecated) | 时间间隔,对应仓颉 Duration 类型。 |
| SqlReal (deprecated) | 浮点数,对应仓颉 Float32 类型。 |
| SqlSmallInt (deprecated) | 小整数,对应仓颉 Int16 类型。 |
| SqlTime (deprecated) | 时间,仅时分秒毫秒有效,对应仓颉 DateTime 类型。 |
| SqlTimestamp (deprecated) | 时间戳,对应仓颉 DateTime 类型。 |
| SqlTimeTz (deprecated) | 带时区的时间,仅时分秒毫秒时区有效,对应仓颉 DateTime 类型。 |
| SqlVarBinary (deprecated) | 变长二进制字符串,对应仓颉 Array<Byte> 类型。 |
| SqlVarchar (deprecated) | 变长字符串,对应仓颉 String 类型。 |
| SqlNullableBigInt (deprecated) | 大整数,对应仓颉 Int64 类型,可为数据库 Null 值。 |
| SqlNullableBinary (deprecated) | 定长二进制字符串,对应仓颉 Array<Byte> 类型,可为数据库 Null 值。 |
| SqlNullableBlob (deprecated) | 变长超大二进制字符串(BINARY LARGE OBJECT),对应仓颉 InputStream 类型,可为数据库 Null 值。 |
| SqlNullableBool (deprecated) | 布尔类型,对应仓颉 Bool 类型,可为数据库 Null 值。 |
| SqlNullableByte (deprecated) | 字节,对应仓颉 Int8 类型,可为数据库 Null 值。 |
| SqlNullableChar (deprecated) | 定长二进制字符串,对应仓颉 String 类型,可为数据库 Null 值。 |
| SqlNullableClob (deprecated) | 变长超大字符串(RUNE LARGE OBJECT),对应仓颉 InputStream 类型,可为数据库 Null 值。 |
| SqlNullableDate (deprecated) | 日期,仅年月日有效,对应仓颉 DateTime 类型,可为数据库 Null 值。 |
| SqlNullableDecimal (deprecated) | 高精度数,对应仓颉 Decimal 类型,可为数据库 Null 值。 |
| SqlNullableDouble (deprecated) | 双精度数,对应仓颉 Float64 类型,可为数据库 Null 值。 |
| SqlNullableInteger (deprecated) | 中整数,对应仓颉 Int32 类型,可为数据库 Null 值。 |
| SqlNullableInterval (deprecated) | 时间间隔,对应仓颉 Duration 类型,可为数据库 Null 值。 |
| SqlNullableReal (deprecated) | 浮点数,对应仓颉 Float32 类型,可为数据库 Null 值。 |
| SqlNullableSmallInt (deprecated) | 小整数,对应仓颉 Int16 类型,可为数据库 Null 值。 |
| SqlNullableTime (deprecated) | 时间,仅时分秒毫秒有效,对应仓颉 DateTime 类型,可为数据库 Null 值。 |
| SqlNullableTimestamp (deprecated) | 时间戳,对应仓颉 DateTime 类型,可为数据库 Null 值。 |
| SqlNullableTimeTz (deprecated) | 带时区的时间,仅时分秒毫秒时区有效,对应仓颉 DateTime 类型,可为数据库 Null 值。 |
| SqlNullableVarBinary (deprecated) | 变长二进制字符串,对应仓颉 Array<Byte> 类型,可为数据库 Null 值。 |
| SqlNullableVarchar (deprecated) | 变长字符串,对应仓颉 String 类型,可为数据库 Null 值。 |
枚举
| 枚举名 | 功能 |
|---|---|
| ConnectionState | 描述与数据源连接的当前状态。 |
| TransactionAccessMode | 事务的读写模式。 |
| TransactionDeferrableMode | 事务的延迟模式。 |
| TransactionIsoLevel | 定义了数据库系统中,一个事务中操作的结果在何时以何种方式对其他并发事务操作可见。 |
异常类
| 异常类名 | 功能 |
|---|---|
| SqlException | 用于处理 sql 相关的异常。 |
接口
interface ColumnInfo
public interface ColumnInfo {
prop displaySize: Int64
prop length: Int64
prop name: String
prop nullable: Bool
prop scale: Int64
prop typeName: String
}
功能:执行 Select/Query 语句返回结果的列信息。
prop displaySize
prop displaySize: Int64
功能:获取列值的最大显示长度,如果无限制,则应该返回 Int64.Max (仍然受数据库的限制)。
类型:Int64
prop length
prop length: Int64
功能:获取列值大小。
说明:
- 对于数值数据,表示最大精度。
- 对于字符数据,表示以字符为单位的长度。
- 对于日期时间数据类型,表示字符串表示形式的最大字符长度。
- 对于二进制数据,表示以字节为单位的长度。
- 对于 RowID 数据类型,表示以字节为单位的长度。
- 对于列大小不适用的数据类型,返回 0。
类型:Int64
prop name
prop name: String
功能:列名或者别名。
类型:String
prop nullable
prop nullable: Bool
功能:表示列值是否允许数据库 Null 值。
类型:Bool
prop scale
prop scale: Int64
功能:获取列值的小数长度,如果无小数部分,返回 0。
类型:Int64
prop typeName
prop typeName: String
功能:获取列类型名称,如果在仓颉中有对应数据类型的定义,返回对应类型的 toString 函数的返回值;如果在仓颉中无对应数据类型的定义,由数据库驱动定义。
类型:String
interface Connection
public interface Connection <: Resource {
prop state: ConnectionState
func createTransaction(): Transaction
func getMetaData(): Map<String, String>
func prepareStatement(sql: String): Statement
}
功能:数据库连接接口。
继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
父类型:
prop state
prop state: ConnectionState
功能:描述与数据源连接的当前状态。
func createTransaction()
func createTransaction(): Transaction
功能:创建事务对象。
返回值:
- Transaction - 事务对象。
异常:
- SqlException - 当已经处于事务状态,不支持并行事务时,抛出异常。
func getMetaData()
func getMetaData(): Map<String, String>
功能:返回连接到的数据源元数据。
返回值:
func prepareStatement(String)
func prepareStatement(sql: String): Statement
功能:通过传入的 sql 语句,返回一个预执行的 Statement 对象实例。
参数:
- sql: String - 预执行的 sql 语句,sql 语句的参数只支持
?符号占位符。
返回值:
- Statement - 一个可以执行 sql 语句的实例对象。
异常:
- SqlException - 当 sql 语句包含不认识的字符时,抛出异常。
interface Datasource
public interface Datasource <: Resource {
func connect(): Connection
func setOption(key: String, value: String): Unit
}
功能:数据源接口。
继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
父类型:
func connect()
func connect(): Connection
功能:返回一个可用的连接。
返回值:
- Connection - 数据库连接实例。
func setOption(String, String)
func setOption(key: String, value: String): Unit
功能:设置连接选项。
参数:
interface Driver
public interface Driver {
prop name: String
prop preferredPooling: Bool
prop version: String
func open(connectionString: String, opts: Array<(String, String)>): Datasource
}
功能:数据库驱动接口。
继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
prop name
prop name: String
功能:驱动名称。
类型:String
prop preferredPooling
prop preferredPooling: Bool
功能:指示驱动程序是否与连接池亲和。
当该属性为 false 时,不建议使用连接池进行管理。例如,对于某些数据库驱动(如 SQLite),连接池化的收益不明显,因此不建议使用连接池。
类型:Bool
prop version
prop version: String
功能:驱动版本。
类型:String
func open(String, Array<(String, String)>)
func open(connectionString: String, opts: Array<(String, String)>): Datasource
功能:通过 connectionString 和选项打开数据源。
参数:
返回值:
- Datasource - 数据源实例。
interface QueryResult
public interface QueryResult <: Resource {
prop columnInfos: Array<ColumnInfo>
func next(values: Array<SqlDbType>): Bool
func next(): Bool
func get<T>(index: Int): T
func getOrNull<T>(index: Int): ?T
}
功能:执行 Select 语句产生的结果接口。
继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
父类型:
prop columnInfos
prop columnInfos: Array<ColumnInfo>
功能:返回结果集的列信息,比如列名,列类型,列长度,是否允许数据库 Null 值等。
类型:Array<ColumnInfo>
func get<T>(Int)
func get<T>(index: Int): T
功能:从结果集的当前行检索指定列的值。
返回值:
- T -
T类型的实例。
func getOrNull<T>(Int)
func getOrNull<T>(index: Int): ?T
功能:从结果集的当前行检索指定列的值,数据库列允许 SQL NULL。
返回值:
- ?T -
T类型的实例,如果为空,返回 None。
异常:
- SqlException - 索引超出列范围,或者行数据未准备好时,抛出异常。
func next()
func next(): Bool
功能:向后移动一行,必须先调用一次 next() 才能移动到第一行,第二次调用移动到第二行,依此类推。当返回 true 时,驱动会在结果集的当前行填入数据,当返回 false 时结束,且不会修改结果集当前行的内容。
返回值:
- Bool - 下一行存在数据则返回
true,否则返回false。
func next(Array<SqlDbType>) (deprecated)
func next(values: Array<SqlDbType>): Bool
功能:向后移动一行,必须先调用一次 next 才能移动到第一行,第二次调用移动到第二行,依此类推。当返回 true 时,驱动会在 values 中填入行数据;当返回 false 时结束,且不会修改 values 的内容。
注意:
未来版本即将废弃不再使用,可使用 next() 替代。
参数:
- values: Array<SqlDbType (deprecated)> - sql 数据类型的数据列表。
返回值:
- Bool - 下一行存在数据则返回
true,否则返回false。
interface SqlDbType (deprecated)
public interface SqlDbType {
prop name: String
}
功能:所有 sql 数据类型的父类。
注意:
未来版本即将废弃不再使用。
要扩展用户定义的类型,请继承 SqlDbType (deprecated) 或 SqlNullableDbType (deprecated)。
说明:
SqlDbType (deprecated) 接口所有实现类型都必须具有公共
value属性。每种 sql 数据类型实现类,同时满足以下条件:
- 只有一个参数的构造函数,参数类型为
T(T为仓颉语言支持的类型)。public修饰的value属性,其类型必须上一条中使用的参数类型一致,其值为对应仓颉类型的值。- 如果数据类型允许
null值,继承 SqlNullableDbType (deprecated),null值时,value字段的值为 Option<T>.None。
prop name
prop name: String
功能:获取类型名称。
类型:String
interface SqlNullableDbType (deprecated)
public interface SqlNullableDbType <: SqlDbType
功能:允许 null 值的 sql 数据类型父类。
注意:
未来版本即将废弃不再使用。
如果为 null 值,value 属性值为 Option.None。
父类型:
interface Statement
public interface Statement <: Resource {
prop parameterColumnInfos: Array<ColumnInfo>
func query(params: Array<SqlDbType>): QueryResult
func setOption(key: String, value: String): Unit
func update(params: Array<SqlDbType>): UpdateResult
func set<T>(index: Int, value: T): Unit
func setNull(index: Int): Unit
func update(): UpdateResult
func query(): QueryResult
}
功能:sql 语句预执行接口。
Statement 绑定了一个 Connection ,继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
父类型:
prop parameterColumnInfos
prop parameterColumnInfos: Array<ColumnInfo>
功能:预执行 sql 语句中,占位参数的列信息,比如列名,列类型,列长度,是否允许数据库 Null 值等。
类型:Array<ColumnInfo>
func query()
func query(): QueryResult
功能:执行 sql 语句,得到查询结果。
返回值:
- QueryResult - 查询结果。
异常:
- SqlException - 当执行过程中发生了异常情况,比如网络中断,服务器超时,参数个数不正确时,抛出异常。
func query(Array<SqlDbType>) (deprecated)
func query(params: Array<SqlDbType>): QueryResult
功能:执行 sql 语句,得到查询结果。
注意:
未来版本即将废弃不再使用,可使用 query() 替代。
参数:
- params: Array<SqlDbType (deprecated)> - sql 数据类型的数据列表,用于替换 sql 语句中的
?占位符。
返回值:
- QueryResult - 查询结果。
异常:
- SqlException - 当执行过程中发生了异常情况,比如网络中断,服务器超时,参数个数不正确时,抛出异常。
func set<T>(Int, T)
func set<T>(index: Int, value: T): Unit
功能:设置 sql 参数,将仓颉的数据类型转成数据库的数据类型。
参数:
- index: Int - 参数所在序列。
- value: T - 参数值。
func setNull(Int)
func setNull(index: Int): Unit
功能:将指定位置处的语句参数设置为 SQL NULL。
参数:
- index: Int - 参数所在序列。
func setOption(String, String)
func setOption(key: String, value: String): Unit
功能:设置预执行 sql 语句选项。
参数:
func update(Array<SqlDbType>) (deprecated)
func update(params: Array<SqlDbType>): UpdateResult
功能:执行 sql 语句,得到更新结果。
注意:
未来版本即将废弃不再使用,可使用 update() 替代。
参数:
- params: Array<SqlDbType (deprecated)> - sql 数据类型的数据列表,用于替换 sql 语句中的
?占位符。
返回值:
- UpdateResult - 更新结果。
异常:
- SqlException - 当执行过程中发生了异常情况,比如网络中断、服务器超时,参数个数不正确时,抛出异常。
func update()
func update(): UpdateResult
功能:执行 sql 语句,得到更新结果。
返回值:
- UpdateResult - 更新结果。
异常:
- SqlException - 当执行过程中发生了异常情况,比如网络中断,服务器超时,参数个数不正确时,抛出异常。
interface Transaction
public interface Transaction {
mut prop accessMode: TransactionAccessMode
mut prop deferrableMode: TransactionDeferrableMode
mut prop isoLevel: TransactionIsoLevel
func begin(): Unit
func commit(): Unit
func release(savePointName: String): Unit
func rollback(): Unit
func rollback(savePointName: String): Unit
func save(savePointName: String): Unit
}
功能:定义数据库事务的核心行为。
继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
prop accessMode
mut prop accessMode: TransactionAccessMode
功能:获取数据库事务访问模式。
prop deferrableMode
mut prop deferrableMode: TransactionDeferrableMode
功能:获取数据库事务延迟模式。
prop isoLevel
mut prop isoLevel: TransactionIsoLevel
功能:获取数据库事务隔离级别。
func begin()
func begin(): Unit
功能:开始数据库事务。
异常:
- SqlException - 当提交事务时服务器端发生错误,以及当事务已提交或回滚或连接已断开时,抛出异常。
func commit()
func commit(): Unit
功能:提交数据库事务。
异常:
- SqlException - 当提交事务时服务器端发生错误,以及当事务已提交或回滚或连接已断开时,抛出异常。
func release(String)
func release(savePointName: String): Unit
功能:销毁先前在当前事务中定义的保存点。这允许系统在事务结束之前回收一些资源。
参数:
- savePointName: String - 保存点名称。
异常:
- SqlException - 当提交事务时服务器端发生错误,以及当事务已提交或回滚或连接已断开时,抛出异常。
func rollback()
func rollback(): Unit
功能:从挂起状态回滚事务。
异常:
- SqlException - 当提交事务时服务器端发生错误,以及当事务已提交或回滚或连接已断开时,抛出异常。
func rollback(String)
func rollback(savePointName: String): Unit
功能:回滚事务至指定保存点名称。
参数:
- savePointName: String - 保存点名称。
异常:
- SqlException - 当提交事务时服务器端发生错误,以及当事务已提交或回滚或连接已断开时,抛出异常。
func save(String)
func save(savePointName: String): Unit
功能:在事务中创建一个指定名称的保存点,可用于回滚此保存点之后的事务。
参数:
- savePointName: String - 保存点名称。
异常:
- SqlException - 当提交事务时服务器端发生错误,以及当事务已提交或回滚或连接已断开时,抛出异常。
interface UpdateResult
public interface UpdateResult {
prop lastInsertId: Int64
prop rowCount: Int64
}
功能:执行 Insert、Update、Delete 语句产生的结果接口。
继承该接口的 class、interface、struct 也需要遵守该接口中函数的入参及返回值定义。
prop lastInsertId
prop lastInsertId: Int64
功能:执行 Insert 语句自动生成的最后 row ID ,如果不支持则 row ID 为 0。
类型:Int64
prop rowCount
prop rowCount: Int64
功能:执行 Insert、Update、Delete 语句影响的行数。
类型:Int64
类
class DriverManager
public class DriverManager
功能:支持运行时根据驱动名获取数据库驱动实例。
static func deregister(String)
public static func deregister(driverName: String): Unit
功能:按名称取消注册数据库驱动(如果存在)。本函数并发安全。
参数:
- driverName: String - 驱动名称。
static func drivers()
public static func drivers(): Array<String>
功能:返回已注册数据库驱动名称的列表(名称已按照字典序排序)。本方法并发安全。
返回值:
static func getDriver(String)
public static func getDriver(driverName: String): Option<Driver>
功能:按名称获取已注册的数据库驱动,如果不存在返回 None。本函数并发安全。
参数:
- driverName: String - 驱动名称。
返回值:
static func register(String, Driver)
public static func register(driverName: String, driver: Driver): Unit
功能:按名称和驱动实例注册数据库驱动,名称和实例一一对应。本方法并发安全。
参数:
异常:
- SqlException - 当指定的驱动名称已经存在时,抛出异常。
class PooledDatasource
public class PooledDatasource <: Datasource {
public init(datasource: Datasource)
}
功能:数据库连接池类,提供数据库连接池能力。
父类型:
prop connectionTimeout
public mut prop connectionTimeout: Duration
功能:从池中获取连接的超时时间。
类型:Duration
异常:
- ArithmeticException - 当该属性被设置为 Duration.Max 或 Duration.Min 时,抛此异常。
- SqlException - 当获取连接超时后,抛出此异常。
prop idleTimeout
public mut prop idleTimeout: Duration
功能:允许连接在池中闲置的最长时间,超过这个时间的空闲连接可能会被回收。
类型:Duration
prop keepaliveTime
public mut prop keepaliveTime: Duration
功能:检查空闲连接健康状况的间隔时间,防止它被数据库或网络基础设施超时。
类型:Duration
prop maxIdleSize
public mut prop maxIdleSize: Int32
功能:最大空闲连接数量,超过这个数量的空闲连接会被关闭,负数或0表示无限制。
类型:Int32
prop maxLifeTime
public mut prop maxLifeTime: Duration
功能:自连接创建以来的最大持续时间,在该持续时间之后,连接将自动关闭。
类型:Duration
prop maxSize
public mut prop maxSize: Int32
功能:连接池最大连接数量,负数或0表示无限制。
类型:Int32
init(Datasource)
public init(datasource: Datasource)
功能:通过数据源 datasource 构造一个 PooledDatasource 实例,入参必须为 Datasource 对象。
参数:
- datasource: Datasource - 数据源。
func close()
public func close(): Unit
功能:关闭连接池中的所有连接并阻止其他连接请求。调用该方法会阻塞至所有连接关闭并归还到连接池。
func connect()
public func connect(): Connection
功能:获取一个连接。
返回值:
- Connection - 获取到的连接。
func isClosed()
public func isClosed(): Bool
功能:判断连接是否关闭。
返回值:
- Bool - 连接是否关闭。
func setOption(String, String)
public func setOption(key: String, value: String): Unit
功能:设置数据库驱动连接选项(公钥在 SqlOption 中预定义)。
参数:
class SqlBigInt (deprecated)
public class SqlBigInt <: SqlDbType {
public init(v: Int64)
}
功能:大整数,对应仓颉 Int64 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlBigInt (deprecated)。
类型:String
prop value
public mut prop value: Int64
功能:该数据的值。
类型:Int64
init(Int64)
public init(v: Int64)
功能:根据传入参数 v 构造一个 SqlBigInt (deprecated) 实例。
参数:
- v: Int64 - 传入的数据。
class SqlBinary (deprecated)
public class SqlBinary <: SqlDbType {
public init(v: Array<Byte>)
}
功能:定长二进制字符串,对应仓颉 Array<Byte> 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlBinary (deprecated)。
类型:String
prop value
public mut prop value: Array<Byte>
功能:该数据的值。
init(Array<Byte>)
public init(v: Array<Byte>)
功能:根据传入参数 v 构造一个 SqlBinary (deprecated) 实例。
参数:
class SqlBlob (deprecated)
public class SqlBlob <: SqlDbType {
public init(v: InputStream)
}
功能:变长超大二进制字符串(BINARY LARGE OBJECT),对应仓颉 InputStream 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlBlob (deprecated)。
类型:String
prop value
public mut prop value: InputStream
功能:该数据的值。
类型:InputStream
init(InputStream)
public init(v: InputStream)
功能:根据传入参数 v 构造一个 SqlBlob (deprecated) 实例。
参数:
- v: InputStream - 传入的数据。
class SqlBool (deprecated)
public class SqlBool <: SqlDbType {
public init(v: Bool)
}
功能:布尔类型,对应仓颉 Bool 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlBool(deprecated)。
类型:String
prop value
public mut prop value: Bool
功能:该数据的值。
类型:Bool
init(Bool)
public init(v: Bool)
功能:根据传入参数 v 构造一个 SqlBool(deprecated) 实例。
参数:
- v: Bool - 传入的数据。
class SqlByte (deprecated)
public class SqlByte <: SqlDbType {
public init(v: Int8)
}
功能:字节,对应仓颉 Int8 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlByte (deprecated)。
类型:String
prop value
public mut prop value: Int8
功能:该数据的值。
类型:Int8
init(Int8)
public init(v: Int8)
功能:根据传入参数 v 构造一个 SqlByte (deprecated) 实例。
参数:
- v: Int8 - 传入的数据。
class SqlChar (deprecated)
public class SqlChar <: SqlDbType {
public init(v: String)
}
功能:定长字符串,对应仓颉 String 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlChar (deprecated)。
类型:String
prop value
public mut prop value: String
功能:该数据的值。
类型:String
init(String)
public init(v: String)
功能:根据传入参数 v 构造一个 SqlChar (deprecated) 实例。
参数:
- v: String - 传入的数据。
class SqlClob (deprecated)
public class SqlClob <: SqlDbType {
public init(v: InputStream)
}
功能:变长超大字符串(RUNE LARGE OBJECT),对应仓颉 InputStream 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlClob。
类型:String
prop value
public mut prop value: InputStream
功能:该数据的值。
类型:InputStream
init(InputStream)
public init(v: InputStream)
功能:根据传入参数 v 构造一个 SqlClob 实例。
参数:
- v: InputStream - 传入的数据。
class SqlDate (deprecated)
public class SqlDate <: SqlDbType {
public init(v: DateTime)
}
功能:日期,仅年月日有效,对应仓颉 DateTime 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlDate (deprecated)。
类型:String
prop value
public mut prop value: DateTime
功能:该数据的值。
类型:DateTime
init(DateTime)
public init(v: DateTime)
功能:根据传入参数 v 构造一个 SqlDate (deprecated) 实例。
参数:
- v: DateTime - 传入的数据。
class SqlDecimal (deprecated)
public class SqlDecimal <: SqlDbType {
public init(v: Decimal)
}
功能:高精度数,对应仓颉 Decimal 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlDecimal (deprecated)。
类型:String
prop value
public mut prop value: Decimal
功能:该数据的值。
类型:Decimal
init(Decimal)
public init(v: Decimal)
功能:根据传入参数 v 构造一个 SqlDecimal (deprecated) 实例。
参数:
- v: Decimal - 传入的数据。
class SqlDouble (deprecated)
public class SqlDouble <: SqlDbType {
public init(v: Float64)
}
功能:双精度数,对应仓颉 Float64 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlDouble (deprecated)。
类型:String
prop value
public mut prop value: Float64
功能:该数据的值。
类型:Float64
init(Float64)
public init(v: Float64)
功能:根据传入参数 v 构造一个 SqlDouble (deprecated) 实例。
参数:
- v: Float64 - 传入的数据。
class SqlInteger (deprecated)
public class SqlInteger <: SqlDbType {
public init(v: Int32)
}
功能:中整数,对应仓颉 Int32 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlInteger (deprecated)。
类型:String
prop value
public mut prop value: Int32
功能:该数据的值。
类型:Int32
init(Int32)
public init(v: Int32)
功能:根据传入参数 v 构造一个 SqlInteger (deprecated) 实例。
参数:
- v: Int32 - 传入的数据。
class SqlInterval (deprecated)
public class SqlInterval <: SqlDbType {
public init(v: Duration)
}
功能:时间间隔,对应仓颉 Duration 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlInterval (deprecated)。
类型:String
prop value
public mut prop value: Duration
功能:该数据的值。
类型:Duration
init(Duration)
public init(v: Duration)
功能:根据传入参数 v 构造一个 SqlInterval (deprecated) 实例。
参数:
- v: Duration - 传入的数据。
class SqlNullableBigInt (deprecated)
public class SqlNullableBigInt <: SqlNullableDbType {
public init(v: ?Int64)
}
功能:大整数,对应仓颉 Int64 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableBigInt (deprecated)。
类型:String
prop value
public mut prop value: ?Int64
功能:该数据的值。
类型:?Int64
init(?Int64)
public init(v: ?Int64)
功能:根据传入参数 v 构造一个 SqlNullableBigInt (deprecated) 实例。
参数:
- v: ?Int64 - 传入的数据。
class SqlNullableBinary (deprecated)
public class SqlNullableBinary <: SqlNullableDbType {
public init(v: ?Array<Byte>)
}
功能:定长二进制字符串,对应仓颉 Array<Byte> 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableBinary (deprecated)。
类型:String
prop value
public mut prop value: ?Array<Byte>
功能:该数据的值。
init(?Array<Byte>)
public init(v: ?Array<Byte>)
功能:根据传入参数 v 构造一个 SqlNullableBinary (deprecated) 实例。
参数:
class SqlNullableBlob (deprecated)
public class SqlNullableBlob <: SqlNullableDbType {
public init(v: ?InputStream)
}
功能:变长超大二进制字符串(BINARY LARGE OBJECT),对应仓颉 InputStream 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableBlob (deprecated)。
类型:String
prop value
public mut prop value: ?InputStream
功能:该数据的值。
类型:?InputStream
init(?InputStream)
public init(v: ?InputStream)
功能:根据传入参数 v 构造一个 SqlNullableBlob (deprecated) 实例。
参数:
- v: ?InputStream - 传入的数据。
class SqlNullableBool (deprecated)
public class SqlNullableBool <: SqlNullableDbType {
public init(v: ?Bool)
}
功能:布尔类型,对应仓颉 Bool 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableBool (deprecated)。
类型:String
prop value
public mut prop value: ?Bool
功能:该数据的值。
类型:?Bool
init(?Bool)
public init(v: ?Bool)
功能:根据传入参数 v 构造一个 SqlNullableBool (deprecated) 实例。
参数:
- v: ?Bool - 传入的数据。
class SqlNullableByte (deprecated)
public class SqlNullableByte <: SqlNullableDbType {
public init(v: ?Int8)
}
功能:字节,对应仓颉 Int8 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableByte (deprecated)。
类型:String
prop value
public mut prop value: ?Int8
功能:该数据的值。
类型:?Int8
init(?Int8)
public init(v: ?Int8)
功能:根据传入参数 v 构造一个 SqlNullableByte (deprecated) 实例。
参数:
- v: ?Int8 - 传入的数据。
class SqlNullableChar (deprecated)
public class SqlNullableChar <: SqlNullableDbType {
public init(v: ?String)
}
功能:定长字符串,对应仓颉 String 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableChar (deprecated)。
类型:String
prop value
public mut prop value: ?String
功能:该数据的值。
类型:?String
init(?String)
public init(v: ?String)
功能:根据传入参数 v 构造一个 SqlNullableChar (deprecated) 实例。
参数:
- v: ?String - 传入的数据。
class SqlNullableClob (deprecated)
public class SqlNullableClob <: SqlNullableDbType {
public init(v: ?InputStream)
}
功能:变长超大字符串(RUNE LARGE OBJECT),对应仓颉 InputStream 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableClob (deprecated)。
类型:String
prop value
public mut prop value: ?InputStream
功能:该数据的值。
类型:?InputStream
init(?InputStream)
public init(v: ?InputStream)
功能:根据传入参数 v 构造一个 SqlNullableClob (deprecated) 实例。
参数:
- v: ?InputStream - 传入的数据。
class SqlNullableDate (deprecated)
public class SqlNullableDate <: SqlNullableDbType {
public init(v: ?DateTime)
}
功能:日期,仅年月日有效,对应仓颉 DateTime 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableDate (deprecated)。
类型:String
prop value
public mut prop value: ?DateTime
功能:该数据的值。
类型:?DateTime
init(?DateTime)
public init(v: ?DateTime)
功能:根据传入参数 v 构造一个 SqlNullableDate (deprecated) 实例。
参数:
- v: ?DateTime - 传入的数据。
class SqlNullableDecimal (deprecated)
public class SqlNullableDecimal <: SqlNullableDbType {
public init(v: ?Decimal)
}
功能:高精度数,对应仓颉 Decimal 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableDecimal (deprecated)。
类型:String
prop value
public mut prop value: ?Decimal
功能:该数据的值。
类型:?Decimal
init(?Decimal)
public init(v: ?Decimal)
功能:根据传入参数 v 构造一个 SqlNullableDecimal (deprecated) 实例。
参数:
- v: ?Decimal - 传入的数据。
class SqlNullableDouble (deprecated)
public class SqlNullableDouble <: SqlNullableDbType {
public init(v: ?Float64)
}
功能:双精度数,对应仓颉 Float64 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableDouble (deprecated)。
类型:String
prop value
public mut prop value: ?Float64
功能:该数据的值。
类型:?Float64
init(?Float64)
public init(v: ?Float64)
功能:根据传入参数 v 构造一个 SqlNullableDouble (deprecated) 实例。
参数:
- v: ?Float64 - 传入的数据。
class SqlNullableInteger (deprecated)
public class SqlNullableInteger <: SqlNullableDbType {
public init(v: ?Int32)
}
功能:中整数,对应仓颉 Int32 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableInteger (deprecated)。
类型:String
prop value
public mut prop value: ?Int32
功能:该数据的值。
类型:?Int32
init(?Int32)
public init(v: ?Int32)
功能:根据传入参数 v 构造一个 SqlNullableInteger (deprecated) 实例。
参数:
- v: ?Int32 - 传入的数据。
class SqlNullableInterval (deprecated)
public class SqlNullableInterval <: SqlNullableDbType {
public init(v: ?Duration)
}
功能:时间间隔,对应仓颉 Duration 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableInterval (deprecated)。
类型:String
prop value
public mut prop value: ?Duration
功能:该数据的值。
类型:?Duration
init(?Duration)
public init(v: ?Duration)
功能:根据传入参数 v 构造一个 SqlNullableInterval (deprecated) 实例。
参数:
- v: ?Duration - 传入的数据。
class SqlNullableReal (deprecated)
public class SqlNullableReal <: SqlNullableDbType {
public init(v: ?Float32)
}
功能:浮点数,对应仓颉 Float32 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableReal (deprecated)。
类型:String
prop value
public mut prop value: ?Float32
功能:该数据的值。
类型:?Float32
init(?Float32)
public init(v: ?Float32)
功能:根据传入参数 v 构造一个 SqlNullableReal (deprecated) 实例。
参数:
- v: ?Float32 - 传入的数据。
class SqlNullableSmallInt (deprecated)
public class SqlNullableSmallInt <: SqlNullableDbType {
public init(v: ?Int16)
}
功能:小整数,对应仓颉 Int16 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableSmallInt (deprecated)。
类型:String
prop value
public mut prop value: ?Int16
功能:该数据的值。
类型:?Int16
init(?Int16)
public init(v: ?Int16)
功能:根据传入参数 v 构造一个 SqlNullableSmallInt (deprecated) 实例。
参数:
- v: ?Int16 - 传入的数据。
class SqlNullableTime (deprecated)
public class SqlNullableTime <: SqlNullableDbType {
public init(v: ?DateTime)
}
功能:时间,仅时分秒毫秒有效,对应仓颉 DateTime 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableTime (deprecated)。
类型:String
prop value
public mut prop value: ?DateTime
功能:该数据的值。
类型:?DateTime
init(?DateTime)
public init(v: ?DateTime)
功能:根据传入参数 v 构造一个 SqlNullableTime (deprecated) 实例。
参数:
- v: ?DateTime - 传入的数据。
class SqlNullableTimeTz (deprecated)
public class SqlNullableTimeTz <: SqlNullableDbType {
public init(v: ?DateTime)
}
功能:带时区的时间,仅时分秒毫秒时区有效,对应仓颉 DateTime 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableTimeTz (deprecated)。
类型:String
prop value
public mut prop value: ?DateTime
功能:该数据的值。
类型:?DateTime
init(?DateTime)
public init(v: ?DateTime)
功能:根据传入参数 v 构造一个 SqlNullableTimeTz (deprecated) 实例。
参数:
- v: ?DateTime - 传入的数据。
class SqlNullableTimestamp (deprecated)
public class SqlNullableTimestamp <: SqlNullableDbType {
public init(v: ?DateTime)
}
功能:时间戳,对应仓颉 DateTime 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableTimestamp (deprecated)。
类型:String
prop value
public mut prop value: ?DateTime
功能:该数据的值。
类型:?DateTime
init(?DateTime)
public init(v: ?DateTime)
功能:根据传入参数 v 构造一个 SqlNullableTimestamp (deprecated) 实例。
参数:
- v: ?DateTime - 传入的数据。
class SqlNullableVarBinary (deprecated)
public class SqlNullableVarBinary <: SqlNullableDbType {
public init(v: ?Array<Byte>)
}
功能:变长二进制字符串,对应仓颉 Array<Byte> 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableVarBinary (deprecated)。
类型:String
prop value
public mut prop value: ?Array<Byte>
功能:该数据的值。
init(?Array<Byte>)
public init(v: ?Array<Byte>)
功能:根据传入参数 v 构造一个 SqlNullableVarBinary (deprecated) 实例。
参数:
class SqlNullableVarchar (deprecated)
public class SqlNullableVarchar <: SqlNullableDbType {
public init(v: ?String)
}
功能:变长字符串,对应仓颉 String 类型,可为数据库 Null 值。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlNullableVarchar (deprecated)。
类型:String
prop value
public mut prop value: ?String
功能:该数据的值。 类型:?String
init(?String)
public init(v: ?String)
功能:根据传入参数 v 构造一个 SqlNullableVarchar (deprecated) 实例。
参数:
- v: ?String - 传入的数据。
class SqlOption
public class SqlOption {
public static const URL = "url"
public static const Host = "host"
public static const Username = "username"
public static const Password = "password"
public static const Driver = "driver"
public static const Database = "database"
public static const Encoding = "encoding"
public static const ConnectionTimeout = "connection_timeout"
public static const UpdateTimeout = "update_timeout"
public static const QueryTimeout = "query_timeout"
public static const FetchRows = "fetch_rows"
public static const SSLMode = "ssl.mode"
public static const SSLModePreferred = "ssl.mode.preferred"
public static const SSLModeDisabled = "ssl.mode.disabled"
public static const SSLModeRequired = "ssl.mode.required"
public static const SSLModeVerifyCA = "ssl.mode.verify_ca"
public static const SSLModeVerifyFull = "ssl.mode.verify_full"
public static const SSLCA = "ssl.ca"
public static const SSLCert = "ssl.cert"
public static const SSLKey = "ssl.key"
public static const SSLKeyPassword = "ssl.key.password"
public static const SSLSni = "ssl.sni"
public static const Tls12Ciphersuites = "tls1.2.ciphersuites"
public static const Tls13Ciphersuites = "tls1.3.ciphersuites"
public static const TlsVersion = "tls.version"
}
功能:预定义的 sql 选项名称和值。如果需要扩展,请不要与这些名称和值冲突。
static const ConnectionTimeout
public static const ConnectionTimeout = "connection_timeout"
功能:获取 connect 操作的超时时间,单位 ms。
类型:String
static const Database
public static const Database = "database"
功能:获取数据库名称。
类型:String
static const Driver
public static const Driver = "driver"
功能:获取数据库驱动名称,比如 postgres,opengauss。
类型:String
static const Encoding
public static const Encoding = "encoding"
功能:获取数据库字符集编码类型。
类型:String
static const FetchRows
public static const FetchRows = "fetch_rows"
功能:获取每次获取额外数据时从数据库中提取的行数。
类型:String
static const Host
public static const Host = "host"
功能:获取数据库服务器主机名或者 IP 地址。
类型:String
static const Password
public static const Password = "password"
功能:获取连接数据库的密码。
类型:String
static const QueryTimeout
public static const QueryTimeout = "query_timeout"
功能:获取 query 操作的超时时间,单位 ms。
类型:String
static const SSLCA
public static const SSLCA = "ssl.ca"
功能:证书颁发机构( CA )证书文件的路径名。
类型:String
static const SSLCert
public static const SSLCert = "ssl.cert"
功能:客户端 SSL 公钥证书文件的路径名。
类型:String
static const SSLKey
public static const SSLKey = "ssl.key"
功能:客户端 SSL 私钥文件的路径名。
类型:String
static const SSLKeyPassword
public static const SSLKeyPassword = "ssl.key.password"
功能:客户端 SSL 私钥文件的密码。
类型:String
static const SSLMode
public static const SSLMode = "ssl.mode"
功能:获取 SSLMode 传输层加密模式。
类型:String
static const SSLModeDisabled
public static const SSLModeDisabled = "ssl.mode.disabled"
功能:建立未加密的连接。
类型:String
static const SSLModePreferred
public static const SSLModePreferred = "ssl.mode.preferred"
功能:如果服务器支持加密连接,则建立加密连接; 如果无法建立加密连接,则回退到未加密连接,这是 SSLMode 的默认值。
类型:String
static const SSLModeRequired
public static const SSLModeRequired = "ssl.mode.required"
功能:如果服务器支持加密连接,则建立加密连接。如果无法建立加密连接,则连接失败。
类型:String
static const SSLModeVerifyCA
public static const SSLModeVerifyCA = "ssl.mode.verify_ca"
功能:SSLModeVerifyCA 和 SSLModeRequired 类似,但是增加了校验服务器证书,如果校验失败,则连接失败。
类型:String
static const SSLModeVerifyFull
public static const SSLModeVerifyFull = "ssl.mode.verify_full"
功能:SSLModeVerifyFull 和 SSLModeVerifyCA 类似,但通过验证服务器证书中的标识与客户端连接的主机名是否匹配,来执行主机名身份验证。
类型:String
static const SSLSni
public static const SSLSni = "ssl.sni"
功能:客户端通过该标识在握手过程开始时试图连接到哪个主机名。
类型:String
static const Tls12Ciphersuites
public static const Tls12Ciphersuites = "tls1.2.ciphersuites"
功能:此选项指定客户端允许使用 TLSv1.2 及以下的加密连接使用哪些密码套件。 值为冒号分隔的字符串,比如 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_DHE_RSA_WITH_AES_128_CBC_SHA"。
类型:String
static const Tls13Ciphersuites
public static const Tls13Ciphersuites = "tls1.3.ciphersuites"
功能:此选项指定客户端允许使用 TLSv1.3 的加密连接使用哪些密码套件。 值为冒号分隔的字符串,比如 "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"。
类型:String
static const TlsVersion
public static const TlsVersion = "tls.version"
功能:支持的 TLS 版本号,值为逗号分隔的字符串,比如 "TLSv1.2,TLSv1.3"。
类型:String
static const URL
public static const URL = "url"
功能:获取数据库连接 URL 字符串。
类型:String
static const UpdateTimeout
public static const UpdateTimeout = "update_timeout"
功能:获取 update 操作的超时时间,单位 ms。
类型:String
static const Username
public static const Username = "username"
功能:获取连接数据库的用户名。
类型:String
class SqlReal (deprecated)
public class SqlReal <: SqlDbType {
public init(v: Float32)
}
功能:浮点数,对应仓颉 Float32 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlReal (deprecated)。
类型:String
prop value
public mut prop value: Float32
功能:该数据的值。
类型:Float32
init(Float32)
public init(v: Float32)
功能:根据传入参数 v 构造一个 SqlReal (deprecated) 实例。
参数:
- v: Float32 - 传入的数据。
class SqlSmallInt (deprecated)
public class SqlSmallInt <: SqlDbType {
public init(v: Int16)
}
功能:小整数,对应仓颉 Int16 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlSmallInt (deprecated)。
类型:String
prop value
public mut prop value: Int16
功能:该数据的值。
类型:Int16
init(Int16)
public init(v: Int16)
功能:根据传入参数 v 构造一个 SqlSmallInt (deprecated) 实例。
参数:
- v: Int16 - 传入的数据。
class SqlTime (deprecated)
public class SqlTime <: SqlDbType {
public init(v: DateTime)
}
功能:时间,仅时分秒毫秒有效,对应仓颉 DateTime 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlTime (deprecated)。
类型:String
prop value
public mut prop value: DateTime
功能:该数据的值。
类型:DateTime
init(DateTime)
public init(v: DateTime)
功能:根据传入参数 v 构造一个 SqlTime (deprecated) 实例。
参数:
- v: DateTime - 传入的数据。
class SqlTimeTz (deprecated)
public class SqlTimeTz <: SqlDbType {
public init(v: DateTime)
}
功能:带时区的时间,仅时分秒毫秒时区有效,对应仓颉 DateTime 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlTimeTz (deprecated)。
类型:String
prop value
public mut prop value: DateTime
功能:该数据的值。
类型:DateTime
init(DateTime)
public init(v: DateTime)
功能:根据传入参数 v 构造一个 SqlTimeTz (deprecated) 实例。
参数:
- v: DateTime - 传入的数据。
class SqlTimestamp (deprecated)
public class SqlTimestamp <: SqlDbType {
public init(v: DateTime)
}
功能:时间戳,对应仓颉 DateTime 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlTimestamp (deprecated)。
类型:String
prop value
public mut prop value: DateTime
功能:该数据的值。
类型:DateTime
init(DateTime)
public init(v: DateTime)
功能:根据传入参数 v 构造一个 SqlTimestamp (deprecated) 实例。
参数:
- v: DateTime - 传入的数据。
class SqlVarBinary (deprecated)
public class SqlVarBinary <: SqlDbType {
public init(v: Array<Byte>)
}
功能:变长二进制字符串,对应仓颉 Array<Byte> 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlVarBinary (deprecated)。
类型:String
prop value
public mut prop value: Array<Byte>
功能:该数据的值。
init(Array<Byte>)
public init(v: Array<Byte>)
功能:根据传入参数 v 构造一个 SqlVarBinary (deprecated) 实例。
参数:
class SqlVarchar (deprecated)
public class SqlVarchar <: SqlDbType {
public init(v: String)
}
功能:变长字符串,对应仓颉 String 类型。
注意:
未来版本即将废弃不再使用,使用仓颉原生类型替代。
父类型:
prop name
public prop name: String
功能:类型名称,即 SqlVarchar (deprecated)。
类型:String
prop value
public mut prop value: String
功能:该数据的值。
类型:String
init(String)
public init(v: String)
功能:根据传入参数 v 构造一个 SqlVarchar (deprecated) 实例。
参数:
- v: String - 传入的数据。
枚举
enum ConnectionState
public enum ConnectionState <: Equatable<ConnectionState> {
| Broken
| Closed
| Connecting
| Connected
}
功能:描述与数据源连接的当前状态。
父类型:
Broken
Broken
功能:表示与数据源的连接已中断。只有在 Connected 之后才可能发生这种情况。
Closed
Closed
功能:表示连接对象已关闭。
Connected
Connected
功能:表示连接对象已与数据源连接上。
Connecting
Connecting
功能:表示连接对象正在与数据源连接。
operator func !=(ConnectionState)
public operator func !=(rhs: ConnectionState): Bool
功能:判断数据源连接状态是否不同。
参数:
- rhs: ConnectionState - 数据源连接状态。
返回值:
- Bool - 传入数据源连接状态与当前状态相同则返回
false,否则返回true。
operator func ==(ConnectionState)
public operator func ==(rhs: ConnectionState): Bool
功能:判断数据源连接状态是否相同。
参数:
- rhs: ConnectionState - 数据源连接状态。
返回值:
- Bool - 传入数据源连接状态与当前状态相同则返回
true,否则返回false。
enum TransactionAccessMode
public enum TransactionAccessMode <: ToString & Hashable & Equatable<TransactionAccessMode> {
| ReadOnly
| ReadWrite
| Unspecified
}
功能:事务读写模式。
父类型:
ReadOnly
ReadOnly
功能:表示只读模式。
ReadWrite
ReadWrite
功能:表示读 + 写模式。
Unspecified
Unspecified
功能:表示未指定的事务读写模式。其行为取决于具体的数据库服务器。
func hashCode()
public func hashCode(): Int64
功能:获取事务读写模式的哈希值。
返回值:
- Int64 - 事务读写模式的哈希值。
func toString()
public func toString(): String
功能:返回事务读写模式的字符串表示。枚举值和字符串的对应关系如下表所示:
| 枚举值 | 字符串 |
|---|---|
| ReadOnly | "Read Only" |
| ReadWrite | "Read Write" |
| Unspecified | "Unspecified" |
返回值:
- String - 事务读写模式的字符串。
operator func !=(TransactionAccessMode)
public operator func != (rhs: TransactionAccessMode): Bool
功能:判断两个 TransactionAccessMode 是否不相等。
参数:
- rhs: TransactionAccessMode - 传入 TransactionAccessMode 的枚举值。
返回值:
- Bool - 如果不相等,则返回
true,否则返回false。
operator func ==(TransactionAccessMode)
public operator func == (rhs: TransactionAccessMode): Bool
功能:判断两个 TransactionAccessMode 是否相等。
参数:
- rhs: TransactionAccessMode - 传入 TransactionAccessMode 的枚举值。
返回值:
- Bool - 如果相等,则返回
true,否则返回false。
enum TransactionDeferrableMode
public enum TransactionDeferrableMode <: ToString & Hashable & Equatable<TransactionDeferrableMode> {
| Deferrable
| NotDeferrable
| Unspecified
}
功能:事务的延迟模式。
父类型:
Deferrable
Deferrable
功能:表示可延迟。
说明:
延迟事务是指在前滚阶段结束时未提交的事务,并且遇到了阻止其回滚的错误。因为事务无法回滚,所以它被延迟。
NotDeferrable
NotDeferrable
功能:表示不可延迟。
Unspecified
Unspecified
功能:未指定的事务延迟模式,其行为取决于具体的数据库服务器。
func hashCode()
public func hashCode(): Int64
功能:获取事务延迟模式的哈希值。
返回值:
- Int64 - 事务延迟模式的哈希值。
func toString()
public func toString(): String
功能:返回事务延迟模式的字符串表示。枚举值和字符串的对应关系如下表所示:
| 枚举值 | 字符串 |
|---|---|
| Deferrable | "Deferrable" |
| NotDeferrable | "Not Deferrable" |
| Unspecified | "Unspecified" |
返回值:
- String - 事务延迟模式的字符串。
operator func !=(TransactionDeferrableMode)
public operator func != (rhs: TransactionDeferrableMode): Bool
功能:判断两个 TransactionDeferrableMode 是否不相等。
参数:
- rhs: TransactionDeferrableMode - 传入 TransactionDeferrableMode 的枚举值。
返回值:
- Bool - 如果不相等,则返回
true,否则返回false。
operator func ==(TransactionDeferrableMode)
public operator func == (rhs: TransactionDeferrableMode): Bool
功能:判断两个 TransactionDeferrableMode 是否相等。
参数:
- rhs: TransactionDeferrableMode - 传入 TransactionDeferrableMode 的枚举值。
返回值:
- Bool - 如果相等,则返回
true,否则返回false。
enum TransactionIsoLevel
public enum TransactionIsoLevel <: ToString & Hashable & Equatable<TransactionIsoLevel> {
| Chaos
| Linearizable
| ReadCommitted
| ReadUncommitted
| RepeatableRead
| Serializable
| Snapshot
| Unspecified
}
功能:事务隔离级别。
说明:
事务隔离定义了数据库系统中,一个事务中操作的结果在何时以何种方式对其他并发事务操作可见。
父类型:
Chaos
Chaos
功能:表示无法覆盖来自隔离级别更高的事务的挂起更改。
Linearizable
Linearizable
功能:表示事务线性化。
说明:
区别于串行化(Serializable),线性化主要强调单个对象上(即 db 行或 nosql 记录)的一组单个操作(比如一系列读写操作),线性化保证这些操作严格按真实时间顺序执行。比如当您查看单个对象上的操作子集时,线性化是相关的。
ReadCommitted
ReadCommitted
功能:表示事务等待,直到其他事务写锁定的行被解锁;这将防止它读取任何“脏”数据。
ReadUncommitted
ReadUncommitted
功能:表示事务之间不隔离。
RepeatableRead
RepeatableRead
功能:表示事务可重复读。对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改。
Serializable
Serializable
功能:表示事务可串行化。此隔离级别下,所有事务顺序执行,因此,脏读、不可重复读、幻读都不会出现。
Snapshot
Snapshot
功能:表示快照隔离通过使用行版本控制避免了大多数锁定和阻止。
Unspecified
Unspecified
功能:未指定的事务隔离级别,其行为取决于具体的数据库服务器。
func hashCode()
public func hashCode(): Int64
功能:获取事务隔离级别的哈希值。
返回值:
- Int64 - 事务隔离级别的哈希值。
func toString()
public func toString(): String
功能:返回事务隔离级别的字符串表示。枚举值和字符串的对应关系如下表所示:
| 枚举值 | 字符串 |
|---|---|
| Chaos | "Chaos" |
| Linearizable | "Linearizable" |
| ReadCommitted | "Read Committed" |
| ReadUncommitted | "Read Uncommitted" |
| RepeatableRead | "Repeatable Read" |
| Serializable | "Serializable" |
| Snapshot | "Snapshot" |
| Unspecified | "Unspecified" |
返回值:
- String - 事务隔离级别的字符串。
operator func !=(TransactionIsoLevel)
public operator func != (rhs: TransactionIsoLevel): Bool
功能:判断两个 TransactionIsoLevel 是否不相等。
参数:
- rhs: TransactionIsoLevel - 传入的 TransactionIsoLevel。
返回值:
- Bool - 如果不相等,则返回
true,否则返回false。
operator func ==(TransactionIsoLevel)
public operator func == (rhs: TransactionIsoLevel): Bool
功能:判断两个 TransactionIsoLevel 是否相等。
参数:
- rhs: TransactionIsoLevel - 传入的 TransactionIsoLevel。
返回值:
- Bool - 如果相等,则返回
true,否则返回false。
异常类
class SqlException
public open class SqlException <: Exception {
public init()
public init(message: String)
public init(message: String, sqlState: String, errorCode: Int64)
}
功能:用于处理 sql 相关的异常。
父类型:
prop errorCode
public prop errorCode: Int64
功能:数据库供应商返回的整数错误代码。
类型:Int64
prop message
public override prop message: String
功能:获取异常信息字符串。
类型:String
prop sqlState
public prop sqlState: String
功能:长度为五个字符的字符串,是数据库系统返回的最后执行的 sql 语句状态。
类型:String
init()
public init()
功能:无参构造函数。
init(String)
public init(message: String)
功能:根据异常信息创建 SqlException 实例。
参数:
- message: String - 异常信息。
init(String, String, Int64)
public init(message: String, sqlState: String, errorCode: Int64)
功能:根据异常信息、SQL语句状态、错误码信息,创建 SqlException 实例。
参数:
- message: String - 异常信息。
- sqlState: String - 长度为五个字符的字符串,是数据库系统返回的最后执行的 sql 语句状态。
- errorCode: Int64 - 数据库供应商返回的整数错误代码。
获取数据库连接示例
import std.database.sql.*
main(): Unit {
// 获取已经注册的驱动
let drv = DriverManager.getDriver("opengauss") ?? return
// 设置打开数据源的选项
let opts = [
("cachePrepStmts", "true"),
("prepStmtCacheSize", "250"),
("prepStmtCacheSqlLimit", "2048")
]
// 通过连接路径和选项打开数据源
let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", opts)
// 设置连接选项
ds.setOption(SqlOption.SSLMode, SqlOption.SSLModeVerifyCA)
ds.setOption(SqlOption.SSLCA, "ca.crt")
ds.setOption(SqlOption.SSLCert, "server.crt")
ds.setOption(SqlOption.SSLKey, "server.key")
ds.setOption(SqlOption.SSLKeyPassword, "key_password")
ds.setOption(SqlOption.TlsVersion, "TLSv1.2,TLSv1.3")
// 返回一个可用连接
ds.connect()
}
删除表、创建表示例
import std.database.sql.*
main() {
// 获取数据库链接示例
let drv = DriverManager.getDriver("opengauss") ?? return
let opts = [
("cachePrepStmts", "true"),
("prepStmtCacheSize", "250"),
("prepStmtCacheSqlLimit", "2048")
]
let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", opts)
let conn = ds.connect()
// 删除和创建表
var stmt = conn.prepareStatement("DROP TABLE IF EXISTS test")
var ur = stmt.update()
println("Update Result: ${ur.rowCount} ${ur.lastInsertId}")
stmt.close()
stmt = conn.prepareStatement("CREATE TABLE test(id SERIAL PRIMARY KEY, name VARCHAR(20) NOT NULL, age INT)")
ur = stmt.update()
println("Update Result: ${ur.rowCount} ${ur.lastInsertId}")
stmt.close()
}
执行数据库操作语句示例
插入数据
import std.database.sql.*
main() {
// 获取数据库连接示例
let drv = DriverManager.getDriver("opengauss") ?? return
let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", [])
let conn = ds.connect()
// 插入数据 1
var stmt = conn.prepareStatement("INSERT INTO test VALUES(?, ?)")
stmt.set<String>(0, "li lei")
stmt.set<Int32>(1, 12)
var ur = stmt.update()
println("Update Result: ${ur.rowCount} ${ur.lastInsertId}")
// 插入数据 2
stmt.set<String>(0, "han meimei")
stmt.set<Int32>(1, 13)
ur = stmt.update()
println("Update Result: ${ur.rowCount} ${ur.lastInsertId}")
// 如果需要在插入数据后返回插入的 id 值,可以参考如下方式:
let sql = "INSERT INTO test (name, age) VALUES (?,?) RETURNING id, name"
try (stmt = conn.prepareStatement(sql)) {
stmt.set<String>(0, "li lei")
stmt.set<Int32>(1, 12)
let qr = stmt.query()
while (qr.next()) {
println("id = ${qr.get<Int32>(0)}, name=${qr.get<String>(1)}")
}
} catch (e: Exception) {
e.printStackTrace()
}
stmt.close()
}
查询数据
import std.database.sql.*
main() {
// 获取数据库连接示例
let drv = DriverManager.getDriver("opengauss") ?? return
let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", [])
let conn = ds.connect()
// 查询操作示例
var stmt = conn.prepareStatement("select * from test where name = ?")
stmt.set<String>(0, "li lei")
let qr = stmt.query()
while (qr.next()) {
println("id = ${qr.get<Int32>(0)}, name = ${qr.get<String>(1)}, age=${qr.get<Int32>(2)}")
}
stmt.close()
}
更新数据
import std.database.sql.*
main() {
// 获取数据库连接示例
let drv = DriverManager.getDriver("opengauss") ?? return
let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", [])
let conn = ds.connect()
// 更新操作示例
var stmt = conn.prepareStatement("update test set age = ? where name = ?")
stmt.set<Int32>(0, 15)
stmt.set<String>(1, "li lei")
var ur = stmt.update()
println("Update Result: ${ur.rowCount} ${ur.lastInsertId}")
stmt.close()
}
删除数据
import std.database.sql.*
main() {
// 获取数据库连接示例
let drv = DriverManager.getDriver("opengauss") ?? return
let ds = drv.open("opengauss://testuser:testpwd@localhost:5432/testdb", [])
let conn = ds.connect()
// 删除操作示例
var stmt = conn.prepareStatement("delete from test where name = ?")
stmt.set<String>(0, "li lei")
var ur = stmt.update()
println("Update Result: ${ur.rowCount} ${ur.lastInsertId}")
stmt.close()
}
执行事务控制语句示例
普通数据库事务
import std.database.sql.*
import std.time.*
main() {
let SQL_INSERT = "INSERT INTO EMPLOYEE (NAME, SALARY, CREATED_DATE) VALUES (?, ?, ?)"
let drv = DriverManager.getDriver("opengauss") ?? return
let db = drv.open("opengauss://localhost:5432/testdb")
try(cn = db.connect()) {
let psInsert = cn.prepareStatement(SQL_INSERT)
// 创建事务对象
let tx = cn.createTransaction()
try {
// 插入第一条数据
psInsert.set<String>(0, "mkyong")
psInsert.set<Array<Byte>>(1, Array<Byte>(1, repeat: 10))
psInsert.set<DateTime>(2, DateTime.now())
psInsert.update()
// 插入第二条数据
psInsert.set<String>(0, "kungfu")
psInsert.set<Array<Byte>>(1, Array<Byte>(1, repeat: 20))
psInsert.set<DateTime>(2, DateTime.now())
psInsert.update()
// 如果连接到数据库,测试回滚 SQLException:未为参数3指定值。
psInsert.set<String>(0, "mkyong")
psInsert.set<Array<Byte>>(1, Array<Byte>(5, {i => UInt8(i + 1)}))
psInsert.update()
// 提交事务
tx.commit()
} catch (e1: SqlException) {
e1.printStackTrace()
try {
// 发生异常,回滚所有事务
tx.rollback()
} catch (e2: SqlException) {
// 如果回滚失败
e2.printStackTrace()
}
}
} catch (e: SqlException) {
// 如果连接失败
e.printStackTrace()
}
}
事务保存点
如果数据库事务支持保存点,可以参考如下样例:
import std.database.sql.*
import std.time.*
main() {
let SQL_INSERT = "INSERT INTO EMPLOYEE (NAME, SALARY, CREATED_DATE) VALUES (?, ?, ?)"
let drv = DriverManager.getDriver("opengauss") ?? return
let db = drv.open("opengauss://localhost:5432/testdb")
try(cn = db.connect()) {
let psInsert = cn.prepareStatement(SQL_INSERT)
let tx = cn.createTransaction()
try {
// 创建保存点 1
tx.save("save1")
psInsert.set<String>(0, "mkyong")
psInsert.set<Array<Byte>>(1, Array<Byte>(1, repeat: 10))
psInsert.set<DateTime>(2, DateTime.now())
psInsert.update()
// 创建保存点 2
tx.save("save2")
psInsert.set<String>(0, "kungfu")
psInsert.set<Array<Byte>>(1, Array<Byte>(1, repeat: 20))
psInsert.set<DateTime>(2, DateTime.now())
psInsert.update()
// 创建保存点 3
tx.save("save3")
psInsert.set<String>(0, "mkyong")
psInsert.set<Array<Byte>>(1, Array<Byte>(5, {i => UInt8(i + 1)}))
psInsert.update()
// 回滚到保存点 2
tx.rollback("save2")
// 提交事务
tx.commit()
} catch (e1: SqlException) {
e1.printStackTrace()
try {
// 发生异常,回滚所有事务
tx.rollback()
} catch (e2: SqlException) {
e2.printStackTrace()
}
}
} catch (e: SqlException) {
e.printStackTrace()
}
}
std.deriving
std.deriving 提供了一种根据类、结构体和枚举类型的字段、属性等自动生成接口实现的方法。
当前支持自动生成以下接口的实现:
更多示例详见 Deriving 用户手册。
API 列表
宏
| 宏名 | 功能 |
|---|---|
| Derive | Derive 是一个核心宏,其仅可修饰结构体、类或枚举等声明,对被修饰的声明自动扩展接口。 |
| DeriveExclude | DeriveExclude 可为已被 @Derive 宏修饰的声明排除不需要处理的字段,字段默认被 Deriving 处理。 |
| DeriveInclude | DeriveInclude 可为已被 @Derive 宏修饰的声明增加需要处理的属性,属性默认情况不会被 Deriving 处理。 |
| DeriveOrder | DeriveOrder 可为已被 @Derive 宏修饰的声明指定处理字段和属性的顺序,通常对 Comparable 接口有意义。 |
宏
@Derive 宏
功能:Derive 是一个核心宏,其仅可修饰结构体、类或枚举等声明,对被修饰的声明自动扩展接口。
@DeriveExclude 宏
功能:DeriveExclude 可为已被 @Derive 宏修饰的声明排除不需要处理的字段,字段默认被 Deriving 处理。
@DeriveInclude 宏
功能:DeriveInclude 可为已被 @Derive 宏修饰的声明增加需要处理的属性,属性默认情况不会被 Deriving 处理。
@DeriveOrder 宏
功能:DeriveOrder 可为已被 @Derive 宏修饰的声明指定处理字段和属性的顺序,通常对 Comparable 接口有意义。
Deriving
一个简单示例:
import std.deriving.*
@Derive[ToString]
class User {
User(
let name: String,
let id: Int
) {}
}
main() {
println(User("root", 0)) // -> "User(name = root, id = 0)"
}
当 @Derive[ToString] 应用于类或结构体时, Deriving 会收集和使用类或结构体的可变和不可变字段,包括在主构造函数中指定的字段,并自动实现 ToString 的方法。当 @Derive[ToString] 应用于枚举时, Deriving 将收集枚举的构造函数参数。静态字段和属性将不会被收集和使用,另外, Deriving 收集的字段不允许存在私有字段,否则将抛出编译错误。
收集到的字段用于 Deriving 时,其类型需要实现目标接口,以便将字段结果组合在一起。例如,当处理 ToString 时,生成的代码将在所有收集到的字段上调用 toString ,然后将结果与对应的字段名称连接成一个字符串。如果其中一个字段的类型不支持 ToString ,则会抛出编译错误并且 Deriving 无法完成。
注意:
标记为派生的类应该是最终的:它不应该是开放的、抽象的或
sealed的。
有些字段可能具有特殊含义,它们的值没有多大意义,则可通过在这些字段上应用 @DeriveExclude 来排除这些字段:
@Derive[ToString]
class User {
User(let name: String) {}
@DeriveExclude
let lazyHashCode = 0 // it will not be printed because it's excluded
}
默认情况 Deriving 仅使能字段,对于属性则需要通过 @DeriveInclude 来显式使能:
@Derive[ToString]
class User {
User(
let id: Int
) {}
@DeriveInclude
prop name: String {
get() { passwdFile.getUserName(id) }
}
}
main() {
println(User(0)) // -> "User(id = 0, name = root)"
}
请注意,因为属性 name 是在 id 之后声明的,因此打印的顺序为先 id 后 name 。
如果需要更改打印的顺序,可以使用 @DeriveOrder :
@Derive[ToString]
@DeriveOrder[name, id]
class User {
User(
let id: Int
) {}
@DeriveInclude
prop name: String {
get() { "s_${id}" }
}
}
main() {
println(User(0)) // -> "User(name = s_0, id = 0)"
}
常见的 Deriving 语法
@Derive 宏支持以逗号分隔的接口名称列表。此外,该宏可以重复多次被调用,但所有 @Derive 宏调用都应位于声明的顶部,而其他宏(如 @DeriveOrder )应始终位于其后。
支持的接口列表的顺序没有影响。
@Derive[ToString, Hashable]
@Derive[Equatable]
@DeriveOrder[currency,price,quantity]
struct Order {}
当 Deriving 多个相交的接口时,例如,Comparable 还包括 Equatable ,则允许两者同时存在,等同于仅有范围最广的一个:
@Derive[Comparable] // does also generate Equatable
等同于:
@Derive[Comparable, Equatable]
包含和排除
默认情况下会处理所有字段,包括定义为主构造函数参数的字段。
当需要排除某个字段时,可以对其应用 @DeriveExclude :
@Derive[ToString]
struct S {
S(let id: Int) { key = "s_${id}" }
@DeriveExclude
let key: String
}
默认情况下不处理属性,需要通过 @DeriveInclude 包含属性。
@Derive[ToString]
struct S {
S(let id: Int) {}
@DeriveInclude
prop key: String {
get() { "s_${id}" }
}
}
被 Deriving 的字段和属性都不能是 private 的。因此,private 的字段或者属性应被除外或者使其为包内可见属性。
注意:
静态的字段和属性始终会被忽略,因此它们都不能被
@DeriveInclude和@DeriveExclude修饰。
支持的接口
当前仅支持如下接口:
ToStringHashableEquatableComparable
暂不支持用户自定义的接口。
变更顺序
在对由多个字段组成的复杂类型的实例进行排序和比较时,测试字段的顺序通常很重要。默认情况下,所有字段都按声明顺序考虑。可以使用 @DeriveOrder 宏修改顺序。
@Derive[Comparable, ToString]
struct Floor {
Floor(
let level: Int,
let building: Int
) {}
}
main() {
let floors = [
Floor(1, 2),
Floor(3, 2),
Floor(2, 1)
]
floors.sort()
for (f in floors) { println(f) }
}
上述示例将打印以下内容,看起来顺序没有很大影响。
Floor(level = 1, building = 2)
Floor(level = 2, building = 1)
Floor(level = 3, building = 2)
但是当我实现 Comparable 时,不同的顺序将影响结果。
@Derive[Comparable, ToString]
@DeriveOrder[building, level]
struct Floor {
Floor(
let level: Int,
let building: Int
) {}
}
此时,结果将首先按 building 排序,然后按 level 排序:
Floor(building = 1, level = 2)
Floor(building = 2, level = 1)
Floor(building = 2, level = 3)
泛型
实现泛型类型的接口通常需要应用约束,以便类型仅在某些条件下实现接口。例如:
class Cell<T> {
Cell(let value: T) {}
}
此时可能希望仅当单元格的值可打印时才能够打印该单元格。为了实现它,编写一个带有约束的扩展:
extend <T> Cell<T> <: ToString where T <: ToString {
public func toString(): String {
"Cell(value = ${value})"
}
}
当使用 Deriving 时,它会默认尝试对所有泛型参数应用约束,因此以下内容与上面的扩展相同:
@Derive[ToString]
class Cell<T> {
Cell(let value: T) {}
}
然而在某些情况下,默认行为并不符合期望。此时,可使用 @Derive 内部的 where 来覆盖默认约束:
interface PrintableCellValue <: ToString { ... }
@Derive[ToString where T <: PrintableCellValue]
class Cell<T> {}
请注意,在上面的示例中,自定义约束仅适用于 ToString ,因此如果需要对所有接口进行约束,则应单独为每个接口重复此动作。
@Derive[ToString where T <: PrintableCellValue]
@Derive[Hashable where T <: PrintableCellValue & Hashable]
class Cell<T> {}
性能说明
由于 Deriving 是基于仓颉宏的,不涉及任何反射,因此 Deriving 实现的运行时性能与手写相当。但是,Deriving 涉及编译时的代码转换,因此它会影响编译时间。
std.env
功能介绍
env 包提供当前进程的相关信息与功能、包括环境变量、命令行参数、标准流、退出程序。也提供标准输入、标准输出、标准错误进行交互的方法。
本包提供多平台统一操控能力,目前支持 Linux 平台,macOS 平台,Windows 平台。
本包提供 getStdErr()、getStdIn() 、getStdOut(),用于获取这三个标准流。
- ConsoleReader 封装了标准输入流的相关功能,可以通过相关的
read方法从标准输入中读取数据。 - ConsoleWriter 封装了标准输出、标准错误流的相关功能,ConsoleWriter 封装了一系列的
write方法,提供了向标准输出、标准错误写入数据的能力。
标准输入(stdin)、标准输出(stdout)和标准错误(stderr)是计算机操作系统中常见的三个流。
标准输入是程序从用户获取输入数据的流,通常是键盘输入。标准输出是程序向用户输出结果的流,通常是屏幕输出。标准错误是程序在发生错误时输出错误信息的流,通常也是屏幕输出。
在 Unix/Linux 系统中,标准输入、标准输出和标准错误分别对应文件描述符 0、1 和 2。程序可以使用这些文件描述符来读取和写入数据。例如,可以使用重定向符号将标准输出重定向到文件中,或将标准错误输出重定向到另一个程序的标准输入中。
API 列表
类
| 类名 | 功能 |
|---|---|
| ConsoleReader | 提供从标准输入读取字符或者字符串的功能。 |
| ConsoleWriter | 提供向标准输出或者标准错误流写入字符或者字符串的功能。 |
函数
| 函数 | 功能 |
|---|---|
| atExit() | 注册回调函数,当前进程退出时执行注册函数。 |
| exit() | 进程退出函数。 |
| getCommand() | 获取当前进程命令。 |
| getCommandLine() | 获取当前进程命令行。 |
| getHomeDirectory() | 获取当前进程 home 目录的路径。 |
| getProcessId() | 获取当前进程 id。 |
| getStdErr() | 获取当前进程标准错误流。 |
| getStdIn() | 获取当前进程标准错误流。 |
| getStdOut() | 获取当前进程标准输出流。 |
| getTempDirectory() | 获取当前进程临时目录的路径。 |
| getVariable() | 获取当前进程指定名称的环境变量值。 |
| getVariables() | 获取当前进程进程环境变量。 |
| getWorkingDirectory() | 获取当前进程工作路径。 |
| removeVariable() | 通过指定环境变量名称移除环境变量。 |
| setVariable() | 设置当前进程一对环境变量。 |
异常类
| 异常类名 | 功能 |
|---|---|
| EnvException | env 包的异常类。 |
函数
func atExit(() -> Unit)
public func atExit(callback: () -> Unit): Unit
功能:注册回调函数,当前进程退出时执行注册函数。
注意:
请不要使用 C 语言 atexit 函数,避免出现不可期问题。
参数:
- callback: () ->Unit - 需要被注册回调的函数。
func exit(Int64)
public func exit(code: Int64): Nothing
功能:注册回调函数,当前进程退出时执行注册函数。
参数:
- code: Int64 - 当前进程退出状态码。
func getCommand()
public func getCommand(): String
功能:获取进程命令。
返回值:
- String - 当前进程命令。
异常:
- EnvException - 当进程不存在或对应进程为僵尸进程,无法获取进程名时,抛出异常。
func getCommandLine()
public func getCommandLine(): Array<String>
功能:获取当前进程命令行。Windows 平台当前进程可获取,其他场景下无法在非特权 API 下获取到本属性,暂不支持获取。
返回值:
异常:
- EnvException - 当进程不存在或对应进程为僵尸进程,或在 Windows 平台下暂不支持场景,无法获取进程命令行时,抛出异常。
func getHomeDirectory()
public func getHomeDirectory(): Path
功能:获取当前进程 home 目录的路径。
返回值:
- Path - 当前进程 home 目录的路径。
func getProcessId()
public func getProcessId(): Int
功能:获取当前进程 id。
返回值:
- Int - 当前进程 id。
func getStdErr()
public func getStdErr(): ConsoleWriter
功能:获取当前进程标准错误流。
返回值:
- ConsoleWriter - 进程标准错误流。
func getStdIn()
public func getStdIn(): ConsoleReader
功能:获取当前进程标准输入流。
返回值:
- ConsoleReader - 进程标准输入流。
func getStdOut()
public func getStdOut(): ConsoleWriter
功能:获取当前进程标准输出流。
返回值:
- ConsoleWriter - 进程标准输出流。
func getTempDirectory()
public func getTempDirectory(): Path
功能:获取当前进程临时目录的路径。从环境变量中获取 TMPDIR、TMP、TEMP 和 TEMPDIR 环境变量。如果以上值在环境变量中均不存在,则默认返回 /tmp 目录。
返回值:
- Path - 当前进程临时目录的路径。
func getVariable(String)
public func getVariable(key: String): ?String
功能:获取当前进程指定名称的环境变量值。
参数:
- key: String - 指定名称。
返回值:
- ?String - 当前进程指定名称的环境变量值。
异常:
- IllegalArgumentException - 当函数参数 key 包含空字符时,抛出异常。
func getVariables()
public func getVariables(): Array<(String, String)>
功能:获取当前进程环境变量。Windows 平台当前进程可获取,其他场景下无法在非特权 API 下获取到本属性,暂不支持获取。
返回值:
异常:
- EnvException - 当进程不存在或对应进程为僵尸进程,或在 Windows 平台下暂不支持场景,无法获取进程环境变量时,抛出异常。
func getWorkingDirectory()
public func getWorkingDirectory(): Path
功能:获取当前进程工作路径。Windows 平台当前进程可获取,其他场景下无法在非特权 API 下获取到本属性,暂不支持获取。
返回值:
- Path - 当前进程工作路径。
异常:
- EnvException - 当进程不存在或对应进程为僵尸进程,或在 Windows 平台下暂不支持场景,无法获取进程工作路径时,抛出异常。
func removeVariable(String)
public func removeVariable(key: String): Unit
功能:通过指定环境变量名称移除环境变量。
参数:
- key: String - 环境变量名称。
异常:
- IllegalArgumentException - 当函数参数 k 包含空字符时,抛出异常时,抛出异常。
func setVariable(String, String)
public func setVariable(key: String, value: String): Unit
功能:用于设置一对环境变量。如果设置了同名环境变量,原始环境变量值将被覆盖。
说明:
Windows 下如果传入的参数 v 是空字符串,那么会从环境中移除变量 k。
参数:
异常:
- IllegalArgumentException - 当函数参数 key 或 value 中包含空字符时,抛出异常。
类
class ConsoleReader
public class ConsoleReader <: InputStream
功能:提供从控制台读出数据并转换成字符或字符串的功能。
该类型无法构造实例,只能通过 getStdIn() 获取实例。
读操作是同步的,内部设有缓存区来保存控制台输入的内容,当到达控制台输入流的结尾时,控制台读取函数将返回None。
说明:
ConsoleReader 只有一个实例,所有方法共享同一个缓存区,相关
read方法返回None的情形有:
- 将标准输入重定向到文件时,读取到文件结尾EOF。
- Linux 环境,按下
Ctrl+D。- Windows 环境,按下
Ctrl+Z后加回车。
父类型:
func read()
public func read(): ?Rune
功能:从标准输入中读取下一个字符。
返回值:
异常:
- IllegalArgumentException - 当输入不符合
UTF-8编码的字符串时,抛此异常。
示例:
import std.env.*
main() {
getStdOut().write("请输入信息:")
var c = getStdIn().read() // 输入:abc
var r = c.getOrThrow()
getStdOut().write("输入的信息为:")
getStdOut().writeln(r)
return
}
运行结果:
请输入信息:abc
输入的信息为:a
func read(Array<Byte>)
public func read(arr: Array<Byte>): Int64
功能:从标准输入中读取并放入 arr 中。
注意:
该函数存在风险,可能读取出来的结果恰好把
UTF-8 code point从中截断,如果发生截断,将导致该 Array<Byte> 转换成字符串的结果不正确或抛出异常。
参数:
返回值:
- Int64 - 返回读取到的字节长度。
示例:
import std.env.*
main() {
var arr = Array<Byte>(3, repeat: 0)
getStdOut().write("请输入信息:")
getStdIn().read(arr) // 输入:567
getStdOut().write("输入后的数组为:")
getStdOut().writeln(arr)
return
}
运行结果:
请输入信息:567
输入后的数组为:567
func readToEnd()
public func readToEnd(): ?String
功能:从标准输入中读取所有字符。
直到读取到文件结束符EOF,或者在 Linux 上键入 Ctrl+D 或在 Windows 上键入 Ctrl+Z + 回车结束。读取到字符,返回 ?String,否则返回 None。读取失败时会返回 None,该接口不会抛出异常,即使输入不符合 UTF-8 编码的字符串,也会构造出一个 String 并返回,其行为等同于 String.fromUtf8Uncheck(Array<Byte>)。
返回值:
func readUntil((Rune) -> Bool)
public func readUntil(predicate: (Rune) -> Bool): ?String
功能:从标准输入中读取数据直到读取到的字符满足predicate条件结束。
满足 predicate: (Rune) -> Bool 条件的字符包含在结果中,读取失败时会返回None。
参数:
- predicate: (Rune) ->Bool - 终止读取的条件。
返回值:
示例:
import std.env.*
main() {
getStdOut().write("请输入信息:")
var c = getStdIn().readUntil({ch: Rune => ch > r'd' && ch < r'g'}) // 输入:abcdefg
var r = c.getOrThrow()
getStdOut().writeln("输入的信息为:" + r)
return
}
运行结果:
请输入信息:abcdefg
输入的信息为:abcde
func readUntil(Rune)
public func readUntil(ch: Rune): ?String
功能:从标准输入中读取数据直到读取到字符 ch 结束。
ch包含在结果中,如果读取到文件结束符 EOF,将返回读取到的所有信息,读取失败时会返回 None。
参数:
- ch: Rune - 终止字符。
返回值:
示例:
import std.env.*
main() {
getStdOut().write("请输入信息:")
var c = getStdIn().readUntil(r'b') // 输入:abc
var r = c.getOrThrow()
getStdOut().write("输入的信息为:")
getStdOut().writeln(r)
return
}
运行结果:
请输入信息:abc
输入的信息为:ab
func readln()
public func readln(): ?String
功能:从标准输入中读取一行字符串。
读取到字符,返回 ?String,结果不包含末尾换行符。该接口不会抛出异常,即使输入不符合UTF-8编码的字符串,也会构造出一个 String 并返回,其行为等同于 String.fromUtf8Uncheck(Array<Byte>)。
返回值:
- ?String - 读取到的行数据,读取失败返回
None。
示例:
import std.env.*
main() {
getStdOut().write("请输入信息:")
var c = getStdIn().readln() // 输入:abc
var r = c.getOrThrow()
getStdOut().write("输入的信息为:")
getStdOut().writeln(r)
return
}
运行结果:
请输入信息:abc
输入的信息为:abc
class ConsoleWriter
public class ConsoleWriter <: OutputStream
功能:此类提供保证线程安全的标准输出功能。
每次 write 调用写到控制台的结果是完整的,不同的 write 函数调用的结果不会混合到一起。 该类型无法构造实例,只能通过 getStdOut() 获取标准输出实例或者 getStdErr() 获取标准错误的实例。
父类型:
func flush()
public func flush(): Unit
功能:刷新输出流。
func write(Array<Byte>)
public func write(buffer: Array<Byte>): Unit
功能:指定的将字节数组 buffer 写入标准输出或标准错误流中。
参数:
func write(Bool)
public func write(v: Bool): Unit
功能:将指定的布尔值的文本表示形式写入标准输出或标准错误流中。
参数:
- v: Bool - 要写入的值。
func write(Float16)
public func write(v: Float16): Unit
功能:将指定的 16 位浮点数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Float16 - 要写入的值。
func write(Float32)
public func write(v: Float32): Unit
功能:将指定的 32 位浮点数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Float32 - 要写入的值。
func write(Float64)
public func write(v: Float64): Unit
功能:将指定的 64 位浮点数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Float64 - 要写入的值。
func write(Int16)
public func write(v: Int16): Unit
功能:将指定的 16 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int16 - 要写入的值。
func write(Int32)
public func write(v: Int32): Unit
功能:将指定的 32 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int32 - 要写入的值。
func write(Int64)
public func write(v: Int64): Unit
功能:将指定的 64 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int64 - 要写入的值。
func write(Int8)
public func write(v: Int8): Unit
功能:将指定的 8 位有符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: Int8 - 要写入的值。
func write(Rune)
public func write(v: Rune): Unit
功能:将指定的 Rune 的 Unicode 字符值写入标准输出或标准错误流中。
参数:
- v: Rune - 要写入的值。
func write(String)
public func write(v: String): Unit
功能:将指定的字符串值写入标准输出或标准错误流中。
参数:
- v: String - 要写入的值。
func write(UInt16)
public func write(v: UInt16): Unit
功能:将指定的 16 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt16 - 要写入的值。
func write(UInt32)
public func write(v: UInt32): Unit
功能:将指定的 32 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt32 - 要写入的值。
func write(UInt64)
public func write(v: UInt64): Unit
功能:将指定的 64 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt64 - 要写入的值。
func write(UInt8)
public func write(v: UInt8): Unit
功能:将指定的 8 位无符号整数值的文本表示写入标准输出或标准错误流中。
参数:
- v: UInt8 - 要写入的值。
func write<T>(T) where T <: ToString
public func write<T>(v: T): Unit where T <: ToString
功能:将实现了 ToString 接口的数据类型写入标准输出或标准错误流中。
参数:
- v: T - 要被写入的 ToString 类型的实例。
func writeln(Array<Byte>)
public func writeln(buffer: Array<Byte>): Unit
功能:指定的将字节数组 buffer (后跟换行符)写入标准输出或标准错误流中。
参数:
func writeln(Bool)
public func writeln(v: Bool): Unit
功能:将指定的布尔值的文本表示形式(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Bool - 要写入的值。
func writeln(Float16)
public func writeln(v: Float16): Unit
功能:将指定的 16 位浮点数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Float16 - 要写入的值。
func writeln(Float32)
public func writeln(v: Float32): Unit
功能:将指定的 32 位浮点数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Float32 - 要写入的值。
func writeln(Float64)
public func writeln(v: Float64): Unit
功能:将指定的 64 位浮点数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Float64 - 要写入的值。
func writeln(Int16)
public func writeln(v: Int16): Unit
功能:将指定的 16 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int16 - 要写入的值。
func writeln(Int32)
public func writeln(v: Int32): Unit
功能:将指定的 32 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int32 - 要写入的值。
func writeln(Int64)
public func writeln(v: Int64): Unit
功能:将指定的 64 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int64 - 要写入的值。
func writeln(Int8)
public func writeln(v: Int8): Unit
功能:将指定的 8 位有符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Int8 - 要写入的值。
func writeln(Rune)
public func writeln(v: Rune): Unit
功能:将指定的 Unicode 字符值(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: Rune - 要写入的值。
func writeln(String)
public func writeln(v: String): Unit
功能:将指定的字符串值(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: String - 要写入的值。
func writeln(UInt16)
public func writeln(v: UInt16): Unit
功能:将指定的 16 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: UInt16 - 要写入的值。
func writeln(UInt32)
public func writeln(v: UInt32): Unit
功能:将指定的 32 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。 参数:
- v: UInt32 - 要写入的值。
func writeln(UInt64)
public func writeln(v: UInt64): Unit
功能:将指定的 64 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: UInt64 - 要写入的值。
func writeln(UInt8)
public func writeln(v: UInt8): Unit
功能:将指定的 8 位无符号整数值的文本表示(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: UInt8 - 要写入的值。
func writeln<T>(T) where T <: ToString
public func writeln<T>(v: T): Unit where T <: ToString
功能:将实现了 ToString 接口的数据类型转换成的字符串(后跟换行符)写入标准输出或标准错误流中。
参数:
- v: T - 要写入的值。
异常
class EnvException
public class EnvException <: Exception {
public init(message: String)
}
功能:env 包的异常类。
父类型:
init(String)
public init(message: String)
功能:创建 EnvException 实例。
参数:
- message: String - 异常提示信息。
env 相关操作
当前进程相关操作
代码如下:
import std.env.*
main(): Int64 {
println(getProcessId())
println(getCommand())
println(getCommandLine().toString())
println(getWorkingDirectory().toString())
atExit(printText)
exit(0)
return 0
}
func printText(): Unit {
println("hello cangjie!")
}
运行结果可能如下(输出结果中main为当前进程执行命令名,回调执行完成后当前进程会退出):
28481
main
[./main]
/root/code/workpalce/cangjie
hello cangjie!
Console 示例
下面是 Console 示例,示例中接收用户输入的两条信息,并将这些信息通过标准输出原样返回给用户。
import std.env.*
main() {
getStdOut().write("请输入信息1:")
var c = getStdIn().readln() // 输入:你好,请问今天星期几?
var r = c.getOrThrow()
getStdOut().writeln("输入的信息1为:" + r)
getStdOut().write("请输入信息2:")
c = getStdIn().readln() // 输入:你好,请问今天几号?
r = c.getOrThrow()
getStdOut().writeln("输入的信息2为:" + r)
return
}
运行结果:
请输入信息1:你好,请问今天星期几?
输入的信息1为:你好,请问今天星期几?
请输入信息2:你好,请问今天几号?
输入的信息2为:你好,请问今天几号?
std.fs
功能介绍
fs(file system)包提供对文件、文件夹、路径、文件元数据信息的一些操作函数。
目前支持 Linux,macOS 和 Windows 平台下使用。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| canonicalize(Path) | 将 Path 实例规范化,获取绝对路径形式的规范化路径。 |
| canonicalize(String) | 用 path 字符串构造 Path 实例,并进行规范化,获取绝对路径形式的规范化路径。 |
| copy(Path, Path, Bool) | 实现文件系统的拷贝功能,用于于复制文件或目录。 |
| copy(String, String, Bool) | 实现文件系统的拷贝功能,用于于复制文件或目录。 |
| exists(Path) | 判断目标地址是否存在。 |
| exists(String) | 判断目标地址是否存在。 |
| rename(Path, Path, Bool) | 重命名文件。 |
| rename(String, String, Bool) | 重命名文件。 |
| remove(Path, Bool) | 删除文件或目录。 |
| remove(String, Bool) | 删除文件或目录。 |
| removeIfExists(Path, Bool) | 判断目标是否存在,如果存在则删除。 |
| removeIfExists(String, Bool) | 判断目标是否存在,如果存在则删除。 |
类
| 类名 | 功能 |
|---|---|
| Directory | 对应文件系统中的目录,它提供创建、查询属性以及遍历目录等能力。 |
| File | 提供一些对文件进行操作的函数,包括文件的打开、创建、关闭、文件的流式读写操作、查询属性以及一些其他函数。 |
| HardLink | 提供处理文件系统硬链接相关接口。 |
| SymbolicLink | 提供处理文件系统符号链接相关接口。 |
枚举
| 枚举名 | 功能 |
|---|---|
| OpenMode | 表示不同的文件打开模式。 |
结构体
| 结构体名 | 功能 |
|---|---|
| FileDescriptor | 用于获取文件句柄信息。 |
| FileInfo | 对应文件系统中的文件元数据,提供一些文件属性的查询和设置等函数。 |
| Path | 提供路径相关的函数。 |
异常类
| 异常类名 | 功能 |
|---|---|
| FSException | 文件流异常类,继承了 IO 流异常类。 |
函数
func canonicalize(Path)
public func canonicalize(path: Path): Path
功能:将 Path 实例规范化,获取绝对路径形式的规范化路径。
所有的中间引用和软链接都会处理(UNC 路径下的软链接无法被规范化),例如,对于路径 "/foo/test/../test/bar.txt",该函数会返回 "/foo/test/bar.txt"。
参数:
返回值:
异常:
- FSException - 路径不存在或无法规范化时抛出异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func canonicalize(String)
public func canonicalize(path: String): Path
功能:用 path 字符串构造 Path 实例,并进行规范化,获取绝对路径形式的规范化路径。
所有的中间引用和软链接都会处理 (UNC 路径下的软链接无法被规范化),例如,对于路径 "/foo/test/../test/bar.txt",该函数会返回 "/foo/test/bar.txt"。
参数:
- path: String - 待规范化的路径字符串。
返回值:
异常:
- FSException - 路径不存在或无法规范化时抛出异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func copy(Path, Path, Bool)
public func copy(sourcePath: Path, to!: Path, overwrite!: Bool = false): Unit
功能:实现文件系统的拷贝功能,用于复制文件或目录。
当目标位置存在且 overwrite 为 true 时,该函数要求 sourcePath 的类型与 to 的类型一致,比如,sourcePath 的类型是 Directory,to 的类型也应该是 Directory,否则函数会抛出异常 FSException。当前支持的文件类型有文件夹(Directory),常规文件(Regular file),符号链接(SymbolicLink)。
参数:
异常:
- FSException - 如果源文件类型和目标文件类型不一致会抛出异常或者
overwrite为false并且目标地址存在时抛出异常。 - IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func copy(String, String, Bool)
public func copy(sourcePath: String, to!: String, overwrite!: Bool = false): Unit
功能:实现文件系统的拷贝功能,用于复制文件或目录。
当目标位置存在且 overwrite 为 true 时,该函数要求 sourcePath 的类型与 to 的类型一致,比如,sourcePath 的类型是 Directory,to 的类型也应该是 Directory,否则函数会抛出异常 FSException。当前支持的文件类型有文件夹(Directory),常规文件(Regular file),符号链接(SymbolicLink)。
参数:
异常:
- FSException - 如果源文件类型和目标文件类型不一致会抛出异常或者
overwrite为false并且目标地址存在时抛出异常。 - IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func exists(Path)
public func exists(path: Path): Bool
功能:判断目标地址是否存在。
参数:
- path: Path - 待判断的目标地址。
返回值:
- Bool - 目标地址是否存在。
异常:
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func exists(String)
public func exists(path: String): Bool
功能:判断目标地址是否存在。
参数:
- path: String - 待判断的目标地址。
返回值:
- Bool - 目标地址是否存在。
异常:
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func rename(Path, Path, Bool)
public func rename(sourcePath: Path, to!: Path, overwrite!: Bool = false): Unit
功能:将 sourcePath 指定的文件或者目录重命名为由 to 给定的名称,sourcePath 必须是现有文件或者目录的路径,如果 to 是现有文件或者目录的路径时,其具体行为由 overwrite 指定, 如果 overwrite 为 true,将会删除现有的文件或者目录,再执行重命名操作,否则会抛出异常。
注意:
当
overwrite为true时,rename的一个隐含行为是删除目标位置的原有文件或者目录,如果目标位置是目录,将会递归删除目录内的所有内容,需要谨慎使用。
参数:
异常:
- FSException - 操作系统执行rename方法失败时抛出异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func rename(String, String, Bool)
public func rename(sourcePath: String, to!: String, overwrite!: Bool = false): Unit
功能:将 sourcePath 指定的文件或者目录重命名为由 to 给定的名称,sourcePath 必须是现有文件或者目录的路径,如果 to 是现有文件或者目录的路径时,其具体行为由 overwrite 指定, 如果 overwrite 为 true,将会删除现有的文件或者目录,再执行重命名操作,overwrite 为 false 会抛出异常。
注意:
当
overwrite为true时,rename的一个隐含行为是删除目标位置的原有文件或者目录,如果目标位置是目录,将会递归删除目录内的所有内容,需要谨慎使用。
参数:
异常:
- FSException - 操作系统执行rename方法失败时抛出异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func remove(Path, Bool)
public func remove(path: Path, recursive!: Bool = false): Unit
功能:删除文件或目录。
当目标是文件夹时,可选择是否递归删除文件夹。
参数:
异常:
- FSException - 如果指定目录不存在或删除失败,则抛出异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func remove(String, Bool)
public func remove(path: String, recursive!: Bool = false): Unit
功能:删除文件或目录。
当目标是文件夹时,可选择是否递归删除文件夹。
参数:
异常:
- FSException - 如果指定目录不存在或删除失败,则抛出异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func removeIfExists(Path, Bool)
public func removeIfExists(path: Path, recursive!: Bool = false): Bool
功能:判断目标是否存在,如果存在则执行remove方法,并返回 true。
参数:
返回值:
- Bool - 目标地址是否存在。
异常:
- FSException - 如果删除失败,抛出此异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
func removeIfExists(String, Bool)
public func removeIfExists(path: String, recursive!: Bool = false): Bool
功能:判断目标是否存在,如果存在则执行 remove 方法,并返回 true。
参数:
返回值:
- Bool - 目标地址是否存在。
异常:
- FSException - 如果删除失败,抛出此异常。
- IllegalArgumentException - 路径为空或包含字符串结束符时抛出异常。
类
class Directory
public class Directory {}
功能:对应文件系统中的目录,它提供创建、移动、复制、删除、查询属性以及遍历目录等能力。
说明:
非法路径指的是以下情况之一:
- 路径中包含非法字符,例如空格、制表符、换行符等;
- 路径中包含不合法的字符,例如特殊字符、控制字符等;
- 路径中包含不存在的目录或文件;
- 路径中包含无法访问的目录或文件,例如权限不足或被锁定等。
在输入路径时,应该避免使用非法字符,确保路径的合法性,以便正确地访问目标文件或目录。
static func create(Path, Bool)
public static func create(path: Path, recursive!: Bool = false): Unit
功能:创建目录。
可指定是否递归创建,如果需要递归创建,将逐级创建路径中不存在的目录。
参数:
异常:
- FSException - 目录已存在时,抛出异常;非递归时中间有不存在的目录时抛出异常。
- IllegalArgumentException - 目录为空、目录为当前目录、目录为根目录或目录中存在空字符时抛出异常。
static func create(String, Bool)
public static func create(path: String, recursive!: Bool = false): Unit
功能:创建目录。
可指定是否递归创建,如果需要递归创建,将逐级创建路径中不存在的目录。
参数:
异常:
- FSException - 目录已存在时,抛出异常;非递归时中间有不存在的目录时抛出异常。
- IllegalArgumentException - 目录为空、目录为当前目录、目录为根目录或目录中存在空字符时抛出异常。
static func createTemp(Path)
public static func createTemp(directoryPath: Path): Path
功能:在指定目录下创建临时目录。
参数:
返回值:
- Path - 临时目录对应的路径。
异常:
- FSException - 目录不存在或创建失败时抛出异常。
- IllegalArgumentException - 目录为空或包含空字符时抛出异常。
static func createTemp(String)
public static func createTemp(directoryPath: String): Path
功能:在指定目录下创建临时目录。
参数:
- directoryPath: String - 字符串形式的目录路径。
返回值:
- Path - 临时目录对应的路径。
异常:
- FSException - 目录不存在或创建失败时抛出异常。
- IllegalArgumentException - 目录为空或包含空字符时抛出异常。
static func isEmpty(Path)
public static func isEmpty(path: Path): Bool
功能:判断指定目录是否为空。
参数:
- path: Path - 待判断是否为空的目录对应的路径。
返回值:
- Bool - 为 true 时目录为空,为 false 时不为空。
异常:
- FSException - 如果指定路径不存在、指定路径不是目录或判断过程中底层接口发生错误,则抛出异常。
- IllegalArgumentException - 当指定路径为空或包含空字符时,抛出异常。
static func isEmpty(String)
public static func isEmpty(path: String): Bool
功能:判断指定目录是否为空。
参数:
- path: String - 待判断是否为空的目录对应的路径。
返回值:
- Bool - 为 true 时目录为空,为 false 时不为空。
异常:
- FSException - 如果指定路径不存在、指定路径不是目录或判断过程中底层接口发生错误,则抛出异常。
- IllegalArgumentException - 当指定路径为空或包含空字符时,抛出异常。
static func readFrom(Path)
public static func readFrom(path: Path): Array<FileInfo>
功能:获取当前目录的子项目列表。
子项目在数组中的顺序取决于文件在系统中的排序。
参数:
- path: Path - 待读取其子项的目录对应的路径。
返回值:
异常:
- FSException - 当指定路径不存在、指定路径不是目录或获取目录的成员信息失败时,抛出异常。
- IllegalArgumentException - 当指定路径为空或包含空字符时,抛出异常。
static func readFrom(String)
public static func readFrom(path: String): Array<FileInfo>
功能:获取当前目录的子项目列表。
子项目在数组中的顺序取决于文件在系统中的排序。
参数:
- path: String - 待读取其子项目的目录对应的路径。
返回值:
异常:
- FSException - 当指定路径不存在、指定路径不是目录或获取目录的成员信息失败时,抛出异常。
- IllegalArgumentException - 当指定路径为空或包含空字符时,抛出异常。
static func walk(Path, (FileInfo)->Bool)
public static func walk(path: Path, f: (FileInfo)->Bool): Unit
功能:遍历 path 对应的目录下的子项目(非递归,即不包含子目录的子项目),对每一个子项目执行回调函数。
walk 函数退出条件为遍历结束或回调函数 f 返回 false。遍历顺序取决于文件在系统中的排序。
参数:
异常:
- FSException - 当指定路径不存在、指定路径不是目录或获取目录的成员信息失败时,抛出异常。
- IllegalArgumentException - 当指定路径为空或包含空字符时,抛出异常。
static func walk(String, (FileInfo)->Bool)
public static func walk(path: String, f: (FileInfo)->Bool): Unit
功能:遍历 path 对应的目录下的子项目(非递归,即不包含子目录的子项目),对每一个子项目执行回调函数。
walk 函数退出条件为遍历结束或回调函数 f 返回 false。遍历顺序取决于文件在系统中的排序。
参数:
异常:
- FSException - 当指定路径不存在、指定路径不是目录或获取目录的成员信息失败时,抛出异常。
- IllegalArgumentException - 当指定路径为空或包含空字符时,抛出异常。
class File
public class File <: Resource & IOStream & Seekable {
public init(path: String, mode: OpenMode)
public init(path: Path, mode: OpenMode)
}
功能:提供一些对文件进行操作的函数,包括文件的打开、创建、关闭、移动、复制、删除,文件的流式读写操作,查询属性以及一些其他函数。
说明:
非法路径指的是以下情况之一:
- 路径中包含非法字符,例如空格、制表符、换行符等;
- 路径中包含不合法的字符,例如特殊字符、控制字符等;
- 路径中包含不存在的目录或文件;
- 路径中包含无法访问的目录或文件,例如权限不足或被锁定等。
在输入路径时,应该避免使用非法字符,确保路径的合法性,以便正确地访问目标文件或目录。
注意:
父类型:
prop fileDescriptor
public prop fileDescriptor: FileDescriptor
功能:获取文件描述符信息。
prop info
public prop info: FileInfo
功能:获取文件元数据信息。
类型:FileInfo
prop length
public prop length: Int64
功能:获取文件头至文件尾的数据字节数。
类型:Int64
init(Path, OpenMode)
public init(path: Path, mode: OpenMode)
功能:创建一个 File 对象。
需指定文件路径和文件打开方式(读写权限),路径支持相对路径和绝对路径。
参数:
异常:
- FSException - 如果以只读方式打开文件但文件不存在、文件的父目录不存在或其他原因导致无法打开文件,则抛出异常。
- IllegalArgumentException - 如果 path 为空路径或者 path 路径中包含空字符,则抛出异常。
init(String, OpenMode)
public init(path: String, mode: OpenMode)
功能:创建 File 对象。
需指定文件路径和文件打开方式(读写权限),路径支持相对路径和绝对路径。
参数:
异常:
- FSException - 如果以只读方式打开文件但文件不存在、文件的父目录不存在或其他原因导致无法打开文件,则抛出异常。
- IllegalArgumentException - 如果 path 是空字符串或者 path 包含空字符,则抛出异常。
static func appendTo(Path, Array<Byte>)
public static func appendTo(path: Path, buffer: Array<Byte>): Unit
功能:打开指定路径的文件并将 buffer 以追加的方式写入,文件不存在则将创建文件。
参数:
异常:
- FSException - 文件打开失败或写入失败,则抛出异常。
- IllegalArgumentException - 如果文件路径为空或包含空字符,则抛出异常。
static func appendTo(String, Array<Byte>)
public static func appendTo(path: String, buffer: Array<Byte>): Unit
功能:打开指定路径的文件并将 buffer 以追加的方式写入,文件不存在则将创建文件。
参数:
异常:
- FSException - 文件打开失败或写入失败,则抛出异常。
- IllegalArgumentException - 如果文件路径为空或包含空字符,则抛出异常。
static func create(Path)
public static func create(path: Path): File
功能:以只写模式创建指定路径的文件。
参数:
- path: Path - 文件路径。
返回值:
异常:
- FSException - 如果路径指向的文件的上级目录不存在或文件已存在,则抛出异常。
- IllegalArgumentException - 如果文件路径为空或包含空字符,则抛出异常。
static func create(String)
public static func create(path: String): File
功能:以只写模式创建指定路径的文件。
参数:
- path: String - 文件路径字符串。
返回值:
异常:
- FSException - 如果路径指向的文件的上级目录不存在或文件已存在,则抛出异常。
- IllegalArgumentException - 如果文件路径为空字符串或包含空字符,则抛出异常。
static func createTemp(Path)
public static func createTemp(directoryPath: Path): File
功能:在指定目录下创建临时文件。
创建的文件名称是 tmpFileXXXXXX 形式,不使用的临时文件应手动删除。
参数:
- directoryPath: Path - 目录路径。
返回值:
异常:
- FSException - 创建文件失败或路径不存在则抛出异常。
- IllegalArgumentException - 如果文件路径为空或包含空字符,则抛出异常。
static func createTemp(String)
public static func createTemp(directoryPath: String): File
功能:在指定目录下创建临时文件。
创建的文件名称是 tmpFileXXXXXX 形式,不使用的临时文件应手动删除。
参数:
- directoryPath: String - 目录路径字符串。
返回值:
异常:
- FSException - 创建文件失败或路径不存在则抛出异常。
- IllegalArgumentException - 如果文件路径为空字符串或包含空字符,则抛出异常。
static func readFrom(Path)
public static func readFrom(path: Path): Array<Byte>
功能:根据指定路径读取文件全部内容,以字节数组的形式返回其内容。
参数:
- path: Path - 文件路径。
返回值:
异常:
- FSException - 文件路径为空、文件不可读、文件读取失败,则抛出异常。
- IllegalArgumentException - 文件路径包含空字符则抛出异常。
static func readFrom(String)
public static func readFrom(path: String): Array<Byte>
功能:根据指定路径读取文件全部内容,以字节数组的形式返回其内容。
参数:
- path: String - 文件路径字符串。
返回值:
异常:
- FSException - 文件读取失败、文件关闭失败、文件路径为空、文件不可读,则抛出异常。
- IllegalArgumentException - 文件路径包含空字符则抛出异常。
static func writeTo(Path, Array<Byte>)
public static func writeTo(path: Path, buffer: Array<Byte>): Unit
功能:打开指定路径的文件并将 buffer 以覆盖的方式写入,即文件存在时会将该文件截断为零字节大小,文件不存在则将创建文件。
参数:
异常:
- FSException - 文件打开失败或写入失败,则抛出异常。
- IllegalArgumentException - 如果文件路径为空或包含空字符,则抛出异常。
static func writeTo(String, Array<Byte>)
public static func writeTo(path: String, buffer: Array<Byte>): Unit
功能:打开指定路径的文件并将 buffer 以覆盖的方式写入,即文件存在时会将该文件截断为零字节大小,文件不存在则将创建文件。
参数:
异常:
- FSException - 文件打开失败或写入失败,则抛出异常。
- IllegalArgumentException - 如果文件路径为空字符串或包含空字符,则抛出异常。
func canRead()
public func canRead(): Bool
功能:判断当前 File 对象是否可读。
该函数返回值由创建文件对象的 openMode 所决定,文件对象关闭后返回 false。
返回值:
- Bool - 返回 true 表示可读,返回 false 表示不可读或文件对象已关闭。
func canWrite()
public func canWrite(): Bool
功能:判断当前 File 对象是否可写。
该函数返回值由创建文件对象的 openMode 所决定,文件对象关闭后返回 false。
返回值:
- Bool - 返回 true 表示可写,false 表示不可写或文件对象已关闭。
func close()
public func close(): Unit
功能:关闭当前 File 对象。
异常:
- FSException - 如果关闭失败,则抛出异常。
func flush()
public func flush(): Unit
功能:将缓冲区数据写入流。由于 File 不存在缓冲区,所以该函数没有具体作用。
func isClosed()
public func isClosed(): Bool
功能:判断当前 File 对象是否已关闭。
返回值:
- Bool - true 表示已关闭,false 表示未关闭。
func read(Array<Byte>)
public func read(buffer: Array<Byte>): Int64
功能:从文件中读出数据到 buffer 中。
参数:
返回值:
- Int64 - 读取成功,返回读取字节数,如果文件被读完,返回 0。
异常:
- IllegalArgumentException - 如果 buffer 为空,则抛出异常。
- FSException - 读取失败、文件已关闭或文件不可读,则抛出异常。
func seek(SeekPosition)
public func seek(sp: SeekPosition): Int64
功能:将光标跳转到指定位置。
指定的位置不能位于文件头部之前,指定位置可以超过文件末尾,但指定位置到文件头部的最大偏移量不能超过当前文件系统允许的最大值,这个最大值接近当前文件系统的所允许的最大文件大小,一般为最大文件大小减去 4096 个字节。
参数:
- sp: SeekPosition - 指定光标跳转后的位置。
返回值:
- Int64 - 返回文件头部到跳转后位置的偏移量(以字节为单位)。
异常:
- FSException - 指定位置不满足以上情况时或文件不能 seek 时均会抛出异常。
func setLength(Int64)
public func setLength(length: Int64): Unit
功能:将当前文件截断为指定长度。当 length 大于当前文件长度时,则将使用 0 填充文件直到目标长度。此方法不会改变文件光标的位置。
参数:
- length: Int64 - 指定截断的长度。
异常:
- IllegalArgumentException - 指定的长度为负数时抛出异常。
- FSException - 文件截断操作失败时,抛出异常。
func write(Array<Byte>)
public func write(buffer: Array<Byte>): Unit
功能:将 buffer 中的数据写入到文件中。
参数:
异常:
- FSException - 如果写入失败、只写入了部分数据、文件已关闭或文件不可写则抛出异常。
class HardLink
public class HardLink
功能:提供处理文件系统硬链接相关接口。
static func create(Path, Path)
public static func create(link: Path, to!: Path): Unit
功能:创建一个新的硬链接到现有路径。如果新的路径存在,则不会覆盖。
参数:
异常:
- IllegalArgumentException - 参数中路径为空、或者包含空字符时抛出异常。
- FSException - 创建硬链接失败时,抛出异常。
static func create(String, String)
public static func create(link: String, to!: String): Unit
功能:创建一个新的硬链接到现有路径。如果新的路径存在,则不会覆盖。
参数:
异常:
- IllegalArgumentException - 参数中路径为空、或者包含空字符时抛出异常。
- FSException - 创建硬链接失败时,抛出异常。
class SymbolicLink
public class SymbolicLink
功能:提供处理文件系统符号链接相关接口。
static func create(Path, Path)
public static func create(link: Path, to!: Path): Unit
功能:创建一个新的符号链接到现有路径。
说明:
在Windows上,创建一个目标不存在的符号链接时,会创建一个文件符号链接,如果目标路径后来被创建为目录,则符号链接将不起作用。
参数:
异常:
- IllegalArgumentException - 参数中路径为空、或者包含空字符时抛出异常。
- FSException - 创建符号链接失败时,抛出异常。
static func create(String, String)
public static func create(link: String, to!: String): Unit
功能:创建一个新的符号链接到现有路径。
说明:
在Windows上,创建一个目标不存在的符号链接时,会创建一个文件符号链接,如果目标路径后来被创建为目录,则符号链接将不起作用。
参数:
异常:
- IllegalArgumentException - 参数中路径为空、或者包含空字符时抛出异常。
- FSException - 创建符号链接失败时,抛出异常。
static func readFrom(Path, Bool)
public static func readFrom(path: Path, recursive!: Bool = false): Path
功能:获取指定符号链接的目标。当指定 'recursive' 为 'true' 时,表示跟踪指向最终目标的链接,并且返回目标的全路径,当指定 'recursive' 为 'false' 时,读取当前目标链接并且返回。
参数:
返回值:
- Path - 符号链接的目标地址。
异常:
- IllegalArgumentException - 参数中路径为空、或者包含空字符时抛出异常。
- FSException - 读取符号链接失败时,抛出异常。
static func readFrom(String, Bool)
public static func readFrom(path: String, recursive!: Bool = false): Path
功能:获取指定符号链接的目标。当指定 'recursive' 为 'true' 时,表示跟踪指向最终目标的链接,并且返回目标的全路径,当指定 'recursive' 为 'false' 时,读取当前目标链接并且返回。
参数:
返回值:
- Path - 符号链接的目标地址。
异常:
- IllegalArgumentException - 参数中路径为空、或者包含空字符时抛出异常。
- FSException - 读取符号链接失败时,抛出异常。
枚举
enum OpenMode
public enum OpenMode <: ToString & Equatable<OpenMode> {
| Read
| Write
| Append
| ReadWrite
}
功能:表示不同的文件打开模式。
父类型:
Read
Read
功能:构造一个 OpenMode 实例,指定以只读的方式打开文件。如果文件不存在,则将引发 FSException 异常。
Write
Write
功能:构造一个 OpenMode 实例,指定以只写的方式打开文件,即文件存在时会将该文件截断为零字节大小,文件不存在则将创建文件。
Append
Append
功能:构造一个 OpenMode 实例,指定以追加写入的方式打开文件。如果文件不存在,则将创建文件。
ReadWrite
ReadWrite
功能:构造一个 OpenMode 实例,指定以可读可写的方式打开文件。如果文件不存在,则将创建文件。
注意:
ReadWrite 模式不会使文件被截断为零字节大小。
func toString()
public func toString(): String
功能:文件打开模式的字符串表示。
返回值:
- String - 文件打开模式名称。
func operator func ==(OpenMode)
public operator func ==(that: OpenMode): Bool
功能:比较 OpenMode 实例是否相等。
参数:
返回值:
- Bool - 如果相等,则返回 true,否则返回 false。
func operator func !=(OpenMode)
public operator func !=(that: OpenMode): Bool
功能:比较 OpenMode 实例是否不等。
参数:
返回值:
- Bool - 如果不相等,则返回 true,否则返回 false。
结构体
struct FileDescriptor
public struct FileDescriptor
功能:用于获取文件句柄信息。
说明:
文件句柄(File Handle)是操作系统为了跟踪文件而分配的一种数据结构,用于标识一个打开文件的实例。文件句柄包含了文件的元数据信息(如文件名、路径、大小、修改时间等)以及文件数据在磁盘上的物理位置等信息。 在不同的操作系统中,文件句柄的形式可能会有所不同。在 Unix 和 Linux 系统中,文件句柄通常是一个非负整数,由操作系统内核分配,并在打开文件时返回给应用程序。在 Windows 系统中,文件句柄通常是一个指向文件对象的指针,由操作系统内核分配,并在打开文件时返回给应用程序。无论文件句柄的形式是什么,应用程序都可以使用它来执行文件的读取、写入、修改等操作。
prop fileHandle
public prop fileHandle: IntNative
功能:获取文件句柄信息。
类型:IntNative
struct FileInfo
public struct FileInfo <: Equatable<FileInfo> {
public init(path: Path)
public init(path: String)
}
功能:对应文件系统中的文件元数据。
说明:
文件元数据是指文件系统中与文件相关的信息,包括文件名、文件大小、创建时间、修改时间、访问时间、文件权限、文件所有者等。
FileInfo 的底层实现是没有直接缓存文件属性的,每次通过 FileInfo 的 API 都是现场获取的最新的文件属性。
因此这里有需要注意的情况,对于创建的同一 FileInfo 实例,如果在两次获取其文件属性操作期间,对应的文件实体可能会被其他用户或进程做了修改或者替换等不期望的操作,就会导致后一次获取的可能不是期望的文件属性。 如果有特殊文件操作需求需要避免上述情况的产生,可以采用设置文件权限或者给关键文件操作加锁的方式来保证。
父类型:
prop creationTime
public prop creationTime: DateTime
功能:获取创建时间。
类型:DateTime
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
prop lastAccessTime
public prop lastAccessTime: DateTime
功能:获取最后访问时间。
类型:DateTime
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
prop lastModificationTime
public prop lastModificationTime: DateTime
功能:获取最后修改时间。
类型:DateTime
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
prop name
public prop name: String
功能:获取当前实例对应的文件名或目录名。
该属性与 this.path.fileName 等价,路径解析规则详见 Path 结构体的 fileName 属性。
类型:String
prop parentDirectory
public prop parentDirectory: Option<FileInfo>
功能:获得父级目录元数据,以 Option<FileInfo> 形式返回,有父级返回 Option<FileInfo>.Some(v);否则返回 Option<FileInfo>.None。
prop path
public prop path: Path
功能:获得当前文件路径,以 Path 形式返回。
类型:Path
prop size
public prop size: Int64
功能:返回当前文件大小。
- 当前是文件时,表示单个文件占用磁盘空间的大小。
- 当前是目录时,表示当前目录的所有文件占用磁盘空间的大小。
类型:Int64
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
init(Path)
public init(path: Path)
功能:创建 FileInfo 实例。
参数:
异常:
- FSException - 当路径非法时,抛出异常。
- IllegalArgumentException - 当路径为空,或包含字符串结束符则抛出异常。
init(String)
public init(path: String)
功能:创建 FileInfo 实例。
参数:
异常:
- FSException - 当路径非法时,抛出异常。
- IllegalArgumentException - 当路径为空,或包含字符串结束符则抛出异常。
func canExecute()
public func canExecute(): Bool
功能:判断当前用户是否有权限执行该实例对应的文件。
- 对文件而言,判断用户是否有执行文件的权限。
- 对目录而言,判断用户是否有进入目录的权限。
- 在 Windows 环境下,用户对于文件的执行权限由文件扩展名决定;用户始终拥有对于目录的执行权限,该函数不生效,返回 true。
- 在 Linux 和 macOS 环境下,该函数正常使用。
返回值:
- Bool - true 表示有权限;false 表示无权限。
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
func canRead()
public func canRead(): Bool
功能:判断当前用户是否有权限读取该实例对应的文件。
- 对文件而言,判断用户是否有读取文件的权限。
- 对目录而言,判断用户是否有浏览目录的权限。
- 在 Windows 环境下,用户始终拥有对于文件和目录的可读权限,该函数不生效,返回 true。
- 在 Linux 和 macOS 环境下,该函数正常使用。
返回值:
- Bool - true 表示有权限;false 表示无权限。
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
func canWrite()
public func canWrite(): Bool
功能:判断当前用户是否有权限写入该实例对应的文件。
- 对文件而言,判断用户是否有写入文件的权限。
- 对目录而言,判断用户是否有删除、移动、创建目录内文件的权限。
- 在 Windows 环境下,用户对于文件的可写权限正常使用,用户始终拥有对于目录的可写权限,该函数不生效,返回 true。
- 在 Linux 和 macOS 环境下,该函数正常使用。
返回值:
- Bool - true 表示有权限;false 表示无权限。
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
func isDirectory()
public func isDirectory(): Bool
功能:判断当前文件是否是目录。
返回值:
- Bool - true 表示是目录;false 表示不是目录。
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
func isRegular()
public func isRegular(): Bool
功能:判断当前文件是否是普通文件。
返回值:
- Bool - true 表示是文件;false 表示不是文件。
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
func isHidden()
public func isHidden(): Bool
功能:判断当前文件是否隐藏。
返回值:
- Bool - true 表示隐藏;false 表示未隐藏。
func isReadOnly()
public func isReadOnly(): Bool
功能:判断当前文件是否只读。
- 在 Windows 环境下,用户对于文件的只读权限正常使用;用户始终拥有对于目录的删除修改权限,该函数不生效,返回 false。
- 在 Linux 和 macOS 环境下,该函数正常使用。
返回值:
- Bool - true 表示是只读;false 表示不是只读。
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
func isSymbolicLink()
public func isSymbolicLink(): Bool
功能:判断当前文件是否是软链接。
返回值:
- Bool - true 表示是软链接;false 表示不是软链接。
异常:
- FSException - 如果判断过程中底层接口发生错误,则抛出异常。
func setExecutable(Bool)
public func setExecutable(executable: Bool): Bool
功能:对当前实例对应的文件设置当前用户是否可执行的权限,当前用户没有权限修改抛出异常。
- 对文件而言,设置用户是否有执行文件的权限,对目录而言,设置用户是否有进入目录的权限。
- 在 Windows 环境下,用户对于文件的执行权限由文件扩展名决定,用户始终拥有对于目录的执行权限该函数不生效,返回 false。
- 在 Linux 和 macOS 环境下,该函数正常使用如果在此函数调用期间,该 FileInfo 对应的文件实体被其他用户或者进程修改,有可能因为竞争条件(Race Condition)导致其他修改不能生效。
参数:
- executable: Bool - 是否设置可执行。
返回值:
- Bool - true,操作成功;false,操作失败。
func setReadable(Bool)
public func setReadable(readable: Bool): Bool
功能:对当前实例对应的文件设置当前用户是否可读取的权限,当前用户没有权限修改抛出异常。
- 对文件而言,设置用户是否有读取文件的权限。
- 对目录而言,设置用户是否有浏览目录的权限。
- 在 Windows 环境下,用户始终拥有对于文件以及目录的可读权限,不可更改,该函数不生效当 readable 为 true 时,函数返回 true,当 readable 为 false 时,函数返回 false。
- 在 Linux 和 macOS 环境下,该函数正常使用如果在此函数调用期间,该 FileInfo 对应的文件实体被其他用户或者进程修改,有可能因为竞争条件(Race Condition)导致其他修改不能生效。
参数:
- readable: Bool - 是否设置可读。
返回值:
- Bool - true,操作成功;false,操作失败。
func setWritable(Bool)
public func setWritable(writable: Bool): Bool
功能:对当前实例对应的文件设置当前用户是否可写入的权限,当前用户没有权限修改抛出异常。
- 对文件而言,设置用户是否有写入文件的权限。
- 对目录而言,设置用户是否有删除、移动、创建目录内文件的权限。
- 在 Windows 环境下,用户对于文件的可写权限正常使用;用户始终拥有对于目录的可写权限,不可更改,该函数不生效,返回 false。
- 在 Linux 和 macOS 环境下,该函数正常使用如果在此函数调用期间,该 FileInfo 对应的文件实体被其他用户或者进程修改,有可能因为竞争条件(Race Condition)导致其他修改不能生效。
参数:
- writable: Bool - 是否设置可写。
返回值:
- Bool - true,操作成功;false,操作失败。
operator func ==(FileInfo)
public operator func ==(that: FileInfo): Bool
功能:判断当前 FileInfo 和另一个 FileInfo 是否对应同一文件。
参数:
返回值:
- Bool - true,是同一文件;false,不是同一文件。
struct Path
public struct Path <: Equatable<Path> & Hashable & ToString {
public static const Separator: String = PATH_SEPARATOR
public static const ListSeparator: String = PATH_LISTSEPARATOR
public init(rawPath: String)
}
功能:提供路径相关的函数。
Path 用来表示本地路径(Windows 平台已支持 DOS 设备路径和 UNC 路径,长度限制跟随系统)。 路径的字符串最大支持 4096 个字节(包括结束符 \0)。
说明:
非法路径指的是以下情况之一:
- 路径中包含非法字符,例如空格、制表符、换行符等;
- 路径中包含不合法的字符,例如特殊字符、控制字符等;
- 路径中包含不存在的目录或文件;
- 路径中包含无法访问的目录或文件,例如权限不足或被锁定等。
在输入路径时,应该避免使用非法字符,确保路径的合法性,以便正确地访问目标文件或目录。
父类型:
static const ListSeparator
public static const ListSeparator: String = PATH_LISTSEPARATOR
功能:获取路径列表分隔符,用于分隔路径列表中的不同路径。
Windows 系统中路径列表分隔符为 ";",非 Windows 系统中为 ":"。
类型:String
static const Separator
public static const Separator: String = PATH_SEPARATOR
功能:获取路径分隔符,用于分隔多级目录。
Windows 系统中分隔符为 "\",非 Windows 系统中为 "/"。
类型:String
prop extensionName
public prop extensionName: String
功能:获得 Path 的文件扩展名部分。
文件名 fileName 根据最后一个 r'.' 被划分为不带扩展名的文件名 fileNameWithoutExtension 和扩展名 extensionName 两部分。无扩展名时返回空字符串。
- 对于路径 "./NewFile.txt",此属性返回
"txt"。 - 对于路径 "./.gitignore",此属性返回
"gitignore"。 - 对于路径 "./noextension",此属性返回
""。 - 对于路径 "./a.b.c",此属性返回
"c"。 - 对于路径 "./NewFile.txt/",此属性返回
"txt"。
类型:String
异常:
- IllegalArgumentException - 当路径为空或包含字符串结束符则抛出异常。
prop fileName
public prop fileName: String
功能:获得 Path 的文件名(含扩展名)部分。
整个路径字符串被划分为 parent 和 fileName 两部分,详见 parent。无文件名时返回空字符串。
以下示例适用于所有系统:
- 对于路径 "./NewFile.txt",此属性返回 "NewFile.txt";
- 对于路径 "./.gitignore",此属性返回 ".gitignore";
- 对于路径 "./noextension",此属性返回 "noextension";
- 对于路径 "./a.b.c",此属性返回 "a.b.c";
- 对于路径 "./NewDir/",此属性返回 "NewDir";
特别地,在 Windows 文件系统中,fileName 不包括卷名部分。
以下示例仅适用于 Windows 系统:
- 对于路径 "c:\a.txt",此属性返回 "a.txt";
- 对于路径 "c:",此属性返回 "";
- 对于路径 "\\Server\Share\a.txt",此属性返回 "a.txt";
- 对于路径 "\\Server\Share\",此属性返回 "";
- 对于路径 "\\?\C:a\b.txt",此属性返回 "b.txt";
- 对于路径 "\\?\C:",此属性返回 ""。
类型:String
异常:
- IllegalArgumentException - 当路径为空或包含字符串结束符则抛出异常。
prop fileNameWithoutExtension
public prop fileNameWithoutExtension: String
功能:获得 Path 的文件名(不含扩展名)部分。
文件名 fileName 根据最后一个 r'.' 被划分为不带扩展名的文件名 fileNameWithoutExtension 和扩展名 extensionName 两部分。无文件名(不含扩展名)时返回空字符串。
- 对于路径 "./NewFile.txt",此属性返回
"NewFile"。 - 对于路径 "./.gitignore",此属性返回
""。 - 对于路径 "./noextension",此属性返回
"noextension"。 - 对于路径 "./a.b.c",此属性返回
"a.b"。 - 对于路径 "./NewFile/",此属性返回
"NewFile"。
类型:String
异常:
- IllegalArgumentException - 当路径为空或包含字符串结束符则抛出异常。
prop parent
public prop parent: Path
功能:获得该 Path 实例的父路径。
整个路径字符串被划分为 parent 和 fileName,以最后一个有效文件分隔符(末尾的分隔符会被忽略)作为分界。如果 parent 不存在,就返回空字符串构造的 Path 实例。parent 和 fileName 部分都不包含末尾分隔符,parent 保留表示根目录的分隔符。无父目录时返回空的 Path 实例。
该属性不会访问文件系统,也不会消除特殊名称。如果有需要可以跟规范化搭配使用。
该属性在不同操作系统行为有差异,在 Windows 系统中,文件分隔符为 "\" 或 "/"(规范化时会统一转换为 "\"),在 Linux、macOS、ohos 系统中,文件分隔符为 "/"。
以下示例适用于所有系统:
- 对于路径 "/a/b/c",此属性返回 Path("/a/b");
- 对于路径 "/a/b/",此属性返回 Path("/a");
- 对于路径 "/a",此属性返回 Path("/");
- 对于路径 "/",此属性返回 Path("/");
- 对于路径 "./a/b",此属性返回 Path("./a");
- 对于路径 "./",此属性返回 Path("");
- 对于路径 ".gitignore",此属性返回 Path("");
- 对于路径 "/a/./../b",此属性返回 Path("/a/./..")。
此外,在 Windows 系统中,path 被分为卷名、目录名和文件名,详情请参见微软官方文档。属性 parent 包含卷名和目录名。
以下示例仅适用于 Windows 系统:
- 对于路径 "C:",此属性返回 Path("C:");
- 对于路径 "C:\a\b",此属性返回 Path("C:\a");
- 对于路径 "\\Server\Share\xx\yy",此属性返回 Path("\\Server\Share\xx");
- 对于路径 "\\?\UNC\Server\Share\xx\yy",此属性返回 Path("\\?\UNC\Server\Share\xx");
- 对于路径 "\\?\c:\xx\yy",此属性返回 Path("\\?\c:\xx")。
类型:Path
异常:
- IllegalArgumentException - 当路径为空或包含字符串结束符则抛出异常。
init(String)
public init(rawPath: String)
功能:创建 Path 实例时不检查路径字符串是否合法,支持绝对路径和相对路径。
参数:
- rawPath: String - 路径的字符串。
func hashCode()
public func hashCode(): Int64
功能:获得 Path 的哈希值。
返回值:
func isAbsolute()
public func isAbsolute(): Bool
功能:判断 Path 是否是绝对路径。在 Unix 中,以 / 开头的路径为绝对路径。
返回值:
- Bool - true,是绝对路径;false,不是绝对路径。
异常:
- IllegalArgumentException - 当路径为空或包含字符串结束符则抛出异常。
func isEmpty()
public func isEmpty(): Bool
功能:判断当前实例是否为空路径。
返回值:
- Bool - 如果当前实例为空路径,返回 true,否则返回 false。
func isRelative()
public func isRelative(): Bool
功能:判断 Path 是否是相对路径,其结果与函数 isAbsolute 结果相反。
返回值:
- Bool - true,是相对路径;false,不是相对路径。
异常:
- IllegalArgumentException - 当路径为空或包含字符串结束符则抛出异常。
func join(Path)
public func join(path: Path): Path
功能:在当前路径后拼接另一个路径字符串形成新路径。
- 对于路径 "a/b","c",返回 "a/b/c"。
- 对于路径 "a","b/c",返回 "a/b/c"。
返回值:
异常:
- FSException - 如果参数 path 是绝对路径则抛出异常。
- IllegalArgumentException - 当前路径为空或当前路径、入参路径非法时抛出异常。
func join(String)
public func join(path: String): Path
功能:在当前路径后拼接另一个路径字符串形成新路径。
- 对于路径 "a/b","c",返回 "a/b/c"。
- 对于路径 "a","b/c",返回 "a/b/c"。
返回值:
异常:
- FSException - 如果参数 path 是绝对路径则抛出异常。
- IllegalArgumentException - 当前路径为空或当前路径、入参路径非法时抛出异常。
func normalize()
public func normalize(): Path
功能:将路径字符串进行规范化处理,并用规范化后的字符串构造新的 Path 实例。该函数仅做字符串解析,不会进行 io 操作。
规范化规则:
- 将连续的多个路径分隔符替换为单个路径分隔符;
- 删除末尾的路径分隔符(不删除作为根目录的路径分隔符或卷名中的字符);
- 删除每一个 "." 路径名元素(代表当前目录);
- 删除每一个路径内的 ".." 路径名元素(代表父目录)和它前面的非 ".." 路径名元素;
- 删除开始于根路径的 ".." 路径名元素,即将路径开始处的 "/.." 替换为 "/"(Windows 系统中还会将 "\.." 替换为 "\");
- 相对路径保留开头的 "../"(Windows 系统中还将保留 "..\");
- 最后如果得到空路径,返回 Path(".")。
特别地,Windows 文件系统中,卷名部分仅做分隔符转换,即 "/" 转换为 "\"。
返回值:
func toString()
public func toString(): String
功能:获得 Path 的路径字符串。
返回值:
operator func ==(Path)
public operator func ==(that: Path): Bool
功能:判断 Path 是否相等。
判等时将对 Path 进行规范化,如果规范化后的字符串相等,则认为两个 Path 实例相等。规范化规则详见函数 normalize。
参数:
返回值:
- Bool - true,是同一路径;false,不是同一路径。
异常类
class FSException
public class FSException <: IOException {
public init()
public init(message: String)
}
功能:文件流异常类,继承了 IO 流异常类。
父类型:
init()
public init()
功能:构造一个文件异常实例,无异常提示信息。
init(String)
public init(message: String)
功能:构造一个文件异常实例,有异常提示信息。
参数:
- message: String - 错误信息。
Directory 示例
Directory 一些基础操作演示
代码如下:
import std.fs.*
main() {
let testDirPath: Path = Path("./testDir")
let subDirPath: Path = Path("./testDir/subDir")
if (exists(testDirPath)) {
remove(testDirPath, recursive: true)
}
/* 递归创建目录 和 "./testDir/subDir" */
Directory.create(subDirPath, recursive: true)
if (exists(subDirPath)) {
println("The directory './testDir/subDir' is successfully created recursively in current directory.")
}
/* 在 "./testDir" 下创建临时目录 */
let tempDirPath: Path = Directory.createTemp(testDirPath)
if (exists(tempDirPath)) {
println("The temporary directory is created successfully in directory './testDir'.")
}
/* 将 "subDir" 移动到临时目录下并重命名为 "subDir_new" */
let newSubDirPath: Path = tempDirPath.join("subDir_new")
rename(subDirPath, to: newSubDirPath)
if (exists(newSubDirPath) && !exists(subDirPath)) {
println("The directory './testDir/subDir' is moved successfully to the temporary directory and renamed 'subDir_new'.")
}
/* 将 "subDir_new" 拷贝到 "./testDir" 下并重命名为 "subDir" */
copy(newSubDirPath, to: subDirPath, overwrite: false)
if (exists(subDirPath) && exists(newSubDirPath)) {
println("The directory 'subDir_new' is copied successfully to directory './testDir' and renamed 'subDir'.")
}
remove(testDirPath, recursive: true)
return 0
}
运行结果:
The directory './testDir/subDir' is successfully created recursively in current directory.
The temporary directory is created successfully in directory './testDir'.
The directory './testDir/subDir' is moved successfully to the temporary directory and renamed 'subDir_new'.
The directory 'subDir_new' is copied successfully to directory './testDir' and renamed 'subDir'.
File 示例
File 常规操作:创建、删除、读写、关闭
代码如下:
import std.fs.*
import std.io.*
main() {
let filePath: Path = Path("./tempFile.txt")
if (exists(filePath)) {
remove(filePath)
}
/* 在当前目录以 只写模式 创建新文件 'tempFile.txt',写入三遍 "123456789\n" 并关闭文件 */
var file: File = File(filePath, Write)
if (exists(filePath)) {
println("The file 'tempFile.txt' is created successfully in current directory.\n")
}
let bytes: Array<Byte> = "123456789\n".toArray()
for (_ in 0..3) {
file.write(bytes)
}
file.close()
/* 以 追加模式 打开文件 './tempFile.txt',写入 "abcdefghi\n" 并关闭文件 */
file = File(filePath, Append)
file.write("abcdefghi\n".toArray())
file.close()
/* 以 只读模式 打开文件 './tempFile.txt',按要求读出数据并关闭文件 */
file = File(filePath, Read)
let bytesBuf: Array<Byte> = Array<Byte>(10, repeat: 0)
// 从文件头开始的第 10 个字节后开始读出 10 个字节的数据
file.seek(SeekPosition.Begin(10))
file.read(bytesBuf)
println("Data of the 10th byte after the 10th byte: ${String.fromUtf8(bytesBuf)}")
// 读出文件尾的 10 个字节的数据
file.seek(SeekPosition.End(-10))
file.read(bytesBuf)
println("Data of the last 10 bytes: ${String.fromUtf8(bytesBuf)}")
file.close()
/* 以 读+写模式 打开文件 './tempFile.txt',按要求进行操作后关闭文件 */
file = File(filePath, ReadWrite)
// 截断文件大小为 0
file.setLength(0)
// 向文件中写入新内容
file.write("The file was truncated to an empty file!".toArray())
// 重置游标到文件头
file.seek(SeekPosition.Begin(0))
// 读取文件内容
let allBytes: Array<Byte> = readToEnd(file)
// 关闭文件
file.close()
println("Data written newly: ${String.fromUtf8(allBytes)}")
remove(filePath)
return 0
}
运行结果:
The file 'tempFile.txt' is created successfully in current directory.
Data of the 10th byte after the 10th byte: 123456789
Data of the last 10 bytes: abcdefghi
Data written newly: The file was truncated to an empty file!
File 的一些 static 函数演示
代码如下:
import std.fs.*
main() {
let filePath: Path = Path("./tempFile.txt")
if (exists(filePath)) {
remove(filePath)
}
/* 以 只写模式 创建文件,并写入 "123456789\n" 并关闭文件 */
var file: File = File.create(filePath)
file.write("123456789\n".toArray())
file.close()
/* 以 追加模式 写入 "abcdefghi\n" 到文件 */
File.appendTo(filePath, "abcdefghi".toArray())
/* 直接读取文件中所有数据 */
let allBytes: Array<Byte> = File.readFrom(filePath)
println(String.fromUtf8(allBytes))
remove(filePath)
return 0
}
运行结果:
123456789
abcdefghi
FileInfo 示例
FileInfo 一些基础操作演示
代码如下:
import std.fs.*
import std.time.DateTime
main() {
// 在当前目录下创建一个临时文件,以便下面 FileInfo 的演示
let curDirPath: Path = canonicalize(Path("./"))
let file: File = File.createTemp(curDirPath)
file.write("123456789\n".toArray())
let fileInfo: FileInfo = file.info
file.close()
/* 获得这个文件父级目录的 FileInfo,这个文件的父目录是当前目录 */
let parentDirectory: Option<FileInfo> = fileInfo.parentDirectory
checkResult(parentDirectory == Some(FileInfo(curDirPath)), "The 'parentFileInfo' is obtained successfully.")
/* 获得这个文件的路径 */
/*
let filePath: Path = fileInfo.path
*/
/* 获取这个文件的创建时间、最后访问时间、最后修改时间 */
/*
let creationTime: DateTime = fileInfo.creationTime
let lastAccessTime: DateTime = fileInfo.lastAccessTime
let lastModificationTime: DateTime = fileInfo.lastModificationTime
*/
/*
* 获取这个文件的 length
* 如果是文件代表这个文件占用磁盘空间的大小
* 如果是目录代表这个目录的所有文件占用磁盘空间的大小(不包含子目录)
*/
/*
let length: Int64 = fileInfo.size
*/
/* 判断这个文件是否是软链接、普通文件、目录 */
checkResult(fileInfo.isSymbolicLink(), "The file is a symbolic link.")
checkResult(fileInfo.isRegular(), "The file is a regular file.")
checkResult(fileInfo.isDirectory(), "The file is a directory.")
/* 判断这个文件对于当前用户是否是只读、隐藏、可执行、可读、可写 */
checkResult(fileInfo.isReadOnly(), "This file is read-only.")
checkResult(fileInfo.isHidden(), "The file is hidden.")
checkResult(fileInfo.canExecute(), "The file is executable.")
checkResult(fileInfo.canRead(), "The file is readable.")
checkResult(fileInfo.canWrite(), "The file is writable.")
/* 修改当前用户对这个文件的权限,这里设置为对当前用户只读 */
checkResult(fileInfo.setExecutable(false), "The file was successfully set to executable.")
checkResult(fileInfo.setReadable(true), "The file was successfully set to readable.")
checkResult(fileInfo.setWritable(false), "The file was successfully set to writable.")
checkResult(fileInfo.isReadOnly(), "This file is now read-only.")
return 0
}
func checkResult(result: Bool, message: String): Unit {
if (result) {
println(message)
}
}
运行结果:
The 'parentFileInfo' is obtained successfully.
The file is a regular file.
The file is readable.
The file is writable.
The file was successfully set to executable.
The file was successfully set to readable.
The file was successfully set to writable.
This file is now read-only.
Path 示例
不同 Path 实例的属性信息展示
打印 Path 实例的目录部分、文件全名(有扩展名)、扩展名、文件名(无扩展名),并判断 Path 实例是绝对路径还是相对路径
代码如下:
import std.fs.Path
main() {
let pathStrArr: Array<String> = [
// 绝对路径
"/a/b/c",
"/a/b/",
"/a/b/c.cj",
"/a",
"/",
// 相对路径
"./a/b/c",
"./a/b/",
"./a/b/c.cj",
"./",
".",
"123."
]
for (i in 0..pathStrArr.size) {
let path: Path = Path(pathStrArr[i])
// 打印 path 的整个路径字符串
println("Path${i}: ${path.toString()}")
// 打印 path 的目录路径
println("Path.parent: ${path.parent}")
// 打印 path 的文件全名(有扩展名)
println("Path.fileName: ${path.fileName}")
// 打印 path 的扩展名
println("Path.extensionName: ${path.extensionName}")
// 打印 path 的文件名(无扩展名)
println("Path.fileNameWithoutExtension: ${path.fileNameWithoutExtension}")
// 打印 path 是否是绝对路径、相对路径
println("Path.isAbsolute: ${path.isAbsolute()}; Path.isRelative: ${path.isRelative()}")
println()
}
return 0
}
运行结果:
Path0: /a/b/c
Path.parent: /a/b
Path.fileName: c
Path.extensionName:
Path.fileNameWithoutExtension: c
Path.isAbsolute: true; Path.isRelative: false
Path1: /a/b/
Path.parent: /a
Path.fileName: b
Path.extensionName:
Path.fileNameWithoutExtension: b
Path.isAbsolute: true; Path.isRelative: false
Path2: /a/b/c.cj
Path.parent: /a/b
Path.fileName: c.cj
Path.extensionName: cj
Path.fileNameWithoutExtension: c
Path.isAbsolute: true; Path.isRelative: false
Path3: /a
Path.parent: /
Path.fileName: a
Path.extensionName:
Path.fileNameWithoutExtension: a
Path.isAbsolute: true; Path.isRelative: false
Path4: /
Path.parent: /
Path.fileName:
Path.extensionName:
Path.fileNameWithoutExtension:
Path.isAbsolute: true; Path.isRelative: false
Path5: ./a/b/c
Path.parent: ./a/b
Path.fileName: c
Path.extensionName:
Path.fileNameWithoutExtension: c
Path.isAbsolute: false; Path.isRelative: true
Path6: ./a/b/
Path.parent: ./a
Path.fileName: b
Path.extensionName:
Path.fileNameWithoutExtension: b
Path.isAbsolute: false; Path.isRelative: true
Path7: ./a/b/c.cj
Path.parent: ./a/b
Path.fileName: c.cj
Path.extensionName: cj
Path.fileNameWithoutExtension: c
Path.isAbsolute: false; Path.isRelative: true
Path8: ./
Path.parent:
Path.fileName: .
Path.extensionName:
Path.fileNameWithoutExtension:
Path.isAbsolute: false; Path.isRelative: true
Path9: .
Path.parent:
Path.fileName: .
Path.extensionName:
Path.fileNameWithoutExtension:
Path.isAbsolute: false; Path.isRelative: true
Path10: 123.
Path.parent:
Path.fileName: 123.
Path.extensionName:
Path.fileNameWithoutExtension: 123
Path.isAbsolute: false; Path.isRelative: true
Path 的拼接、判等、转规范化路径等操作
代码如下:
import std.fs.*
main() {
let dirPath: Path = Path("./a/b/c")
if (!exists(dirPath)) {
Directory.create(dirPath, recursive: true)
}
let filePath: Path = dirPath.join("d.cj") // ./a/b/c/d.cj
if (filePath == Path("./a/b/c/d.cj")) {
println("filePath.join: success")
}
if (!exists(filePath)) {
File.create(filePath).close()
}
let curCanonicalizedPath: Path = canonicalize(Path("."))
let fileCanonicalizedPath: Path = canonicalize(Path("././././a/./../a/b/../../a/b/c/.././../../a/b/c/d.cj"))
if (fileCanonicalizedPath == canonicalize(filePath) &&
fileCanonicalizedPath.toString() == curCanonicalizedPath.toString() + "/a/b/c/d.cj") {
println("canonicalize filePath: success")
}
remove(dirPath, recursive: true)
return 0
}
运行结果:
filePath.join: success
canonicalize filePath: success
通过 Path 创建文件和目录
代码如下:
import std.fs.*
main() {
let curPath: Path = Path("./")
let dirPath: Path = curPath.join("tempDir")
let filePath: Path = dirPath.join("tempFile.txt")
if (exists(dirPath)) {
remove(dirPath, recursive: true)
}
Directory.create(dirPath)
if (exists(dirPath)) {
println("Directory 'tempDir' is created successfully.")
}
File.create(filePath).close()
if (exists(filePath)) {
println("File 'tempFile.txt' is created successfully in directory 'tempDir'.")
}
remove(dirPath, recursive: true)
return 0
}
运行结果:
Directory 'tempDir' is created successfully.
File 'tempFile.txt' is created successfully in directory 'tempDir'.
std.io
功能介绍
io 包提供程序与外部设备进行数据交换的能力。
I/O 操作是指程序与外部设备进行数据交换的操作。仓颉提供了流式 I/O 操作的通用接口和一些特殊实现。输入输出流类似一个数据通道,承载一段有序数据,程序从输入流读取数据(来自文件、网络等),往输出流(通往文件、网络等)写入数据。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| copy(InputStream, OutputStream) | 将一个输入流中未被读取的数据拷贝到另一个输出流中。 |
| readString<T>(T) where T <: InputStream & Seekable | 读取入参中的所有剩余内容,并返回一个字符串。 |
| readStringUnchecked<T>(T) where T <: InputStream & Seekable | 读取入参中的所有剩余内容,并返回一个字符串。该函数不会检查字符串的合法性。 |
| func readToEnd<T>(T) where T <: InputStream & Seekable | 获取入参中未被读取的数据。 |
接口
| 接口名 | 功能 |
|---|---|
| InputStream | 输入流接口。 |
| IOStream | 输入输出流接口。 |
| OutputStream | 输出流接口。 |
| Seekable | 移动光标接口。 |
类
| 类名 | 功能 |
|---|---|
| BufferedInputStream<T> where T <: InputStream | 提供带缓冲区的输入流。 |
| BufferedOutputStream<T> where T <: OutputStream | 提供带缓冲区的输出流。 |
| ByteBuffer | 输入流接口。 |
| ChainedInputStream<T> where T <: InputStream | 提供顺序从 InputStream 数组中读取数据的能力。 |
| MultiOutputStream<T> where T <: OutputStream | 提供将数据同时写入到 OutputStream 数组中每个输出流中的能力。 |
| StringReader<T> where T <: InputStream | 提供从 InputStream 输入流中读出数据并转换成字符或字符串的能力。 |
| StringWriter<T> where T <: OutputStream | 提供将 String 以及一些 ToString 类型转换成指定编码格式和字节序配置的字符串并写入到输出流的能力。 |
枚举
| 枚举名 | 功能 |
|---|---|
| SeekPosition | 输入流接口。 |
异常类
| 异常类名 | 功能 |
|---|---|
| ContentFormatException | 提供字符格式相关的异常处理。 |
| IOException | 提供 IO 流相关的异常处理。 |
函数
func copy(InputStream, OutputStream)
public func copy(from: InputStream, to!: OutputStream): Int64
功能:将一个输入流中未被读取的数据拷贝到另一个输出流中。
参数:
- from: InputStream - 待读取数据的输入流。
- to!: OutputStream - 数据将要拷贝到的输出流。
返回值:
- Int64 - 拷贝数据的字节数。
示例:
import std.io.ByteBuffer
import std.io.copy
main(): Unit {
let sourceStream = ByteBuffer()
let targetStream = ByteBuffer()
/* 向源输入流写入数据 */
let sourceData = "Hello, World!".toArray()
sourceStream.write(sourceData)
/* 使用 copy 函数将源输入流的数据拷贝到目标输出流 */
let copiedBytes = copy(sourceStream, to: targetStream)
println("Copied ${copiedBytes} bytes.")
/* 读取目标输出流中的数据 */
let targetData: Array<Byte> = Array<Byte>(sourceData.size, repeat: 0)
targetStream.read(targetData)
println("Data copied to target stream: ${String.fromUtf8(targetData)}")
}
运行结果:
Copied 13 bytes.
Data copied to target stream: Hello, World!
func readString<T>(T) where T <: InputStream & Seekable
public func readString<T>(from: T): String where T <: InputStream & Seekable
功能:读取入参中的所有剩余内容,并返回一个字符串。
参数:
- from: T - 要读取数据的对象。
返回值:
- String - 读取到的结果字符串。
异常:
- ContentFormatException - 当剩余字节不符合 UTF-8 编码规则时,抛出异常。 示例:
import std.io.ByteBuffer
import std.io.readString
import std.io.ContentFormatException
main(): Unit {
let inputStream = ByteBuffer()
/* 向输入流写入数据 */
let sourceData = "Hello, World!".toArray()
inputStream.write(sourceData)
/* 使用 readString 函数读取输入流中的所有剩余内容 */
try {
let result = readString(inputStream)
println("Read string: ${result}")
} catch (e: ContentFormatException) {
println("Error: ${e.message}")
}
/* 向输入流写入一个不合法的 UTF-8 字符串 */
let sourceDataError: Array<UInt8> = [0xC3, 0x28, 0x48, 0x65, 0x6C, 0x6C, 0x6F]
inputStream.write(sourceDataError)
/* 使用 readString 函数读取输入流中的所有剩余内容 */
try {
let result = readString(inputStream)
println("Read string: ${result}")
} catch (e: ContentFormatException) {
println("Error: ${e.message}")
}
}
运行结果:
Read string: Hello, World!
Error: Invalid unicode scalar value.
func readStringUnchecked<T>(T) where T <: InputStream & Seekable
public unsafe func readStringUnchecked<T>(from: T): String where T <: InputStream & Seekable
功能:读取入参中的所有剩余内容,并返回一个字符串。该函数不会检查字符串的合法性。
参数:
- from: T - 要读取数据的对象。
返回值:
- String - 读取到的结果字符串。
示例:
import std.io.ByteBuffer
import std.io.readStringUnchecked
import std.io.ContentFormatException
main(): Unit {
let inputStream = ByteBuffer()
/* 向输入流写入数据 */
let sourceData = "Hello, World!".toArray()
inputStream.write(sourceData)
/* 使用 readString 函数读取输入流中的所有剩余内容,可以正常输出:Read string: Hello, World! */
unsafe {
let result = readStringUnchecked(inputStream)
println("Read string: ${result}")
}
/* 向输入流写入一个不合法的 UTF-8 字符串 */
let sourceDataError: Array<UInt8> = [0xC3, 0x28, 0x48, 0x65, 0x6C, 0x6C, 0x6F]
inputStream.write(sourceDataError)
/* 使用 readString 函数读取输入流中的所有剩余内容,由于 inputStream 的第一位是不合法的UTF-8字符,所以将产生不可期的输出字符 */
unsafe {
let result = readStringUnchecked(inputStream)
println("Read string: ${result}")
}
}
func readToEnd<T>(T) where T <: InputStream & Seekable
public func readToEnd<T>(from: T): Array<Byte> where T <: InputStream & Seekable
功能:获取入参中未被读取的数据。
参数:
- from: T - 要读取数据的对象。
返回值:
示例:
import std.io.ByteBuffer
import std.io.readToEnd
main(): Unit {
let inputStream = ByteBuffer()
/* 向输入流写入数据 */
let sourceData = "Hello, World!".toArray()
inputStream.write(sourceData)
/* 使用 readToEnd 函数读取输入流中的所有剩余内容 */
let data = readToEnd(inputStream)
println("${String.fromUtf8(data)}")
}
运行结果:
Hello, World!
接口
interface IOStream
public interface IOStream <: InputStream & OutputStream {}
功能:输入输出流接口。
父类型:
interface InputStream
public interface InputStream {
func read(buffer: Array<Byte>): Int64
}
功能:输入流接口。
func read(Array<Byte>)
func read(buffer: Array<Byte>): Int64
功能:从输入流中读取数据放到 buffer 中。
参数:
返回值:
- Int64 - 读取的数据的字节数。
interface OutputStream
public interface OutputStream {
func write(buffer: Array<Byte>): Unit
func flush(): Unit
}
功能:输出流接口。
func flush()
func flush(): Unit
功能:清空缓存区。该函数提供默认实现,默认实现为空。
func write(Array<Byte>)
func write(buffer: Array<Byte>): Unit
功能:将 buffer 中的数据写入到输出流中。
参数:
interface Seekable
public interface Seekable {
prop length: Int64
prop position: Int64
prop remainLength: Int64
func seek(sp: SeekPosition): Int64
}
功能:移动光标接口。
prop length
prop length: Int64
功能:返回当前流中的总数据量。
类型:Int64
prop position
prop position: Int64
功能:返回当前光标位置。
类型:Int64
prop remainLength
prop remainLength: Int64
功能:返回当前流中未读的数据量。
类型:Int64
func seek(SeekPosition)
func seek(sp: SeekPosition): Int64
功能:移动光标到指定的位置。
参数:
- sp: SeekPosition - 指定光标移动后的位置。
返回值:
- Int64 - 返回流中数据的起点到移动后位置的偏移量(以字节为单位)。
类
class BufferedInputStream<T> where T <: InputStream
public class BufferedInputStream<T> <: InputStream where T <: InputStream {
public init(input: T)
public init(input: T, buffer: Array<Byte>)
public init(input: T, capacity: Int64)
}
功能:提供带缓冲区的输入流。
可将其他 InputStream 类型的输入流(如 ByteBuffer)绑定到 BufferedInputStream 实例,从该实例读取数据时,先把数据从被绑定的流读入缓冲区暂存,再从缓冲区读取用户需要的数据。
父类型:
init(T)
public init(input: T)
功能:创建 BufferedInputStream 实例,缓冲区容量取默认值 4096。
参数:
- input: T - 绑定指定输入流。
示例:
import std.io.ByteBuffer
import std.io.BufferedInputStream
main(): Unit {
let inputData = "Hello World".toArray()
let inputStream = ByteBuffer(inputData)
/* 绑定指定输入流 */
let bufferedStream = BufferedInputStream(inputStream)
/* 从输入流中读取数据 */
let data = Array<Byte>(inputData.size, repeat: 0)
bufferedStream.read(data)
println(String.fromUtf8(data))
}
运行结果:
Hello World
init(T, Array<Byte>)
public init(input: T, buffer: Array<Byte>)
功能:创建 BufferedInputStream 实例。
其内部使用的缓存区由入参决定,在注重性能的场景下,通过复用传入的 buffer,可以减少内存分配次数,提高性能。
参数:
- input: T - 绑定一个输入流。
- buffer: Array<Byte> - BufferedInputStream 使用的内部缓存区。
异常:
- IllegalArgumentException - 当 buffer 大小等于 0 时,抛出异常。
示例:
import std.io.ByteBuffer
import std.io.BufferedInputStream
main(): Unit {
let inputStream = ByteBuffer()
/* 使用合法的内部缓冲区创建 BufferedInputStream 实例,不会抛出异常 */
try {
let buffer = Array<Byte>(1024, repeat: 0)
let bufferedStream = BufferedInputStream(inputStream, buffer)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
/* 内部缓冲区大小被定义为0的情况 */
try {
let invalidBuffer = Array<Byte>()
let bufferedStream = BufferedInputStream(inputStream, invalidBuffer)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
}
运行结果:
Error: The buffer cannot be empty.
init(T, Int64)
public init(input: T, capacity: Int64)
功能:创建 BufferedInputStream 实例。
参数:
- input: T - 绑定指定输入流。
- capacity: Int64 - 内部缓冲区容量。
异常:
- IllegalArgumentException - 当 capacity 小于等于 0 时,抛出异常。
func read(Array<Byte>)
public func read(buffer: Array<Byte>): Int64
功能:从绑定的输入流读出数据到 buffer 中。
参数:
返回值:
- Int64 - 读取数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 为空时,抛出异常。
示例:
import std.io.ByteBuffer
import std.io.BufferedInputStream
main(): Unit {
let inputStream = ByteBuffer()
/* 使用合法的内部缓冲区容量创建 BufferedInputStream 实例,不会抛出异常 */
try {
let capacity = 2048
let bufferedStream = BufferedInputStream(inputStream, capacity)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
/* 当内部缓冲区被设置成 0 时,抛出异常 */
try {
let zeroCapacity = 0
let bufferedStream = BufferedInputStream(inputStream, zeroCapacity)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
/* 当内部缓冲区被设置成负数时,抛出异常 */
try {
let negativeCapacity = -1024
let bufferedStream = BufferedInputStream(inputStream, negativeCapacity)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
}
运行结果:
Error: Invalid capacity size: capacity = 0.
Error: Invalid capacity size: capacity = -1024.
func readByte()
public func readByte(): ?Byte
功能:从输入流中读取一个字节。
返回值:
- ?Byte - 读取到的数据。读取失败时会返回
None。
示例:
import std.io.ByteBuffer
import std.io.BufferedInputStream
main(): Unit {
/* 创建输入流并写入数据 */
let inputStream = ByteBuffer()
let sourceData = "abc".toArray()
inputStream.write(sourceData)
let bufferedStream = BufferedInputStream(inputStream)
/* 依次读取所有字节 */
while (true) {
let byte = bufferedStream.readByte()
if (byte == None) {
break
}
println(String.fromUtf8(byte.getOrThrow()))
}
}
运行结果:
a
b
c
func reset(T)
public func reset(input: T): Unit
功能:绑定新的输入流,重置状态,但不重置 capacity。
参数:
- input: T - 待绑定的输入流。
示例:
import std.io.ByteBuffer
import std.io.BufferedInputStream
import std.io.IOException
main(): Unit {
/* 创建第一个输入流并写入数据 */
let inputStream1 = ByteBuffer()
let sourceData1 = "First message: Hello".toArray()
inputStream1.write(sourceData1)
/* 创建第二个输入流并写入数据 */
let inputStream2 = ByteBuffer()
let sourceData2 = "Second message: World".toArray()
inputStream2.write(sourceData2)
/* 使用 BufferedInputStream 包装第一个输入流 */
let bufferedStream = BufferedInputStream(inputStream1)
/* 读取第一个输入流的部分数据 */
var result1 = ""
for (_ in 0..sourceData1.size) {
let byte = bufferedStream.readByte()
if (byte == None) {
break
}
result1 += String.fromUtf8(byte.getOrThrow())
}
println(result1)
/* 重置输入流为第二个输入流 */
bufferedStream.reset(inputStream2)
var result2 = ""
for (_ in 0..sourceData2.size) {
let byte = bufferedStream.readByte()
if (byte == None) {
break
}
result2 += String.fromUtf8(byte.getOrThrow())
}
println(result2)
}
运行结果:
First message: Hello
Second message: World
extend<T> BufferedInputStream<T> <: Resource where T <: Resource
extend<T> BufferedInputStream<T> <: Resource where T <: Resource
功能:为 BufferedInputStream 实现 Resource 接口,该类型对象可在 try-with-resource 语法上下文中实现自动资源释放。
父类型:
func close()
public func close(): Unit
功能:关闭当前流。
注意:
- 调用此方法后不可再调用 BufferedInputStream 的其他接口,否则会造成不可期现象。
func isClosed()
public func isClosed(): Bool
功能:判断当前流是否关闭。
返回值:
- Bool - 如果当前流已经被关闭,返回 true,否则返回 false。
示例:
import std.io.BufferedInputStream
import std.io.InputStream
import std.io.ByteBuffer
/**
* 自定义实现 InputStream 和 Resource 接口的类A
*/
public class A <: InputStream & Resource {
private var closed: Bool = false
public func read(buffer: Array<Byte>): Int64 {
let inputData = "Hello World".toArray()
let inputStream = ByteBuffer(inputData)
let num = inputStream.read(buffer)
return num
}
public func isClosed(): Bool {
return closed
}
public func close(): Unit {
println("Resource is closed")
closed = true
}
}
main(): Unit {
let bufferedStream = BufferedInputStream(A())
/* 使用try-with-resource语法获取资源 */
try (r = bufferedStream) {
println("Get the resource")
let data = Array<Byte>(11, repeat: 0)
r.read(data)
println(r.isClosed())
println(String.fromUtf8(data))
}
/* 自动调用 close() 函数释放资源 */
println(bufferedStream.isClosed())
}
运行结果:
Get the resource
false
Hello World
Resource is closed
true
extend<T> BufferedInputStream<T> <: Seekable where T <: Seekable
extend<T> BufferedInputStream<T> <: Seekable where T <: Seekable
功能:为 BufferedInputStream 实现 Seekable 接口,支持查询数据长度,移动光标等操作。
父类型:
prop length
public prop length: Int64
功能:返回当前流中的总数据量。
类型:Int64
prop position
public prop position: Int64
功能:返回当前光标位置。
类型:Int64
prop remainLength
public prop remainLength: Int64
功能:返回当前流中未读的数据量。
类型:Int64
func seek(SeekPosition)
public func seek(sp: SeekPosition): Int64
功能:移动光标到指定的位置。
说明:
- 指定的位置不能位于流中数据头部之前。
- 指定位置可以超过流中数据末尾。
- 调用该函数会先清空缓存区,再移动光标的位置。
参数:
- sp: SeekPosition - 指定光标移动后的位置。
返回值:
- Int64 - 返回流中数据的起点到移动后位置的偏移量(以字节为单位)。
异常:
- IOException - 当指定的位置位于流中数据头部之前时,抛出异常。
示例:
import std.io.BufferedInputStream
import std.io.InputStream
import std.io.ByteBuffer
import std.io.Seekable
import std.io.SeekPosition
import std.io.IOException
import std.io.readToEnd
/**
* 自定义实现 InputStream 和 Seekable 接口的类A
*/
public class A <: InputStream & Seekable {
public var inputStream: ByteBuffer = ByteBuffer()
public func read(buffer: Array<Byte>): Int64 {
let inputData = "Hello World".toArray()
inputStream = ByteBuffer(inputData)
let num = inputStream.read(buffer)
return num
}
public func seek(sp: SeekPosition): Int64 {
return inputStream.seek(sp)
}
}
main(): Unit {
let seekableStream = A()
let bufferedStream = BufferedInputStream(seekableStream)
let buffer = Array<Byte>(11, repeat: 0)
bufferedStream.read(buffer)
/* 输出当前流中总数据量,当前光标位置,当前流中未读的数据量 */
println("Length : " + bufferedStream.length.toString())
println("Position : " + bufferedStream.position.toString())
println("Remain Length : " + bufferedStream.remainLength.toString())
/* 移动光标到指定位置,虽然超过了流中数据末尾但是合法的 */
println("Position after seek() : " + bufferedStream.seek(SeekPosition.Current(11)).toString())
/* 尝试移动到数据头部之前,抛出异常 */
try {
bufferedStream.seek(SeekPosition.Begin(-1))
} catch (e: IOException) {
println("Error: " + e.message)
}
/* 将光标移动到第一个单词之后,读取后续的数据 */
bufferedStream.seek(SeekPosition.Begin(6))
println(String.fromUtf8(readToEnd(seekableStream.inputStream)))
}
运行结果:
Length : 11
Position : 11
Remain Length : 0
Position after seek() : 22
Error: Can't move the position before the beginning of the stream.
World
class BufferedOutputStream<T> where T <: OutputStream
public class BufferedOutputStream<T> <: OutputStream where T <: OutputStream {
public init(output: T)
public init(output: T, buffer: Array<Byte>)
public init(output: T, capacity: Int64)
}
功能:提供带缓冲区的输出流。
可将其他 OutputStream 类型的输入流(如 ByteBuffer)绑定到 BufferedOutputStream 实例,从该实例写入数据时,先把数据写入缓冲区暂存,再从缓冲区写入数据到流中。
父类型:
init(T)
public init(output: T)
功能:创建 BufferedOutputStream 实例,缓冲区容量取默认值 4096。
参数:
- output: T - 绑定指定输出流。
示例:
import std.io.ByteBuffer
import std.io.BufferedOutputStream
import std.io.readToEnd
main(): Unit {
let outputStream = ByteBuffer()
/* 绑定指定输出流 */
let bufferedStream = BufferedOutputStream(outputStream)
/* 将输出数据写入缓冲流 bufferedStream 并刷新内部绑定的输出流 outputStream */
let outputData = "Hello World".toArray()
bufferedStream.write(outputData)
bufferedStream.flush()
println(String.fromUtf8(readToEnd(outputStream)))
}
运行结果:
Hello World
init(T, Array<Byte>)
public init(output: T, buffer: Array<Byte>)
功能:创建 BufferedOutputStream 实例。
其内部使用的缓存区由入参决定,在注重性能的场景下,通过复用传入的 buffer,可以减少内存分配次数,提高性能。
参数:
- output: T - 绑定一个输出流。
- buffer: Array<Byte> - BufferedOutputStream 使用的内部缓存区。
异常:
- IllegalArgumentException - 当 buffer 大小等于 0 时,抛出异常。
示例:
import std.io.ByteBuffer
import std.io.BufferedOutputStream
main(): Unit {
let outputStream = ByteBuffer()
/* 使用合法的内部缓冲区创建 BufferedOutputStream 实例,不会抛出异常 */
try {
let buffer = Array<Byte>(1024, repeat: 0)
let bufferedStream = BufferedOutputStream(outputStream, buffer)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
/* 内部缓冲区大小被定义为0的情况 */
try {
let invalidBuffer = Array<Byte>()
let bufferedStream = BufferedOutputStream(outputStream, invalidBuffer)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
}
运行结果:
Error: The buffer cannot be empty.
init(T, Int64)
public init(output: T, capacity: Int64)
功能:创建 BufferedOutputStream 实例。
参数:
- output: T - 绑定指定输出流。
- capacity: Int64 - 内部缓冲区容量。
异常:
- IllegalArgumentException - 当 capacity 小于等于 0 时,抛出异常。
示例:
import std.io.ByteBuffer
import std.io.BufferedOutputStream
main(): Unit {
let outputStream = ByteBuffer()
/* 使用合法的内部缓冲区容量创建 BufferedoutputStream 实例,不会抛出异常 */
try {
let capacity = 2048
let bufferedStream = BufferedOutputStream(outputStream, capacity)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
/* 当内部缓冲区被设置成 0 时,抛出异常 */
try {
let zeroCapacity = 0
let bufferedStream = BufferedOutputStream(outputStream, zeroCapacity)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
/* 当内部缓冲区被设置成负数时,抛出异常 */
try {
let negativeCapacity = -1024
let bufferedStream = BufferedOutputStream(outputStream, negativeCapacity)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
}
运行结果:
Error: Invalid capacity size: capacity = 0.
Error: Invalid capacity size: capacity = -1024.
func flush()
public func flush(): Unit
功能:刷新 BufferedOutputStream:将内部缓冲区的剩余数据写入绑定的输出流,并刷新 BufferedOutputStream。
示例:
import std.io.ByteBuffer
import std.io.BufferedOutputStream
import std.io.readToEnd
main(): Unit {
let outputStream = ByteBuffer()
/* 绑定指定输出流 */
let bufferedStream = BufferedOutputStream(outputStream)
/* 将输出数据写入缓冲流 bufferedStream 并刷新内部绑定的输出流 outputStream */
let outputData = "Hello World".toArray()
bufferedStream.write(outputData)
bufferedStream.flush()
println(String.fromUtf8(readToEnd(outputStream)))
}
运行结果:
Hello World
func reset(T)
public func reset(output: T): Unit
功能:绑定新的输出流,重置状态,但不重置 capacity。
参数:
- output: T - 待绑定的输出流。
示例:
import std.io.ByteBuffer
import std.io.BufferedOutputStream
import std.io.IOException
import std.io.readToEnd
main(): Unit {
/* 创建第一个输出流 */
let outputStream1 = ByteBuffer()
let sourceData1 = "First message: Hello".toArray()
/* 创建第二个输出流 */
let outputStream2 = ByteBuffer()
let sourceData2 = "Second message: World".toArray()
/* 使用 BufferedOutputStream 包装第一个输出流 */
let bufferedStream = BufferedOutputStream(outputStream1)
/* 将第一个源数据写入到绑定的第一个输出流中并刷新 */
bufferedStream.write(sourceData1)
bufferedStream.flush()
println(String.fromUtf8(readToEnd(outputStream1)))
/* 重置输出流为第二个输出流,将第二个源数据写入到绑定的第二个输出流中并刷新 */
bufferedStream.reset(outputStream2)
bufferedStream.write(sourceData2)
bufferedStream.flush()
println(String.fromUtf8(readToEnd(outputStream2)))
}
运行结果:
First message: Hello
Second message: World
func write(Array<Byte>)
public func write(buffer: Array<Byte>): Unit
功能:将 buffer 中的数据写入到绑定的输出流中。
参数:
示例:
import std.io.ByteBuffer
import std.io.BufferedOutputStream
import std.io.readToEnd
main(): Unit {
let outputStream = ByteBuffer()
/* 绑定指定输出流 */
let bufferedStream = BufferedOutputStream(outputStream)
/* 将输出数据写入缓冲流 bufferedStream 并刷新内部绑定的输出流 outputStream */
let outputData = "Hello World".toArray()
bufferedStream.write(outputData)
bufferedStream.flush()
println(String.fromUtf8(readToEnd(outputStream)))
}
运行结果:
Hello World
func writeByte(Byte)
public func writeByte(v: Byte): Unit
功能:写入一个字节到绑定的输出流中。
参数:
- v: Byte - 待写入的字节。
示例:
import std.io.ByteBuffer
import std.io.BufferedOutputStream
import std.io.readToEnd
main(): Unit {
let outputStream = ByteBuffer()
/* 绑定指定输出流 */
let bufferedStream = BufferedOutputStream(outputStream)
/* 将输出数据逐个写入缓冲流 bufferedStream 并刷新内部绑定的输出流 outputStream */
let outputData = "Hello World".toArray()
for (byte in outputData){
bufferedStream.writeByte(byte)
}
bufferedStream.flush()
println(String.fromUtf8(readToEnd(outputStream)))
}
运行结果:
Hello World
extend<T> BufferedOutputStream<T> <: Resource where T <: Resource
extend<T> BufferedOutputStream<T> <: Resource where T <: Resource
功能:为 BufferedOutputStream 实现 Resource 接口,该类型对象可在 try-with-resource 语法上下文中实现自动资源释放。
父类型:
func close()
public func close(): Unit
功能:关闭当前流。
注意:
- 调用此方法后不可再调用 BufferedOutputStream 的其他接口,否则会造成不可期现象。
func isClosed()
public func isClosed(): Bool
功能:判断当前流是否关闭。
返回值:
- Bool - 如果当前流已经被关闭,返回 true,否则返回 false。
示例:
import std.io.BufferedOutputStream
import std.io.OutputStream
import std.io.ByteBuffer
import std.io.readToEnd
/**
* 自定义实现 OutputStream 和 Resource 接口的类A
*/
public class A <: OutputStream & Resource {
private var closed: Bool = false
public var outputStream = ByteBuffer()
public func write(buffer: Array<Byte>): Unit {
this.outputStream = ByteBuffer(buffer)
}
public func isClosed(): Bool {
return closed
}
public func close(): Unit {
println("Resource is closed")
closed = true
}
}
main(): Unit {
let resourceStream = A()
let bufferedStream = BufferedOutputStream(resourceStream)
/* 使用try-with-resource语法获取资源 */
try (r = bufferedStream) {
println("Get the resource")
let data = "Hello World".toArray()
r.write(data)
r.flush()
println(r.isClosed())
println(String.fromUtf8(readToEnd(resourceStream.outputStream)))
}
/* 自动调用 close() 函数释放资源 */
println(bufferedStream.isClosed())
}
运行结果:
Get the resource
false
Hello World
Resource is closed
true
extend<T> BufferedOutputStream<T> <: Seekable where T <: Seekable
extend<T> BufferedOutputStream<T> <: Seekable where T <: Seekable
功能:为 BufferedOutputStream 实现 Seekable 接口,支持查询数据长度,移动光标等操作。
父类型:
prop length
public prop length: Int64
功能:返回当前流中的总数据量。
类型:Int64
prop position
public prop position: Int64
功能:返回当前光标位置。
类型:Int64
prop remainLength
public prop remainLength: Int64
功能:返回当前流中未读的数据量。
类型:Int64
func seek(SeekPosition)
public func seek(sp: SeekPosition): Int64
功能:移动光标到指定的位置。
说明:
- 指定的位置不能位于流中数据头部之前。
- 指定位置可以超过流中数据末尾。
- 调用该函数会先将缓存区内的数据写到绑定的输出流里,再移动光标的位置。
参数:
- sp: SeekPosition - 指定光标移动后的位置。
返回值:
- Int64 - 返回流中数据的起点到移动后位置的偏移量(以字节为单位)。
异常:
- IOException - 当指定的位置位于流中数据头部之前时,抛出异常。
示例:
import std.io.BufferedOutputStream
import std.io.OutputStream
import std.io.ByteBuffer
import std.io.Seekable
import std.io.SeekPosition
import std.io.IOException
import std.io.readToEnd
/**
* 自定义实现 OutputStream 和 Seekable 接口的类A
*/
public class A <: OutputStream & Seekable {
public var outputStream: ByteBuffer = ByteBuffer()
public func write(buffer: Array<Byte>): Unit {
this.outputStream = ByteBuffer(buffer)
}
public func seek(sp: SeekPosition): Int64 {
return outputStream.seek(sp)
}
}
main(): Unit {
let seekableStream = A()
let bufferedStream = BufferedOutputStream(seekableStream)
let data = "Hello World".toArray()
bufferedStream.write(data)
bufferedStream.flush()
/* 输出当前流中总数据量,当前光标位置,当前流中未读的数据量 */
println("Length : " + bufferedStream.length.toString())
println("Position : " + bufferedStream.position.toString())
println("Remain Length : " + bufferedStream.remainLength.toString())
/* 移动光标到指定位置,虽然超过了流中数据末尾但是合法的 */
println("Position after seek() : " + bufferedStream.seek(SeekPosition.Current(11)).toString())
/* 尝试移动到数据头部之前,抛出异常 */
try {
bufferedStream.seek(SeekPosition.Begin(-1))
} catch (e: IOException) {
println("Error: " + e.message)
}
/* 将光标移动到第一个单词之后,读取后续的数据 */
bufferedStream.seek(SeekPosition.Begin(6))
println(String.fromUtf8(readToEnd(seekableStream.outputStream)))
}
运行结果:
Length : 11
Position : 0
Remain Length : 11
Position after seek() : 11
Error: Can't move the position before the beginning of the stream.
World
class ByteBuffer
public class ByteBuffer <: IOStream & Seekable {
public init()
public init(capacity: Int64)
public init(source: Array<Byte>)
}
功能:基于 Array<Byte> 数据类型,提供对字节流的写入、读取等操作。
父类型:
prop capacity
public prop capacity: Int64
功能:获取当前缓冲区容量。
返回值:
- Int64 - 当前缓冲区容量。
init()
public init()
功能:创建 ByteBuffer 实例,默认的初始容量是 32。
示例:
import std.io.ByteBuffer
main(): Unit {
let buffer = ByteBuffer()
println(buffer.capacity)
}
运行结果:
32
init(Array<Byte>)
public init(source: Array<Byte>)
功能:根据传入的数组构造 ByteBuffer 实例。
参数:
示例:
import std.io.ByteBuffer
main(): Unit {
let inputData = "Hello World".toArray()
let buffer = ByteBuffer(inputData)
println(buffer.capacity)
/* 从缓冲区中读取数据 */
println(String.fromUtf8(buffer.bytes()))
}
运行结果:
11
Hello World
init(Int64)
public init(capacity: Int64)
功能:创建 ByteBuffer 实例。
参数:
- capacity: Int64 - 指定的初始容量。
异常:
- IllegalArgumentException - 当 capacity 小于 0 时,抛出异常。
示例:
import std.io.ByteBuffer
main(): Unit {
let buffer = ByteBuffer(1024)
println(buffer.capacity)
try{
let errorBuffer = ByteBuffer(-1024)
println(errorBuffer.capacity)
}catch(e: Exception){
println("Error: ${e.message}")
}
}
运行结果:
1024
Error: The capacity must be greater than or equal to 0: -1024.
func bytes()
public func bytes(): Array<Byte>
功能:获取当前 ByteBuffer 中未被读取的数据的切片。
注意:
- 缓冲区进行读取,写入或重置等修改操作会导致这个切片失效。
- 对切片的修改会影响缓冲区的内容。
返回值:
示例:
import std.io.ByteBuffer
main(): Unit {
let inputData = "Hello World".toArray()
let buffer = ByteBuffer(inputData)
/* 从缓冲区中读取数据 */
println(String.fromUtf8(buffer.bytes()))
}
运行结果:
Hello World
func clear()
public func clear(): Unit
功能:清除当前 ByteBuffer 中所有数据。
示例:
import std.io.ByteBuffer
main(): Unit {
let inputData = "Hello World".toArray()
let buffer = ByteBuffer(inputData)
println(buffer.capacity)
/* 读取原始数据 */
println(String.fromUtf8(buffer.bytes()))
/* 清除缓冲区 */
buffer.clear()
/* 读取清除后的缓冲区 */
println("buffer after clear: " + String.fromUtf8(buffer.bytes()))
println("capacity after clear: ${buffer.capacity}")
}
运行结果:
11
Hello World
buffer after clear:
capacity after clear: 11
func clone()
public func clone(): ByteBuffer
功能:用当前 ByteBuffer 中的数据来构造一个新的 ByteBuffer。
返回值:
- ByteBuffer - 新构造的 ByteBuffer 对象。
示例:
import std.io.ByteBuffer
main(): Unit {
let inputData = "Hello World".toArray()
let originalBuffer = ByteBuffer(inputData)
/* 克隆原始缓冲区 */
let clonedBuffer = originalBuffer.clone()
println("originalBuffer: " + String.fromUtf8(originalBuffer.bytes()))
println("clonedBuffer: " + String.fromUtf8(clonedBuffer.bytes()))
/* 修改原始缓冲区的数据 */
originalBuffer.write(" New Data".toArray())
println("originalBuffer: " + String.fromUtf8(originalBuffer.bytes()))
println("clonedBuffer: " + String.fromUtf8(clonedBuffer.bytes()))
}
运行结果:
originalBuffer: Hello World
clonedBuffer: Hello World
originalBuffer: Hello World New Data
clonedBuffer: Hello World
func read(Array<Byte>)
public func read(buffer: Array<Byte>): Int64
功能:从输入流中读取数据放到 buffer 中。
参数:
返回值:
- Int64 - 读取数据的字节数。
异常:
- IllegalArgumentException - 当 buffer 为空时,抛出异常。
示例:
import std.io.ByteBuffer
main(): Unit {
let inputData = "Hello World".toArray()
let buffer = ByteBuffer(inputData)
/* 创建一个目标缓冲区,读取数据到目标缓冲区 */
let targetBuffer = Array<Byte>(5,repeat:0)
buffer.read(targetBuffer)
println(String.fromUtf8(targetBuffer))
/* 尝试读取空缓冲区 */
try {
let emptyBuffer = Array<Byte>()
buffer.read(emptyBuffer)
} catch (e: IllegalArgumentException) {
println("Error: " + e.message)
}
}
运行结果:
Hello
Error: The buffer is empty.
func readByte()
public func readByte(): ?Byte
功能:从输入流中读取一个字节。
返回值:
- ?Byte - 读取到的数据。读取失败时会返回
None。
示例:
import std.io.ByteBuffer
main(): Unit {
let inputData = "Hello World".toArray()
let buffer = ByteBuffer(inputData)
for (_ in 0..inputData.size) {
print(String.fromUtf8(buffer.readByte().getOrThrow()))
}
println()
/* 尝试读取下一个不存在的字节 */
let nextByte = buffer.readByte()
match (nextByte) {
case None => println("nextByte: None")
case _ => println("nextByte: ${nextByte.getOrThrow()}")
}
}
运行结果:
Hello World
nextByte: None
func reserve(Int64)
public func reserve(additional: Int64): Unit
功能:将缓冲区扩容指定大小。
说明:
- 当缓冲区剩余字节数大于等于
additional时不发生扩容。- 当缓冲区剩余字节数量小于
additional时,取(additional+capacity)与(capacity的1.5倍向下取整)两个值中的最大值进行扩容。
参数:
- additional: Int64 - 将要扩容的大小。
异常:
- IllegalArgumentException - 当 additional 小于 0 时,抛出异常。
- OverflowException - 当扩容后的缓冲区大小超过 Int64 的最大值时,抛出异常。
示例:
import std.io.ByteBuffer
main(): Unit {
let buffer = ByteBuffer(11)
println("initial capacity: " + buffer.capacity.toString())
buffer.write("Hello World".toArray())
/* 尝试扩容,需要增加的容量大于剩余空间,发生扩容 */
buffer.reserve(5)
println("reserve 5: " + buffer.capacity.toString())
/* 尝试扩容,需要增加的容量小于剩余空间,不发生扩容 */
buffer.reserve(2)
println("reserve 2: " + buffer.capacity.toString())
/* 尝试扩容,additional为负数 */
try {
buffer.reserve(-1)
} catch (e: IllegalArgumentException) {
println("Error: " + e.message)
}
/* 尝试扩容,导致容量超过Int64最大值 */
try {
buffer.reserve(Int64.Max - buffer.capacity + 1)
} catch (e: OverflowException) {
println("Error: " + e.message)
}
}
运行结果:
initial capacity: 11
reserve 5: 16
reserve 2: 16
Error: The additional must be greater than or equal to 0.
Error:The maximum value for capacity expansion cannot exceed the maximum value of Int64.
func seek(SeekPosition)
public func seek(sp: SeekPosition): Int64
功能:将光标跳转到指定位置。
说明:
- 指定的位置不能位于流中数据头部之前。
- 指定位置可以超过流中数据末尾。
参数:
- sp: SeekPosition - 指定光标跳转后的位置。
返回值:
- Int64 - 流中数据的头部到跳转后位置的偏移量(以字节为单位)。
异常:
- IOException - 当指定的位置位于流中数据头部之前时,抛出异常。
示例:
import std.io.ByteBuffer
import std.io.SeekPosition
import std.io.IOException
main(): Unit {
let buffer = ByteBuffer("Hello World".toArray())
println("initial position: ${buffer.position}")
/* 移动到当前位置之后6个字节 */
buffer.seek(SeekPosition.Current(6))
println(String.fromUtf8(buffer.bytes()))
/* 移动位置超过流中数据末尾,为合法操作 */
println(buffer.seek(SeekPosition.End(1)))
/* 尝试移动到数据头部之前,抛出异常 */
try {
buffer.seek(SeekPosition.Begin(-1))
} catch (e: IOException) {
println("Error: " + e.message)
}
}
运行结果:
initial position: 0
World
12
Error: Can't move the position before the beginning of the stream.
func setLength(Int64)
public func setLength(length: Int64): Unit
功能:将当前数据修改为指定长度。该操作不会改变seek的偏移。
参数:
- length: Int64 - 要修改的长度。
异常:
- IllegalArgumentException - 当
length小于 0 时,抛此异常。 - OverflowException - 当 length 过大导致扩容后的缓冲区大小超过 Int64 的最大值时,抛出异常。
示例:
import std.io.ByteBuffer
main(): Unit {
let buffer = ByteBuffer("Hello World".toArray())
println("initial length: " + buffer.length.toString())
/* 设置长度为5,并读取缓冲区中所有的内容 */
buffer.setLength(5)
println("set length to 5: " + String.fromUtf8(buffer.bytes()))
/* 尝试设置扩容后的缓冲区大小超过 Int64 的最大值时,抛出异常 */
try {
buffer.setLength(Int64.Max + 1)
} catch (e: OverflowException) {
println("Error: " + e.message)
}
/* 尝试设置长度为-1,抛出异常 */
try {
buffer.setLength(-1)
} catch (e: IllegalArgumentException) {
println("Error: " + e.message)
}
}
运行结果:
initial length: 11
set length to 5: Hello
Error: add
Error: The length must be greater than or equal to 0.
func write(Array<Byte>)
public func write(buffer: Array<Byte>): Unit
功能:将 buffer 中的数据写入到输出流中。
参数:
示例:
import std.io.ByteBuffer
main(): Unit {
let buffer = ByteBuffer()
let dataToWrite = "Hello World".toArray()
/* 写入数据 */
buffer.write(dataToWrite)
println(String.fromUtf8(buffer.bytes()))
}
运行结果:
Hello World
func writeByte(Byte)
public func writeByte(v: Byte): Unit
功能:将一个字节写入到输出流中。
参数:
- v: Byte - 待写入的字节。
示例:
import std.io.ByteBuffer
main(): Unit {
let buffer = ByteBuffer()
let dataToWrite : Array<Byte> = "Hello World".toArray()
/* 每次写入单个字节 */
for( i in 0 .. dataToWrite.size){
buffer.writeByte(dataToWrite[i])
}
println(String.fromUtf8(buffer.bytes()))
}
运行结果:
Hello World
class ChainedInputStream<T> where T <: InputStream
public class ChainedInputStream<T> <: InputStream where T <: InputStream {
public init(input: Array<T>)
}
功能:提供顺序从 InputStream 数组中读取数据的能力。
父类型:
init(Array<T>)
public init(input: Array<T>)
功能:创建 ChainedInputStream 实例。
参数:
- input: Array<T> - 绑定指定输入流数组。
异常:
- IllegalArgumentException - 当 input 为空时,抛出异常。
func read(Array<Byte>)
public func read(buffer: Array<Byte>): Int64
功能:依次从绑定 InputStream 数组中读出数据到 buffer 中。
参数:
返回值:
- Int64 - 读取字节数。
异常:
- IllegalArgumentException - 当 buffer 为空时,抛出异常。
示例:
import std.io.*
main(): Unit {
let inputData = "Hello World".toArray()
let bufferInput = ByteBuffer(inputData)
let cis = ChainedInputStream(bufferInput)
// 缓冲区容量是 7
let bufferOutput = Array<Byte>(7, repeat: 0)
cis.read(bufferOutput)
let result = String.fromUtf8(bufferOutput)
println(result)
}
运行结果:
Hello W
class MultiOutputStream<T> where T <: OutputStream
public class MultiOutputStream<T> <: OutputStream where T <: OutputStream {
public init(output: Array<T>)
}
功能:提供将数据同时写入到 OutputStream 数组中每个输出流中的能力。
父类型:
init(Array<T>)
public init(output: Array<T>)
功能:创建 MultiOutputStream 实例。
参数:
- output: Array<T> - 绑定指定输出流数组。
异常:
- IllegalArgumentException - 当 output 为空时,抛出异常。
func flush()
public func flush(): Unit
功能:刷新绑定的输出流数组里的每个输出流。
func write(Array<Byte>)
public func write(buffer: Array<Byte>): Unit
功能:将 buffer 同时写入到绑定的 OutputStream 数组里的每个输出流中。
参数:
class StringReader<T> where T <: InputStream
public class StringReader<T> where T <: InputStream {
public init(input: T)
}
功能:提供从 InputStream 输入流中读出数据并转换成字符或字符串的能力。
说明:
- StringReader 内部默认有缓冲区,缓冲区容量 4096 个字节。
- StringReader 目前仅支持 UTF-8 编码,暂不支持 UTF-16、UTF-32。
init(T)
public init(input: T)
功能:创建 StringReader 实例。
参数:
- input: T - 待读取数据的输入流。
func lines()
public func lines(): Iterator<String>
功能:获得 StringReader 的行迭代器。
相当于循环调用 func readln(),内部遇到非法字符时也会抛出异常。
说明:
- 每行都由换行符进行分隔。
- 换行符是
\n\r\r\n之一。- 每行不包括换行符。
返回值:
异常:
- ContentFormatException - 当
for-in或者调用next()方法时读取到非法字符,抛出异常。
func read()
public func read(): ?Rune
功能:按字符读取流中的数据。
返回值:
异常:
- ContentFormatException - 当读取到非法字符时,抛出异常。
func readToEnd()
public func readToEnd(): String
功能:读取流中所有剩余数据。
返回值:
- String - 流中所有剩余数据。
异常:
- ContentFormatException - 当读取到非法字符时,抛出异常。
func readUntil((Rune)->Bool)
public func readUntil(predicate: (Rune)->Bool): Option<String>
功能:从流内读取到使 predicate 返回 true 的字符位置(包含这个字符)或者流结束位置的数据。
参数:
- predicate: (Rune)->Bool - 满足一定条件返回
true的表达式。
返回值:
异常:
- ContentFormatException - 当读取到非法字符时,抛出异常。
func readUntil(Rune)
public func readUntil(v: Rune): Option<String>
功能:从流内读取到指定字符(包含指定字符)或者流结束位置的数据。
参数:
- v: Rune - 指定字符。
返回值:
异常:
- ContentFormatException - 当读取到非法字符时,抛出异常。
func readln()
public func readln(): Option<String>
功能:按行读取流中的数据。
说明:
- 读取的数据会去掉原换行符。
返回值:
异常:
- ContentFormatException - 当读取到非法字符时,抛出异常。
func runes()
public func runes(): Iterator<Rune>
功能:获得 StringReader 的 Rune 迭代器。
返回值:
异常:
- ContentFormatException - 当
for-in或者调用next()方法时读取到非法字符,抛出异常。
extend<T> StringReader<T> <: Resource where T <: Resource
extend<T> StringReader<T> <: Resource where T <: Resource
功能:为 StringReader 实现 Resource 接口,该类型对象可在 try-with-resource 语法上下文中实现自动资源释放。
父类型:
func close()
public func close(): Unit
功能:关闭当前流。
注意:
- 调用此方法后不可再调用 StringReader 的其他接口,否则会造成不可期现象。
func isClosed()
public func isClosed(): Bool
功能:判断当前流是否关闭。
返回值:
- Bool - 如果当前流已经被关闭,返回 true,否则返回 false。
extend<T> StringReader<T> <: Seekable where T <: Seekable
extend<T> StringReader<T> <: Seekable where T <: Seekable
功能:为 StringReader 实现 Seekable 接口,支持查询数据长度,移动光标等操作。
父类型:
prop position
public prop position: Int64
功能:返回当前光标位置。
类型:Int64
func seek(SeekPosition)
public func seek(sp: SeekPosition): Int64
功能:移动光标到指定的位置。
说明:
- 指定的位置不能位于流中数据头部之前。
- 指定位置可以超过流中数据末尾。
参数:
- sp: SeekPosition - 指定光标移动后的位置。
返回值:
- Int64 - 返回流中数据的起点到移动后位置的偏移量(以字节为单位)。
异常:
- IOException - 当指定的位置位于流中数据头部之前时,抛出异常。
class StringWriter<T> where T <: OutputStream
public class StringWriter<T> where T <: OutputStream {
public init(output: T)
}
功能:提供将 String 以及一些 ToString 类型转换成指定编码格式和字节序配置的字符串并写入到输出流的能力。
说明:
- StringWriter 内部默认有缓冲区,缓冲区容量 4096 个字节。
- StringWriter 目前仅支持 UTF-8 编码,暂不支持 UTF-16、UTF-32。
init(T)
public init(output: T)
功能:创建 StringWriter 实例。
参数:
- output: T - 待写入数据的输出流。
func flush()
public func flush(): Unit
功能:刷新内部缓冲区,将缓冲区数据写入 output 中,并刷新 output。
func write(Bool)
public func write(v: Bool): Unit
功能:写入 Bool 类型。
参数:
func write(Float16)
public func write(v: Float16): Unit
功能:写入 Float16 类型。
参数:
func write(Float32)
public func write(v: Float32): Unit
功能:写入 Float32 类型。
参数:
func write(Float64)
public func write(v: Float64): Unit
功能:写入 Float64 类型。
参数:
func write(Int16)
public func write(v: Int16): Unit
功能:写入 Int16 类型。
参数:
func write(Int32)
public func write(v: Int32): Unit
功能:写入 Int32 类型。
参数:
func write(Int64)
public func write(v: Int64): Unit
功能:写入 Int64 类型。
参数:
func write(Int8)
public func write(v: Int8): Unit
功能:写入 Int8 类型。
参数:
func write(Rune)
public func write(v: Rune): Unit
功能:写入 Rune 类型。
参数:
func write(String)
public func write(v: String): Unit
功能:写入字符串。
参数:
- v: String - 待写入的字符串。
func write(UInt16)
public func write(v: UInt16): Unit
功能:写入 UInt16 类型。
参数:
func write(UInt32)
public func write(v: UInt32): Unit
功能:写入 UInt32 类型。
参数:
func write(UInt64)
public func write(v: UInt64): Unit
功能:写入 UInt64 类型。
参数:
func write(UInt8)
public func write(v: UInt8): Unit
功能:写入 UInt8 类型。
参数:
func write<T>(T) where T <: ToString
public func write<T>(v: T): Unit where T <: ToString
功能:写入 ToString 类型。
参数:
- v: T - ToString 类型的实例。
func writeln()
public func writeln(): Unit
功能:写入换行符。
func writeln(Bool)
public func writeln(v: Bool): Unit
功能:写入 Bool 类型 + 换行符。
参数:
func writeln(Float16)
public func writeln(v: Float16): Unit
功能:写入 Float16 类型 + 换行符。
参数:
func writeln(Float32)
public func writeln(v: Float32): Unit
功能:写入 Float32 类型 + 换行符。
参数:
func writeln(Float64)
public func writeln(v: Float64): Unit
功能:写入 Float64 类型 + 换行符。
参数:
func writeln(Int16)
public func writeln(v: Int16): Unit
功能:写入 Int16 类型 + 换行符。
参数:
func writeln(Int32)
public func writeln(v: Int32): Unit
功能:写入 Int32 类型 + 换行符。
参数:
func writeln(Int64)
public func writeln(v: Int64): Unit
功能:写入 Int64 类型 + 换行符。
参数:
func writeln(Int8)
public func writeln(v: Int8): Unit
功能:写入 Int8 类型 + 换行符。
参数:
func writeln(Rune)
public func writeln(v: Rune): Unit
功能:写入 Rune 类型 + 换行符。
参数:
func writeln(String)
public func writeln(v: String): Unit
功能:写入字符串 + 换行符。
参数:
- v: String - 待写入的字符串。
func writeln(UInt16)
public func writeln(v: UInt16): Unit
功能:写入 UInt16 类型 + 换行符。
参数:
func writeln(UInt32)
public func writeln(v: UInt32): Unit
功能:写入 UInt32 类型 + 换行符。
参数:
func writeln(UInt64)
public func writeln(v: UInt64): Unit
功能:写入 UInt64 类型 + 换行符。
参数:
func writeln(UInt8)
public func writeln(v: UInt8): Unit
功能:写入 UInt8 类型 + 换行符。
参数:
func writeln<T>(T) where T <: ToString
public func writeln<T>(v: T): Unit where T <: ToString
功能:写入 ToString 类型 + 换行符。
参数:
- v: T - ToString 类型的实例。
extend<T> StringWriter<T> <: Resource where T <: Resource
extend<T> StringWriter<T> <: Resource where T <: Resource
功能:为 StringWriter 实现 Resource 接口,该类型对象可在 try-with-resource 语法上下文中实现自动资源释放。
父类型:
func close()
public func close(): Unit
功能:关闭当前流。
注意:
- 调用此方法后不可再调用 StringWriter 的其他接口,否则会造成不可期现象。
func isClosed()
public func isClosed(): Bool
功能:判断当前流是否关闭。
返回值:
- Bool - 如果当前流已经被关闭,返回 true,否则返回 false。
extend<T> StringWriter<T> <: Seekable where T <: Seekable
extend<T> StringWriter<T> <: Seekable where T <: Seekable
功能:为 StringWriter 实现 Seekable 接口,支持查询数据长度,移动光标等操作。
父类型:
func seek(SeekPosition)
public func seek(sp: SeekPosition): Int64
功能:移动光标到指定的位置。
说明:
- 指定的位置不能位于流中数据头部之前。
- 指定位置可以超过流中数据末尾。
参数:
- sp: SeekPosition - 指定光标移动后的位置。
返回值:
- Int64 - 返回流中数据的起点到移动后位置的偏移量(以字节为单位)。
异常:
- IOException - 当指定的位置位于流中数据头部之前时,抛出异常。
枚举
enum SeekPosition
public enum SeekPosition {
| Begin(Int64)
| Current(Int64)
| End(Int64)
}
功能:该枚举类型表示光标在文件中的位置。
Begin(Int64)
Begin(Int64)
功能:表示从起点开始移动。
Current(Int64)
Current(Int64)
功能:表示从当前位置开始移动。
End(Int64)
End(Int64)
功能:表示从末尾开始移动。
异常
class ContentFormatException
public class ContentFormatException <: Exception {
public init()
public init(message: String)
}
功能:提供字符格式相关的异常处理。
父类型:
init()
public init()
功能:创建 ContentFormatException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 ContentFormatException 实例。
参数:
- message: String - 异常提示信息。
class IOException
public open class IOException <: Exception {
public init()
public init(message: String)
}
功能:提供 IO 流相关的异常处理。
父类型:
init()
public init()
功能:创建 IOException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 IOException 实例。
参数:
- message: String - 异常提示信息。
func getClassName()
protected open func getClassName(): String
功能:获得类名。
返回值:
- String - 类名。
BufferedInputStream 示例
下面是 BufferedInputStream 从流中读取数据示例。
import std.io.*
main(): Unit {
let arr1 = "0123456789".toArray()
let byteBuffer = ByteBuffer()
byteBuffer.write(arr1)
let bufferedInputStream = BufferedInputStream(byteBuffer)
let arr2 = Array<Byte>(20, repeat: 0)
/* 读取流中数据,返回读取到的数据的长度 */
let readLen = bufferedInputStream.read(arr2)
println(String.fromUtf8(arr2[..readLen]))
}
运行结果:
0123456789
BufferedOutputStream 示例
下面是 BufferedOutputStream 向流中写入数据示例。
import std.io.*
main(): Unit {
let arr1 = "01234".toArray()
let byteBuffer = ByteBuffer()
byteBuffer.write(arr1)
let bufferedOutputStream = BufferedOutputStream(byteBuffer)
let arr2 = "56789".toArray()
/* 向流中写入数据,此时数据在外部流的缓冲区中 */
bufferedOutputStream.write(arr2)
/* 调用 flush 函数,真正将数据写入内部流中 */
bufferedOutputStream.flush()
println(String.fromUtf8(readToEnd(byteBuffer)))
}
运行结果:
0123456789
ByteBuffer 示例
下面是 ByteBuffer 对流进行写入数据,读取数据等操作的示例。
import std.io.*
main(): Unit {
let arr1 = "test case".toArray()
let byteBuffer = ByteBuffer()
/* 将 arr1 中的数据写入到流中 */
byteBuffer.write(arr1)
/* 读取前 4 个字节的数据到 arr2 中 */
let arr2 = Array<Byte>(4, repeat: 0)
byteBuffer.read(arr2)
println(String.fromUtf8(arr2))
/* 将流的索引指向起点 */
byteBuffer.seek(Begin(0))
/* 读取流中全部数据 */
let arr3 = readToEnd(byteBuffer)
println(String.fromUtf8(arr3))
/* 将流的索引指向字母 'c' 的位置 */
byteBuffer.seek(End(-4))
/* 读取流中剩余数据 */
let str = readString(byteBuffer)
println(str)
}
运行结果:
test
test case
case
ChainedInputStream 示例
下面是 ChainedInputStream 从绑定的流中循环读取数据示例。
import std.io.*
import std.collection.ArrayList
main(): Unit {
const size = 2
/* 创建两个 ByteBuffer 并写入数据 */
let streamArr = Array<InputStream>(size, {_ => ByteBuffer()})
for (i in 0..size) {
match (streamArr[i]) {
case v: OutputStream =>
let str = "now ${i}"
v.write(str.toArray())
case _ => throw Exception()
}
}
/* 将两个 ByteBuffer 绑定到 ChainedInputStream */
let chainedInputStream = ChainedInputStream(streamArr)
let res = ArrayList<Byte>()
let buffer = Array<Byte>(20, repeat: 0)
var readLen = chainedInputStream.read(buffer)
/* 循环读取 chainedInputStream 中数据 */
while (readLen != 0) {
res.add(all: buffer[..readLen])
readLen = chainedInputStream.read(buffer)
}
println(String.fromUtf8(res.toArray()))
}
运行结果:
now 0now 1
MultiOutputStream 示例
下面是 MultiOutputStream 向绑定的所有流中写入数据示例。
import std.io.*
main(): Unit {
const size = 2
/* 将两个 ByteBuffer 绑定到 MultiOutputStream */
let streamArr = Array<OutputStream>(size, {_ => ByteBuffer()})
let multiOutputStream = MultiOutputStream(streamArr)
/* 往 MultiOutputStream 写入数据,会同时写入绑定的两个 ByteBuffer */
multiOutputStream.write("test".toArray())
/* 读取 ByteBuffer 中数据,验证结果 */
for (i in 0..size) {
match (streamArr[i]) {
case v: ByteBuffer =>
println(String.fromUtf8(readToEnd(v)))
case _ => throw Exception()
}
}
}
运行结果:
test
test
StringReader 示例
下面是 StringReader 从流中读取数据示例。
import std.io.*
main(): Unit {
let arr1 = "012\n346789".toArray()
let byteBuffer = ByteBuffer()
byteBuffer.write(arr1)
let stringReader = StringReader(byteBuffer)
/* 读取一个字节 */
let ch = stringReader.read()
println(ch ?? 'a')
/* 读取一行数据 */
let line = stringReader.readln()
println(line ?? "error")
/* 读取数据直到遇到字符6 */
let until = stringReader.readUntil(r'6')
println(until ?? "error")
/* 读取全部数据 */
let all = stringReader.readToEnd()
println(all)
}
运行结果:
0
12
346
789
StringWriter 示例
下面是 StringWriter 向流中写入数据示例。
import std.io.*
main(): Unit {
let byteBuffer = ByteBuffer()
let stringWriter = StringWriter(byteBuffer)
/* 写入字符串 */
stringWriter.write("number")
/* 写入字符串并自动转行 */
stringWriter.writeln(" is:")
/* 写入数字 */
stringWriter.write(100.0f32)
stringWriter.flush()
println(String.fromUtf8(readToEnd(byteBuffer)))
}
运行结果:
number is:
100.000000
std.math
功能介绍
math 包提供常见的数学运算,常数定义,浮点数处理等功能。
包括了以下能力:
- 科学常数与类型常数定义;
- 浮点数的判断,规整;
- 常用的位运算;
- 通用的数学函数,如绝对值,三角函数,指数,对数计算;
- 最大公约数与最小公倍数。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| abs(Float16) | 求一个半精度浮点数的绝对值。 |
| abs(Float32) | 求一个单精度浮点数的绝对值。 |
| abs(Float64) | 求一个双精度浮点数的绝对值。 |
| abs(Int16) | 求一个 16 位有符号整数的绝对值。 |
| abs(Int32) | 求一个 32 位有符号整数的绝对值。 |
| abs(Int64) | 求一个 64 位有符号整数的绝对值。 |
| abs(Int8) | 求一个 8 位有符号整数的绝对值。 |
| acos(Float16) | 计算半精度浮点数的反余弦函数值,单位为弧度。 |
| acos(Float32) | 计算单精度浮点数的反余弦函数值,单位为弧度。 |
| acos(Float64) | 计算双精度浮点数的反余弦函数值,单位为弧度。 |
| acosh(Float16) | 计算半精度浮点数的反双曲余弦函数值。 |
| acosh(Float32) | 计算单精度浮点数的反双曲余弦函数值。 |
| acosh(Float64) | 计算双精度浮点数的反双曲余弦函数值。 |
| asin(Float16) | 计算半精度浮点数的反正弦函数值,单位为弧度。 |
| asin(Float32) | 计算单精度浮点数的反正弦函数值,单位为弧度。 |
| asin(Float64) | 计算双精度浮点数的反正弦函数值,单位为弧度。 |
| asinh(Float16) | 计算半精度浮点数的反双曲正弦函数值。 |
| asinh(Float32) | 计算单精度浮点数的反双曲正弦函数值。 |
| asinh(Float64) | 计算双精度浮点数的反双曲正弦函数值。 |
| atan(Float16) | 计算半精度浮点数的反正切函数值,单位为弧度。 |
| atan(Float32) | 计算单精度浮点数的反正切函数值,单位为弧度。 |
| atan(Float64) | 计算双精度浮点数的反正切函数值,单位为弧度。 |
| atan2(Float16, Float16) | 计算两个半精度浮点数的反正切函数值,单位为弧度。 |
| atan2(Float32, Float32) | 计算两个单精度浮点数的反正切函数值,单位为弧度。 |
| atan2(Float64, Float64) | 计算两个双精度浮点数的反正切函数值,单位为弧度。 |
| atanh(Float16) | 计算半精度浮点数的反双曲正切函数值。 |
| atanh(Float32) | 计算单精度浮点数的反双曲正切函数值。 |
| atanh(Float64) | 计算双精度浮点数的反双曲正切函数值。 |
| cbrt(Float16) | 求半精度浮点数的立方根。 |
| cbrt(Float32) | 求单精度浮点数的立方根。 |
| cbrt(Float64) | 求双精度浮点数的立方根。 |
| ceil(Float16) | 求半精度浮点数的向上取整值。 |
| ceil(Float32) | 求单精度浮点数的向上取整值。 |
| ceil(Float64) | 求双精度浮点数的向上取整值。 |
| checkedAbs(Int16) | 检查并求一个 16 位有符号整数的绝对值。如果入参是 16 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。 |
| checkedAbs(Int32) | 检查并求一个 32 位有符号整数的绝对值。如果入参是 32 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。 |
| checkedAbs(Int64) | 检查并求一个 64 位有符号整数的绝对值。如果入参是 64 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。 |
| checkedAbs(Int8) | 检查并求一个 8 位有符号整数的绝对值。如果入参是 8 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。 |
| clamp(Float16, Float16, Float16) | 求浮点数的范围区间数。如果此浮点数在该范围区间则返回此浮点数;如果此浮点数小于这个范围区间,则返回该范围区间的最小值;如果此浮点数大于这个范围区间,则返回该范围区间的最大值;如果是 NaN 则返回 NaN。 |
| clamp(Float32, Float32, Float32) | 求浮点数的范围区间数。如果此浮点数在该范围区间则返回此浮点数;如果此浮点数小于这个范围区间,则返回该范围区间的最小值;如果此浮点数大于这个范围区间,则返回该范围区间的最大值;如果是 NaN 则返回 NaN。 |
| clamp(Float64, Float64, Float64) | 求浮点数的范围区间数。如果此浮点数在该范围区间则返回此浮点数;如果此浮点数小于这个范围区间,则返回该范围区间的最小值;如果此浮点数大于这个范围区间,则返回该范围区间的最大值;如果是 NaN 则返回 NaN。 |
| cos(Float16) | 计算半精度浮点数的余弦函数值,入参单位为弧度。 |
| cos(Float32) | 计算单精度浮点数的余弦函数值,入参单位为弧度。 |
| cos(Float64) | 计算双精度浮点数的余弦函数值,入参单位为弧度。 |
| cosh(Float16) | 计算半精度浮点数的双曲余弦函数值。 |
| cosh(Float32) | 计算单精度浮点数的双曲余弦函数值。 |
| cosh(Float64) | 计算双精度浮点数的双曲余弦函数值。 |
| countOne(Int16) (deprecated) | 求 16 位整型的二进制表达中的 1 的位的个数。 |
| countOne(Int32) (deprecated) | 求 32 位整型的二进制表达中的 1 的位的个数。 |
| countOne(Int64) (deprecated) | 求 64 位整型的二进制表达中的 1 的位的个数。 |
| countOne(Int8) (deprecated) | 求 8 位整型的二进制表达中的 1 的位的个数。 |
| countOne(UInt16) (deprecated) | 求 16 位无符号整型的二进制表达中的 1 的位的个数。 |
| countOne(UInt32) (deprecated) | 求 32 位无符号整型的二进制表达中的 1 的位的个数。 |
| countOne(UInt64) (deprecated) | 求 64 位无符号整型的二进制表达中的 1 的位的个数。 |
| countOne(UInt8) (deprecated) | 求 8 位无符号整型的二进制表达中的 1 的位的个数。 |
| countOnes(Int16) | 求 16 位整型的二进制表达中的 1 的位的个数。 |
| countOnes(Int32) | 求 32 位整型的二进制表达中的 1 的位的个数。 |
| countOnes(Int64) | 求 64 位整型的二进制表达中的 1 的位的个数。 |
| countOnes(Int8) | 求 8 位整型的二进制表达中的 1 的位的个数。 |
| countOnes(UInt16) | 求 16 位无符号整型的二进制表达中的 1 的位的个数。 |
| countOnes(UInt32) | 求 32 位无符号整型的二进制表达中的 1 的位的个数。 |
| countOnes(UInt64) | 求 64 位无符号整型的二进制表达中的 1 的位的个数。 |
| countOnes(UInt8) | 求 8 位无符号整型的二进制表达中的 1 的位的个数。 |
| erf(Float16) | 求半精度浮点数的误差值。 |
| erf(Float32) | 求单精度浮点数的误差值。 |
| erf(Float64) | 求双精度浮点数的误差值。 |
| exp(Float16) | 求自然常数 e 的 x 次幂。 |
| exp(Float32) | 求自然常数 e 的 x 次幂。 |
| exp(Float64) | 求自然常数 e 的 x 次幂。 |
| exp2(Float16) | 求 2 的 x 次幂。 |
| exp2(Float32) | 求 2 的 x 次幂。 |
| exp2(Float64) | 求 2 的 x 次幂。 |
| floor(Float16) | 求浮点数的向下取整值。 |
| floor(Float32) | 求浮点数的向下取整值。 |
| floor(Float64) | 求浮点数的向下取整值。 |
| fmod(Float16, Float16) | 求两个半精度浮点数相除的余数。 |
| fmod(Float32, Float32) | 求两个单精度浮点数相除的余数。 |
| fmod(Float64, Float64) | 求两个双精度浮点数相除的余数。 |
| gamma(Float16) | 求浮点数的 Gamma 值。 |
| gamma(Float32) | 求浮点数的 Gamma 值。 |
| gamma(Float64) | 求浮点数的 Gamma 值。 |
| gcd(Int16, Int16) | 求两个 16 位有符号整数的最大公约数。 |
| gcd(Int32, Int32) | 求两个 32 位有符号整数的最大公约数。 |
| gcd(Int64, Int64) | 求两个 64 位有符号整数的最大公约数。 |
| gcd(Int8, Int8) | 求两个 8 位有符号整数的最大公约数。 |
| gcd(UInt16, UInt16) | 求两个 16 位无符号整数的最大公约数。 |
| gcd(UInt32, UInt32) | 求两个 32 位无符号整数的最大公约数。 |
| gcd(UInt64, UInt64) | 求两个 64 位无符号整数的最大公约数。 |
| gcd(UInt8, UInt8) | 求两个 8 位无符号整数的最大公约数。 |
| lcm(Int16, Int16) | 求两个 16 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| lcm(Int32, Int32) | 求两个 32 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| lcm(Int64, Int64) | 求两个 64 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| lcm(Int8, Int8) | 求两个 8 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| lcm(UInt16, UInt16) | 求两个 16 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| lcm(UInt32, UInt32) | 求两个 32 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| lcm(UInt64, UInt64) | 求两个 64 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| lcm(UInt8, UInt8) | 求两个 8 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。 |
| leadingZeros(Int16) | 求 16 位有符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。 |
| leadingZeros(Int32) | 求 32 位有符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。 |
| leadingZeros(Int64) | 求 64 位有符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。 |
| leadingZeros(Int8) | 求 8 位有符号整数的二进制表达中的从最高位算起,包含符号位,连续位为 0 的个数。如果最高位不是 0,则返回 0。 |
| leadingZeros(UInt16) | 求 16 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。 |
| leadingZeros(UInt32) | 求 32 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。 |
| leadingZeros(UInt64) | 求 64 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。 |
| leadingZeros(UInt8) | 求 8 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。 |
| log(Float16) | 求以 e 为底 x 的对数。 |
| log(Float32) | 求以 e 为底 x 的对数。 |
| log(Float64) | 求以 e 为底 x 的对数。 |
| log10(Float16) | 求以 10 为底 x 的对数。 |
| log10(Float32) | 求以 10 为底 x 的对数。 |
| log10(Float64) | 求以 10 为底 x 的对数。 |
| log2(Float16) | 求以 2 为底 x 的对数。 |
| log2(Float32) | 求以 2 为底 x 的对数。 |
| log2(Float64) | 求以 2 为底 x 的对数。 |
| logBase(Float16, Float16) | 求以 base 为底 x 的对数。 |
| logBase(Float32, Float32) | 求以 base 为底 x 的对数。 |
| logBase(Float64, Float64) | 求以 base 为底 x 的对数。 |
| pow(Float32, Float32) | 求浮点数 base 的 exponent 次幂。 |
| pow(Float32, Int32) | 求浮点数 base 的 exponent 次幂。 |
| pow(Float64, Float64) | 求浮点数 base 的 exponent 次幂。 |
| pow(Float64, Int64) | 求浮点数 base 的 exponent 次幂。 |
| reverse(UInt16) | 求无符号整数按位反转后的数。 |
| reverse(UInt32) | 求无符号整数按位反转后的数。 |
| reverse(UInt64) | 求无符号整数按位反转后的数。 |
| reverse(UInt8) | 求无符号整数按位反转后的数。 |
| rotate(Int16, Int8) | 求整数的按位旋转后的结果。 |
| rotate(Int32, Int8) | 求整数的按位旋转后的结果。 |
| rotate(Int64, Int8) | 求整数的按位旋转后的结果。 |
| rotate(Int8, Int8) | 求整数的按位旋转后的结果。 |
| rotate(UInt16, Int8) | 求整数的按位旋转后的结果。 |
| rotate(UInt32, Int8) | 求整数的按位旋转后的结果。 |
| rotate(UInt64, Int8) | 求整数的按位旋转后的结果。 |
| rotate(UInt8, Int8) | 求整数的按位旋转后的结果。 |
| round(Float16) | 此函数采用 IEEE-754 的向最近舍入规则,计算浮点数的舍入值。 |
| round(Float32) | 此函数采用 IEEE-754 的向最近舍入规则,计算浮点数的舍入值。 |
| round(Float64) | 此函数采用 IEEE-754 的向最近舍入规则,计算浮点数的舍入值。 |
| sin(Float16) | 计算半精度浮点数的正弦函数值,入参单位为弧度。 |
| sin(Float32) | 计算单精度浮点数的正弦函数值,入参单位为弧度。 |
| sin(Float64) | 计算双精度浮点数的正弦函数值,入参单位为弧度。 |
| sinh(Float16) | 计算半精度浮点数的双曲正弦函数值。 |
| sinh(Float32) | 计算单精度浮点数的双曲正弦函数值。 |
| sinh(Float64) | 计算双精度浮点数的双曲正弦函数值。 |
| sqrt(Float16) | 求浮点数的算术平方根。 |
| sqrt(Float32) | 求浮点数的算术平方根。 |
| sqrt(Float64) | 求浮点数的算术平方根。 |
| tan(Float16) | 计算半精度浮点数的正切函数值,入参单位为弧度。 |
| tan(Float32) | 计算单精度浮点数的正切函数值,入参单位为弧度。 |
| tan(Float64) | 计算双精度浮点数的正切函数值,入参单位为弧度。 |
| tanh(Float16) | 计算半精度浮点数的双曲正切函数值。 |
| tanh(Float32) | 计算单精度浮点数的双曲正切函数值。 |
| tanh(Float64) | 计算双精度浮点数的双曲正切函数值。 |
| trailingZeros(Int16) | 求 16 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trailingZeros(Int32) | 求 32 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trailingZeros(Int64) | 求 64 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trailingZeros(Int8) | 求 16 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trailingZeros(UInt16) | 求 16 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trailingZeros(UInt32) | 求 32 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trailingZeros(UInt64) | 求 64 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trailingZeros(UInt8) | 求 8 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
| trunc(Float16) | 求浮点数的截断取整值。 |
| trunc(Float32) | 求浮点数的截断取整值。 |
| trunc(Float64) | 求浮点数的截断取整值。 |
接口
| 接口名 | 功能 |
|---|---|
| FloatingPoint<T> | 本接口提供了浮点数相关的方法。 |
| Integer<T> | 本接口提供了整数类型相关的方法。 |
| MathExtension (deprecated) | 为了导出 prop 而作辅助接口,浮点数导出 PI,E 属性。 |
| MaxMinValue<T> | 提供获取最大值和最小值的方法。 |
| Number<T> | 提供数值类型相关的方法。 |
枚举
| 枚举 | 功能 |
|---|---|
| RoundingMode | 舍入规则枚举类,共包含 6 种舍入规则。除包含 IEEE 754 浮点数规定约定的 5 种舍入规则外,提供使用较多的 “四舍五入” 舍入规则。 |
接口
interface FloatingPoint<T>
public interface FloatingPoint<T> <: Number<T> {
static func getE(): T
static func getInf(): T
static func getPI(): T
static func getMinDenormal(): T
static func getMinNormal(): T
static func getNaN(): T
func isInf(): Bool
func isNaN(): Bool
func isNormal(): Bool
}
功能:本接口提供了浮点数相关的方法。
父类型:
- Number<T>
static func getE()
static func getE(): T
功能:获取 T 类型的自然常数。
返回值:
- T - 类型 T 的自然常数。
static func getInf()
static func getInf(): T
功能:获取浮点数的无穷数。
返回值:
- T - 类型 T 的无穷数。
static func getPI()
static func getPI(): T
功能:获取 T 类型的圆周率常数。
返回值:
- T - 类型 T 的圆周率常数。
static func getMinDenormal()
static func getMinDenormal(): T
功能:获取单精度浮点数的最小次正规数。
返回值:
- T - 类型 T 的最小次正规数。
static func getMinNormal()
static func getMinNormal(): T
功能:获取单精度浮点数的最小正规数。
返回值:
- T - 类型 T 的最小正规数。
static func getNaN()
static func getNaN(): T
功能:获取浮点数的非数。
返回值:
- T - 类型 T 的非数。
func isInf()
func isInf(): Bool
功能:判断浮点数是否为无穷数值。
返回值:
- Bool - 如果浮点数的值正无穷大或负无穷大,则返回
true;否则,返回false。
func isNaN()
func isNaN(): Bool
功能:判断浮点数是否为非数值。
返回值:
- Bool - 如果浮点数的值为非数值,则返回
true;否则,返回false。
func isNormal()
func isNormal(): Bool
功能:判断浮点数是否为常规数值。
返回值:
- Bool - 如果是正常的浮点数,返回
true;否则,返回false。
extend Float16 <: FloatingPoint<Float16>
extend Float16 <: FloatingPoint<Float16>
功能:为 Float16 类型扩展 FloatingPoint<Float16> 接口。
父类型:
static func getE()
public static func getE(): Float16
功能:获取半精度浮点数类型的自然常数。
返回值:
- Float16 - 半精度浮点数类型的自然常数。
static func getInf()
public static func getInf(): Float16
功能:获取半精度浮点数类型的无穷数值。
返回值:
- Float16 - 半精度浮点数类型的无穷数值。
static func getPI()
public static func getPI(): Float16
功能:获取半精度浮点数类型的圆周率常数。
返回值:
- Float16 - 半精度浮点数类型的圆周率常数。
static func getMinDenormal()
public static func getMinDenormal(): Float16
功能:获取半精度浮点数类型的最小次正规数。
返回值:
- Float16 - 半精度浮点数类型的最小次正规数。
static func getMinNormal()
public static func getMinNormal(): Float16
功能:获取半精度浮点数类型的最小正规数。
返回值:
- Float16 - 半精度浮点数类型的最小正规数。
static func getNaN()
public static func getNaN(): Float16
功能:获取半精度浮点数类型的非数。
返回值:
- Float16 - 半精度浮点数类型的非数。
extend Float32 <: FloatingPoint<Float32>
extend Float32 <: FloatingPoint<Float32>
功能:为 Float32 类型扩展 FloatingPoint<Float32> 接口。
父类型:
static func getE()
public static func getE(): Float32
功能:获取单精度浮点数类型的自然常数。
返回值:
- Float32 - 单精度浮点数类型的自然常数。
static func getInf()
public static func getInf(): Float32
功能:获取单精度浮点数类型的无穷数值。
返回值:
- Float32 - 单精度浮点数类型的无穷数值。
static func getPI()
public static func getPI(): Float32
功能:获取单精度浮点数类型的圆周率常数。
返回值:
- Float32 - 单精度浮点数类型的圆周率常数。
static func getMinDenormal()
public static func getMinDenormal(): Float32
功能:获取单精度浮点数类型的最小次正规数。
返回值:
- Float32 - 单精度浮点数类型的最小次正规数。
static func getMinNormal()
public static func getMinNormal(): Float32
功能:获取单精度浮点数类型的最小正规数。
返回值:
- Float32 - 单精度浮点数类型的最小正规数。
static func getNaN()
public static func getNaN(): Float32
功能:获取单精度浮点数类型的非数。
返回值:
- Float32 - 单精度浮点数类型的非数。
extend Float64 <: FloatingPoint<Float64>
extend Float64 <: FloatingPoint<Float64>
功能:为 Float64 类型扩展 FloatingPoint<Float64> 接口。
父类型:
static func getE()
public static func getE(): Float64
功能:获取双精度浮点数类型的自然常数。
返回值:
- Float64 - 双精度浮点数类型的自然常数。
static func getInf()
public static func getInf(): Float64
功能:获取双精度浮点数类型的无穷数值。
返回值:
- Float64 - 双精度浮点数类型的无穷数值。
static func getPI()
public static func getPI(): Float64
功能:获取双精度浮点数类型的圆周率常数。
返回值:
- Float64 - 双精度浮点数类型的圆周率常数。
static func getMinDenormal()
public static func getMinDenormal(): Float64
功能:获取双精度浮点数类型的最小次正规数。
返回值:
- Float64 - 双精度浮点数类型的最小次正规数。
static func getMinNormal()
public static func getMinNormal(): Float64
功能:获取双精度浮点数类型的最小正规数。
返回值:
- Float64 - 双精度浮点数类型的最小正规数。
static func getNaN()
public static func getNaN(): Float64
功能:获取双精度浮点数类型的非数。
返回值:
- Float64 - 双精度浮点数类型的非数。
interface Integer<T>
public interface Integer<T> <: Number<T> {
static func isSigned(): Bool
operator func %(rhs: T): T
operator func &(rhs: T): T
operator func |(rhs: T): T
operator func ^(rhs: T): T
operator func !(): T
operator func >>(n: Int64): T
operator func <<(n: Int64): T
}
功能:本接口提供了整数类型相关的方法。
父类型:
static func isSigned()
static func isSigned(): Bool
功能:判断类型是否是有符号的。
返回值:
- Bool - 如果类型是有符号的,返回
true;否则返回false。
operator func %(T)
operator func %(rhs: T): T
功能:算术运算符,计算余数。
参数:
- rhs: T - 运算符右边的数,表示除数。
返回值:
- T - 计算所得余数。
operator func &(T)
operator func &(rhs: T): T
功能:位运算符,按位与。
参数:
- rhs: T - 运算符右边的数。
返回值:
- T - 计算所得结果。
operator func |(T)
operator func |(rhs: T): T
功能:位运算符,按位或。
参数:
- rhs: T - 运算符右边的数。
返回值:
- T - 计算所得结果。
operator func ^(T)
operator func ^(rhs: T): T
功能:位运算符,按位异或。
参数:
- rhs: T - 运算符右边的数。
返回值:
- T - 计算所得结果。
operator func !()
operator func !(): T
功能:位运算符,按位取反。
返回值:
- T - 计算所得结果。
operator func >>(Int64)
operator func >>(n: Int64): T
功能:位运算符,按位右移。
参数:
- n: Int64 - 运算符右边的数,表示右移的位数。
返回值:
- T - 计算所得结果。
operator func <<(Int64)
operator func <<(n: Int64): T
功能:位运算符,按位左移。
参数:
- n: Int64 - 运算符右边的数,表示左移的位数。
返回值:
- T - 计算所得结果。
extend Int16 <: Integer<Int16>
extend Int16 <: Integer<Int16>
功能:为 Int16 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 Int16 类型是否是有符号类型。
返回值:
- Bool - 总是返回
true。
extend Int32 <: Integer<Int32>
extend Int32 <: Integer<Int32>
功能:为 Int32 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 Int32 类型是否是有符号类型。
返回值:
- Bool - 总是返回
true。
extend Int64 <: Integer<Int64>
extend Int64 <: Integer<Int64>
功能:为 Int64 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 Int64 类型是否是有符号类型。
返回值:
- Bool - 总是返回
true。
extend Int8 <: Integer<Int8>
extend Int8 <: Integer<Int8>
功能:为 Int8 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 Int8 类型是否是有符号类型。
返回值:
- Bool - 总是返回
true。
extend IntNative <: Integer<IntNative>
extend IntNative <: Integer<IntNative>
功能:为 IntNative 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 IntNative 类型是否是有符号类型。
返回值:
- Bool - 总是返回
true。
extend UInt16 <: Integer<UInt16>
extend UInt16 <: Integer<UInt16>
功能:为 UInt16 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 UInt16 类型是否是有符号类型。
返回值:
- Bool - 总是返回
false。
extend UInt32 <: Integer<UInt32>
extend UInt32 <: Integer<UInt32>
功能:为 UInt32 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 UInt32 类型是否是有符号类型。
返回值:
- Bool - 总是返回
false。
extend UInt64 <: Integer<UInt64>
extend UInt64 <: Integer<UInt64>
功能:为 UInt64 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 UInt64 类型是否是有符号类型。
返回值:
- Bool - 总是返回
false。
extend UInt8 <: Integer<UInt8>
extend UInt8 <: Integer<UInt8>
功能:为 UInt8 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 UInt8 类型是否是有符号类型。
返回值:
- Bool - 总是返回
false。
extend UIntNative <: Integer<UIntNative>
extend UIntNative <: Integer<UIntNative>
功能:为 UIntNative 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 UIntNative 类型是否是有符号类型。
返回值:
- Bool - 总是返回
false。
interface MathExtension<T> (deprecated)
public interface MathExtension<T> {
static func GetPI(): T
static func GetE(): T
}
功能:本接口提供了统一的方法获取一些数学常数。
注意:
未来版本即将废弃,使用 FloatingPoint<T> 替代。
static func GetPI()
static func GetPI(): T
功能:获取 T 类型的圆周率常数。
返回值:
- T - 类型 T 的圆周率常数。
static func GetE()
static func GetE(): T
功能:获取 T 类型的自然常数。
返回值:
- T - 类型 T 的自然常数。
extend Float16 <: MathExtension<Float16>
extend Float16 <: MathExtension<Float16>
功能:拓展半精度浮点数以支持一些数学常数。
父类型:
static func GetPI()
public static func GetPI(): Float16
功能:获取半精度浮点数的圆周率常数。
返回值:
- Float16 - 类型的圆周率常数
static func GetE()
public static func GetE(): Float16
功能:获取半精度浮点数的自然常数。
返回值:
- Float16 - 类型的自然常数
extend Float32 <: MathExtension<Float32>
extend Float32 <: MathExtension<Float32>
功能:拓展单精度浮点数以支持一些数学常数。
父类型:
static func GetPI()
public static func GetPI(): Float32
功能:获取单精度浮点数的圆周率常数。
返回值:
- Float32 - 类型的圆周率常数
static func GetE()
public static func GetE(): Float32
功能:获取单精度浮点数的自然常数。
返回值:
- Float32 - 类型的自然常数
extend Float64 <: MathExtension<Float64>
extend Float64 <: MathExtension<Float64>
功能:拓展双精度浮点数以支持一些数学常数。
父类型:
static func GetPI()
public static func GetPI(): Float64
功能:获取双精度浮点数的圆周率常数。
返回值:
- Float64 - 类型的圆周率常数
static func GetE()
public static func GetE(): Float64
功能:获取双精度浮点数的自然常数。
返回值:
- Float64 - 类型的自然常数
interface MaxMinValue<T>
public interface MaxMinValue<T> {
static func getMax(): T
static func getMin(): T
}
功能:提供获取最大值和最小值的方法。
static func getMax()
static func getMax(): T
功能:获取最大值。
返回值:
- T - 最大值。
static func getMax()
static func getMin(): T
功能:获取最小值。
返回值:
- T - 最小值。
extend Float16 <: MaxMinValue<Float16>
extend Float16 <: MaxMinValue<Float16>
功能:为 Float16 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): Float16
功能:获取 Float16 类型的最大值。
返回值:
- Float16 - 半精度浮点数类型的最大值。
static func getMin()
public static func getMin(): Float16
功能:获取 Float16 类型的最小值。
返回值:
- Float16 - 半精度浮点数类型的最小值。
extend Float32 <: MaxMinValue<Float32>
extend Float32 <: MaxMinValue<Float32>
功能:为 Float32 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): Float32
功能:获取 Float32 类型的最大值。
返回值:
- Float32 - 单精度浮点数类型的最大值。
static func getMin()
public static func getMin(): Float32
功能:获取 Float32 类型的最小值。
返回值:
- Float32 - 单精度浮点数类型的最小值。
extend Float64 <: MaxMinValue<Float64>
extend Float64 <: MaxMinValue<Float64>
功能:为 Float64 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): Float64
功能:获取 Float64 类型的最大值。
返回值:
- Float64 - 双精度浮点数类型的最大值。
static func getMin()
public static func getMin(): Float64
功能:获取 Float64 类型的最小值。
返回值:
- Float64 - 双精度浮点数类型的最小值。
extend Int16 <: MaxMinValue<Int16>
extend Int16 <: MaxMinValue<Int16>
功能:为 Int16 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): Int16
功能:获取 Int16 类型的最大值。
返回值:
static func getMin()
public static func getMin(): Int16
功能:获取 Int16 类型的最小值。
返回值:
extend Int32 <: MaxMinValue<Int32>
extend Int32 <: MaxMinValue<Int32>
功能:为 Int32 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): Int32
功能:获取 Int32 类型的最大值。
返回值:
static func getMin()
public static func getMin(): Int32
功能:获取 Int32 类型的最小值。
返回值:
extend Int64 <: MaxMinValue<Int64>
extend Int64 <: MaxMinValue<Int64>
功能:为 Int64 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): Int64
功能:获取 Int64 类型的最大值。
返回值:
static func getMin()
public static func getMin(): Int64
功能:获取 Int64 类型的最小值。
返回值:
extend Int8 <: MaxMinValue<Int8>
extend Int8 <: MaxMinValue<Int8>
功能:为 Int8 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): Int8
功能:获取 Int8 类型的最大值。
返回值:
static func getMin()
public static func getMin(): Int8
功能:获取 Int8 类型的最小值。
返回值:
extend IntNative <: MaxMinValue<IntNative>
extend IntNative <: MaxMinValue<IntNative>
功能:为 IntNative 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): IntNative
功能:获取 IntNative 类型的最大值。
返回值:
static func getMin()
public static func getMin(): IntNative
功能:获取 IntNative 类型的最小值。
返回值:
extend UInt16 <: MaxMinValue<UInt16>
extend UInt16 <: MaxMinValue<UInt16>
功能:为 UInt16 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): UInt16
功能:获取 UInt16 类型的最大值。
返回值:
static func getMin()
public static func getMin(): UInt16
功能:获取 UInt16 类型的最小值。
返回值:
extend UInt32 <: MaxMinValue<UInt32>
extend UInt32 <: MaxMinValue<UInt32>
功能:为 UInt32 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): UInt32
功能:获取 UInt32 类型的最大值。
返回值:
static func getMin()
public static func getMin(): UInt32
功能:获取 UInt32 类型的最小值。
返回值:
extend UInt64 <: MaxMinValue<UInt64>
extend UInt64 <: MaxMinValue<UInt64>
功能:为 UInt64 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): UInt64
功能:获取 UInt64 类型的最大值。
返回值:
static func getMin()
public static func getMin(): UInt64
功能:获取 UInt64 类型的最小值。
返回值:
extend UInt8 <: MaxMinValue<UInt8>
extend UInt8 <: MaxMinValue<UInt8>
功能:为 UInt8 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): UInt8
功能:获取 UInt8 类型的最大值。
返回值:
static func getMin()
public static func getMin(): UInt8
功能:获取 UInt8 类型的最小值。
返回值:
extend UIntNative <: MaxMinValue<UIntNative>
extend UIntNative <: MaxMinValue<UIntNative>
功能:为 UIntNative 类型扩展 MaxMinValue 接口。
父类型:
static func getMax()
public static func getMax(): UIntNative
功能:获取 UIntNative 类型的最大值。
返回值:
- UIntNative - UIntNative 类型的最大值。
static func getMin()
public static func getMin(): UIntNative
功能:获取 UIntNative 类型的最小值。
返回值:
- UIntNative - UIntNative 类型的最小值。
interface Number<T>
public interface Number<T> {
operator func +(rhs: T): T
operator func -(rhs: T): T
operator func *(rhs: T): T
operator func /(rhs: T): T
operator func -(): T
}
功能:提供数值类型相关的方法。
operator func +(T)
operator func +(rhs: T): T
功能:算术运算符,计算加法。
参数:
- rhs: T - 运算符右边的数,表示另一个加数。
返回值:
- T - 计算所得和。
operator func -(T)
operator func -(rhs: T): T
功能:算术运算符,计算减法。
参数:
- rhs: T - 运算符右边的数,表示减数。
返回值:
- T - 计算所得差。
operator func *(T)
operator func *(rhs: T): T
功能:算术运算符,计算乘法。
参数:
- rhs: T - 运算符右边的数,表示另一个乘数。
返回值:
- T - 计算所得积。
operator func /(T)
operator func /(rhs: T): T
功能:算术运算符,计算除法。
参数:
- rhs: T - 运算符右边的数,表示除数。
返回值:
- T - 计算所得商。
operator func -()
operator func -(): T
功能:算术运算符,计算取负的值。
返回值:
- T - 取负的值。
extend Float16 <: Number<Float16>
extend Float16 <: Number<Float16> {}
功能:为 Float16 类型扩展 Number<T> 接口。
父类型:
extend Float32 <: Number<Float32>
extend Float32 <: Number<Float32> {}
功能:为 Float32 类型扩展 Number<T> 接口。
父类型:
extend Float64 <: Number<Float64>
extend Float64 <: Number<Float64> {}
功能:为 Float64 类型扩展 Number<T> 接口。
父类型:
extend Int16 <: Number<Int16>
extend Int16 <: Number<Int16> {}
父类型:
extend Int32 <: Number<Int32>
extend Int32 <: Number<Int32> {}
父类型:
extend Int64 <: Number<Int64>
extend Int64 <: Number<Int64> {}
父类型:
extend Int8 <: Number<Int8>
extend Int8 <: Number<Int8> {}
父类型:
extend IntNative <: Number<IntNative>
extend IntNative <: Number<IntNative> {}
功能:为 IntNative 类型扩展 Number<T> 接口。
父类型:
extend UInt16 <: Number<UInt16>
extend UInt16 <: Number<UInt16> {}
功能:为 UInt16 类型扩展 Number<T> 接口。
父类型:
extend UInt32 <: Number<UInt32>
extend UInt32 <: Number<UInt32> {}
功能:为 UInt32 类型扩展 Number<T> 接口。
父类型:
extend UInt64 <: Number<UInt64>
extend UInt64 <: Number<UInt64> {}
功能:为 UInt64 类型扩展 Number<T> 接口。
父类型:
extend UInt8 <: Number<UInt8>
extend UInt8 <: Number<UInt8> {}
父类型:
extend UIntNative <: Number<UIntNative>
extend UIntNative <: Number<UIntNative> {}
功能:为 UIntNative 类型扩展 Number<T> 接口。
父类型:
函数
func abs(Float16)
public func abs(x: Float16): Float16
功能:求一个半精度浮点数的绝对值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的绝对值。
示例:
import std.math.abs
main() {
let n: Float16 = -23.0
let abs = abs(n)
println(abs)
}
运行结果:
23.000000
func abs(Float32)
public func abs(x: Float32): Float32
功能:求一个单精度浮点数的绝对值。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的绝对值。
示例:
import std.math.abs
main() {
let n: Float32 = -23.0
let abs = abs(n)
println(abs)
}
运行结果:
23.000000
func abs(Float64)
public func abs(x: Float64): Float64
功能:求一个双精度浮点数的绝对值。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的绝对值。
示例:
import std.math.abs
main() {
let n: Float64 = -23.0
let abs = abs(n)
println(abs)
}
运行结果:
23.000000
func abs(Int16)
public func abs(x: Int16): Int16
功能:求一个 16 位有符号整数的绝对值。
参数:
- x: Int16 - 传入的 16 位有符号整数。
返回值:
- Int16 - 返回传入参数的绝对值。
异常:
- OverflowException - 当输入参数是有符号整数的最小值,抛出异常。
示例:
import std.math.abs
main() {
let n: Int16 = -23
let abs = abs(n)
println(abs)
}
运行结果:
23
以下示例抛出异常:
import std.math.abs
main(): Unit {
try {
let n = Int16(-2 ** 15)
let abs: Int16 = abs(n)
println(abs)
} catch (e: OverflowException) {
println("异常:输入参数是有符号整数的最小值")
}
}
运行结果:
异常:输入参数是有符号整数的最小值
func abs(Int32)
public func abs(x: Int32): Int32
功能:求一个 32 位有符号整数的绝对值。
参数:
- x: Int32 - 传入的 32 位有符号整数。
返回值:
- Int32 - 返回传入参数的绝对值。
异常:
- OverflowException - 当输入参数是有符号整数的最小值,抛出异常。
示例:
import std.math.abs
main() {
let n: Int32 = -23
let abs = abs(n)
println(abs)
}
运行结果:
23
func abs(Int64)
public func abs(x: Int64): Int64
功能:求一个 64 位有符号整数的绝对值。
参数:
- x: Int64 - 传入的 64 位有符号整数。
返回值:
- Int64 - 返回传入参数的绝对值。
异常:
- OverflowException - 当输入参数是有符号整数的最小值,抛出异常。
示例:
import std.math.abs
main() {
let n: Int64 = -23
let abs = abs(n)
println(abs)
}
运行结果:
23
func abs(Int8)
public func abs(x: Int8): Int8
功能:求一个 8 位有符号整数的绝对值。
参数:
- x: Int8 - 传入的 8 位有符号整数。
返回值:
- Int8 - 返回传入参数的绝对值。
异常:
- OverflowException - 当输入参数是有符号整数的最小值,抛出异常。
示例:
import std.math.abs
main() {
let n: Int8 = -23
let abs = abs(n)
println(abs)
}
运行结果:
23
func acos(Float16)
public func acos(x: Float16): Float16
功能:计算半精度浮点数的反余弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数。-1.0 <=
x<= 1.0。
返回值:
- Float16 - 返回传入参数的反余弦函数值,单位为弧度。
异常:
- IllegalArgumentException - 当参数
x大于 1.0 或小于 -1.0 时,抛出异常。
示例:
import std.math.acos
main() {
let n: Float16 = 1.0
let acos = acos(n)
println(acos)
}
运行结果:
0.000000
以下示例将抛出异常:
import std.math.acos
main(): Unit {
let n = -1.5
let acos = acos(n)
println(acos)
}
func acos(Float32)
public func acos(x: Float32): Float32
功能:计算单精度浮点数的反余弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数。-1.0 <=
x<= 1.0。
返回值:
- Float32 - 返回传入参数的反余弦函数值,单位为弧度。
异常:
- IllegalArgumentException - 当参数
x大于 1.0 或小于 -1.0 时,抛出异常。
示例:
import std.math.acos
main() {
let n: Float32 = 1.0
let acos = acos(n)
println(acos)
}
运行结果:
0.000000
func acos(Float64)
public func acos(x: Float64): Float64
功能:计算双精度浮点数的反余弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数。-1.0 <=
x<= 1.0。
返回值:
- Float64 - 返回传入参数的反余弦函数值,单位为弧度。
异常:
- IllegalArgumentException - 当参数
x大于 1.0 或小于 -1.0 时,抛出异常。
示例:
import std.math.acos
main() {
let n: Float64 = 1.0
let acos = acos(n)
println(acos)
}
运行结果:
0.000000
func acosh(Float16)
public func acosh(x: Float16): Float16
功能:计算半精度浮点数的反双曲余弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的反双曲余弦函数值。
x>= 1.0。
异常:
- IllegalArgumentException - 当参数
x小于 1.0 时,抛出异常。
示例:
import std.math.acosh
main() {
let n: Float16 = 1.0
let acosh = acosh(n)
println(acosh)
}
运行结果:
0.000000
以下示例将抛出异常:
import std.math.acosh
main(): Unit {
let n = 0.4
let acosh = acosh(n)
println(acosh)
}
func acosh(Float32)
public func acosh(x: Float32): Float32
功能:计算单精度浮点数的反双曲余弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数。
x>= 1.0。
返回值:
- Float32 - 返回传入参数的反双曲余弦函数值。
异常:
- IllegalArgumentException - 当参数
x小于 1.0 时,抛出异常。
示例:
import std.math.acosh
main() {
let n: Float32 = 1.0
let acosh = acosh(n)
println(acosh)
}
运行结果:
0.000000
func acosh(Float64)
public func acosh(x: Float64): Float64
功能:计算双精度浮点数的反双曲余弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数。
x>= 1.0。
返回值:
- Float64 - 返回传入参数的反双曲余弦函数值。
异常:
- IllegalArgumentException - 当参数
x小于 1.0 时,抛出异常。
示例:
import std.math.acosh
main() {
let n: Float64 = 1.0
let acosh = acosh(n)
println(acosh)
}
运行结果:
0.000000
func asin(Float16)
public func asin(x: Float16): Float16
功能:计算半精度浮点数的反正弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数。-1.0 <=
x<= 1.0。
返回值:
- Float16 - 返回传入参数的反正弦函数值,单位为弧度。
异常:
- IllegalArgumentException - 当参数
x大于 1.0 或小于 -1.0 时,抛出异常。
示例:
import std.math.asin
main() {
let n: Float16 = 0.0
let asin = asin(n)
println(asin)
}
运行结果:
0.000000
以下示例将抛出异常:
import std.math.asin
main(): Unit {
let n = 1.4
let asin = asin(n)
println(asin)
}
func asin(Float32)
public func asin(x: Float32): Float32
功能:计算单精度浮点数的反正弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数。-1.0 <=
x<= 1.0。
返回值:
- Float32 - 返回传入参数的反正弦函数值,单位为弧度。
异常:
- IllegalArgumentException - 当参数
x大于 1.0 或小于 -1.0 时,抛出异常。
示例:
import std.math.asin
main() {
let n: Float32 = 0.0
let asin = asin(n)
println(asin)
}
运行结果:
0.000000
func asin(Float64)
public func asin(x: Float64): Float64
功能:计算双精度浮点数的反正弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数。-1.0 <=
x<= 1.0。
返回值:
- Float64 - 返回传入参数的反正弦函数值,单位为弧度。
异常:
- IllegalArgumentException - 当参数
x大于 1.0 或小于 -1.0 时,抛出异常。
示例:
import std.math.asin
main() {
let n: Float64 = 0.0
let asin = asin(n)
println(asin)
}
运行结果:
0.000000
func asinh(Float16)
public func asinh(x: Float16): Float16
功能:计算半精度浮点数的反双曲正弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的反双曲正弦函数值。
示例:
import std.math.asinh
main() {
let n: Float16 = 0.0
let asinh = asinh(n)
println(asinh)
}
运行结果:
0.000000
func asinh(Float32)
public func asinh(x: Float32): Float32
功能:计算单精度浮点数的反双曲正弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的反双曲正弦函数值。
示例:
import std.math.asinh
main() {
let n: Float32 = 0.0
let asinh = asinh(n)
println(asinh)
}
运行结果:
0.000000
func asinh(Float64)
public func asinh(x: Float64): Float64
功能:计算双精度浮点数的反双曲正弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的反双曲正弦函数值。
示例:
import std.math.asinh
main() {
let n: Float64 = 0.0
let asinh = asinh(n)
println(asinh)
}
运行结果:
0.000000
func atan(Float16)
public func atan(x: Float16): Float16
功能:计算半精度浮点数的反正切函数值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的反正切函数值,单位为弧度。
示例:
import std.math.atan
main() {
let n: Float16 = 0.0
let atan = atan(n)
println(atan)
}
运行结果:
0.000000
func atan(Float32)
public func atan(x: Float32): Float32
功能:计算单精度浮点数的反正切函数值。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的反正切函数值,单位为弧度。
示例:
import std.math.atan
main() {
let n: Float32 = 0.0
let atan = atan(n)
println(atan)
}
运行结果:
0.000000
func atan(Float64)
public func atan(x: Float64): Float64
功能:计算双精度浮点数的反正切函数值。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的反正切函数值,单位为弧度。
示例:
import std.math.atan
main() {
let n: Float64 = 0.0
let atan = atan(n)
println(atan)
}
运行结果:
0.000000
func atan2(Float16, Float16)
public func atan2(y: Float16, x: Float16): Float16
功能:计算两个半精度浮点数 y/x 的反正切函数值,单位为弧度。
参数:
返回值:
- Float16 - 返回 y/x 的反正切函数值,单位为弧度。
示例:
import std.math.*
import std.convert.Formattable
main() {
let y: Float16 = 1.0
let x: Float16 = 1.0
let atan2 = atan2(y, x) / Float16.getPI() * 180.0 // 将弧度值转为角度值打印
println("${atan2.format(".1")}°")
}
运行结果:
45.0°
func atan2(Float32, Float32)
public func atan2(y: Float32, x: Float32): Float32
功能:计算两个单精度浮点数 y/x 的反正切函数值,单位为弧度。
参数:
返回值:
- Float32 - 返回 y/x 的反正切函数值,单位为弧度。
示例:
import std.math.*
import std.convert.Formattable
main() {
let y: Float32 = 1.0
let x: Float32 = 1.0
let atan2 = atan2(y, x) / Float32.getPI() * 180.0 // 将弧度值转为角度值打印
println("${atan2.format(".1")}°")
}
运行结果:
45.0°
func atan2(Float64, Float64)
public func atan2(y: Float64, x: Float64): Float64
功能:计算两个双精度浮点数 y/x 的反正切函数值,单位为弧度。
参数:
返回值:
- Float64 - 返回 y/x 的反正切函数值,单位为弧度。
示例:
import std.math.*
import std.convert.Formattable
main() {
let y: Float64 = 1.0
let x: Float64 = 1.0
let atan2 = atan2(y, x) / Float64.getPI() * 180.0 // 将弧度值转为角度值打印
println("${atan2.format(".1")}°")
}
运行结果:
45.0°
func atanh(Float16)
public func atanh(x: Float16): Float16
功能:计算半精度浮点数的反双曲正切函数值。
参数:
- x: Float16 - 传入的半精度浮点数。-1.0 <
x< 1.0。
返回值:
- Float16 - 返回传入参数的反双曲正切函数值。
异常:
- IllegalArgumentException - 当参数
x大于等于 1.0 或小于等于 -1.0 时,抛出异常。
示例:
import std.math.atanh
main() {
let n: Float16 = 0.0
let atanh = atanh(n)
println(atanh)
}
运行结果:
0.000000
以下示例将抛出异常:
import std.math.atanh
main(): Unit {
let n = -1.4
let atanh = atanh(n)
println(atanh)
}
func atanh(Float32)
public func atanh(x: Float32): Float32
功能:计算单精度浮点数的反双曲正切函数值。
参数:
- x: Float32 - 传入的单精度浮点数。-1.0 <
x< 1.0。
返回值:
- Float32 - 返回传入参数的反双曲正切函数值。
异常:
- IllegalArgumentException - 当参数
x大于等于 1.0 或小于等于 -1.0 时,抛出异常。
示例:
import std.math.atanh
main() {
let n: Float32 = 0.0
let atanh = atanh(n)
println(atanh)
}
运行结果:
0.000000
func atanh(Float64)
public func atanh(x: Float64): Float64
功能:计算双精度浮点数的反双曲正切函数值。
参数:
- x: Float64 - 传入的双精度浮点数。-1.0 <
x< 1.0。
返回值:
- Float64 - 返回传入参数的反双曲正切函数值。
异常:
- IllegalArgumentException - 当参数
x大于等于 1.0 或小于等于 -1.0 时,抛出异常。
示例:
import std.math.atanh
main() {
let n: Float64 = 0.0
let atanh = atanh(n)
println(atanh)
}
运行结果:
0.000000
func cbrt(Float16)
public func cbrt(x: Float16): Float16
功能:求半精度浮点数的立方根。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的立方根。
示例:
import std.math.cbrt
main() {
let n: Float16 = -1000.0
let cbrt = cbrt(n)
println(cbrt)
}
运行结果:
-10.000000
func cbrt(Float32)
public func cbrt(x: Float32): Float32
功能:求单精度浮点数的立方根。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的立方根。
示例:
import std.math.cbrt
main() {
let n: Float32 = -1000.0
let cbrt = cbrt(n)
println(cbrt)
}
运行结果:
-10.000000
func cbrt(Float64)
public func cbrt(x: Float64): Float64
功能:求双精度浮点数的立方根。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的立方根。
示例:
import std.math.cbrt
main() {
let n: Float64 = -1000.0
let cbrt = cbrt(n)
println(cbrt)
}
运行结果:
-10.000000
func ceil(Float16)
public func ceil(x: Float16): Float16
功能:求半精度浮点数的向上取整值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的向上取整值。
示例:
import std.math.ceil
main() {
let n: Float16 = 0.7
let ceil = ceil(n)
println(ceil)
}
运行结果:
1.000000
func ceil(Float32)
public func ceil(x: Float32): Float32
功能:求单精度浮点数的向上取整值。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的向上取整值。
示例:
import std.math.ceil
main() {
let n: Float32 = 0.7
let ceil = ceil(n)
println(ceil)
}
运行结果:
1.000000
func ceil(Float64)
public func ceil(x: Float64): Float64
功能:求双精度浮点数的向上取整值。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的向上取整值。
示例:
import std.math.ceil
main() {
let n: Float64 = 0.7
let ceil = ceil(n)
println(ceil)
}
运行结果:
1.000000
func checkedAbs(Int16)
public func checkedAbs(x: Int16): Option<Int16>
功能:求一个 16 位有符号整数的绝对值。如果入参是 16 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。
参数:
- x: Int16 - 传入的 16 位有符号整数。
返回值:
示例:
import std.math.checkedAbs
main() {
let n: Int16 = -23
let checkedAbs = checkedAbs(n)
println(checkedAbs)
}
运行结果:
Some(23)
func checkedAbs(Int32)
public func checkedAbs(x: Int32): Option<Int32>
功能:求一个 32 位有符号整数的绝对值。如果入参是 32 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。
参数:
- x: Int32 - 传入的 32 位有符号整数。
返回值:
示例:
import std.math.checkedAbs
main() {
let n: Int32 = -23
let checkedAbs = checkedAbs(n)
println(checkedAbs)
}
运行结果:
Some(23)
func checkedAbs(Int64)
public func checkedAbs(x: Int64): Option<Int64>
功能:求一个 64 位有符号整数的绝对值。如果入参是 64 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。
参数:
- x: Int64 - 传入的 64 位有符号整数。
返回值:
示例:
import std.math.checkedAbs
main() {
let n: Int64 = -23
let checkedAbs = checkedAbs(n)
println(checkedAbs)
}
运行结果:
Some(23)
func checkedAbs(Int8)
public func checkedAbs(x: Int8): Option<Int8>
功能:求一个 8 位有符号整数的绝对值。如果入参是 8 位有符号整数的最小值,函数返回 None;否则,返回 Some(abs(x))。
参数:
- x: Int8 - 传入的 8 位有符号整数。
返回值:
示例:
import std.math.checkedAbs
main() {
let n: Int8 = -23
let checkedAbs = checkedAbs(n)
println(checkedAbs)
}
运行结果:
Some(23)
func clamp(Float16, Float16, Float16)
public func clamp(v: Float16, min: Float16, max: Float16): Float16
功能:求浮点数的范围区间数。如果此浮点数在该范围区间则返回此浮点数;如果此浮点数小于这个范围区间,则返回该范围区间的最小值;如果此浮点数大于这个范围区间,则返回该范围区间的最大值;如果是 NaN 则返回 NaN。
参数:
返回值:
- Float16 - 如果
v在min与max之间则返回v;如果v小于等于min则返回min;如果v大于等于max,则返回max;如果是NaN则返回NaN。
异常:
- IllegalArgumentException - 当参数
min大于参数max或者min和max是NaN时,抛出异常。
示例:
import std.math.clamp
main() {
let n: Float16 = -23.0
let clamp = clamp(n, -100.0, 100.0)
println(clamp)
}
运行结果:
-23.000000
func clamp(Float32, Float32, Float32)
public func clamp(v: Float32, min: Float32, max: Float32): Float32
功能:求浮点数的范围区间数。如果此浮点数在该范围区间则返回此浮点数;如果此浮点数小于这个范围区间,则返回该范围区间的最小值;如果此浮点数大于这个范围区间,则返回该范围区间的最大值;如果是 NaN 则返回 NaN。
参数:
返回值:
- Float32 - 如果
v在min与max之间则返回v;如果v小于等于min则返回min;如果v大于等于max,则返回max;如果是NaN则返回NaN。
异常:
- IllegalArgumentException - 当参数
min大于参数max或者min和max是NaN时,抛出异常。
示例:
import std.math.clamp
main() {
var m: Float32 = -23.0
var clamp1 = clamp(m, -100.0, 100.0)
println(clamp1)
var n: Float32 = -123.0
var clamp2 = clamp(n, -100.0, 100.0)
println(clamp2)
var p: Float32 = 123.0
var clamp3 = clamp(p, -100.0, 100.0)
println(clamp3)
}
运行结果:
-23.000000
-100.000000
100.000000
func clamp(Float64, Float64, Float64)
public func clamp(v: Float64, min: Float64, max: Float64): Float64
功能:求浮点数的范围区间数。如果此浮点数在该范围区间则返回此浮点数;如果此浮点数小于这个范围区间,则返回该范围区间的最小值;如果此浮点数大于这个范围区间,则返回该范围区间的最大值;如果是 NaN 则返回 NaN。
参数:
返回值:
- Float64 - 如果
v在min与max之间则返回v;如果v小于等于min则返回min;如果v大于等于max,则返回max;如果是NaN则返回NaN。
异常:
- IllegalArgumentException - 当参数
min大于参数max或者min和max是NaN时,抛出异常。
示例:
import std.math.clamp
main() {
let n: Float64 = -23.0
let clamp = clamp(n, -100.0, 100.0)
println(clamp)
}
运行结果:
-23.000000
func cos(Float16)
public func cos(x: Float16): Float16
功能:计算半精度浮点数的余弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数,入参单位为弧度。
返回值:
- Float16 - 返回传入参数的余弦函数值。
示例:
import std.math.cos
main() {
let n: Float16 = 3.14159265
let cos = cos(n)
println(cos)
}
运行结果:
-1.000000
func cos(Float32)
public func cos(x: Float32): Float32
功能:计算单精度浮点数的余弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数,入参单位为弧度。
返回值:
- Float32 - 返回传入参数的余弦函数值。
示例:
import std.math.cos
main() {
let n: Float32 = 3.14159265
let cos = cos(n)
println(cos)
}
运行结果:
-1.000000
func cos(Float64)
public func cos(x: Float64): Float64
功能:计算双精度浮点数的余弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数,入参单位为弧度。
返回值:
- Float64 - 返回传入参数的余弦函数值。
示例:
import std.math.cos
main() {
let n: Float64 = 3.14159265
let cos = cos(n)
println(cos)
}
运行结果:
-1.000000
func cosh(Float16)
public func cosh(x: Float16): Float16
功能:计算半精度浮点数的双曲余弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的双曲余弦函数值。
示例:
import std.math.cosh
main() {
let n: Float16 = 0.0
let cosh = cosh(n)
println(cosh)
}
运行结果:
1.000000
func cosh(Float32)
public func cosh(x: Float32): Float32
功能:计算单精度浮点数的双曲余弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的双曲余弦函数值。
示例:
import std.math.cosh
main() {
let n: Float32 = 0.0
let cosh = cosh(n)
println(cosh)
}
运行结果:
1.000000
func cosh(Float64)
public func cosh(x: Float64): Float64
功能:计算双精度浮点数的双曲余弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的双曲余弦函数值。
示例:
import std.math.cosh
main() {
let n: Float64 = 0.0
let cosh = cosh(n)
println(cosh)
}
运行结果:
1.000000
func countOne(Int16) (deprecated)
public func countOne(x: Int16): Int8
功能:求 16 位整型的二进制表达中 1 的个数。
注意:
未来版本即将废弃,使用 countOnes(Int16) 替代。
参数:
- x: Int16 - 传入的 16 位有符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(Int16)
public func countOnes(x: Int16): Int64
功能:求 16 位整型的二进制表达中 1 的个数。
参数:
- x: Int16 - 传入的 16 位有符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: Int16 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func countOne(Int32) (deprecated)
public func countOne(x: Int32): Int8
功能:求 32 位整型的二进制表达中 1 的个数。
注意:
未来版本即将废弃,使用 countOnes(Int32) 替代。
参数:
- x: Int32 - 传入的 32 位有符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(Int32)
public func countOnes(x: Int32): Int64
功能:求 32 位整型的二进制表达中 1 的个数。
参数:
- x: Int32 - 传入的 32 位有符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: Int32 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func countOne(Int64) (deprecated)
public func countOne(x: Int64): Int8
功能:求 64 位整型的二进制表达中 1 的个数。
注意:
未来版本即将废弃,使用 countOnes(Int64) 替代。
参数:
- x: Int64 - 传入的 64 位有符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(Int64)
public func countOnes(x: Int64): Int64
功能:求 64 位整型的二进制表达中 1 的个数。
参数:
- x: Int64 - 传入的 64 位有符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: Int64 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func countOne(Int8) (deprecated)
public func countOne(x: Int8): Int8
功能:求 8 位整型的二进制表达中 1 的个数。
注意:
未来版本即将废弃,使用 countOnes(Int8) 替代。
参数:
- x: Int8 - 传入的 8 位有符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(Int8)
public func countOnes(x: Int8): Int64
功能:求 8 位整型的二进制表达中 1 的个数。
参数:
- x: Int8 - 传入的 8 位有符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: Int8 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func countOne(UInt16) (deprecated)
public func countOne(x: UInt16): Int8
功能:求 16 位无符号整型的二进制表达中的 1 的位的个数。
注意:
未来版本即将废弃,使用 countOnes(UInt16) 替代。
参数:
- x: UInt16 - 传入的 16 位无符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(UInt16)
public func countOnes(x: UInt16): Int64
功能:求 16 位无符号整型的二进制表达中的 1 的位的个数。
参数:
- x: UInt16 - 传入的 16 位无符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: UInt16 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func countOne(UInt32) (deprecated)
public func countOne(x: UInt32): Int8
功能:求 32 位无符号整型的二进制表达中的 1 的位的个数。
注意:
未来版本即将废弃,使用 countOnes(UInt32) 替代。
参数:
- x: UInt32 - 传入的 32 位无符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(UInt32)
public func countOnes(x: UInt32): Int64
功能:求 32 位无符号整型的二进制表达中的 1 的位的个数。
参数:
- x: UInt32 - 传入的 32 位无符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: UInt32 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func countOne(UInt64) (deprecated)
public func countOne(x: UInt64): Int8
功能:求 64 位无符号整型的二进制表达中的 1 的位的个数。
注意:
未来版本即将废弃,使用 countOnes(UInt64) 替代。
参数:
- x: UInt64 - 传入的 64 位无符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(UInt64)
public func countOnes(x: UInt64): Int64
功能:求 64 位无符号整型的二进制表达中的 1 的位的个数。
参数:
- x: UInt64 - 传入的 64 位无符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: UInt64 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func countOne(UInt8) (deprecated)
public func countOne(x: UInt8): Int8
功能:求 8 位无符号整型的二进制表达中的 1 的位的个数。
注意:
未来版本即将废弃,使用 countOnes(UInt8) 替代。
参数:
- x: UInt8 - 传入的 8 位无符号整数。
返回值:
- Int8 - 返回传入参数的二进制表达中的 1 的位的个数。
func countOnes(UInt8)
public func countOnes(x: UInt8): Int64
功能:求 8 位无符号整型的二进制表达中的 1 的位的个数。
参数:
- x: UInt8 - 传入的 8 位无符号整数。
返回值:
- Int64 - 返回传入参数的二进制表达中的 1 的位的个数。
示例:
import std.math.countOnes
main() {
let n: UInt8 = 15
let countOnes = countOnes(n)
println(countOnes)
}
运行结果:
4
func erf(Float16)
public func erf(x: Float16): Float16
功能:求半精度浮点数的误差值。相关定义是:$$erf(x) = \frac{2}{\sqrt{\pi}}\int_0^xe^{-t^2}dt$$。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的半精度浮点数的误差值。
示例:
import std.math.erf
main() {
let n: Float16 = 5.0
let erf = erf(n)
println(erf)
}
运行结果:
1.000000
func erf(Float32)
public func erf(x: Float32): Float32
功能:求单精度浮点数的误差值。相关定义是:$$erf(x) = \frac{2}{\sqrt{\pi}}\int_0^xe^{-t^2}dt$$。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的单精度浮点数的误差值。
示例:
import std.math.erf
main() {
let n: Float32 = 5.0
let erf = erf(n)
println(erf)
}
运行结果:
1.000000
func erf(Float64)
public func erf(x: Float64): Float64
功能:求双精度浮点数的误差值。相关定义是:$$erf(x) = \frac{2}{\sqrt{\pi}}\int_0^xe^{-t^2}dt$$。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的双精度浮点数的误差值。
示例:
import std.math.erf
main() {
let n: Float64 = 5.0
let erf = erf(n)
println(erf)
}
运行结果:
1.000000
func exp(Float16)
public func exp(x: Float16): Float16
功能:求自然常数 e 的 x 次幂。
参数:
- x: Float16 - 传入的半精度浮点数指数。
返回值:
- Float16 - 返回自然常数 e 的
x次幂。
示例:
import std.math.exp
main() {
let n: Float16 = 1.0
let exp = exp(n)
println(exp)
}
运行结果:
2.718750
func exp(Float32)
public func exp(x: Float32): Float32
功能:求自然常数 e 的 x 次幂。
参数:
- x: Float32 - 传入的单精度浮点数指数。
返回值:
- Float32 - 返回自然常数 e 的
x次幂。
示例:
import std.math.exp
main() {
let n: Float32 = 1.0
let exp = exp(n)
println(exp)
}
运行结果:
2.718282
func exp(Float64)
public func exp(x: Float64): Float64
功能:求自然常数 e 的 x 次幂。
参数:
- x: Float64 - 传入的双精度浮点数指数。
返回值:
- Float64 - 返回自然常数 e 的
x次幂。
示例:
import std.math.exp
main() {
let n: Float64 = 1.0
let exp = exp(n)
println(exp)
}
运行结果:
2.718282
func exp2(Float16)
public func exp2(x: Float16): Float16
功能:求 2 的 x 次幂。
参数:
- x: Float16 - 传入的半精度浮点数指数。
返回值:
- Float16 - 返回 2 的
x次幂。
示例:
import std.math.exp2
main() {
let n: Float16 = 10.0
let exp2 = exp2(n)
println(exp2)
}
运行结果:
1024.000000
func exp2(Float32)
public func exp2(x: Float32): Float32
功能:求 2 的 x 次幂。
参数:
- x: Float32 - 传入的单精度浮点数指数。
返回值:
- Float32 - 返回 2 的
x次幂。
示例:
import std.math.exp2
main() {
let n: Float32 = 10.0
let exp2 = exp2(n)
println(exp2)
}
运行结果:
1024.000000
func exp2(Float64)
public func exp2(x: Float64): Float64
功能:求 2 的 x 次幂。
参数:
- x: Float64 - 传入的双精度浮点数指数。
返回值:
- Float64 - 返回 2 的
x次幂。
示例:
import std.math.exp2
main() {
let n: Float64 = 10.0
let exp = exp2(n)
println(exp)
}
运行结果:
1024.000000
func floor(Float16)
public func floor(x: Float16): Float16
功能:求浮点数的向下取整值。
参数:
- x: Float16 - 传入的需要向下取整的半精度浮点数。
返回值:
- Float16 - 返回传入浮点数的向下取整值。
示例:
import std.math.floor
main() {
let n: Float16 = 10.5
let floor = floor(n)
println(floor)
}
运行结果:
10.000000
func floor(Float32)
public func floor(x: Float32): Float32
功能:求浮点数的向下取整值。
参数:
- x: Float32 - 传入的需要向下取整的单精度浮点数。
返回值:
- Float32 - 返回传入浮点数的向下取整值。
示例:
import std.math.floor
main() {
let n: Float32 = 10.5
let floor = floor(n)
println(floor)
}
运行结果:
10.000000
func floor(Float64)
public func floor(x: Float64): Float64
功能:求浮点数的向下取整值。
参数:
- x: Float64 - 传入的需要向下取整的双精度浮点数。
返回值:
- Float64 - 返回传入浮点数的向下取整值。
示例:
import std.math.floor
main() {
let n: Float64 = 10.5
let floor = floor(n)
println(floor)
}
运行结果:
10.000000
func fmod(Float16, Float16)
public func fmod(x: Float16, y: Float16): Float16
功能:求两个半精度浮点数 x/y 的余数。
参数:
返回值:
- Float16 - 返回 x/y 的余数, 当 x 或 y 为
NaN时 返回NaN。
异常:
- IllegalArgumentException - 当 x 为
Inf或 y 为 0 时,抛出异常。
示例:
import std.math.fmod
import std.convert.Formattable
main() {
let x: Float16 = 3.3
let y: Float16 = 2.2
let fmod = fmod(x, y)
println(fmod.format(".1"))
}
运行结果:
1.1
func fmod(Float32, Float32)
public func fmod(x: Float32, y: Float32): Float32
功能:求两个单精度浮点数 x/y 的余数。
参数:
返回值:
- Float32 - 返回 x/y 的余数, 当 x 或 y 为
NaN时 返回NaN。
异常:
- IllegalArgumentException - 当 x 为
Inf或 y 为 0 时,抛出异常。
示例:
import std.math.fmod
import std.convert.Formattable
main() {
let x: Float32 = 3.3
let y: Float32 = 2.2
let fmod = fmod(x, y)
println(fmod.format(".1"))
}
运行结果:
1.1
func fmod(Float64, Float64)
public func fmod(x: Float64, y: Float64): Float64
功能:求两个双精度浮点数 x/y 的余数。
参数:
返回值:
- Float64 - 返回 x/y 的余数, 当 x 或 y 为
NaN时 返回NaN。
异常:
- IllegalArgumentException - 当 x 为
Inf或 y 为 0 时,抛出异常。
示例:
import std.math.fmod
import std.convert.Formattable
main() {
let x: Float64 = 3.3
let y: Float64 = 2.2
let fmod = fmod(x, y)
println(fmod.format(".1"))
}
运行结果:
1.1
func gamma(Float16)
public func gamma(x: Float16): Float16
功能:求浮点数的伽马函数值,该函数是阶乘概念在实数上的推广,其求值公式为:
$${\displaystyle \Gamma (x)=\int _{0}^{\infty }t^{x-1}\mathrm {e} ^{-t}{\rm {{d}t,}}}$$
参数:
- x: Float16 - 传入的需要求伽马函数值的半精度浮点数。
返回值:
- Float16 - 返回传入浮点数的伽马函数值。
示例:
import std.math.gamma
main() {
let n: Float16 = -1.1
let gamma = gamma(n)
println(gamma)
}
运行结果:
9.750000
func gamma(Float32)
public func gamma(x: Float32): Float32
功能:求浮点数的伽马函数值,该函数是阶乘概念在实数上的推广。
参数:
- x: Float32 - 传入的需要求伽马函数值的单精度浮点数。
返回值:
- Float32 - 返回传入浮点数的伽马函数值。
示例:
import std.math.gamma
main() {
let n: Float32 = -1.1
let gamma = gamma(n)
println(gamma)
}
运行结果:
9.714804
func gamma(Float64)
public func gamma(x: Float64): Float64
功能:求浮点数的伽马函数值,该函数是阶乘概念在实数上的推广。
参数:
- x: Float64 - 传入的需要求伽马函数值的双精度浮点数。
返回值:
- Float64 - 返回传入浮点数的伽马函数值。
示例:
import std.math.gamma
main() {
let n: Float64 = -1.1
let gamma = gamma(n)
println(gamma)
}
运行结果:
9.714806
func gcd(Int16, Int16)
public func gcd(x: Int16, y: Int16): Int16
功能:求两个 16 位有符号整数的最大公约数。
参数:
返回值:
- Int16 - 返回两个整数的最大公约数。
异常:
- IllegalArgumentException - 当两参数都为有符号整数最小值,或一个参数为有符号整数的最小值且另一个参数为 0 时,抛出异常。
示例:
import std.math.gcd
main() {
let x: Int16 = 15
let y: Int16 = 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func gcd(Int32, Int32)
public func gcd(x: Int32, y: Int32): Int32
功能:求两个 32 位有符号整数的最大公约数。
参数:
返回值:
- Int32 - 返回两个整数的最大公约数。
异常:
- IllegalArgumentException - 当两参数都为有符号整数最小值,或一个参数为有符号整数的最小值且另一个参数为 0 时,抛出异常。
示例:
import std.math.gcd
main() {
let x: Int32 = 15
let y: Int32 = 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func gcd(Int64, Int64)
public func gcd(x: Int64, y: Int64): Int64
功能:求两个 64 位有符号整数的最大公约数。
参数:
返回值:
- Int64 - 返回两个整数的最大公约数。
异常:
- IllegalArgumentException - 当两参数都为有符号整数最小值,或一个参数为有符号整数的最小值且另一个参数为 0 时,抛出异常。
示例:
import std.math.gcd
main() {
let x: Int64 = 15
let y: Int64 = 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func gcd(Int8, Int8)
public func gcd(x: Int8, y: Int8): Int8
功能:求两个 8 位有符号整数的最大公约数。
参数:
返回值:
- Int8 - 返回两个整数的最大公约数。
异常:
- IllegalArgumentException - 当两参数都为有符号整数最小值,或一个参数为有符号整数的最小值且另一个参数为 0 时,抛出异常。
示例:
import std.math.gcd
main() {
let x: Int8 = 15
let y: Int8= 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func gcd(UInt16, UInt16)
public func gcd(x: UInt16, y: UInt16): UInt16
功能:求两个 16 位无符号整数的最大公约数。
参数:
返回值:
- UInt16 - 返回两个整数的最大公约数。
示例:
import std.math.gcd
main() {
let x: UInt16 = 15
let y: UInt16 = 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func gcd(UInt32, UInt32)
public func gcd(x: UInt32, y: UInt32): UInt32
功能:求两个 32 位无符号整数的最大公约数。
参数:
返回值:
- UInt32 - 返回两个整数的最大公约数。
示例:
import std.math.gcd
main() {
let x: UInt32 = 15
let y: UInt32 = 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func gcd(UInt64, UInt64)
public func gcd(x: UInt64, y: UInt64): UInt64
功能:求两个 64 位无符号整数的最大公约数。
参数:
返回值:
- UInt64 - 返回两个整数的最大公约数。
示例:
import std.math.gcd
main() {
let x: UInt64 = 15
let y: UInt64 = 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func gcd(UInt8, UInt8)
public func gcd(x: UInt8, y: UInt8): UInt8
功能:求两个 8 位无符号整数的最大公约数。
参数:
返回值:
- UInt8 - 返回两个整数的最大公约数。
示例:
import std.math.gcd
main() {
let x: UInt8 = 15
let y: UInt8= 9
let gcd = gcd(x, y)
println(gcd)
}
运行结果:
3
func lcm(Int16, Int16)
public func lcm(x: Int16, y: Int16): Int16
功能:求两个 16 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- Int16 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 16 位有符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: Int16 = -15
let y: Int16 = 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func lcm(Int32, Int32)
public func lcm(x: Int32, y: Int32): Int32
功能:求两个 32 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- Int32 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 32 位有符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: Int32 = -15
let y: Int32 = 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func lcm(Int64, Int64)
public func lcm(x: Int64, y: Int64): Int64
功能:求两个 64 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- Int64 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 64 位有符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: Int64 = 15
let y: Int64 = 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func lcm(Int8, Int8)
public func lcm(x: Int8, y: Int8): Int8
功能:求两个 8 位有符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- Int8 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 8 位有符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: Int8 = 15
let y: Int8= 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func lcm(UInt16, UInt16)
public func lcm(x: UInt16, y: UInt16): UInt16
功能:求两个 16 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- UInt16 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 16 位无符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: UInt16 = 15
let y: UInt16 = 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func lcm(UInt32, UInt32)
public func lcm(x: UInt32, y: UInt32): UInt32
功能:求两个 32 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- UInt32 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 32 位无符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: UInt32 = 15
let y: UInt32 = 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func lcm(UInt64, UInt64)
public func lcm(x: UInt64, y: UInt64): UInt64
功能:求两个 64 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- UInt64 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 64 位无符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: UInt64 = 15
let y: UInt64 = 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func lcm(UInt8, UInt8)
public func lcm(x: UInt8, y: UInt8): UInt8
功能:求两个 8 位无符号整数的最小的非负的公倍数,当入参有 0 时才返回 0。
参数:
返回值:
- UInt8 - 返回两个整数的最小的非负的公倍数,当入参有 0 时才返回 0。
异常:
- IllegalArgumentException - 当返回值超出 8 位无符号整数的最大值时抛出异常。
示例:
import std.math.lcm
main() {
let x: UInt8 = 15
let y: UInt8= 9
let lcm = lcm(x, y)
println(lcm)
}
运行结果:
45
func leadingZeros(Int16)
public func leadingZeros(x: Int16): Int64
功能:求 16 位有符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: Int16 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: Int16 = 512
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
6
func leadingZeros(Int32)
public func leadingZeros(x: Int32): Int64
功能:求 32 位有符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: Int32 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: Int32 = 512
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
22
func leadingZeros(Int64)
public func leadingZeros(x: Int64): Int64
功能:求 64 位有符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: Int64 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: Int64 = 512
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
54
func leadingZeros(Int8)
public func leadingZeros(x: Int8): Int64
功能:求 8 位有符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: Int8 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: Int8 = 4
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
5
func leadingZeros(UInt16)
public func leadingZeros(x: UInt16): Int64
功能:求 16 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: UInt16 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: UInt16 = 512
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
6
func leadingZeros(UInt32)
public func leadingZeros(x: UInt32): Int64
功能:求 32 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: UInt32 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: UInt32 = 512
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
22
func leadingZeros(UInt64)
public func leadingZeros(x: UInt64): Int64
功能:求 64 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: UInt64 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: UInt64 = 512
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
54
func leadingZeros(UInt8)
public func leadingZeros(x: UInt8): Int64
功能:求 8 位无符号整数的二进制表达中的从最高位算起,连续位为 0 的个数。如果最高位不是 0,则返回 0。
参数:
- x: UInt8 - 需要求前导 0 的整数。
返回值:
- Int64 - 返回前导 0 的位数。
示例:
import std.math.leadingZeros
main() {
let x: UInt8 = 64
let leadingZeros = leadingZeros(x)
println(leadingZeros)
}
运行结果:
1
func log(Float16)
public func log(x: Float16): Float16
功能:求以 e 为底 x 的对数。
参数:
- x: Float16 - 真数。
返回值:
- Float16 - 返回以 e 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log
main() {
let x: Float16 = 2.718282
let log1 = log(x)
let log2 = log(-x)
let log3 = log(0.0)
println(log1)
println(log2)
println(log3)
let log4 = -log3
println(log4)
}
运行结果:
1.000000
nan
-inf
inf
func log(Float32)
public func log(x: Float32): Float32
功能:求以 e 为底 x 的对数。
参数:
- x: Float32 - 真数。
返回值:
- Float32 - 返回以 e 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log
main() {
let x: Float32 = 2.718282
let log = log(x)
println(log)
}
运行结果:
1.000000
func log(Float64)
public func log(x: Float64): Float64
功能:求以 e 为底 x 的对数。
参数:
- x: Float64 - 真数。
返回值:
- Float64 - 返回以 e 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log
main() {
let x: Float64 = 2.718282
let log = log(x)
println(log)
}
运行结果:
1.000000
func log10(Float16)
public func log10(x: Float16): Float16
功能:求以 10 为底 x 的对数。
参数:
- x: Float16 - 真数。
返回值:
- Float16 - 返回以 10 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log10
main() {
let x: Float16 = 1000.0
let log10 = log10(x)
println(log10)
}
运行结果:
3.000000
func log10(Float32)
public func log10(x: Float32): Float32
功能:求以 10 为底 x 的对数。
参数:
- x: Float32 - 真数。
返回值:
- Float32 - 返回以 10 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log10
main() {
let x: Float32 = 1000.0
let log10 = log10(x)
println(log10)
}
运行结果:
3.000000
func log10(Float64)
public func log10(x: Float64): Float64
功能:求以 10 为底 x 的对数。
参数:
- x: Float64 - 真数。
返回值:
- Float64 - 返回以 10 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log10
main() {
let x: Float64 = 1000.0
let log10 = log10(x)
println(log10)
}
运行结果:
3.000000
func log2(Float16)
public func log2(x: Float16): Float16
功能:求以 2 为底 x 的对数。
参数:
- x: Float16 - 真数。
返回值:
- Float16 - 返回以 2 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log2
main() {
let x: Float16 = 1024.0
let log2 = log2(x)
println(log2)
}
运行结果:
10.000000
func log2(Float32)
public func log2(x: Float32): Float32
功能:求以 2 为底 x 的对数。
参数:
- x: Float32 - 真数。
返回值:
- Float32 - 返回以 2 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log2
main() {
let x: Float32 = 1024.0
let log2 = log2(x)
println(log2)
}
运行结果:
10.000000
func log2(Float64)
public func log2(x: Float64): Float64
功能:求以 2 为底 x 的对数。
参数:
- x: Float64 - 真数。
返回值:
- Float64 - 返回以 2 为底
x的对数。
说明:
返回值存在如下特殊场景:
示例:
import std.math.log2
main() {
let x: Float64 = 1024.0
let log2 = log2(x)
println(log2)
}
运行结果:
10.000000
func logBase(Float16, Float16)
public func logBase(x: Float16, base: Float16): Float16
功能:求以 base 为底 x 的对数。
参数:
返回值:
- Float16 - 返回以以
base为底x的对数。
异常:
- IllegalArgumentException - 当真数或底数不为正,或底数为 1 时,抛出异常。
示例:
import std.math.logBase
main() {
let x: Float16 = 512.0
let base: Float16 = 2.0
let logBase = logBase(x, base)
println(logBase)
}
运行结果:
9.000000
以下示例将抛出相应异常:
import std.math.logBase
main() {
let x: Float16 = 512.0
let base: Float16 = -2.0
// 示例1:底数为负数
try {
let logBase1 = logBase(x, base)
println(logBase1)
} catch (e: IllegalArgumentException) {
println("异常1:底数为负数")
}
// 示例2:真数为负数
try {
let logBase2 = logBase(-x, base)
println(logBase2)
} catch (e: IllegalArgumentException) {
println("异常2:真数为负数")
}
// 示例3:底数为1
try {
let logBase3 = logBase(x, 1.0)
println(logBase3)
} catch (e: IllegalArgumentException) {
println("异常3:底数为1")
}
}
运行结果:
异常1:底数为负数
异常2:真数为负数
异常3:底数为1
func logBase(Float32, Float32)
public func logBase(x: Float32, base: Float32): Float32
功能:求以 base 为底 x 的对数。
参数:
返回值:
- Float32 - 返回以以
base为底x的对数。
异常:
- IllegalArgumentException - 当真数或底数不为正,或底数为 1 时,抛出异常。
示例:
import std.math.logBase
main() {
let x: Float32 = 1024.0
let base: Float32 = 2.0
let logBase = logBase(x, base)
println(logBase)
}
运行结果:
10.000000
func logBase(Float64, Float64)
public func logBase(x: Float64, base: Float64): Float64
功能:求以 base 为底 x 的对数。
参数:
返回值:
- Float64 - 返回以以
base为底x的对数。
异常:
- IllegalArgumentException - 当真数或底数不为正,或底数为 1 时,抛出异常。
示例:
import std.math.logBase
main() {
let x: Float64 = 1024.0
let base: Float64 = 2.0
let logBase = logBase(x, base)
println(logBase)
}
运行结果:
10.000000
func pow(Float32, Float32)
public func pow(base: Float32, exponent: Float32): Float32
功能:求浮点数 base 的 exponent 次幂。
参数:
返回值:
- Float32 - 返回传入浮点数
base的exponent次幂。如果值不存在,则返回nan。
示例:
import std.math.pow
main() {
let base: Float32 = -1.0
let exponent: Float32 = 0.5
let pow = pow(base, exponent)
println(pow)
}
运行结果:
nan
func pow(Float32, Int32)
public func pow(base: Float32, exponent: Int32): Float32
功能:求浮点数 base 的 exponent 次幂。
参数:
返回值:
- Float32 - 返回传入浮点数
base的exponent次幂。
示例:
import std.math.pow
main() {
let base: Float32 = -1.0
let exponent: Int32 = 2
let pow = pow(base, exponent)
println(pow)
}
运行结果:
1.000000
func pow(Float64, Float64)
public func pow(base: Float64, exponent: Float64): Float64
功能:求浮点数 base 的 exponent 次幂。
参数:
返回值:
- Float64 - 返回传入浮点数
base的exponent次幂。如果值不存在,则返回nan。
示例:
import std.math.pow
main() {
let base: Float64 = -1.0
let exponent: Float64 = 0.5
let pow = pow(base, exponent)
println(pow)
}
运行结果:
nan
func pow(Float64, Int64)
public func pow(base: Float64, exponent: Int64): Float64
功能:求浮点数 base 的 exponent 次幂。
参数:
返回值:
- Float64 - 返回传入浮点数
base的exponent次幂。
示例:
import std.math.pow
main() {
let base: Float64 = -1.0
let exponent: Int64 = 2
let pow = pow(base, exponent)
println(pow)
}
运行结果:
1.000000
func reverse(UInt16)
public func reverse(x: UInt16): UInt16
功能:求无符号整数按位反转后的数。
参数:
- x: UInt16 - 需要进行反转的无符号整数。
返回值:
- UInt16 - 返回反转后的无符号数。
示例:
import std.math.reverse
main() {
let n: UInt16 = 0x8000
let reverse = reverse(n)
println(reverse)
}
运行结果:
1
func reverse(UInt32)
public func reverse(x: UInt32): UInt32
功能:求无符号整数按位反转后的数。
参数:
- x: UInt32 - 需要进行反转的无符号整数。
返回值:
- UInt32 - 返回反转后的无符号数。
示例:
import std.math.reverse
main() {
let n: UInt32 = 0x8000_0000
let reverse = reverse(n)
println(reverse)
}
运行结果:
1
func reverse(UInt64)
public func reverse(x: UInt64): UInt64
功能:求无符号整数按位反转后的数。
参数:
- x: UInt64 - 需要进行反转的无符号整数。
返回值:
- UInt64 - 返回反转后的无符号数。
示例:
import std.math.reverse
main() {
let n: UInt64 = 0x8000_0000_0000_0000
let reverse = reverse(n)
println(reverse)
}
运行结果:
1
func reverse(UInt8)
public func reverse(x: UInt8): UInt8
功能:求无符号整数按位反转后的数。
参数:
- x: UInt8 - 需要进行反转的无符号整数。
返回值:
- UInt8 - 返回反转后的无符号数。
示例:
import std.math.reverse
main() {
let n: UInt8 = 0x80
let reverse = reverse(n)
println(reverse)
}
运行结果:
1
func rotate(Int16, Int8)
public func rotate(num: Int16, d: Int8): Int16
功能:求整数的按位旋转后的结果。
参数:
返回值:
- Int16 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: Int16 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func rotate(Int32, Int8)
public func rotate(num: Int32, d: Int8): Int32
功能:求整数的按位旋转后的结果。
参数:
返回值:
- Int32 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: Int32 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func rotate(Int64, Int8)
public func rotate(num: Int64, d: Int8): Int64
功能:求整数的按位旋转后的结果。
参数:
返回值:
- Int64 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: Int64 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func rotate(Int8, Int8)
public func rotate(num: Int8, d: Int8): Int8
功能:求整数的按位旋转后的结果。
参数:
返回值:
- Int8 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: Int8 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func rotate(UInt16, Int8)
public func rotate(num: UInt16, d: Int8): UInt16
功能:求整数的按位旋转后的结果。
参数:
返回值:
- UInt16 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: UInt16 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func rotate(UInt32, Int8)
public func rotate(num: UInt32, d: Int8): UInt32
功能:求整数的按位旋转后的结果。
参数:
返回值:
- UInt32 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: UInt32 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func rotate(UInt64, Int8)
public func rotate(num: UInt64, d: Int8): UInt64
功能:求整数的按位旋转后的结果。
参数:
返回值:
- UInt64 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: UInt64 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func rotate(UInt8, Int8)
public func rotate(num: UInt8, d: Int8): UInt8
功能:求整数的按位旋转后的结果。
参数:
返回值:
- UInt8 - 返回旋转后的整数。
示例:
import std.math.rotate
main() {
let n: UInt8 = 1
let rotate = rotate(n, 2)
println(rotate)
}
运行结果:
4
func round(Float16)
public func round(x: Float16): Float16
功能:此函数采用 IEEE-754 的向最近舍入规则,计算浮点数的舍入值。如果该浮点数有两个最近整数,则向偶数舍入。
参数:
- x: Float16 - 需要计算舍入值的浮点数。
返回值:
- Float16 - 返回浮点数向最近整数方向的舍入值。如果该浮点数有两个最近整数,则返回向偶数舍入值。
示例:
import std.math.round
main() {
let n: Float16 = 1.5
let round = round(n)
println(round)
}
运行结果:
2.000000
func round(Float32)
public func round(x: Float32): Float32
功能:此函数采用 IEEE-754 的向最近舍入规则,计算浮点数的舍入值。如果该浮点数有两个最近整数,则向偶数舍入。
参数:
- x: Float32 - 需要计算舍入值的浮点数。
返回值:
- Float32 - 返回浮点数向最近整数方向的舍入值。如果该浮点数有两个最近整数,则返回向偶数舍入值。
示例:
import std.math.round
main() {
let n: Float32 = 1.5
let round = round(n)
println(round)
}
运行结果:
2.000000
func round(Float64)
public func round(x: Float64): Float64
功能:此函数采用 IEEE-754 的向最近舍入规则,计算浮点数的舍入值。如果该浮点数有两个最近整数,则向偶数舍入。
参数:
- x: Float64 - 需要计算舍入值的浮点数。
返回值:
- Float64 - 返回浮点数向最近整数方向的舍入值。如果该浮点数有两个最近整数,则返回向偶数舍入值。
示例:
import std.math.round
main() {
let n: Float64 = 1.5
let round = round(n)
println(round)
}
运行结果:
2.000000
func sin(Float16)
public func sin(x: Float16): Float16
功能:计算半精度浮点数的正弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数,入参单位为弧度。
返回值:
- Float16 - 返回传入参数的正弦函数值。
示例:
import std.math.sin
main() {
let n: Float16 = 3.1415926/2.0
let sin = sin(n)
println(sin)
}
运行结果:
1.000000
func sin(Float32)
public func sin(x: Float32): Float32
功能:计算单精度浮点数的正弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数,入参单位为弧度。
返回值:
- Float32 - 返回传入参数的正弦函数值。
示例:
import std.math.sin
main() {
let n: Float32 = 3.1415926/2.0
let sin = sin(n)
println(sin)
}
运行结果:
1.000000
func sin(Float64)
public func sin(x: Float64): Float64
功能:计算双精度浮点数的正弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数,入参单位为弧度。
返回值:
- Float64 - 返回传入参数的正弦函数值。
示例:
import std.math.sin
main() {
let n: Float64 = 3.1415926/2.0
let sin = sin(n)
println(sin)
}
运行结果:
1.000000
func sinh(Float16)
public func sinh(x: Float16): Float16
功能:计算半精度浮点数的双曲正弦函数值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的双曲正弦函数值。
示例:
import std.math.sinh
main() {
let n: Float16 = 0.0
let sinh = sinh(n)
println(sinh)
}
运行结果:
0.000000
func sinh(Float32)
public func sinh(x: Float32): Float32
功能:计算单精度浮点数的双曲正弦函数值。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的双曲正弦函数值。
示例:
import std.math.sinh
main() {
let n: Float32 = 0.0
let sinh = sinh(n)
println(sinh)
}
运行结果:
0.000000
func sinh(Float64)
public func sinh(x: Float64): Float64
功能:计算双精度浮点数的双曲正弦函数值。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的双曲正弦函数值。
示例:
import std.math.sinh
main() {
let n: Float64 = 0.0
let sinh = sinh(n)
println(sinh)
}
运行结果:
0.000000
func sqrt(Float16)
public func sqrt(x: Float16): Float16
功能:求浮点数的算术平方根。
参数:
- x: Float16 - 需要计算算数平方根的浮点数。
x需要大于等于 0。
返回值:
- Float16 - 返回传入的浮点数的算术平方根。
异常:
- IllegalArgumentException - 当参数为负数时,抛出异常。
示例:
import std.math.sqrt
main() {
let n: Float16 = 16.0
let sqrt = sqrt(n)
println(sqrt)
}
运行结果:
4.000000
func sqrt(Float32)
public func sqrt(x: Float32): Float32
功能:求浮点数的算术平方根。
参数:
- x: Float32 - 需要计算算数平方根的浮点数。
x需要大于等于 0。
返回值:
- Float32 - 返回传入的浮点数的算术平方根。
异常:
- IllegalArgumentException - 当参数为负数时,抛出异常。
示例:
import std.math.sqrt
main() {
let n: Float32 = 16.0
let sqrt = sqrt(n)
println(sqrt)
}
运行结果:
4.000000
func sqrt(Float64)
public func sqrt(x: Float64): Float64
功能:求浮点数的算术平方根。
参数:
- x: Float64 - 需要计算算数平方根的浮点数。
x需要大于等于 0。
返回值:
- Float64 - 返回传入的浮点数的算术平方根。
异常:
- IllegalArgumentException - 当参数为负数时,抛出异常。
示例:
import std.math.sqrt
main() {
let n: Float64 = 16.0
let sqrt = sqrt(n)
println(sqrt)
}
运行结果:
4.000000
func tan(Float16)
public func tan(x: Float16): Float16
功能:计算半精度浮点数的正切函数值。
参数:
- x: Float16 - 传入的半精度浮点数,入参单位为弧度。
返回值:
- Float16 - 返回传入参数的正切函数值。
示例:
import std.math.tan
main() {
let n: Float16 = 0.0
let tan = tan(n)
println(tan)
}
运行结果:
0.000000
func tan(Float32)
public func tan(x: Float32): Float32
功能:计算单精度浮点数的正切函数值。
参数:
- x: Float32 - 传入的单精度浮点数,入参单位为弧度。
返回值:
- Float32 - 返回传入参数的正切函数值。
示例:
import std.math.tan
main() {
let n: Float32 = 0.0
let tan = tan(n)
println(tan)
}
运行结果:
0.000000
func tan(Float64)
public func tan(x: Float64): Float64
功能:计算双精度浮点数的正切函数值。
参数:
- x: Float64 - 传入的双精度浮点数,入参单位为弧度。
返回值:
- Float64 - 返回传入参数的正切函数值。
示例:
import std.math.tan
main() {
let n: Float64 = 0.0
let tan = tan(n)
println(tan)
}
运行结果:
0.000000
func tanh(Float16)
public func tanh(x: Float16): Float16
功能:计算半精度浮点数的双曲正切函数值。
参数:
- x: Float16 - 传入的半精度浮点数。
返回值:
- Float16 - 返回传入参数的双曲正切函数值。
示例:
import std.math.tanh
main() {
let n: Float16 = 0.0
let tanh = tanh(n)
println(tanh)
}
运行结果:
0.000000
func tanh(Float32)
public func tanh(x: Float32): Float32
功能:计算单精度浮点数的双曲正切函数值。
参数:
- x: Float32 - 传入的单精度浮点数。
返回值:
- Float32 - 返回传入参数的双曲正切函数值。
示例:
import std.math.tanh
main() {
let n: Float32 = 0.0
let tanh = tanh(n)
println(tanh)
}
运行结果:
0.000000
func tanh(Float64)
public func tanh(x: Float64): Float64
功能:计算双精度浮点数的双曲正切函数值。
参数:
- x: Float64 - 传入的双精度浮点数。
返回值:
- Float64 - 返回传入参数的双曲正切函数值。
示例:
import std.math.tanh
main() {
let n: Float64 = 0.0
let tanh = tanh(n)
println(tanh)
}
运行结果:
0.000000
func trailingZeros(Int16)
public func trailingZeros(x: Int16): Int64
功能:求 16 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: Int16 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: Int16 = 512
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
9
func trailingZeros(Int32)
public func trailingZeros(x: Int32): Int64
功能:求 32 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: Int32 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: Int32 = 512
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
9
func trailingZeros(Int64)
public func trailingZeros(x: Int64): Int64
功能:求 64 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: Int64 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: Int64 = 512
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
9
func trailingZeros(Int8)
public func trailingZeros(x: Int8): Int64
功能:求 16 位有符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: Int8 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: Int8 = 64
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
6
func trailingZeros(UInt16)
public func trailingZeros(x: UInt16): Int64
功能:求 16 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: UInt16 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: UInt16 = 512
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
9
func trailingZeros(UInt32)
public func trailingZeros(x: UInt32): Int64
功能:求 32 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: UInt32 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: UInt32 = 512
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
9
func trailingZeros(UInt64)
public func trailingZeros(x: UInt64): Int64
功能:求 64 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: UInt64 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: UInt64 = 512
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
9
func trailingZeros(UInt8)
public func trailingZeros(x: UInt8): Int64
功能:求 8 位无符号整数的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
- x: UInt8 - 需要求后置 0 的整数。
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.trailingZeros
main() {
let x: UInt8 = 64
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
6
func trunc(Float16)
public func trunc(x: Float16): Float16
功能:求浮点数的截断取整值。
参数:
- x: Float16 - 需要截断取整的浮点数。
返回值:
- Float16 - 返回传入浮点数截断取整后的值。
示例:
import std.math.trunc
main() {
let x: Float16 = 64.555566
let trunc = trunc(x)
println(trunc)
}
运行结果:
64.000000
func trunc(Float32)
public func trunc(x: Float32): Float32
功能:求浮点数的截断取整值。
参数:
- x: Float32 - 需要截断取整的浮点数。
返回值:
- Float32 - 返回传入浮点数截断取整后的值。
示例:
import std.math.trunc
main() {
let x: Float32 = 64.555566
let trunc = trunc(x)
println(trunc)
}
运行结果:
64.000000
func trunc(Float64)
public func trunc(x: Float64): Float64
功能:求浮点数的截断取整值。
参数:
- x: Float64 - 需要截断取整的浮点数。
返回值:
- Float64 - 返回传入浮点数截断取整后的值。
示例:
import std.math.trunc
main() {
let x: Float64 = 64.555566
let trunc = trunc(x)
println(trunc)
}
运行结果:
64.000000
枚举
enum RoundingMode
public enum RoundingMode <: Equatable<RoundingMode> & ToString {
| Ceiling
| Down
| Floor
| HalfEven
| HalfUp
| Up
}
功能:舍入规则枚举类,共包含 6 种舍入规则。除包含 IEEE 754 浮点数规定约定的 5 种舍入规则外,提供使用较多的 “四舍五入” 舍入规则。
| 十进制数 | Up | Down | Ceiling | Floor | HalfUp | HalfEven |
|---|---|---|---|---|---|---|
| 7.5 | 8 | 7 | 8 | 7 | 8 | 8 |
| 4.5 | 5 | 4 | 5 | 4 | 5 | 4 |
| -1.1 | -2 | -1 | -1 | -2 | -1 | -1 |
| -4.5 | -5 | -4 | -4 | -5 | -5 | -4 |
| -7.5 | -8 | -7 | -7 | -8 | -8 | -8 |
父类型:
Ceiling
Ceiling
功能:向正无穷方向舍入。
Down
Down
功能:向靠近零的方向舍入。
Floor
Floor
功能:向负无穷方向舍入。
HalfEven
HalfEven
功能:四舍六入五取偶,又称 “银行家舍入”。
HalfUp
HalfUp
功能:四舍五入。
Up
Up
功能:向远离零的方向舍入。
func toString()
public func toString(): String
功能:生成舍入规则名称字符串。
返回值:
- String - 舍入规则名称字符串。
operator func ==(RoundingMode)
public operator func ==(that: RoundingMode): Bool
功能:判等。
参数:
- that: RoundingMode - 被比较的舍入规则。
返回值:
- Bool - 若舍入规则相同,返回 true;否则,返回 false。
数学基础运算示例
import std.math.clamp
import std.math.gcd
import std.math.lcm
import std.math.rotate
// 范围截断示例
func clampTest() {
let min: Float16 = -0.123
let max: Float16 = 0.123
let v: Float16 = 0.121
let c = clamp(v, min, max)
println("${c==v}")
let min2: Float16 = -0.999
let max2: Float16 = 10.123
let v2: Float16 = 11.121
let c2 = clamp(v2, min2, max2)
println("${c2==max2}")
let min3: Float16 = -0.999
let max3: Float16 = 10.123
let v3: Float16 = -1.121
let c3 = clamp(v3, min3, max3)
println("${c3==min3}")
}
// 求两个数的最大公约数
func gcdTest() {
let c2 = gcd(0, -60)
println("c2=${c2}")
let c4 = gcd(-33, 27)
println("c4=${c4}")
}
// 求两个数的最小公倍数
func lcmTest() {
let a: Int8 = lcm(Int8(-3), Int8(5))
println("a=${a}")
}
// 整数按二进制某一位前后翻转
func rotateTest() {
let a: Int8 = rotate(Int8(92), Int8(4))
println("a=${a}")
let b: Int32 = rotate(Int32(1), Int8(4))
println("b=${b}")
}
main(): Unit {
println("/*********************** clampTest **********************/")
clampTest()
println("/*********************** gcdTest ************************/")
gcdTest()
println("/*********************** lcmTest ************************/")
lcmTest()
println("/*********************** rotateTest *********************/")
rotateTest()
}
运行结果:
/*********************** clampTest **********************/
true
true
true
/*********************** gcdTest ************************/
c2=60
c4=3
/*********************** lcmTest ************************/
a=15
/*********************** rotateTest *********************/
a=-59
b=16
std.math.numeric
功能介绍
math.numeric 包对基础类型可表达范围之外提供扩展能力。
例如:
- 支持大整数(BigInt);
- 支持高精度十进制数(Decimal)类型;
- 提供常见的数学运算能力包括高精度运算规则。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| abs(BigInt) | 求一个 BigInt 的绝对值。 |
| abs(Decimal) | 求一个 Decimal 的绝对值。 |
| countOne(BigInt) (deprecated) | 计算并返回入参 BigInt 的二进制补码中 1 的个数。 |
| countOnes(BigInt) | 计算并返回入参 BigInt 的二进制补码中 1 的个数。 |
| gcd(BigInt, BigInt) | 求两个 BigInt 的最大公约数。总是返回非负数(相当于绝对值的最大公约数)。 |
| lcm(BigInt, BigInt) | 求两个 BigInt 的最小公倍数。除了入参有 0 时返回 0 外,总是返回正数(相当于绝对值的最小公倍数)。 |
| round(Decimal, RoundingMode) | 计算 Decimal 的舍入值,根据舍入方式向邻近的整数舍入。 |
| sqrt(BigInt) | 求 BigInt 的算术平方根,向下取整。 |
| sqrt(Decimal) | 求 Decimal 的算术平方根。结果为无限小数场景时,默认采用 IEEE 754-2019 decimal128 对结果进行舍入。 |
| trailingZeros(BigInt) | 求 BigInt 的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。 |
枚举
| 枚举 | 功能 |
|---|---|
| OverflowStrategy | 溢出策略枚举类,共包含 3 种溢出策略。BigInt 类型、Decimal 类型转换为整数类型时,允许指定不同的溢出处理策略。 |
结构体
| 结构体 | 功能 |
|---|---|
| BigInt | BigInt 定义为任意精度(二进制)的有符号整数。仓颉的 struct BigInt 用于任意精度有符号整数的计算,类型转换等。 |
| Decimal | Decimal 用于表示任意精度的有符号的十进制数。允许操作过程指定上下文,指定结果精度及舍入规则。提供基础类型 (Int、UInt、String、Float等) 与 BigInt 类型互相转换能力,支持 Decimal 对象基本属性查询等能力,支持基础数学运算操作,提供对象比较、hash、字符串打印等基础能力。 |
函数
func abs(BigInt)
public func abs(i: BigInt): BigInt
功能:求一个 BigInt 的绝对值。
参数:
返回值:
示例:
import std.math.numeric.*
main() {
let n: BigInt = BigInt(-23)
let abs = abs(n)
println(abs)
}
运行结果:
23
func abs(Decimal)
public func abs(d: Decimal): Decimal
功能:求一个 Decimal 的绝对值。
参数:
返回值:
示例:
import std.math.numeric.*
main() {
let d: Decimal = Decimal.parse("-1.23")
let abs = abs(d)
println(abs)
}
运行结果:
1.23
func countOne(BigInt) (deprecated)
public func countOne(i: BigInt): Int64
功能:计算并返回入参 BigInt 的二进制补码中 1 的个数。
注意:
未来版本即将废弃,使用 countOnes(BigInt) 替代。
参数:
返回值:
func countOnes(BigInt)
public func countOnes(i: BigInt): Int64
功能:计算并返回入参 BigInt 的二进制补码中 1 的个数。
参数:
返回值:
示例:
import std.math.numeric.*
main() {
let i: BigInt = BigInt(255)
let countOnes = countOnes(i)
println(countOnes)
}
运行结果:
8
func gcd(BigInt, BigInt)
public func gcd(i1: BigInt, i2: BigInt): BigInt
功能:求两个 BigInt 的最大公约数。总是返回非负数(相当于绝对值的最大公约数)。
参数:
返回值:
- BigInt - 返回
i1和i2的最大公约数,总是返回非负数。
示例:
import std.math.numeric.*
main() {
let i1: BigInt = BigInt(-36)
let i2: BigInt = BigInt(48)
let gcd = gcd(i1, i2)
println(gcd)
}
运行结果:
12
func lcm(BigInt, BigInt)
public func lcm(i1: BigInt, i2: BigInt): BigInt
功能:求两个 BigInt 的最小公倍数。除了入参有 0 时返回 0 外,总是返回正数(相当于绝对值的最小公倍数)。
参数:
返回值:
- BigInt - 返回
i1和i2的最小公倍数,当入参有 0 时返回 0,其余情况返回正数。
示例:
import std.math.numeric.*
main() {
let i1: BigInt = BigInt(-36)
let i2: BigInt = BigInt(48)
let lcm = lcm(i1, i2)
println(lcm)
}
运行结果:
144
func round(Decimal, RoundingMode)
public func round(d: Decimal, roundingMode!: RoundingMode = RoundingMode.HalfEven): Decimal
功能:计算 Decimal 的舍入值,根据舍入方式向邻近的整数舍入。
参数:
- d: Decimal - 需要计算舍入值的 Decimal。
- roundingMode!: RoundingMode - 舍入规则。
返回值:
异常:
- OverflowException - 当舍入操作结果标度值溢出时,抛出此异常。
func sqrt(BigInt)
public func sqrt(i: BigInt): BigInt
功能:求 BigInt 的算术平方根,向下取整。
参数:
返回值:
异常:
- IllegalArgumentException - 如果入参为负数,则抛此异常。
示例:
import std.math.numeric.*
main() {
let n: BigInt = BigInt(23)
let sqrt = sqrt(n)
println(sqrt)
}
运行结果:
4
func sqrt(Decimal)
public func sqrt(d: Decimal): Decimal
功能:求 Decimal 的算术平方根。结果为无限小数场景时,默认采用 IEEE 754-2019 decimal128 对结果进行舍入。
参数:
返回值:
异常:
- IllegalArgumentException - 如果入参为负数,则抛此异常。
- OverflowException - 当计算平方根操作结果标度值溢出时,抛出此异常。
示例:
import std.math.numeric.*
main() {
let n: Decimal = Decimal.parse("36")
let sqrt = sqrt(n)
println(sqrt)
}
运行结果:
6
func trailingZeros(BigInt)
public func trailingZeros(x: BigInt): Int64
功能:求 BigInt 的二进制表达中的从最低位算起,连续位为 0 的个数。如果最低位不是 0,则返回 0。
参数:
返回值:
- Int64 - 后置 0 的位数。
示例:
import std.math.numeric.{BigInt, trailingZeros}
main() {
let x: BigInt = BigInt(0xC000_0000)
let trailingZeros = trailingZeros(x)
println(trailingZeros)
}
运行结果:
30
枚举
enum OverflowStrategy
public enum OverflowStrategy <: Equatable<OverflowStrategy> & ToString {
| Saturating
| Throwing
| Wrapping
}
功能:溢出策略枚举类,共包含 3 种溢出策略。BigInt 类型、Decimal 类型转换为整数类型时,允许指定不同的溢出处理策略。
父类型:
Saturating
Saturating
功能:出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
Throwing
Throwing
功能:出现溢出,抛出异常。
Wrapping
Wrapping
功能:出现溢出,高位截断。
func toString()
public func toString(): String
功能:生成溢出策略名称字符串。
返回值:
- String - 溢出策略名称字符串。
operator func ==(OverflowStrategy)
public operator func ==(that: OverflowStrategy): Bool
功能:判等。
参数:
- that: OverflowStrategy - 被比较的溢出策略。
返回值:
- Bool - 溢出策略相同,返回 true;否则,返回 false。
结构体
struct BigInt
public struct BigInt <: Comparable<BigInt> & Hashable & ToString {
public init(bytes: Array<Byte>)
public init(sign: Bool, magnitude: Array<Byte>)
public init(n: Int8)
public init(n: Int16)
public init(n: Int32)
public init(n: Int64)
public init(n: UInt8)
public init(n: UInt16)
public init(n: UInt32)
public init(n: UInt64)
public init(n: UIntNative)
public init(n: IntNative)
public init(n: Float16)
public init(n: Float32)
public init(n: Float64)
public init(sign: Bool, bitLen: Int64, rand!: Random = Random())
public init(s: String, base!: Int64 = 10)
}
功能:BigInt 定义为任意精度(二进制)的有符号整数。仓颉的 struct BigInt 用于任意精度有符号整数的计算,类型转换等。
父类型:
prop bitLen
public prop bitLen: Int64
功能:获取此 BigInt 的最短 bit 长度。如 -3 (101) 返回 3,-1 (11) 返回 2,0 (0) 返回 1。
类型:Int64
示例:
import std.math.numeric.BigInt
main() {
let bigInt1 = BigInt(-3)
let bitLen1 = bigInt1.bitLen
println(bitLen1)
let bigInt2 = BigInt(-1)
let bitLen2 = bigInt2.bitLen
println(bitLen2)
let bigInt3 = BigInt(0)
let bitLen3 = bigInt3.bitLen
println(bitLen3)
}
运行结果:
3
2
1
prop sign
public prop sign: Int64
功能:获取此 BigInt 的符号。正数返回 1;0 返回 0;负数返回 -1。
类型:Int64
示例:
import std.math.numeric.BigInt
main() {
let bigInt1 = BigInt(-3)
let sign1 = bigInt1.sign
println(sign1)
let bigInt2 = BigInt(3)
let sign2 = bigInt2.sign
println(sign2)
let bigInt3 = BigInt(0)
let sign3 = bigInt3.sign
println(sign3)
}
运行结果:
-1
1
0
init(Array<Byte>)
public init(bytes: Array<Byte>)
功能:通过大端的 Byte 数组以补码形式构建一个 BigInt 结构体。
数据存储方法有以下两种:
-
大端存储方式:高位字节存放在低位地址。
-
小端存储方式:将数据的低位字节存放在内存的高位地址。
参数:
异常:
- IllegalArgumentException - 当传入空数组时,抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt([1, 2, 3])
println(bigInt)
}
运行结果:
66051
init(Bool, Array<Byte>)
public init(sign: Bool, magnitude: Array<Byte>)
功能:通过符号位和真值的绝对值构建一个 BigInt 结构体。视空数组为 0。
参数:
异常:
- IllegalArgumentException - 当
sign为 false 且传入的数组为 0 时,抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(false, [1, 2, 3])
println(bigInt)
}
运行结果:
-66051
init(Bool, Int64, Random)
public init(sign: Bool, bitLen: Int64, rand!: Random = Random())
功能:通过指定正负、bit 长度和随机数种子构建一个随机的 BigInt 结构体。bit 长度需要大于 0。
参数:
异常:
- IllegalArgumentException - 如果指定的 bit 长度小于等于 0,则抛此异常。
示例:
import std.math.numeric.BigInt
import std.random.*
main() {
let random = Random(2)
let bigInt = BigInt(false, 3, rand: random)
println(bigInt)
}
运行结果:
-4
init(Float16)
public init(n: Float16)
功能:通过半精度浮点数构建一个 BigInt 结构体。
将丢弃浮点数的小数部分,即向零取整。
参数:
- n: Float16 - 半精度浮点数。
异常:
- IllegalArgumentException - 如果 n 为
Inf或NaN,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let float16: Float16 = 24.8
let bigInt = BigInt(float16)
println(bigInt)
}
运行结果:
24
init(Float32)
public init(n: Float32)
功能:通过单精度浮点数构建一个 BigInt 结构体。
将丢弃浮点数的小数部分,即向零取整。
参数:
- n: Float32 - 单精度浮点数。
异常:
- IllegalArgumentException - 如果 n 为
Inf或NaN,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let float32: Float32 = 24.8
let bigInt = BigInt(float32)
println(bigInt)
}
运行结果:
24
init(Float64)
public init(n: Float64)
功能:通过双精度浮点数构建一个 BigInt 结构体。
将丢弃浮点数的小数部分,即向零取整。
参数:
- n: Float64 - 单精度浮点数。
异常:
- IllegalArgumentException - 如果 n 为
Inf或NaN,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let float64: Float64 = 24.8
let bigInt = BigInt(float64)
println(bigInt)
}
运行结果:
24
init(Int16)
public init(n: Int16)
功能:通过 16 位有符号整数构建一个 BigInt 结构体。
参数:
- n: Int16 - 16 位有符号整数。
示例:
import std.math.numeric.BigInt
main() {
let int16: Int16 = 24
let bigInt = BigInt(int16)
println(bigInt)
}
运行结果:
24
init(Int32)
public init(n: Int32)
功能:通过 32 位有符号整数构建一个 BigInt 结构体。
参数:
- n: Int32 - 32 位有符号整数。
示例:
import std.math.numeric.BigInt
main() {
let int32: Int32 = 24
let bigInt = BigInt(int32)
println(bigInt)
}
运行结果:
24
init(Int64)
public init(n: Int64)
功能:通过 64 位有符号整数构建一个 BigInt 结构体。
参数:
- n: Int64 - 64 位有符号整数。
示例:
import std.math.numeric.BigInt
main() {
let int64: Int64 = 24
let bigInt = BigInt(int64)
println(bigInt)
}
运行结果:
24
init(Int8)
public init(n: Int8)
功能:通过 8 位有符号整数构建一个 BigInt 结构体。
参数:
- n: Int8 - 8 位有符号整数。
示例:
import std.math.numeric.BigInt
main() {
let int8: Int8 = 24
let bigInt = BigInt(int8)
println(bigInt)
}
运行结果:
24
init(IntNative)
public init(n: IntNative)
功能:通过平台相关有符号整数构建一个 BigInt 结构体。
参数:
- n: IntNative - 平台相关有符号整数。
示例:
import std.math.numeric.BigInt
main() {
let intNative: IntNative = 24
let bigInt = BigInt(intNative)
println(bigInt)
}
运行结果:
24
init(String, Int64) (deprecated)
public init(s: String, base!: Int64 = 10)
功能:通过字符串和进制构建一个 BigInt 结构体,支持 2 进制到 36 进制。
字符串的规则如下,即开头是可选的符号(正号或负号),接一串字符串表示的数字:
IntegerString : (SignString)? ValueString
-
SignString : + | -
-
ValueString : Digits
-
Digits: Digit | Digit Digits
-
Digit : '0' ~ '9' | 'A' ~ 'Z' | 'a' ~ 'z'
-
如果 Digit 在 '0' ~ '9' 内, 需要满足 (Digit - '0') < base;
-
如果 Digit 在 'A' ~ 'Z' 内, 需要满足 (Digit - 'A') + 10 < base;
-
如果 Digit 在 'a' ~ 'z' 内, 需要满足 (Digit - 'A') + 10 < base。
-
-
-
注意:
未来版本即将废弃,使用 parse(String, Int) 替代。
参数:
- s: String - 用于构建 BigInt 结构体的字符串。字符串规则为,开头可选一个正号(+)或者负号(-)。接下来必选非空阿拉伯数字或大小写拉丁字母的字符序列,大小写字符含义一样,'a' 和 'A' 的大小等于十进制的 10,'b' 和 'B' 的大小等于十进制的 11,以此类推。序列中的字符大小不得大于等于进制大小。
- base!: Int64 - 进制。字符串所表示的进制,范围为 [2, 36]。
异常:
- IllegalArgumentException - 如果字符串
s不符合上述规则,或base表示的进制不在 [2, 36] 区间内,抛此异常。
init(UInt16)
public init(n: UInt16)
功能:通过 16 位无符号整数构建一个 BigInt 结构体。
参数:
- n: UInt16 - 16 位无符号整数。
示例:
import std.math.numeric.BigInt
main() {
let uint16: UInt16 = 24
let bigInt = BigInt(uint16)
println(bigInt)
}
运行结果:
24
init(UInt32)
public init(n: UInt32)
功能:通过 32 位无符号整数构建一个 BigInt 结构体。
参数:
- n: UInt32 - 32 位无符号整数。
示例:
import std.math.numeric.BigInt
main() {
let uint32: UInt32 = 24
let bigInt = BigInt(uint32)
println(bigInt)
}
运行结果:
24
init(UInt64)
public init(n: UInt64)
功能:通过 64 位无符号整数构建一个 BigInt 结构体。
参数:
- n: UInt64 - 64 位无符号整数。
示例:
import std.math.numeric.BigInt
main() {
let uint64: UInt64 = 24
let bigInt = BigInt(uint64)
println(bigInt)
}
运行结果:
24
init(UInt8)
public init(n: UInt8)
功能:通过 8 位无符号整数构建一个 BigInt 结构体。
参数:
- n: UInt8 - 8 位无符号整数。
示例:
import std.math.numeric.BigInt
main() {
let uint8: UInt8 = 24
let bigInt = BigInt(uint8)
println(bigInt)
}
运行结果:
24
init(UIntNative)
public init(n: UIntNative)
功能:通过平台相关无符号整数构建一个 BigInt 结构体。
参数:
- n: UIntNative - 平台相关无符号整数。
示例:
import std.math.numeric.BigInt
main() {
let uintnative: UIntNative = 24
let bigInt = BigInt(uintnative)
println(bigInt)
}
运行结果:
24
static func randomProbablePrime(Int64, UInt64, Random)
public static func randomProbablePrime(bitLen: Int64, certainty: UInt64, rand!: Random = Random()): BigInt
功能:通过可选的随机数种子构建一个随机的 BigInt 素数,素数的 bit 长度不超过入参 bitLen。
显然,素数必定是大于等于 2 的整数,因此 bitLen 必须大于等于 2。素数检测使用 Miller-Rabin 素数测试算法。Miller-Rabin 测试会有概率将一个合数判定为素数,其出错概率随着入参 certainty 的增加而减少。
参数:
- bitLen: Int64 - 所要生成的随机素数的 bit 长度的上限。
- certainty: UInt64 - 生成的随机素数通过 Miller-Rabin 素数测试算法的次数,通过的次数越多,将合数误判为素数的概率越低。
- rand!: Random - 指定的随机数种子。
返回值:
- BigInt - 返回生成的随机素数。
异常:
- IllegalArgumentException - 如果指定的 bit 长度小于等于 1,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let randomProbablePrime = BigInt.randomProbablePrime(6, 3)
println(randomProbablePrime)
}
func clearBit(Int64)
public func clearBit(index: Int64): BigInt
功能:通过将指定索引位置的 bit 修改为 0 来构造一个新 BigInt。
参数:
- index: Int64 - 需要设置的 bit 位置的索引。
index需要大于等于 0。
返回值:
异常:
- IllegalArgumentException - 如果入参
index小于 0,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1024)
let clearBit = bigInt.clearBit(10)
println(clearBit)
}
运行结果:
0
func compare(BigInt)
public func compare(that: BigInt): Ordering
参数:
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1024)
let that1 = BigInt(512)
let that2 = BigInt(2048)
let that3 = BigInt(1024)
let compare1 = bigInt.compare(that1)
println(compare1)
let compare2 = bigInt.compare(that2)
println(compare2)
let compare3 = bigInt.compare(that3)
println(compare3)
}
运行结果:
Ordering.GT
Ordering.LT
Ordering.EQ
func divAndMod(BigInt)
public func divAndMod(that: BigInt): (BigInt, BigInt)
功能:BigInt 的除法运算。
与另一个 BigInt 相除,返回商和模。此除法运算的行为与基础类型保持一致,即商向靠近 0 的方向取整,模的符号与被除数保持一致。
参数:
- that: BigInt - 除数。除数不得为 0。
返回值:
异常:
- ArithmeticException - 除数为 0 抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1025)
let that = BigInt(512)
let (div, mod) = bigInt.divAndMod(that)
println(div)
println(mod)
}
运行结果:
2
1
func flipBit(Int64)
public func flipBit(index: Int64): BigInt
功能:通过翻转指定索引位置的 bit 来构造一个新 BigInt。
参数:
- index: Int64 - 需要翻转的 bit 位置的索引。
index需要大于等于 0。
返回值:
异常:
- IllegalArgumentException - 如果入参
index小于 0,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1024)
let flipBit = bigInt.flipBit(10)
println(flipBit)
}
运行结果:
0
func hashCode()
public func hashCode(): Int64
功能:计算并返回此 BigInt 的哈希值。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1024)
let hashCode = bigInt.hashCode()
println(hashCode)
}
运行结果:
1024
func isProbablePrime(UInt64)
public func isProbablePrime(certainty: UInt64): Bool
功能:判断一个数是不是素数。
说明:
该函数使用了 Miller-Rabin 测试算法,此算法的准确率会随着 certainty 参数的增加而增加。如果该数是素数,那么 Miller-Rabin 测试必定返回 true;如果该数是合数(期待返回 false),那么会有低于 1/4certainty 概率返回 true。素数只对大于等于 2 的正整数有意义,即负数,0,1 都不是素数。
参数:
- certainty: UInt64 - 需要执行 Miller-Rabin 测试的次数。注意,如果测试次数为 0,表示不测试,那么总是返回 true(即不是素数的数也必定返回 true)。
返回值:
- Bool - 如果使用此函数测定了一个数为素数,则返回 true;不为素数,则返回 false。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1024)
let isProbablePrime = bigInt.isProbablePrime(10)
println(isProbablePrime)
}
运行结果:
false
func lowestOneBit() (deprecated)
public func lowestOneBit(): Int64
功能:判断为 1 的最低位的 bit 的位置。
注意:
未来版本即将废弃,使用 trailingZeros(BigInt) 替代。
返回值:
- Int64 - 返回为 1 的最低位的 bit 的位置。如果 bit 全为 0,则返回 -1。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(-1)
let lowestOneBit = bigInt.lowestOneBit()
println(lowestOneBit)
}
运行结果:
0
func modInverse(BigInt)
public func modInverse(that: BigInt): BigInt
功能:求模逆元。
模逆元 r 满足 $(this * r) % that == 1$。显然,this 和 that 必须互质。当 that 为 正负 1 时,结果总是 0。
参数:
返回值:
- BigInt - 返回模逆元。
异常:
- IllegalArgumentException - 当
this和that不互质或that为 0 时,抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1025)
let that = BigInt(512)
let modInverse = bigInt.modInverse(that)
println(modInverse)
}
运行结果:
1
func modPow(BigInt, ?BigInt)
public func modPow(n: BigInt, m!: ?BigInt = None): BigInt
功能:计算此 BigInt 的 n 次幂模 m 的结果,并返回。
模的规则与基础类型一致,即模的符号与被除数保持一致。
参数:
返回值:
- BigInt - 乘方后取模的运算结果。
异常:
- ArithmeticException - 除数为 0 抛此异常。
- IllegalArgumentException - 指数为负数时抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(2)
let n = BigInt(10)
let modPow = bigInt.modPow(n)
println(modPow)
}
运行结果:
1024
func quo(BigInt) (deprecated)
public func quo(that: BigInt): BigInt
功能:BigInt 的除法运算。
与另一个 BigInt 相除,返回结果。此除法运算的行为与运算符重载函数区别于,如果被除数为负数,此函数的结果向着远离 0 的方向取整,保证余数大于等于 0。
注意:
未来版本即将废弃。
参数:
- that: BigInt - 除数。除数不得为 0。
返回值:
异常:
- ArithmeticException - 除数为 0 抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1025)
let that = BigInt(512)
let quo = bigInt.quo(that)
println(quo)
}
运行结果:
2
func quoAndRem(BigInt) (deprecated)
public func quoAndRem(that: BigInt): (BigInt, BigInt)
功能:BigInt 的除法运算。
与另一个 BigInt 相除,返回商和余数。此除法运算的行为与 divAndMod 函数区别于,如果被除数为负数,此函数的结果向着远离 0 的方向取整,保证余数总是大于等于 0。
注意:
未来版本即将废弃。
参数:
- that: BigInt - 除数。除数不得为 0。
返回值:
异常:
- ArithmeticException - 除数为 0 抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1025)
let that = BigInt(512)
let (quo, rem) = bigInt.quoAndRem(that)
println(quo)
println(rem)
}
运行结果:
2
1
func rem(BigInt) (deprecated)
public func rem(that: BigInt): BigInt
功能:BigInt 的模运算。
与另一个 BigInt 相除,返回余数。余数的结果总是大于等于 0。
注意:
未来版本即将废弃。
参数:
- that: BigInt - 除数。除数不得为 0。
返回值:
异常:
- ArithmeticException - 除数为 0 抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(1025)
let that = BigInt(512)
let rem = bigInt.rem(that)
println(rem)
}
运行结果:
1
func setBit(Int64)
public func setBit(index: Int64): BigInt
功能:通过将指定索引位置的 bit 修改为 1 来构造一个新 BigInt。
参数:
- index: Int64 - 需要设置的 bit 位置的索引。
index需要大于等于 0。
返回值:
异常:
- IllegalArgumentException - 如果入参
index小于 0,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(0)
let setBit = bigInt.setBit(10)
println(setBit)
}
运行结果:
1024
func testBit(Int64)
public func testBit(index: Int64): Bool
功能:判断指定位置的 bit 信息,如果指定位置的 bit 为 0,则返回 false;为 1,则返回 true。
参数:
- index: Int64 - 需要知道的 bit 的索引。
index需要大于等于 0。
返回值:
- Bool - 指定位置的 bit 信息。
异常:
- IllegalArgumentException - 如果入参
index小于 0,则抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(-1)
let testBit = bigInt.testBit(100)
println(testBit)
}
运行结果:
true
func toBytes()
public func toBytes(): Array<Byte>
功能:计算并返回此 BigInt 的大端补码字节数组。
字节数组最低索引的最低位为符号位,如 128 返回 [0, 128](符号位为 0),-128 返回 [128](符号位为 1)。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(0x400)
let toBytes = bigInt.toBytes()
println(toBytes)
}
运行结果:
[4, 0]
func toFloat16()
public func toFloat16(): Float16
功能:将当前 BigInt 对象转化为 Float16 类型。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(32)
let toFloat16 = bigInt.toFloat16()
println(toFloat16)
}
运行结果:
32.000000
func toFloat32()
public func toFloat32(): Float32
功能:将当前 BigInt 对象转化为 Float32 类型。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(32)
let toFloat32 = bigInt.toFloat32()
println(toFloat32)
}
运行结果:
32.000000
func toFloat64()
public func toFloat64(): Float64
功能:将当前 BigInt 对象转化为 Float64 类型。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(32)
let toFloat64 = bigInt.toFloat64()
println(toFloat64)
}
运行结果:
32.000000
func toInt16(OverflowStrategy)
public func toInt16(overflowHandling!: OverflowStrategy = Throwing): Int16
功能:将当前 BigInt 对象转化为 Int16 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt(0x8000_0000_0000)
let toInt16 = bigInt.toInt16(overflowHandling: Saturating)
println(toInt16)
}
运行结果:
32767
func toInt32(OverflowStrategy)
public func toInt32(overflowHandling!: OverflowStrategy = Throwing): Int32
功能:将当前 BigInt 对象转化为 Int32 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt(0x8000_0000_00FF)
let toInt32 = bigInt.toInt32(overflowHandling: Wrapping)
println(toInt32)
}
运行结果:
255
func toInt64(OverflowStrategy)
public func toInt64(overflowHandling!: OverflowStrategy = Throwing): Int64
功能:将当前 BigInt 对象转化为 Int64 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt.parse("800000000000000000", radix: 16)
let toInt64 = bigInt.toInt64(overflowHandling: Wrapping)
println(toInt64)
}
运行结果:
0
func toInt8(OverflowStrategy)
public func toInt8(overflowHandling!: OverflowStrategy = Throwing): Int8
功能:将当前 BigInt 对象转化为 Int8 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "Throwing":异常模式。出现溢出抛出异常。
- "Wrapping":溢出模式。出现溢出高位截断。
- "Saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt(1024)
let toInt8 = bigInt.toInt8(overflowHandling: Saturating)
println(toInt8)
}
运行结果:
127
func toIntNative(OverflowStrategy)
public func toIntNative(overflowHandling!: OverflowStrategy = Throwing): IntNative
功能:将当前 BigInt 对象转化为 IntNative 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt.parse("800000000000000000", radix: 16)
let toIntNative = bigInt.toIntNative(overflowHandling: Wrapping)
println(toIntNative)
}
运行结果:
0
func toString()
public func toString(): String
功能:计算并返回此 BigInt 的十进制字符串表示。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(0x400)
let toString = bigInt.toString()
println(toString)
}
运行结果:
1024
func toUInt16(OverflowStrategy)
public func toUInt16(overflowHandling!: OverflowStrategy = Throwing): UInt16
功能:将当前 BigInt 对象转化为 UInt16 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt.parse("800000000000000000", radix: 16)
let toUInt16 = bigInt.toUInt16(overflowHandling: Wrapping)
println(toUInt16)
}
运行结果:
0
func toUInt32(OverflowStrategy)
public func toUInt32(overflowHandling!: OverflowStrategy = Throwing): UInt32
功能:将当前 BigInt 对象转化为 UInt32 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt.parse("800000000000000000", radix: 16)
let toUInt32 = bigInt.toUInt32(overflowHandling: Wrapping)
println(toUInt32)
}
运行结果:
0
func toUInt64(OverflowStrategy)
public func toUInt64(overflowHandling!: OverflowStrategy = Throwing): UInt64
功能:将当前 BigInt 对象转化为 UInt64 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt.parse("-800000000000000000", radix: 16)
let toUInt64 = bigInt.toUInt64(overflowHandling: Saturating)
println(toUInt64)
}
运行结果:
0
func toUInt8(OverflowStrategy)
public func toUInt8(overflowHandling!: OverflowStrategy = Throwing): UInt8
功能:将当前 BigInt 对象转化为 UInt8 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt.parse("800000000000000000", radix: 16)
try {
bigInt.toUInt8(overflowHandling: Throwing)
} catch (e: OverflowException) {
println(e.message)
}
return
}
运行结果:
Out of range of the UInt8.
func toUIntNative(OverflowStrategy)
public func toUIntNative(overflowHandling!: OverflowStrategy = Throwing): UIntNative
功能:将当前 BigInt 对象转化为 UIntNative 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
- "throwing":异常模式。出现溢出抛出异常。
- "wrapping":溢出模式。出现溢出高位截断。
- "saturating":边界值模式。出现溢出,当前值大于目标类型的 MAX 值,返回目标类型 MAX 值,当前值小于目标类型的 MIN 值,返回目标类型 MIN 值。
返回值:
- UIntNative - 返回转换后的 UInt64 值。
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.BigInt
import std.math.numeric.OverflowStrategy
main() {
let bigInt = BigInt.parse("-800000000000000000", radix: 16)
let toUIntNative = bigInt.toUIntNative(overflowHandling: Saturating)
println(toUIntNative)
}
运行结果:
0
operator func !()
public operator func !(): BigInt
功能:按位非。将操作数中的二进制位 0 变 1,1 变 0。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let no = !bigInt
println(no)
}
运行结果:
0
operator func !=(BigInt)
public operator func !=(that: BigInt): Bool
功能:判不等运算。
参数:
返回值:
- Bool - 判不等的结果。不等返回 true,相等返回 false。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("-2")
println(bigInt != that)
}
运行结果:
true
operator func %(BigInt)
public operator func %(that: BigInt): BigInt
功能:BigInt 的模运算。
取模运算的行为与基础类型保持一致,即符号与被除数保持一致。
参数:
- that: BigInt - 除数。除数不得为 0。
返回值:
异常:
- ArithmeticException - 除数为 0 抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-23456789123456789")
let that = BigInt.parse("-23456789123456789")
let mod = bigInt % that
println(mod)
}
运行结果:
0
operator func &(BigInt)
public operator func &(that: BigInt): BigInt
功能:按位与。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位都为 1 时,结果位才为 1。
参数:
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("8")
let that = BigInt.parse("7")
let and = bigInt & that
println(and)
}
运行结果:
0
operator func *(BigInt)
public operator func *(that: BigInt): BigInt
功能:BigInt 乘法。
参数:
- that: BigInt - 乘数。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("-23456789123456789")
let mul = bigInt * that
println(mul)
}
运行结果:
23456789123456789
operator func **(UInt64)
public operator func **(n: UInt64): BigInt
功能:求 BigInt 的 n 次幂。
参数:
- n: UInt64 - 指数。
返回值:
- BigInt - 幂运算结果。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-2")
let power = bigInt ** 64
println(power.toString(radix: 16))
}
运行结果:
10000000000000000
operator func +(BigInt)
public operator func +(that: BigInt): BigInt
功能:BigInt 加法。
参数:
- that: BigInt - 加数。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("123456789123456789")
let that = BigInt.parse("-23456789123456789")
let plus = bigInt + that
println(plus)
}
运行结果:
100000000000000000
operator func -()
public operator func -(): BigInt
功能:求 BigInt 的相反数。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-23456789123456789")
let opposite = -bigInt
println(opposite)
}
运行结果:
23456789123456789
operator func -(BigInt)
public operator func -(that: BigInt): BigInt
功能:BigInt 减法。
参数:
- that: BigInt - 减数。
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("100000000000000000")
let that = BigInt.parse("-23456789123456789")
let sub = bigInt - that
println(sub)
}
运行结果:
123456789123456789
operator func <(BigInt)
public operator func <(that: BigInt): Bool
功能:小于比较运算。
参数:
返回值:
- Bool - 比较的结果。小于返回 true,否则返回 false。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("-2")
println(bigInt < that)
}
运行结果:
false
operator func <<(Int64)
public operator func <<(n: Int64): BigInt
功能:左移运算。
参数:
- n: Int64 - 左移 n 位,n 需要大于等于 0。
返回值:
异常:
- ArithmeticException - 入参小于 0 时抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let leftShift = bigInt << 64
println(leftShift.toString(radix: 16))
}
运行结果:
-10000000000000000
operator func <=(BigInt)
public operator func <=(that: BigInt): Bool
功能:小于等于比较运算。
参数:
返回值:
- Bool - 比较的结果。小于等于返回 true,否则返回 false。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("-2")
println(bigInt <= that)
}
运行结果:
false
operator func ==(BigInt)
public operator func ==(that: BigInt): Bool
功能:判等运算。
参数:
返回值:
- Bool - 判等的结果。相等返回 true,不等返回 false。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("-2")
println(bigInt == that)
}
运行结果:
false
operator func >(BigInt)
public operator func >(that: BigInt): Bool
功能:大于比较运算。
参数:
返回值:
- Bool - 比较的结果。大于返回 true,否则返回 false。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("-2")
println(bigInt > that)
}
运行结果:
true
operator func >=(BigInt)
public operator func >=(that: BigInt): Bool
功能:大于等于比较运算。
参数:
返回值:
- Bool - 比较的结果。大于等于返回 true,否则返回 false。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("-2")
println(bigInt >= that)
}
运行结果:
true
operator func >>(Int64)
public operator func >>(n: Int64): BigInt
功能:右移运算。
参数:
- n: Int64 - 右移 n 位,n 需要大于等于 0。
返回值:
异常:
- ArithmeticException - 入参小于 0 时抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let rightShift = bigInt >> 10000
println(rightShift)
}
运行结果:
-1
operator func /(BigInt)
public operator func /(that: BigInt): BigInt
功能:BigInt 除法。
除法运算的行为与基础类型保持一致,即结果向靠近 0 的方向取整。
参数:
- that: BigInt - 除数。除数不得为 0。
返回值:
异常:
- ArithmeticException - 除数为 0 抛此异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-23456789123456789")
let that = BigInt.parse("-23456789123456789")
let div = bigInt / that
println(div)
}
运行结果:
1
operator func ^(BigInt)
public operator func ^(that: BigInt): BigInt
功能:按位异或。其功能是参与运算的两数各对应的二进位相异或。二进制位结果不相同时,异或结果为 1;二进制位结果相同时,异或结果为 0。
参数:
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("-1")
let that = BigInt.parse("7")
let xor = bigInt ^ that
println(xor)
}
运行结果:
-8
operator func |(BigInt)
public operator func |(that: BigInt): BigInt
功能:按位或。其功能是参与运算的两数各对应的二进位相或。只有对应的两个二进位都为 0 时,结果位才为 0。
参数:
返回值:
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt.parse("8")
let that = BigInt.parse("7")
let or = bigInt | that
println(or)
}
运行结果:
15
extend BigInt <: Integer<BigInt>
extend BigInt <: Integer<BigInt>
功能:为 BigInt 类型扩展 Integer<T> 接口。
父类型:
static func isSigned()
public static func isSigned(): Bool
功能:判断 BigInt 类型是否是有符号类型。
返回值:
- Bool - 总是返回
true。
extend BigInt <: Formattable
extend BigInt <: Formattable
功能:为 BigInt 扩展 Formattable 接口,以实现将 BigInt 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 BigInt 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend BigInt <: Number<BigInt>
extend BigInt <: Number<BigInt> {}
功能:为 BigInt 类型扩展 Number<T> 接口。
父类型:
extend BigInt <: Parsable<BigInt>
extend BigInt <: Parsable<BigInt>
功能:此扩展主要用于实现将 BigInt 类型字面量的字符串转换为 BigInt 结构体的相关操作函数。
父类型:
static func parse(String)
public static func parse(value: String): BigInt
功能:将字符串解析成一个 BigInt 结构体。
字符串的规则如下,即开头是可选的符号(正号或负号),接进制前缀,再接一串字符串表示的数字:
IntegerString : SignString? BaseString? ValueString
-
SignString : + | -
-
BaseString : "0b" | "0B" | "0o" | "0O" | "0x" | "0X" | ""
-
ValueString : Digits
-
Digits: Digit | Digit Digits
-
Digit : '0' ~ '9' | 'A' ~ 'Z' | 'a' ~ 'z'
-
如果进制前缀是 "0b" 或 "0B",则 Digit 取值范围应为 '0' ~ '1';
-
如果进制前缀是 "0o" 或 "0O",则 Digit 取值范围应为 '0' ~ '7';
-
如果进制前缀是 "0x" 或 "0X",则 Digit 取值范围应为 '0' ~ '9'、'a' ~ 'z' 或 'A' ~ 'Z';
-
如果进制前缀是空,则 Digit 取值范围应为 '0' ~ '9'。
-
-
-
参数:
- value: String - 用于构建 BigInt 结构体的字符串。字符串规则为,开头可选一个正号(+)或者负号(-)。接下来可选的进制前缀,默认为十进制,使用 "0b" 或 "0B" 表示二进制,使用 "0o" 或 "0O" 表示八进制,使用 "0x" 或 "0X" 表示十六进制。再接下来必选非空阿拉伯数字或大小写拉丁字母的字符序列,大小写字符含义一样,'a' 和 'A' 的大小等于十进制的 10,'b' 和 'B' 的大小等于十进制的 11,以此类推。序列中的字符应符合相应进制的字符集要求。
返回值:
异常:
- IllegalArgumentException - 如果字符串
value不符合上述规则,抛此异常。
static func tryParse(String)
public static func tryParse(value: String): ?BigInt
功能:尝试将字符串解析成一个 BigInt 结构体。
字符串的规则如下,即开头是可选的符号(正号或负号),接进制前缀,再接一串字符串表示的数字:
IntegerString : SignString? BaseString? ValueString
-
SignString : + | -
-
BaseString : "0b" | "0B" | "0o" | "0O" | "0x" | "0X" | ""
-
ValueString : Digits
-
Digits: Digit | Digit Digits
-
Digit : '0' ~ '9' | 'A' ~ 'Z' | 'a' ~ 'z'
-
如果进制前缀是 "0b" 或 "0B",则 Digit 取值范围应为 '0' ~ '1';
-
如果进制前缀是 "0o" 或 "0O",则 Digit 取值范围应为 '0' ~ '7';
-
如果进制前缀是 "0x" 或 "0X",则 Digit 取值范围应为 '0' ~ '9'、'a' ~ 'z' 或 'A' ~ 'Z';
-
如果进制前缀是空,则 Digit 取值范围应为 '0' ~ '9'。
-
-
-
参数:
- value: String - 用于构建 BigInt 结构体的字符串。字符串规则为,开头可选一个正号(+)或者负号(-)。接下来可选的进制前缀,默认为十进制,使用 "0b" 或 "0B" 表示二进制,使用 "0o" 或 "0O" 表示八进制,使用 "0x" 或 "0X" 表示十六进制。再接下来必选非空阿拉伯数字或大小写拉丁字母的字符序列,大小写字符含义一样,'a' 和 'A' 的大小等于十进制的 10,'b' 和 'B' 的大小等于十进制的 11,以此类推。序列中的字符应符合相应进制的字符集要求。
返回值:
extend BigInt <: RadixConvertible<BigInt>
extend BigInt <: RadixConvertible<BigInt>
功能:此扩展主要用于实现将 BigInt 类型字面量的字符串转换为 BigInt 结构体的相关操作函数。
父类型:
static func parse(String, Int)
public static func parse(value: String, radix!: Int): BigInt
功能:根据指定进制将字符串解析成一个 BigInt 结构体,支持 2 进制到 36 进制。
字符串的规则如下,即开头是可选的符号(正号或负号),接一串字符串表示的数字:
IntegerString : SignString? ValueString
-
SignString : + | -
-
ValueString : Digits
-
Digits: Digit | Digit Digits
-
Digit : '0' ~ '9' | 'A' ~ 'Z' | 'a' ~ 'z'
-
如果 Digit 在 '0' ~ '9' 内, 需要满足 (Digit - '0') < radix;
-
如果 Digit 在 'A' ~ 'Z' 内, 需要满足 (Digit - 'A') + 10 < radix;
-
如果 Digit 在 'a' ~ 'z' 内, 需要满足 (Digit - 'A') + 10 < radix。
-
-
-
参数:
- value: String - 用于构建 BigInt 结构体的字符串。字符串规则为,开头可选一个正号(+)或者负号(-)。接下来必选非空阿拉伯数字或大小写拉丁字母的字符序列,大小写字符含义一样,'a' 和 'A' 的大小等于十进制的 10,'b' 和 'B' 的大小等于十进制的 11,以此类推。序列中的字符大小不得大于等于进制大小。
- radix!: Int - 进制。字符串所表示的进制,范围为 [2, 36]。
返回值:
异常:
- IllegalArgumentException - 如果字符串
value不符合上述规则,或radix表示的进制不在 [2, 36] 区间内,抛此异常。
static func tryParse(String, Int)
public static func tryParse(value: String, radix!: Int): ?BigInt
功能:尝试根据指定进制将字符串解析成一个 BigInt 结构体,支持 2 进制到 36 进制。
字符串的规则如下,即开头是可选的符号(正号或负号),接一串字符串表示的数字:
IntegerString : SignString? ValueString
-
SignString : + | -
-
ValueString : Digits
-
Digits: Digit | Digit Digits
-
Digit : '0' ~ '9' | 'A' ~ 'Z' | 'a' ~ 'z'
-
如果 Digit 在 '0' ~ '9' 内, 需要满足 (Digit - '0') < radix;
-
如果 Digit 在 'A' ~ 'Z' 内, 需要满足 (Digit - 'A') + 10 < radix;
-
如果 Digit 在 'a' ~ 'z' 内, 需要满足 (Digit - 'A') + 10 < radix。
-
-
-
参数:
- value: String - 用于构建 BigInt 结构体的字符串。字符串规则为,开头可选一个正号(+)或者负号(-)。接下来必选非空阿拉伯数字或大小写拉丁字母的字符序列,大小写字符含义一样,'a' 和 'A' 的大小等于十进制的 10,'b' 和 'B' 的大小等于十进制的 11,以此类推。序列中的字符大小不得大于等于进制大小。
- radix!: Int - 进制。字符串所表示的进制,范围为 [2, 36]。
返回值:
func toString(Int)
public func toString(radix!: Int): String
功能:计算并返回此 BigInt 的任意进制字符串表示。
参数:
- radix!: Int - 进制。字符串所表示的进制,范围为 [2, 36]。
返回值:
异常:
- IllegalArgumentException - 当入参 radix 不在 [2, 36] 范围内时,抛出异常。
示例:
import std.math.numeric.BigInt
main() {
let bigInt = BigInt(0x400)
let toString = bigInt.toString(radix: 2)
println(toString)
}
运行结果:
10000000000
struct Decimal
public struct Decimal <: Comparable<Decimal> & Hashable & ToString {
public init(val: String)
public init(val: BigInt, scale: Int32)
public init(val: BigInt)
public init(val: Int8)
public init(val: Int16)
public init(val: Int32)
public init(val: IntNative)
public init(val: Int64)
public init(val: UInt8)
public init(val: UInt16)
public init(val: UInt32)
public init(val: UIntNative)
public init(val: UInt64)
public init(val: Float16)
public init(val: Float32)
public init(val: Float64)
}
功能:Decimal 用于表示任意精度的有符号的十进制数。允许操作过程指定结果精度及舍入规则。提供基础类型 (Int、UInt、String、Float等) 与 BigInt 类型互相转换能力,支持 Decimal 对象基本属性查询等能力,支持基础数学运算操作,提供对象比较、hash、字符串打印等基础能力。
父类型:
prop precision
public prop precision: Int64
功能:获取 Decimal 精度值,即无标度整数部分十进制有效数字位数,非负数。如果精度值为 0,表示无精度限制。
类型:Int64
prop scale
public prop scale: Int32
功能:获取 Decimal 标度值。
类型:Int32
prop sign
public prop sign: Int64
功能:获取 Decimal 实例符号值。
类型:Int64
prop value
public prop value: BigInt
功能:获取 Decimal 无标度整数值,BigInt 承载。
类型:BigInt
init(BigInt)
public init(val: BigInt)
功能:通过有符号大整数 BigInt 构建 Deciaml 结构体。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: BigInt - 有符号大整数值。
示例:
import std.math.numeric.BigInt
import std.math.numeric.Decimal
main() {
let bigInt = BigInt(24)
let decimal = Decimal(bigInt)
println(decimal)
}
运行结果:
24
init(BigInt, Int32)
public init(val: BigInt, scale: Int32)
功能:通过有符号大整数 BigInt 和标度值构建 Deciaml 结构体。默认采用精度值为 0,即无限精度进行构建。
参数:
示例:
import std.math.numeric.BigInt
import std.math.numeric.Decimal
main() {
let bigInt = BigInt(24)
let decimal = Decimal(bigInt, 4)
println(decimal)
}
运行结果:
0.0024
init(Float16)
public init(val: Float16)
功能:通过 16 位有符号浮点数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
注意:
由于部分十进制小数无法通过二进制浮点数精确表示,此构造函数以精确值构建 Decimal 对象,传入浮点数值可能与最终构建 Decimal 对象字符串打印值不一致。
参数:
- val: Float16 - 16 位有符号二进制浮点数。
异常:
- IllegalArgumentException - 当入参为
inf、-inf或nan时,抛出此异常。
示例:
import std.math.numeric.Decimal
main() {
let float16: Float16 = 0.8
let decimal = Decimal(float16)
println(decimal)
}
运行结果:
0.7998046875
init(Float32)
public init(val: Float32)
功能:通过 32 位有符号浮点数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
注意:
由于部分十进制小数无法通过二进制浮点数精确表示,此构造函数以精确值构建 Decimal 对象,传入浮点数值可能与最终构建 Decimal 对象字符串打印值不一致。
参数:
- val: Float32 - 32 位有符号二进制浮点数。
异常:
- IllegalArgumentException - 当入参为
inf、-inf或nan时,抛出此异常。
示例:
import std.math.numeric.Decimal
main() {
let float32: Float32 = 0.8
let decimal = Decimal(float32)
println(decimal)
}
运行结果:
0.800000011920928955078125
init(Float64)
public init(val: Float64)
功能:通过 64 位有符号浮点数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
注意:
由于部分十进制小数无法通过二进制浮点数精确表示,此构造函数以精确值构建 Decimal 对象,传入浮点数值可能与最终构建 Decimal 对象字符串打印值不一致。
参数:
- val: Float64 - 64 位有符号二进制浮点数。
异常:
- IllegalArgumentException - 当入参为
inf、-inf或nan时,抛出此异常。
示例:
import std.math.numeric.Decimal
main() {
let float64: Float64 = 0.8
let decimal = Decimal(float64)
println(decimal)
}
运行结果:
0.8000000000000000444089209850062616169452667236328125
init(Int16)
public init(val: Int16)
功能:通过 16 位有符号整数构建 Decimal 结构体。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: Int16 - 16 位有符号整数。
示例:
import std.math.numeric.Decimal
main() {
let int16: Int16 = 24
let decimal = Decimal(int16)
println(decimal)
}
运行结果:
24
init(Int32)
public init(val: Int32)
功能:通过 32 位有符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: Int32 - 32 位有符号整数。
示例:
import std.math.numeric.Decimal
main() {
let int32: Int32 = 24
let decimal = Decimal(int32)
println(decimal)
}
运行结果:
24
init(Int64)
public init(val: Int64)
功能:通过 64 位有符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: Int64 - 64 位有符号整数。
示例:
import std.math.numeric.Decimal
main() {
let int64: Int64 = 24
let decimal = Decimal(int64)
println(decimal)
}
运行结果:
24
init(Int8)
public init(val: Int8)
功能:通过 8 位有符号整数构建 Decimal 结构体。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: Int8 - 8 位有符号整数。
示例:
import std.math.numeric.Decimal
main() {
let int8: Int8 = 24
let decimal = Decimal(int8)
println(decimal)
}
运行结果:
24
init(IntNative)
public init(val: IntNative)
功能:通过 32 位或 64 位 (具体长度与平台相关) 有符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: IntNative - 32 位或 64位有符号整数。
示例:
import std.math.numeric.Decimal
main() {
let intnative: IntNative = 24
let decimal = Decimal(intnative)
println(decimal)
}
运行结果:
24
init(String) (deprecated)
public init(val: String)
功能:通过规定格式字符串构建 Decimal 结构体。默认采用精度值为 0,即无限精度进行构建。字符串需满足如下格式,即开头可选的符号(正号或负号),接 ValueString 字符串,再接可选的 ExponentString 字符串:
Decimal 字符串: (SignString)? ValueString (ExponentString)?
-
SignString: + | -
-
ValueString: IntegerPart.(FractionPart)? | .FractionPart | IntegerPart
-
IntegerPart:Digits
-
FractionPart:Digits
-
Digits: Digit | Digit Digits
- Digit:'0' ~ '9'
-
-
ExponentString: ExponentIndicator (SignString)? IntegerPart
- ExponentIndicator:e | E
注意:
未来版本即将废弃,使用 parse(String) 替代。
参数:
- val: String - 规定格式字符串。
异常:
- IllegalArgumentException - 当入参字符串不满足规定格式时,抛此异常。
- OverflowException - 当构建值标度溢出时,抛此异常。
init(UInt16)
public init(val: UInt16)
功能:通过 16 位无符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: UInt16 - 16 位无符号整数。
示例:
import std.math.numeric.Decimal
main() {
let uint16: UInt16 = 24
let decimal = Decimal(uint16)
println(decimal)
}
运行结果:
24
init(UInt32)
public init(val: UInt32)
功能:通过 32 位无符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: UInt32 - 32 位无符号整数。
示例:
import std.math.numeric.Decimal
main() {
let uint32: UInt32 = 24
let decimal = Decimal(uint32)
println(decimal)
}
运行结果:
24
init(UInt64)
public init(val: UInt64)
功能:通过 64 位无符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: UInt64 - 64 位无符号整数。
示例:
import std.math.numeric.Decimal
main() {
let uint64: UInt64 = 24
let decimal = Decimal(uint64)
println(decimal)
}
运行结果:
24
init(UInt8)
public init(val: UInt8)
功能:通过 8 位无符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: UInt8 - 8 位无符号整数。
示例:
import std.math.numeric.Decimal
main() {
let uint8: UInt8 = 24
let decimal = Decimal(uint8)
println(decimal)
}
运行结果:
24
init(UIntNative)
public init(val: UIntNative)
功能:通过 32 位或 64 位 (具体长度与平台相关) 无符号整数构建 Decimal 对象。默认采用精度值为 0,即无限精度进行构建。
参数:
- val: UIntNative - 32 位或 64位无符号整数。
示例:
import std.math.numeric.Decimal
main() {
let uintnative: UIntNative = 24
let decimal = Decimal(uintnative)
println(decimal)
}
运行结果:
24
func compare(Decimal)
public func compare(d: Decimal): Ordering
功能:比较当前对象与入参 Decimal 对象,返回比较结果值。
参数:
返回值:
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(-5)
let B = Decimal(3)
let C = A.compare(B)
println(C)
}
运行结果:
Ordering.LT
func divWithPrecision(Decimal, Int64, RoundingMode)
public func divWithPrecision(d: Decimal, precision: Int64, roundingMode!: RoundingMode = HalfEven): Decimal
功能:除法运算,支持自定义运算精度和舍入方式,除以入参 Decimal 对象,返回结果值,如果结果精度超过 precision 指定精度,则根据指定的精度对除法运算结果进行舍入。
参数:
- d: Decimal - Decimal 除数对象。
- precision: Int64 - 精度值。
- roundingMode!: RoundingMode - 舍入规则。
返回值:
异常:
- ArithmeticException - 当除数为 0 时,抛出此异常。
- OverflowException - 当除法结果值范围超过 [-(maxValue(precision) * (10 Int32.MAX)), maxValue(precision) * (10 Int32.MAX)] 时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(2)
let B = Decimal(3)
let C = A.divWithPrecision(B, 0)
println("C = ${C}")
}
运行结果:
C = 0.6666666666666666666666666666666667
func divAndRem(Decimal) (deprecated)
public func divAndRem(d: Decimal): (BigInt, Decimal)
功能:除法取商和余数运算,除以入参 Decimal 对象,返回整数商值和余数值。结果保留实际精度值。
注意:
未来版本即将废弃,使用 divAndMod(Decimal) 替代。
参数:
返回值:
异常:
- ArithmeticException - 当除数为 0 时,抛出此异常。
- OverflowException - 当除法结果值范围超过 [-(maxValue(precision) * (10 Int32.MAX)), maxValue(precision) * (10 Int32.MAX)] 时,抛出此异常。
func divAndMod(Decimal)
public func divAndMod(d: Decimal): (BigInt, Decimal)
功能:除法取商和余数运算,除以入参 Decimal 对象,返回整数商值和余数值。结果保留实际精度值。
参数:
返回值:
异常:
- ArithmeticException - 当除数为 0 时,抛出此异常。
- OverflowException - 当除法结果值范围超过 [-(maxValue(precision) * (10 Int32.MAX)), maxValue(precision) * (10 Int32.MAX)] 时,抛出此异常。
func hashCode()
public func hashCode(): Int64
功能:获取当前对象哈希值。
返回值:
- Int64 - 返回当前对象哈希值。
示例:
import std.math.numeric.Decimal
main() {
let decimal = Decimal(24)
let hashcode = decimal.hashCode()
println(hashcode)
}
运行结果:
744
func isInteger()
public func isInteger(): Bool
功能:判断当前 Decimal 对象是否为整数。
返回值:
- Bool - 返回当前对象是否为整数判断结果。当前对象为整数时返回 true,否则返回 false。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(100)
println("${A}.isInteger() = ${A.isInteger()}")
}
运行结果:
100.isInteger() = true
func powWithPrecision(Int64, Int64, RoundingMode)
public func powWithPrecision(n: Int64, precision: Int64, roundingMode!: RoundingMode = RoundingMode.HalfEven): Decimal
功能:乘方运算,支持自定义运算精度和舍入方式,获取当前对象为底数,入参 Int64 为指数的乘方运算结果,如果运算结果超过 precision 指定的精度,则根据指定的精度对乘方结果进行舍入。
参数:
- n: Int64 - 乘方运算的指数值。
- precision: Int64 - 精度值。
- roundingMode!: RoundingMode - 舍入规则。
返回值:
异常:
- OverflowException - 当乘方运算结果标度值溢出时,抛出此异常。
示例:
import std.math.numeric.*
import std.math.*
main(): Unit {
let A = Decimal(2.5)
println("A.powWithPrecision(3, 0) = ${A.powWithPrecision(3, 0, roundingMode: HalfEven)}")
}
运行结果:
A.powWithPrecision(3, 0) = 15.625
func reScale(Int32, RoundingMode)
public func reScale(newScale: Int32, roundingMode!: RoundingMode = HalfEven): Decimal
功能:调整 Decimal 对象标度值,允许指定舍入规则,返回标度调整后新的 Decimal 对象。
参数:
- newScale: Int32 - 新的标度值。
- roundingMode!: RoundingMode - 舍入规则。
返回值:
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(1.234568)
println("A.reScale(3) = ${A.reScale(3)}")
}
运行结果:
A.reScale(3) = 1.235
func removeTrailingZeros()
public func removeTrailingZeros(): Decimal
功能:对当前 Decimal 对象移除尾部零,不改变对象数值。
返回值:
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(1.00)
println("A.removeTrailingZeros() = ${A.removeTrailingZeros()}")
}
运行结果:
A.removeTrailingZeros() = 1
func roundWithPrecision(Int64, RoundingMode)
public func roundWithPrecision(precision: Int64, roundingMode!: RoundingMode = RoundingMode.HalfEven): Decimal
功能:按照指定舍入精度和舍入规则对当前 Decimal 对象进行舍入操作。
参数:
- precision: Int64 - 精度值。
- roundingMode!: RoundingMode - 舍入规则。
返回值:
异常:
- OverflowException - 当舍入操作结果标度值溢出时,抛出此异常。
示例:
import std.math.numeric.Decimal
import std.math.*
main(): Unit {
let A = Decimal(1.0)
println("A.roundWithPrecision(1.0) = ${A.roundWithPrecision(0, roundingMode: HalfEven)}")
let B = Decimal(0.1f16).roundWithPrecision(5, roundingMode: Up)
println("B = ${B}")
}
运行结果:
A.roundWithPrecision(1.0) = 1
B = 0.099976
func scaleUnit()
public func scaleUnit(): Decimal
功能:对当前 Decimal 对象返回标度单位,即数值为 1 ,标度值与当前对象相等的 Decimal 对象。
返回值:
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(100)
println("A.scaleUnit() = ${A.scaleUnit()}")
}
运行结果:
A.scaleUnit() = 1
func shiftPoint(Int32)
public func shiftPoint(n: Int32): Decimal
功能:移动当前 Decimal 对象小数点 abs(n) 位返回结果对象,当 n 为正数时,左移小数点,n 为负数时,右移小数点,n 为零时,返回当前对象。
参数:
- n: Int32 - 指定小数点移动位数及方向。
返回值:
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(25)
println("A.shiftPoint(1) = ${A.shiftPoint(1)}")
}
运行结果:
A.shiftPoint(1) = 2.5
func sqrtWithPrecision(Int64, RoundingMode)
public func sqrtWithPrecision(precision: Int64, roundingMode!: RoundingMode = RoundingMode.HalfEven): Decimal
功能:开方运算,支持自定义运算精度和结果舍入方式,获取当前对象开方结果,如果运算结果超过 presision 指定的精度,则根据指定的精度对开方结果进行舍入。
参数:
- precision: Int64 - 精度值。
- roundingMode!: RoundingMode - 舍入规则。
返回值:
异常:
- IllegalArgumentException - 如果被计算平方根的对象为负数,则抛此异常。
- OverflowException - 当计算平方根操作结果标度值溢出时,抛出此异常。
示例:
import std.math.numeric.*
main() {
let n: Decimal = Decimal.parse("2")
let s = n.sqrtWithPrecision(2)
println(s)
}
运行结果:
1.4
func toBigInt()
public func toBigInt(): BigInt
功能:将当前 Decimal 对象转化为 BigInt 类型。
返回值:
func toEngString()
public func toEngString(): String
功能:以工程计数法的形式打印输出 Decimal 对象,指数为 3 的倍数, 当值小于 0 时以 “-” 开头后跟十进制数字,大于等于 0 时,直接打印输出数字,不额外添加 “+”。指数小于 0 时同样遵循以上规则。
返回值:
func toSciString()
public func toSciString(): String
功能:以科学计数法的形式打印输出 Decimal 对象,当值小于 0 时以 “-” 开头后跟十进制数字,大于等于 0 时,直接打印输出数字,不额外添加 “+”。指数小于 0 时同样遵循以上规则。
返回值:
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(6.25)
println("A.toFloat16() = ${A.toFloat16()}")
println("A.toFloat32() = ${A.toFloat32()}")
println("A.toFloat64() = ${A.toFloat64()}")
println("A.toBigInt() = ${A.toBigInt()}")
println("A.toEngString() = ${A.toEngString()}")
println("A.toSciString() = ${A.toSciString()}")
}
运行结果:
A.toFloat16() = 6.250000
A.toFloat32() = 6.250000
A.toFloat64() = 6.250000
A.toBigInt() = 6
A.toEngString() = 6.25E0
A.toSciString() = 6.25E0
func toFloat16()
public func toFloat16(): Float16
功能:将当前 Decimal 对象转化为 Float16 类型。
返回值:
func toFloat32()
public func toFloat32(): Float32
功能:将当前 Decimal 对象转化为 Float32 类型。
返回值:
func toFloat64()
public func toFloat64(): Float64
功能:将当前 Decimal 对象转化为 Float64 类型。
返回值:
func toInt16(OverflowStrategy)
public func toInt16(overflowHandling!: OverflowStrategy = Throwing): Int16
功能:将当前 Decimal 对象转化为 Int16 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toInt32(OverflowStrategy)
public func toInt32(overflowHandling!: OverflowStrategy = Throwing): Int32
功能:将当前 Decimal 对象转化为 Int32 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toInt64(OverflowStrategy)
public func toInt64(overflowHandling!: OverflowStrategy = Throwing): Int64
功能:将当前 Decimal 对象转化为 Int64 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toInt8(OverflowStrategy)
public func toInt8(overflowHandling!: OverflowStrategy = Throwing): Int8
功能:将当前 Decimal 对象转化为 Int8 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toIntNative(OverflowStrategy)
public func toIntNative(overflowHandling!: OverflowStrategy = Throwing): IntNative
功能:将当前 Decimal 对象转化为 IntNative 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(6.25)
println("A.toInt8() = ${A.toInt8()}")
println("A.toInt16() = ${A.toInt16()}")
println("A.toInt32() = ${A.toInt32()}")
println("A.toInt64() = ${A.toInt64()}")
println("A.toIntNative() = ${A.toIntNative()}")
}
运行结果:
A.toInt8() = 6
A.toInt16() = 6
A.toInt32() = 6
A.toInt64() = 6
A.toIntNative() = 6
func toString()
public func toString(): String
功能:以不带指数形式打印输出 Decimal 对象,小于 0 时以 “-” 开头后跟十进制数字,大于等于 0 时,直接打印输出数字,不额外添加 “+”。
返回值:
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(-5)
let B = Decimal(3 ** 5)
println("A.hashCode() = ${A.hashCode()}")
println("B.toString() = ${B.toString()}")
}
运行结果:
A.hashCode() = 155
B.toString() = 243
func toUInt16(OverflowStrategy)
public func toUInt16(overflowHandling!: OverflowStrategy = Throwing): UInt16
功能:将当前 Decimal 对象转化为 UInt16 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toUInt32(OverflowStrategy)
public func toUInt32(overflowHandling!: OverflowStrategy = Throwing): UInt32
功能:将当前 Decimal 对象转化为 UInt32 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toUInt64(OverflowStrategy)
public func toUInt64(overflowHandling!: OverflowStrategy = Throwing): UInt64
功能:将当前 Decimal 对象转化为 UInt64 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toUInt8(OverflowStrategy)
public func toUInt8(overflowHandling!: OverflowStrategy = Throwing): UInt8
功能:将当前 Decimal 对象转化为 UInt8 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
func toUIntNative(OverflowStrategy)
public func toUIntNative(overflowHandling!: OverflowStrategy = Throwing): UIntNative
功能:将当前 Decimal 对象转化为 UIntNative 类型,支持自定义溢出策略。
参数:
- overflowHandling!: OverflowStrategy - 转换溢出策略。
返回值:
- UIntNative - 转换后的 UIntNative 值。
异常:
- OverflowException - 当不指定溢出策略或溢出策略为
throwing转换溢出时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(6.25)
println("A.toUInt8() = ${A.toUInt8()}")
println("A.toUInt16() = ${A.toUInt16()}")
println("A.toUInt32() = ${A.toUInt32()}")
println("A.toUInt64() = ${A.toUInt64()}")
println("A.toUIntNative() = ${A.toUIntNative()}")
}
运行结果:
A.toUInt8() = 6
A.toUInt16() = 6
A.toUInt32() = 6
A.toUInt64() = 6
A.toUIntNative() = 6
operator func !=(Decimal)
public operator func !=(d: Decimal): Bool
功能:不等比较运算,不等运算符重载,判断入参 Decimal 对象与当前对象是否不相等,返回比较结果值。
参数:
返回值:
- Bool - 返回不等比较运算结果。当前对象不等于入参时,返回 true,否则返回 false。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(-5)
let B = Decimal(3)
println(" -A = ${-A}")
println(" A <= B = ${ A <= B}")
println(" A != B = ${ A != B}")
}
运行结果:
-A = 5
A <= B = true
A != B = true
operator func *(Decimal)
public operator func *(d: Decimal): Decimal
功能:乘法运算,乘法运算符重载,乘以入参 Decimal 对象,返回结果值。保留乘法运算结果实际精度值。
参数:
返回值:
异常:
- OverflowException - 当两个乘数标度值相加溢出时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(2)
let B = Decimal(3)
let C = A * B
println("C = ${C}")
}
运行结果:
C = 6
operator func **(Int64)
public operator func **(n: Int64): Decimal
功能:乘方运算,乘方运算符重载,获取当前对象为底数,入参 Int64 为指数的乘方运算结果,其中指数为入参 Decimal 对象的整数部分。
注意:
指数为负值且结果为无限小数场景时,默认采用 IEEE 754-2019 decimal128 对结果进行舍入。
参数:
- n: Int64 - 乘方运算的指数值。
返回值:
异常:
- OverflowException - 当乘方运算结果标度值溢出时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(2.5)
println("A ** 3 = ${A ** 3}")
}
运行结果:
A ** 3 = 15.625
operator func +(Decimal)
public operator func +(d: Decimal): Decimal
功能:加法运算,加法运算符重载,加上入参 Decimal 对象,返回结果值。结果保留实际精度值。
参数:
返回值:
异常:
- OverflowException - 当两个加数标度值相减溢出时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(2)
let B = Decimal(3)
let C = A + B
println("C = ${C}")
}
运行结果:
C = 5
operator func -()
public operator func -(): Decimal
功能:取反运算,一元负数运算符重载,对当前 Decimal 对象取反,返回结果值。保留取反运算结果实际精度值。
返回值:
operator func -(Decimal)
public operator func -(d: Decimal): Decimal
功能:减法运算,减法运算符重载,减去入参 Decimal 对象,返回结果值。保留减法运算结果实际精度值。
参数:
返回值:
异常:
- OverflowException - 当被减数与减数标度值相减溢出时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(2)
let B = Decimal(3)
let C = A - B
println("C = ${C}")
}
运行结果:
C = -1
operator func <(Decimal)
public operator func <(d: Decimal): Bool
功能:小于比较运算,小于运算符重载,判断入参 Decimal 对象是否小于当前对象,返回比较结果值。
参数:
返回值:
- Bool - 返回小于比较运算结果。当前对象小于入参时,返回 true,否则返回 false。
operator func <=(Decimal)
public operator func <=(d: Decimal): Bool
功能:小于等于比较运算,小于等于运算符重载,判断入参 Decimal 对象是否小于等于当前对象,返回比较结果值。
参数:
返回值:
- Bool - 返回小于等于比较运算结果。当前对象小于等于入参时,返回 true,否则返回 false
operator func ==(Decimal)
public operator func ==(d: Decimal): Bool
功能:等于比较运算,等于运算符重载,判断入参 Decimal 对象与当前对象是否相等,返回比较结果值。
参数:
返回值:
- Bool - 返回等于比较运算结果。当前对象等于入参时,返回 true,否则返回 false。
operator func >(Decimal)
public operator func >(d: Decimal): Bool
功能:大于比较运算,大于运算符重载,判断入参 Decimal 对象是否大于当前对象,返回比较结果值。
参数:
返回值:
- Bool - 返回大于比较运算结果。当前对象大于入参时,返回 true,否则返回 false
operator func >=(Decimal)
public operator func >=(d: Decimal): Bool
功能:大于等于比较运算,大于等于运算符重载,判断入参 Decimal 对象是否大于等于当前对象,返回比较结果值。
参数:
返回值:
- Bool - 返回大于等于比较运算结果。当前对象大于等于入参时,返回 true,否则返回 false。
operator func /(Decimal)
public operator func /(d: Decimal): Decimal
功能:除法运算,除法运算符重载,除以入参 Decimal 对象,返回结果值。
注意:
结果为无限小数场景时,默认采用 IEEE 754-2019 decimal128 对结果进行舍入。
参数:
返回值:
异常:
- IllegalArgumentException - 当除数为 0 时,抛出此异常。
- OverflowException - 当除法结果值范围超过 [-(maxValue(precision) * (10 Int32.MAX)), maxValue(precision) * (10 Int32.MAX)] 时,抛出此异常。
示例:
import std.math.numeric.Decimal
main(): Unit {
let A = Decimal(2)
let B = Decimal(3)
let C = A / B
println("C = ${C}")
}
运行结果:
C = 0.6666666666666666666666666666666667
extend Decimal <: Formattable
extend Decimal <: Formattable
功能:为 Decimal 扩展 Formattable 接口,以实现将 Decimal 实例转换为格式化字符串。
父类型:
func format(String)
public func format(fmt: String): String
功能:根据格式化参数将当前 Decimal 类型实例格式化为对应格式的字符串。
参数:
- fmt: String - 格式化参数。
返回值:
异常:
- IllegalArgumentException - 当 fmt 不合法时抛出异常。
extend Decimal <: Number<Decimal>
extend Decimal <: Number<Decimal> {}
功能:为 Decimal 类型扩展 Number<T> 接口。
父类型:
extend Decimal <: Parsable<Decimal>
extend Decimal <: Parsable<Decimal>
功能:此扩展主要用于实现将 Decimal 类型字面量的字符串转换为 Decimal 结构体的相关操作函数。
父类型:
static func parse(String)
public static func parse(value: String): Decimal
功能:通过规定格式字符串构建 Decimal 结构体。默认采用精度值为 0,即无限精度进行构建。字符串需满足如下格式,即开头可选的符号(正号或负号),接 ValueString 字符串,再接可选的 ExponentString 字符串:
Decimal 字符串: SignString? ValueString ExponentString?
-
SignString: + | -
-
ValueString: IntegerPart.(FractionPart)? | .FractionPart | IntegerPart
-
IntegerPart:Digits
-
FractionPart:Digits
-
Digits: Digit | Digit Digits
- Digit:'0' ~ '9'
-
-
ExponentString: ExponentIndicator (SignString)? IntegerPart
- ExponentIndicator:e | E
参数:
- value: String - 规定格式字符串。
返回值:
异常:
- IllegalArgumentException - 当入参字符串不满足规定格式时,抛此异常。
- OverflowException - 当构建值标度溢出时,抛此异常。
static func tryParse(String)
public static func tryParse(value: String): ?Decimal
功能:尝试通过规定格式字符串构建 Decimal 结构体。默认采用精度值为 0,即无限精度进行构建。字符串需满足如下格式,即开头可选的符号(正号或负号),接 ValueString 字符串,再接可选的 ExponentString 字符串:
Decimal 字符串: SignString? ValueString ExponentString?
-
SignString: + | -
-
ValueString: IntegerPart.(FractionPart)? | .FractionPart | IntegerPart
-
IntegerPart:Digits
-
FractionPart:Digits
-
Digits: Digit | Digit Digits
- Digit:'0' ~ '9'
-
-
ExponentString: ExponentIndicator (SignString)? IntegerPart
- ExponentIndicator:e | E
参数:
- value: String - 规定格式字符串。
返回值:
BigInt 基础数学运算示例
以下为通过不同构造函数初始化 BigInt 对象的,并进行基础数学运算示例:
import std.math.numeric.*
main() {
let int1: BigInt = BigInt.parse("123456789")
let int2: BigInt = BigInt.parse("987654321")
println("${int1} + ${int2} = ${int1 + int2}")
println("${int1} - ${int2} = ${int1 - int2}")
println("${int1} * ${int2} = ${int1 * int2}")
println("${int1} / ${int2} = ${int1 / int2}")
let (quo, mod) = int1.divAndMod(int2)
println("${int1} / ${int2} = ${quo} .. ${mod}")
return 0
}
运行结果:
123456789 + 987654321 = 1111111110
123456789 - 987654321 = -864197532
123456789 * 987654321 = 121932631112635269
123456789 / 987654321 = 0
123456789 / 987654321 = 0 .. 123456789
BigInt 基本属性示例
以下为初始化 BigInt 对象的,并查询对象的基本属性的示例:
import std.math.numeric.*
main() {
let int = BigInt.parse("-123456")
println("BigInt: ${int}")
println("BigInt sign: ${int.sign}")
println("BigInt bitLen: ${int.bitLen}")
return 0
}
运行结果:
BigInt: -123456
BigInt sign: -1
BigInt bitLen: 18
BigInt 大小比较示例
以下为初始化多个 BigInt 对象,相互之间大小比较的示例:
import std.math.numeric.*
main() {
let int1 = BigInt.parse("123456789")
let int2 = BigInt.parse("987654321")
println("${int1} > ${int2} = ${int1 > int2}")
println("${int1} < ${int2} = ${int1 < int2}")
println("${int1} == ${int2} = ${int1 == int2}")
println("${int1} != ${int2} = ${int1 != int2}")
println("${int1} <= ${int2} = ${int1 <= int2}")
println("${int1} >= ${int2} = ${int1 >= int2}")
println("${int1}.compare(${int2}) = ${int1.compare(int2)}")
return 0
}
运行结果:
123456789 > 987654321 = false
123456789 < 987654321 = true
123456789 == 987654321 = false
123456789 != 987654321 = true
123456789 <= 987654321 = true
123456789 >= 987654321 = false
123456789.compare(987654321) = Ordering.LT
Decimal 基础数学运算示例
以下为通过不同构造函数初始化 Decimal 对象的,并进行基础数学运算示例:
import std.math.*
import std.math.numeric.*
main() {
let decimal1: Decimal = Decimal.parse("12345.6789")
let decimal2: Decimal = Decimal(BigInt.parse("987654321"), 6)
println("${decimal1} + ${decimal2} = ${decimal1 + decimal2}")
println("${decimal1} - ${decimal2} = ${decimal1 - decimal2}")
println("${decimal1} * ${decimal2} = ${decimal1 * decimal2}")
println("${decimal1} / ${decimal2} = ${decimal1 / decimal2}")
println("${decimal1} / ${decimal2} with precision 10 and rounding mode HalfEven = ${decimal1.divWithPrecision(decimal2, 10, roundingMode: HalfEven)}")
let (quo, rem) = decimal1.divAndMod(decimal2)
println("${decimal1} / ${decimal2} = ${quo} .. ${rem}")
return 0
}
运行结果:
12345.6789 + 987.654321 = 13333.333221
12345.6789 - 987.654321 = 11358.024579
12345.6789 * 987.654321 = 12193263.1112635269
12345.6789 / 987.654321 = 12.49999988609375000142382812498220
12345.6789 / 987.654321 with precision 10 and rounding mode HalfEven = 12.49999989
12345.6789 / 987.654321 = 12 .. 493.827048
Decimal 基本属性示例
以下为初始化 Decimal 对象,并查询对象的基本属性的示例:
import std.math.*
import std.math.numeric.*
main() {
let decimalProperties = Decimal.parse("-123456.7890123456789")
println("decimal: ${decimalProperties}")
println("decimal sign: ${decimalProperties.sign}")
println("decimal scale: ${decimalProperties.scale}")
println("decimal value: ${decimalProperties.value}")
println("decimal precision: ${decimalProperties.precision}")
// 如果希望初始化一个带有指定精度和舍入方式的 Decimal 对象,可以采用如下方式
let decimalProperties2 = Decimal.parse("-123456.7890123456789").roundWithPrecision(10, roundingMode: HalfEven)
println("decimal2: ${decimalProperties2}")
println("decimal2 sign: ${decimalProperties2.sign}")
println("decimal2 scale: ${decimalProperties2.scale}")
println("decimal2 value: ${decimalProperties2.value}")
println("decimal2 precision: ${decimalProperties2.precision}")
return 0
}
运行结果:
decimal: -123456.7890123456789
decimal sign: -1
decimal scale: 13
decimal value: -1234567890123456789
decimal precision: 19
decimal2: -123456.7890
decimal2 sign: -1
decimal2 scale: 4
decimal2 value: -1234567890
decimal2 precision: 10
Decimal 大小比较示例
以下为初始化多个 Decimal 对象,相互之间大小比较的示例:
import std.math.*
import std.math.numeric.*
main() {
let decimal1 = Decimal.parse("12345.6789")
let decimal2 = Decimal.parse("987.654321")
println("${decimal1} > ${decimal2} = ${decimal1 > decimal2}")
println("${decimal1} < ${decimal2} = ${decimal1 < decimal2}")
println("${decimal1} == ${decimal2} = ${decimal1 == decimal2}")
println("${decimal1} != ${decimal2} = ${decimal1 != decimal2}")
println("${decimal1} <= ${decimal2} = ${decimal1 <= decimal2}")
println("${decimal1} >= ${decimal2} = ${decimal1 >= decimal2}")
println("${decimal1}.compare(${decimal2}) = ${decimal1.compare(decimal2)}")
return 0
}
运行结果:
12345.6789 > 987.654321 = true
12345.6789 < 987.654321 = false
12345.6789 == 987.654321 = false
12345.6789 != 987.654321 = true
12345.6789 <= 987.654321 = false
12345.6789 >= 987.654321 = true
12345.6789.compare(987.654321) = Ordering.GT
std.net
功能介绍
net 包用于进行网络通信,提供启动 Socket 服务器、连接 Socket 服务器、发送数据、接收数据等功能和 IP 地址、IP前缀(又称IP子网)、Socket 地址的相关数据结构。
我们支持 UDP/TCP/UDS 三种 Socket 类型,用户可按需选用。
UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输协议,它不提供可靠性和流量控制,但是具有较低的延迟和较小的网络开销。UDP协议主要用于一些实时性要求高的应用场景,例如视频直播、在线游戏等。
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的传输协议。它提供了可靠的数据传输、流量控制、拥塞控制、错误检测和流量管理等功能,是互联网中最常用的传输协议之一。
UDS(Unix Domain Socket)是一种用于在同一台计算机上的进程之间进行通信的机制。与网络套接字不同,UDS不需要网络协议栈和网络设备,因此可以更快地进行通信,具有更低的延迟和更高的吞吐量。
如下为本库提供 Socket 的类继承关系:
Hierarchy
Resource
├StreamingSocket
│ ├TcpSocket
│ └UnixSocket
│
├DatagramSocket
│ ├UdpSocket
│ └UnixDatagramSocket
│
└ServerSocket
├TcpServerSocket
└UnixServerSocket
API 列表
接口
| 接口名 | 功能 |
|---|---|
| DatagramSocket | DatagramSocket 是一种接收和读取数据包的套接字。 |
| ServerSocket | 提供服务端的 Socket 需要的接口。 |
| StreamingSocket | 双工流模式下的运行的 Socket,可被读写。 |
类
| 类名 | 功能 |
|---|---|
| IPAddress | 此类表示Internet协议(IP)地址。 |
| IPPrefix | 这个类表示一个 IP 前缀(也称为“IP子网”),即一个连续的 IP 地址块,边界为2的幂。 |
| IPSocketAddress | 此类实现了IP协议 Socket 地址(IP地址+端口号)。 |
| IPv4Address | 此类表示 Internet 协议版本4(IPv4)地址。 |
| IPv6Address | 此类表示 Internet 协议版本6(IPv6)地址。 |
| RawSocket | RawSocket 提供了套接字的基本功能。 |
| SocketAddress | 此类表示协议无关的 Socket 地址。 |
| TcpServerSocket | 监听 TCP 连接的服务端。 |
| TcpSocket | 请求 TCP 连接的客户端。 |
| UdpSocket | 提供 udp 报文通信。 |
| UnixDatagramSocket | 提供基于数据包的主机通讯能力。 |
| UnixServerSocket | 提供基于双工流的主机通讯服务端。 |
| UnixSocket | 提供基于双工流的主机通讯客户端。 |
| UnixSocketAddress | 此类实现了 Unix Domain Socket 地址。 |
枚举
| 枚举名 | 功能 |
|---|---|
| SocketNet | 传输层协议类型。 |
结构体
| 结构体名 | 功能 |
|---|---|
| AddressFamily | 地址族用于在个别地址的使用可能不明确的上下文中标识用于网络通信的个别网络地址方案或编号计划。 |
| OptionLevel | 提供了常用的套接字选项级别。 |
| OptionName | 提供了常用的套接字选项。 |
| ProtocolType | 提供了常用的套接字协议,以及通过指定 Int32 值来构建套接字协议的功能。 |
| RawAddress | 提供了 RawSocket 的通信地址创建和获取功能。 |
| SocketDomain | 提供了常用的套接字通信域,以及通过指定 Int32 值来构建套接字通信域的功能。 |
| SocketKeepAliveConfig | TCP KeepAlive 属性配置。 |
| SocketOptions | SocketOptions 存储了设置套接字选项的一些参数常量方便后续调用。 |
| SocketType | 提供了常用的套接字类型,以及通过指定 Int32 值来构建套接字类型的功能。 |
异常类
| 异常类名 | 功能 |
|---|---|
| SocketException | 提供套接字相关的异常处理。 |
| SocketTimeoutException | 提供字符格式相关的异常处理。 |
接口
interface DatagramSocket
public interface DatagramSocket <: Resource & ToString {
prop localAddress: SocketAddress
prop remoteAddress: ?SocketAddress
mut prop receiveTimeout: ?Duration
mut prop sendTimeout: ?Duration
func receiveFrom(buffer: Array<Byte>): (SocketAddress, Int64)
func sendTo(address: SocketAddress, payload: Array<Byte>): Unit
}
功能:DatagramSocket 是一种接收和读取数据包的套接字。
一个数据包通常有有限的大小,可能为空。不同的数据包套接字类型有不同的数据包最大值。例如 UDP 套接字一次可以处理最大 64KB 的数据包。
数据包传输不是一种可靠的传输,不保证传输顺序。数据包大小在发送端决定,例如:一端发送了 10 字节和 15 字节的报文,对端将收到相同大小的对应报文,10 字节和 15 字节。
父类型:
prop localAddress
prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭或无可用的本地地址(本地地址未配置并且套接字未连接)时,抛出异常。
prop receiveTimeout
mut prop receiveTimeout: ?Duration
功能:设置和读取 receiveFrom 超时时间,无超时时间设置为 None。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
prop remoteAddress
prop remoteAddress: ?SocketAddress
功能:读取 Socket 已经连接的远端地址,当 Socket 未连接时返回 None。
类型:?SocketAddress
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop sendTimeout
mut prop sendTimeout: ?Duration
功能:设置和读取 sendTo 超时时间,默认设置为 None。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
func receiveFrom(Array<Byte>)
func receiveFrom(buffer: Array<Byte>): (SocketAddress, Int64)
功能:阻塞式等待收取报文到 buffer 中。
参数:
返回值:
- (SocketAddress, Int64) - 报文发送地址和收取到的报文大小(可能为 0,或大于参数
buffer大小)。
异常:
- SocketException - 当本机缓存过小无法读取报文时,抛出异常。
- SocketTimeoutException - 当读取超时时,抛出异常。
func sendTo(SocketAddress, Array<Byte>)
func sendTo(address: SocketAddress, payload: Array<Byte>): Unit
功能:发送报文到指定的远端地址,当对端无足够缓存时,此操作可能被阻塞,报文可能被丢弃。
参数:
- address: SocketAddress - 需要发送到的远端地址。
- payload: Array<Byte> - 需要发送的报文内容。
interface ServerSocket
public interface ServerSocket <: Resource & ToString {
prop localAddress: SocketAddress
func accept(): StreamingSocket
func accept(timeout!: ?Duration): StreamingSocket
func bind(): Unit
}
功能:提供服务端的 Socket 需要的接口。
父类型:
prop localAddress
prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
func accept()
func accept(): StreamingSocket
功能:接受一个客户端套接字的连接请求,阻塞式等待连接请求。
返回值:
- StreamingSocket - 连接成功的客户端套接字。
func accept(?Duration)
func accept(timeout!: ?Duration): StreamingSocket
功能:接受一个客户端套接字的连接请求,阻塞式等待连接请求。
参数:
- timeout!: ?Duration - 等待连接超时的时间。
返回值:
- StreamingSocket - 连接成功的客户端套接字。
异常:
- SocketTimeoutException - 当等待连接请求超时,抛出异常。
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
func bind()
func bind(): Unit
功能:绑定套接字。
当没有设置 reuse 属性,本地端口、地址、文件路径已被占用或者上次绑定套接字的连接失败后需要 close 套接字。不支持多次重试此操作后可执行 accept() 操作。
异常:
- SocketException - 当因系统原因绑定失败时,抛出异常。
interface StreamingSocket
public interface StreamingSocket <: IOStream & Resource & ToString {
prop localAddress: SocketAddress
prop remoteAddress: SocketAddress
mut prop readTimeout: ?Duration
mut prop writeTimeout: ?Duration
}
功能:双工流模式下的运行的 Socket,可被读写。
StreamingSocket 可以被绑定 (bind) 和连接 (connect),用户可以通过属性设置绑定和连接的远端和本地地址。
StreamingSocket 可以有序分包传输字节流。我们会使用一段缓存空间存储读写的字节流。读取接口 (read()) 默认在无数据到来时阻塞式等待,直到下一次数据到达,或超时。写操作 (write()) 会写入缓存中的数据并在后续被发出,如果缓存不足,或者写入速度快于转发速度,写操作将会阻塞等待缓存空闲,或超时。
读写字符始终保持有序,但不保证传输过程中的分包策略及大小与发包时一致。例如:一端发送 10 字节报文后,又发送了 15 字节报文,对端可能分别收到 10 字节 和 15 字节报文,也可能一次性收到 25 字节的一个报文。
当收到一段异常报文时,将返回报文长度为 -1 。
父类型:
prop localAddress
prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭或无可用的本地地址(本地地址未配置并且套接字未连接)时,抛出异常。
prop readTimeout
mut prop readTimeout: ?Duration
功能:设置和读取读超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
prop remoteAddress
prop remoteAddress: SocketAddress
功能:读取 Socket 将要或已经连接的远端地址。
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop writeTimeout
mut prop writeTimeout: ?Duration
功能:设置和读取写超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
类
class IPAddress
abstract sealed class IPAddress <: ToString & Equatable<IPAddress> & Hashable & BigEndianOrder<IPAddress>
功能:此类表示Internet协议(IP)地址。互联网协议地址(IP地址)是一个数字标签,例如 192.0.2.1 或 2001:0db8:0000:0000:0000:ff00:0042:8329,分配给连接到使用互联网协议进行通信的计算机网络设备。IP地址有两个主要功能:网络接口标识和位置寻址。
父类型:
prop hostName
public prop hostName: ?String
功能:返回当前 IPAddress 对象对应的主机名,如果无法成功解析,则为 None,当前暂未实现。
异常:
- UnsupportedException - 如果不是合法字符串,抛出异常。
类型:?String
prop size
public prop size: Int64
功能:获取 IP 地址对象字节长度。
类型:Int64
static func parse(String)
public static func parse(s: String): IPAddress
功能:将 IP 协议的 Socket 字符串转换为 IPAddress 对象。
参数:
- s: String - IP 协议的 Socket 字符串。
返回值:
异常:
- IllegalFormatException - 如果不是合法字符串,抛出异常。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: IPAddress = IPAddress.parse("192.168.1.2")
let v6: IPAddress = IPAddress.parse("2001:0250:1006:dff0:4913:2aa5:8075:7c10")
@Assert(v4.toString(), "192.168.1.2")
@Assert(v6.toString(), "2001:250:1006:dff0:4913:2aa5:8075:7c10")
}
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): IPAddress
功能:从字节数组中以大端序的方式读取一个 IPAddress 对象。
参数:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 IPAddress 值时,抛出异常。
返回值:
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let bufferV4: Array<Byte> = [0xC0, 0xA8, 0x1, 0x2]
let bufferV6: Array<Byte> = [0x20, 0x01, 0x02, 0x50, 0x10, 0x06, 0xdf, 0xf0, 0x49, 0x13, 0x2a, 0xa5, 0x80, 0x75, 0x7c, 0x10]
let v4: IPAddress = IPAddress.readBigEndian(bufferV4)
let v6: IPAddress = IPAddress.readBigEndian(bufferV6)
@Assert(v4.toString(), "192.168.1.2")
@Assert(v6.toString(), "2001:250:1006:dff0:4913:2aa5:8075:7c10")
}
static func resolve(AddressFamily, String)
public static func resolve(family: AddressFamily, domain: String): Array<IPAddress>
功能:解析域名,得到 IPAddress 列表。
参数:
- family: AddressFamily - 地址族。
- domain: String - 域名。
返回值:
示例:
import std.net.*
main () {
let iplist: Array<IPAddress> = IPAddress.resolve(AddressFamily.UNSPEC, "localhost")
println(iplist)
}
// may output: [127.0.0.1, ::1]
static func resolve(String)
public static func resolve(domain: String): Array<IPAddress>
功能:解析域名,得到 IPAddress 列表。
参数:
- domain: String - 域名。
返回值:
示例:
import std.net.*
main () {
let iplist: Array<IPAddress> = IPAddress.resolve("localhost")
println(iplist)
}
// may output: [127.0.0.1, ::1]
static func tryParse(String)
public static func tryParse(s: String): ?IPAddress
功能:将 IP 地址字符串转换为 IPAddress 对象,如果不是合法字符串,则返回 None。
参数:
- s: String - IP 地址字符串。
返回值:
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: ?IPAddress = IPAddress.tryParse("192.168.1.2")
let v6: ?IPAddress = IPAddress.tryParse("2001:0250:1006:dff0:4913:2aa5:8075:7c10")
@Assert(v4.toString(), "Some(192.168.1.2)")
@Assert(v6.toString(), "Some(2001:250:1006:dff0:4913:2aa5:8075:7c10)")
}
func getAddressBytes()
public func getAddressBytes(): Array<Byte>
功能:返回此 IPAddress 对象的原始IP地址。
返回值:
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let expectV4: Array<Byte> = [0xC0, 0xA8, 0x1, 0x2]
let expectV6: Array<Byte> = [0x20, 0x01, 0x02, 0x50, 0x10, 0x06, 0xdf, 0xf0, 0x49, 0x13, 0x2a, 0xa5, 0x80, 0x75, 0x7c, 0x10]
let v4: IPAddress = IPAddress.parse("192.168.1.2")
let v6: IPAddress = IPAddress.parse("2001:0250:1006:dff0:4913:2aa5:8075:7c10")
@Assert(v4.getAddressBytes(), expectV4)
@Assert(v6.getAddressBytes(), expectV6)
}
func getPrefix(UInt8)
public open func getPrefix(prefixLen: UInt8): IPPrefix
功能:此 IPAddress 地址对象根据指定的网络前缀长度创建一个网络前缀对象。
参数:
- prefixLen: UInt8 - 网络前缀长度。
异常:
- IllegalArgumentException - 如果 prefixLen 大小超出范围,抛出异常。
返回值:
- IPPrefix - 网络前缀对象。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let prefix: IPPrefix = IPAddress.parse("192.168.1.2").getPrefix(24)
@Assert(prefix.toString(), "192.168.1.2/24")
}
func hashCode()
public func hashCode(): Int64
功能:获取 hashcode 值。
返回值:
- Int64 -
hashcode值。
func isGlobalUnicast()
public open func isGlobalUnicast(): Bool
功能:判断此 IPAddress 对象是不是全局单播地址。
返回值:
- Bool - 返回 true 表示是全局单播地址,否则返回 false。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
// 2000::/3
@Assert(IPAddress.parse("2001:250:1006:dff0:4913:2aa5:8075:7c10").isGlobalUnicast(), true)
}
func isIPv4()
public func isIPv4(): Bool
功能:判断此 IPAddress 对象是不是 IPv4 地址。
返回值:
- Bool - 返回 true 表示是 IPv4 地址,否则返回 false。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
@Assert(IPAddress.parse("192.168.1.2").isIPv4(), true)
}
func isIPv6()
public func isIPv6(): Bool
功能:判断此 IPAddress 对象是不是 IPv6 地址。
返回值:
- Bool - 返回 true 表示是 IPv6 地址,否则返回 false。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
@Assert(IPAddress.parse("2001:250:1006:dff0:4913:2aa5:8075:7c10").isIPv6(), true)
}
func isLinkLocal()
public open func isLinkLocal(): Bool
功能:判断此 IPAddress 对象是不是链路本地地址。
返回值:
- Bool - 返回 true 表示是链路本地地址,否则返回 false。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
// 169.254.0.0 ~ 169.254.255.255
@Assert(IPAddress.parse("169.254.0.1").isLinkLocal(), true)
// fe80::/10
@Assert(IPAddress.parse("fe80::1").isLinkLocal(), true)
}
func isLoopback()
public open func isLoopback(): Bool
功能:判断此 IPAddress 对象是不是环回地址。
返回值:
- Bool - 返回 true 表示是环回地址,否则返回 false。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
@Assert(IPAddress.parse("127.0.0.1").isLoopback(), true)
@Assert(IPAddress.parse("::1").isLoopback(), true)
}
func isMulticast()
public open func isMulticast(): Bool
功能:判断此 IPAddress 对象是不是多播地址。
返回值:
- Bool - 返回 true 表示是多播地址,否则返回 false。
func isPrivate()
public open func isPrivate(): Bool
功能:判断此 IPAddress 对象是不是私有地址。
返回值:
- Bool - 返回 true 表示是私有地址,否则返回 false。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
// 10.0.0.0 ~ 10.255.255.255
@Assert(IPAddress.parse("10.0.0.1").isPrivate(), true)
// 172.16.0.0 ~ 172.31.255.255
@Assert(IPAddress.parse("172.16.0.1").isPrivate(), true)
// 192.168.0.0 ~192.168.255.255
@Assert(IPAddress.parse("192.168.0.1").isPrivate(), true)
// fc00::/7
@Assert(IPAddress.parse("fc00::1").isPrivate(), true)
}
func isUnspecified()
public open func isUnspecified(): Bool
功能:判断此 IPAddress 对象是不是“未指定” IP 地址。
返回值:
- Bool - 返回 true 表示是“未指定” IP 地址,否则返回 false。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
@Assert(IPAddress.parse("0.0.0.0").isUnspecified(), true)
@Assert(IPAddress.parse("::").isUnspecified(), true)
}
func writeBigEndian(Array<Byte>)
public open func writeBigEndian(buffer: Array<Byte>): Int64
功能:返回此 IPAddress 对象以大端序的方式写入字节数组中。
参数:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以写入 IPv4Address 或 IPv6Address 值时,抛出异常。
返回值:
- Int64 - 写入的数据的字节数。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let buffer = Array<Byte>(128, repeat: 0)
let expectV4: Array<Byte> = [0xC0, 0xA8, 0x1, 0x2]
let expectV6: Array<Byte> = [0x20, 0x01, 0x02, 0x50, 0x10, 0x06, 0xdf, 0xf0, 0x49, 0x13, 0x2a, 0xa5, 0x80, 0x75, 0x7c, 0x10]
let v4: IPAddress = IPAddress.parse("192.168.1.2")
let v6: IPAddress = IPAddress.parse("2001:0250:1006:dff0:4913:2aa5:8075:7c10")
var len = v4.writeBigEndian(buffer)
@Assert(buffer[..len], expectV4)
len = v6.writeBigEndian(buffer)
@Assert(buffer[..len], expectV6)
}
operator func ==(IPAddress)
public operator func ==(rhs: IPAddress): Bool
功能:判断两个 IPAddress 对象是否相等。
参数:
返回值:
operator func !=(IPAddress)
public operator func !=(rhs: IPAddress): Bool
功能:判断两个 IPAddress 对象是否不等。
参数:
返回值:
class IPPrefix
abstract sealed class IPPrefix <: Equatable<IPPrefix> & Hashable & ToString
功能:这个类表示一个 IP 前缀,即一个连续的 IP 地址块,边界为2的幂(也称为“IP子网”)。
一个 IP 前缀由两条信息指定:
- 起始IP地址(IPv4或IPv6)。这是前缀的第一个IP地址。
- 前缀长度。这通过指定IP地址中的位数来指定前缀的长度,从网络字节顺序中的最高有效位开始,对于前缀中的所有地址都是恒定的。
例如,前缀 192.0.2.0/24 涵盖从192.0.2.0到192.0.2.255(含)的256个IPv4地址,前缀2001:db8:1:2涵盖从2001:db8:1:2:: 到 2001:db8:1:2:ffff:ffff:ffff:ffff(含)的2^64个IPv6地址。这个类的对象是不可变的。
父类型:
prop address
public prop address: IPAddress
功能:获取构造当前 IPPrefix 对象时的 IPAddress 地址。
类型:IPAddress
prop prefixLength
public prop prefixLength: UInt8
功能:获取前缀长度。
类型:UInt8
static func parse(String)
public static func parse(s: String): IPPrefix
功能:将 IP 协议的 Socket 字符串转换为 IPPrefix 对象。
参数:
- s: String - IP 协议的 Socket 字符串。
异常:
- IllegalFormatException - 如果不是合法字符串,抛出异常。
返回值:
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: IPPrefix = IPPrefix.parse("192.168.1.2/24")
let v6: IPPrefix = IPPrefix.parse("2001:0250:1006:dff0:4913:2aa5:8075:7c10/32")
@Assert(v4.toString(), "192.168.1.2/24")
@Assert(v6.toString(), "2001:250:1006:dff0:4913:2aa5:8075:7c10/32")
}
static func tryParse(String)
public static func tryParse(s: String): ?IPPrefix
功能:将 IP 协议的 Socket 字符串转换为 IPPrefix 对象,如果不是合法字符串,则返回 None。
参数:
- s: String - IP 协议的 Socket 字符串。
返回值:
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: ?IPPrefix = IPPrefix.tryParse("192.168.1.2/24")
let v6: ?IPPrefix = IPPrefix.tryParse("2001:0250:1006:dff0:4913:2aa5:8075:7c10/32")
@Assert(v4.toString(), "Some(192.168.1.2/24)")
@Assert(v6.toString(), "Some(2001:250:1006:dff0:4913:2aa5:8075:7c10/32)")
}
func broadcast()
public open func broadcast(): IPAddress
功能:返回此 IPPrefix 地址的广播地址。
返回值:
func contains(IPAddress)
public func contains(rhs: IPAddress): Bool
功能:此 IPPrefix 地址是不是包含指定的 IPAddress 地址。
参数:
返回值:
func contains(IPPrefix)
public func contains(rhs: IPPrefix): Bool
功能:此 IPPrefix 地址是不是包含指定的 IPPrefix 地址。
参数:
返回值:
func hostmask()
public open func hostmask(): IPAddress
功能:返回此 IPPrefix 地址的主机网络掩码地址。
返回值:
func masked()
public open func masked(): IPPrefix
功能:返回此 IPPrefix 地址根据前缀长度进行掩码后的 IPPrefix 地址,比如 192.168.12.34/16 返回 192.168.0.0/16; fc00::1:2:3:4/16 返回 fc00::/16。
返回值:
func netmask()
public open func netmask(): IPAddress
功能:返回此 IPPrefix 地址的网络掩码地址。
返回值:
func network()
public open func network(): IPAddress
功能:返回此 IPPrefix 地址的网络地址。
返回值:
func overlaps(IPPrefix)
public func overlaps(rhs: IPPrefix): Bool
功能:此 IPPrefix 地址是不是和指定的 IPPrefix 地址有重叠。
参数:
返回值:
func toString()
public func toString(): String
功能:返回当前 IPPrefix 的文本表示字符串。
返回值:
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: IPPrefix = IPAddress.parse("192.168.1.2").getPrefix(24)
let v6: IPPrefix = IPAddress.parse("2001:0250:1006:dff0:4913:2aa5:8075:7c10").getPrefix(32)
@Assert(v4.toString(), "192.168.1.2/24")
@Assert(v6.toString(), "2001:250:1006:dff0:4913:2aa5:8075:7c10/32")
}
operator func ==(IPPrefix)
public operator func ==(rhs: IPPrefix): Bool
功能:判断两个 IPPrefix 对象是否相等。
参数:
返回值:
operator func !=(IPPrefix)
public operator func !=(rhs: IPPrefix): Bool
功能:判断两个 IPPrefix 对象是否不等。
参数:
返回值:
class IPSocketAddress
public class IPSocketAddress <: SocketAddress & Equatable<IPSocketAddress>{
public init(address: Array<Byte>, port: UInt16)
public init(address: String, port: UInt16)
public init(address: IPAddress, port: UInt16)
}
功能:此类实现了IP协议 Socket 地址(IP地址+端口号)。它提供了一个不可变的对象,用于 Socket 的绑定、连接或作为返回值。
父类型:
prop address
public prop address: IPAddress
功能:获取当前 IPSocketAddress 对象的 IP 地址。
类型:IPAddress
prop family
public prop family: AddressFamily
功能:获取当前 IPSocketAddress 对象的地址族。
prop port
public prop port: UInt16
功能:获取当前 IPSocketAddress 对象的端口。
类型:UInt16
prop size
public prop size: Int64
功能:获取当前 IPSocketAddress 对象的原始字节长度。
类型:Int64
init(Array<Byte>, UInt16)
public init(address: Array<Byte>, port: UInt16)
功能:根据大端序 Array<Byte> 表示的 IP 地址和本机序 UInt16 端口构造 IPSocketAddress 地址。
参数:
异常:
- IllegalArgumentException - 如果 address 不合法,抛出异常。
init(String, UInt16)
public init(address: String, port: UInt16)
功能:根据字符串表示的 IP 地址和 本机序 UInt16 端口构造 IPSocketAddress 地址。
参数:
异常:
- IllegalFormatException - 如果传入的 IP 地址不合法,抛出异常。
init(IPAddress, UInt16)
public init(address: IPAddress, port: UInt16)
功能:根据 IPAddress 对象和 本机序 UInt16 端口构造 IPSocketAddress 地址。
参数:
static func parse(String)
public static func parse(s: String): IPSocketAddress
功能:将 IP 协议的 Socket 字符串转换为 IPSocketAddress 对象。
参数:
- s: String - IP 协议的 Socket 字符串。
返回值:
异常:
- IllegalFormatException - 入参需要是合法的socket地址,比如 192.168.0.0:80 或 [fc00::1]:8080,否则抛出异常。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: IPSocketAddress = IPSocketAddress.parse("192.168.1.2:8080")
let v6: IPSocketAddress = IPSocketAddress.parse("[2001:0250:1006:dff0:4913:2aa5:8075:7c10]:8080")
@Assert(v4.address.toString(), "192.168.1.2")
@Assert(v4.port, 8080u16)
@Assert(v6.address.toString(), "2001:250:1006:dff0:4913:2aa5:8075:7c10")
@Assert(v6.port, 8080u16)
@Assert(v4.toString(), "192.168.1.2:8080")
@Assert(v6.toString(), "[2001:250:1006:dff0:4913:2aa5:8075:7c10]:8080")
}
static func tryParse(String)
public static func tryParse(s: String): ?IPSocketAddress
功能:将 IP 协议的 Socket 字符串转换为 IPSocketAddress 对象,如果不是合法字符串,则返回 None。
参数:
- s: String - IP 协议的 Socket 字符串。
返回值:
- ?IPSocketAddress - ?IPSocketAddress 对象。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: ?IPSocketAddress = IPSocketAddress.tryParse("192.168.1.2:8080")
let v6: ?IPSocketAddress = IPSocketAddress.tryParse("[2001:0250:1006:dff0:4913:2aa5:8075:7c10]:8080")
@Assert(v4.toString(), "Some(192.168.1.2:8080)")
@Assert(v6.toString(), "Some([2001:250:1006:dff0:4913:2aa5:8075:7c10]:8080)")
}
func getAddressBytes()
public func getAddressBytes(): Array<Byte>
功能:返回此 IPSocketAddress 对象的原始地址的 Array<Byte> 表示,内容布局与 sockaddr_in 或 sockaddr_in6 一致。
返回值:
- Array<Byte> - IPSocketAddress 对象的原始地址的 Array<Byte> 表示。
func hashCode()
public func hashCode(): Int64
功能:获取 hashcode 值。
返回值:
- Int64 -
hashcode值。
func isIPv4()
public func isIPv4(): Bool
功能:判断此 IPSocketAddress 对象是不是 IPv4 Socket 地址。
返回值:
- Bool - 返回 true 表示是 IPv4 地址,否则返回 false。
func isIPv6()
public func isIPv6(): Bool
功能:判断此 IPSocketAddress 对象是不是 IPv6 Socket 地址。
返回值:
- Bool - 返回 true 表示是 IPv6 地址,否则返回 false。
func toString()
public func toString(): String
功能:返回当前 IPSocketAddress 的文本表示字符串。
返回值:
- String - 当前 IPSocketAddress 的文本表示字符串,比如
192.168.1.2:8080或[fc00::/16]:8080。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let v4: IPSocketAddress = IPSocketAddress.parse("192.168.1.2:8080")
let v6: IPSocketAddress = IPSocketAddress.parse("[2001:0250:1006:dff0:4913:2aa5:8075:7c10]:8080")
@Assert(v4.toString(), "192.168.1.2:8080")
@Assert(v6.toString(), "[2001:250:1006:dff0:4913:2aa5:8075:7c10]:8080")
}
operator func ==(IPSocketAddress)
public operator func ==(rhs: IPSocketAddress): Bool
功能:判断两个 IPSocketAddress 对象是否相等。
参数:
- rhs: IPSocketAddress - 参与比较的 IPSocketAddress 对象。
返回值:
- Bool - 如果两个 IPSocketAddress 对象相等,则返回
true;否则,返回false。
operator func !=(IPSocketAddress)
public operator func !=(rhs: IPSocketAddress): Bool
功能:判断两个 IPSocketAddress 对象是否不等。
参数:
- rhs: IPSocketAddress - 参与比较的 IPSocketAddress 对象。
返回值:
- Bool - 如果两个 IPSocketAddress 对象不等,则返回
true;否则,返回false。
class IPv4Address
public class IPv4Address <: IPAddress & ToString & Equatable<IPv4Address> & LessOrEqual<IPv4Address> {
public static let broadcast = IPv4Address(0xFF, 0xFF, 0xFF, 0xFF)
public static let localhost = IPv4Address(0x7F, 0, 0, 0x01)
public static let unspecified = IPv4Address(0, 0, 0, 0)
public init(bits: UInt32)
public init(a: Byte, b: Byte, c: Byte, d: Byte)
}
功能:此类表示 Internet 协议版本4 (IPv4)地址。由 RFC 790、RFC 1918 和 RFC 2365 定义。
父类型:
static let broadcast
public static let broadcast = IPv4Address(0xFF, 0xFF, 0xFF, 0xFF)
功能:返回 IPv4Address 的广播地址:255.255.255.255。
类型:IPv4Address
static let localhost
public static let localhost = IPv4Address(0x7F, 0, 0, 0x01)
功能:返回 IPv4Address 的 localhost 地址:127.0.0.1。
类型:IPv4Address
static let unspecified
public static let unspecified = IPv4Address(0, 0, 0, 0)
功能:返回表示未指定的 IPv4Address 地址:0.0.0.0,这对应于其他语言中的常量 INADDR_ANY。
类型:IPv4Address
init(UInt32)
public init(bits: UInt32)
功能:根据本机字节序 UInt32 值构造 IPv4Address 地址。
参数:
init(Byte, Byte, Byte, Byte)
public init(a: Byte, b: Byte, c: Byte, d: Byte)
功能:根据4 个 8-bit 字节构造 IPv4Address 地址对象,文本将表示为 a.b.c.d。
参数:
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): IPv4Address
功能:从字节数组中以大端序的方式读取一个 IPv4Address 对象。
参数:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 IPv4Address 值时,抛出异常。
返回值:
- IPv4Address - IPv4Address 对象。
func getPrefix(UInt8)
public func getPrefix(prefixLen: UInt8): IPPrefix
功能:将 IPv4Address 地址根据指定的网络前缀长度创建一个网络前缀对象。
参数:
- prefixLen: UInt8 - 网络前缀长度,必须 >= 0 且 <= 32。
异常:
- IllegalArgumentException - 如果 prefixLen 大小超出范围,抛出异常。
返回值:
- IPPrefix - 网络前缀对象。
func isBroadcast()
public func isBroadcast(): Bool
功能:判断此 IPv4Address 对象是不是广播地址。
返回值:
- Bool - 返回 true 表示是广播地址,否则返回 false。
func isGlobalUnicast()
public func isGlobalUnicast(): Bool
功能:判断此 IPv4Address 对象是不是全局单播地址。
返回值:
- Bool - 返回 true 表示是全局单播地址,否则返回 false。
func isLinkLocal()
public func isLinkLocal(): Bool
功能:判断此 IPv4Address 对象是不是链路本地地址。
返回值:
- Bool - 返回 true 表示是链路本地地址,否则返回 false。
func isLoopback()
public func isLoopback(): Bool
功能:判断此 IPv4Address 对象是不是环回地址。
返回值:
- Bool - 返回 true 表示是环回地址,否则返回 false。
func isMulticast()
public func isMulticast(): Bool
功能:判断此 IPv4Address 对象是不是多播地址。
返回值:
- Bool - 返回 true 表示是多播地址,否则返回 false。
func isPrivate()
public func isPrivate(): Bool
功能:判断此 IPv4Address 对象是不是私有地址。
返回值:
- Bool - 返回 true 表示是私有地址,否则返回 false。
func isUnspecified()
public func isUnspecified(): Bool
功能:判断此 IPv4Address 对象是不是“未指定” IP 地址。
返回值:
- Bool - 返回 true 表示是“未指定” IP 地址,否则返回 false。
func toBits()
public func toBits(): UInt32
功能:此 IPv4Address 地址转换为本机字节序的 UInt32 值。
返回值:
func toIPv6Compatible()
public func toIPv6Compatible(): IPv6Address
功能:此 IPv4Address 地址转换为 IPv4 兼容的 IPv6Address 地址。a.b.c.d 变为 ::a.b.c.d。
返回值:
- IPv6Address - IPv6Address 对象。
func toIPv6Mapped()
public func toIPv6Mapped(): IPv6Address
功能:此 IPv4Address 地址转换为 IPv4 映射的 IPv6Address 地址。a.b.c.d 变为 ::ffff:a.b.c.d。
返回值:
- IPv6Address - IPv6Address 对象。
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:此 IPv4Address 对象以大端序的方式写入字节数组中。
参数:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以写入 IPv4Address 值时,抛出异常。
返回值:
- Int64 - 写入的数据的字节数。
func toString()
public func toString(): String
功能:返回当前 IPv4Address 的文本表示字符串。
返回值:
- String - 当前 IPv4Address 的文本表示字符串,比如
a.b.c.d。
operator func <=(IPv4Address)
public operator func <=(rhs: IPv4Address): Bool
功能:判断本 IPv4Address 对象是否小于等于被比较的 IPv4Address 对象。
参数:
- rhs: IPv4Address - 被比较的 IPv4Address 对象。
返回值:
- Bool - 如果本 IPv4Address 对象小于等于被比较的 IPv4Address 对象,则返回
true;否则,返回false。
operator func ==(IPv4Address)
public operator func ==(rhs: IPv4Address): Bool
功能:判断两个 IPv4Address 对象是否相等。
参数:
- rhs: IPv4Address - 参与比较的 IPv4Address 对象。
返回值:
- Bool - 如果两个 IPv4Address 对象相等,则返回
true;否则,返回false。
operator func !=(IPv4Address)
public operator func !=(rhs: IPv4Address): Bool
功能:判断两个 IPv4Address 对象是否不等。
参数:
- rhs: IPv4Address - 参与比较的 IPv4Address 对象。
返回值:
- Bool - 如果两个 IPv4Address 对象不等,则返回
true;否则,返回false。
class IPv6Address
public class IPv6Address <: IPAddress & ToString & Equatable<IPv6Address> & LessOrEqual<IPv6Address> {
public static let localhost = IPv6Address(0u16, 0, 0, 0, 0, 0, 0, 1)
public static let unspecified = IPv6Address(0u16, 0, 0, 0, 0, 0, 0, 0)
public init(octets: Array<Byte>, scopeId!: ?UInt32 = None)
public init(a: UInt16, b: UInt16, c: UInt16, d: UInt16, e: UInt16, f: UInt16, g: UInt16, h: UInt16, scopeId!: ?UInt32 = None)
}
功能:此类表示 Internet 协议版本6 (IPv6)地址。由 RFC4291、RFC5952、RFC4007 定义。
父类型:
static let localhost
public static let localhost = IPv6Address(0u16, 0, 0, 0, 0, 0, 0, 1)
功能:返回 IPv6Address 的 localhost 地址:::1。
类型:IPv6Address
static let unspecified
public static let unspecified = IPv6Address(0u16, 0, 0, 0, 0, 0, 0, 0)
功能:返回表示未指定的 IPv6Address 地址:::,这对应于其他语言中的常量 INADDR_ANY。
类型:IPv6Address
prop scopeId
public prop scopeId: ?UInt32
功能:获取默认范围 ID。
init(Array<Byte>, ?UInt32)
public init(octets: Array<Byte>, scopeId!: ?UInt32 = None)
功能:根据大端序 Array<Byte> 构造 IPv6Address 地址。
异常:
- IllegalArgumentException - 如果 octets 长度小于 16,抛出异常。
参数:
init(UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, ?UInt32)
public init(a: UInt16, b: UInt16, c: UInt16, d: UInt16, e: UInt16, f: UInt16, g: UInt16, h: UInt16, scopeId!: ?UInt32 = None)
功能:根据 8 个 16-bit 分段构造 IPv6Address 地址对象,文本将表示为 a:b:c:d:e:f:g:h%scopeId。
参数:
- a: UInt16 - 16-bit 分段。
- b: UInt16 - 16-bit 分段。
- c: UInt16 - 16-bit 分段。
- d: UInt16 - 16-bit 分段。
- e: UInt16 - 16-bit 分段。
- f: UInt16 - 16-bit 分段。
- g: UInt16 - 16-bit 分段。
- h: UInt16 - 16-bit 分段。
- scopeId!: ?UInt32 - 范围 ID。
static func readBigEndian(Array<Byte>)
public static func readBigEndian(buffer: Array<Byte>): IPv6Address
功能:从字节数组中以大端序的方式读取一个 IPv6Address 对象。
参数:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以读出 IPv6Address 值时,抛出异常。
返回值:
- IPv6Address - IPv6Address 对象。
func getPrefix(UInt8)
public func getPrefix(prefixLen: UInt8): IPPrefix
功能:此 IPv6Address 地址对象根据指定的网络前缀长度创建一个网络前缀对象。
参数:
- prefixLen: UInt8 - 网络前缀长度,必须 >= 0 且 <= 128。
异常:
- IllegalArgumentException - 如果 prefixLen 大小超出范围,抛出异常。
返回值:
- IPPrefix - 网络前缀对象。
func isGlobalUnicast()
public func isGlobalUnicast(): Bool
功能:判断此 IPv6Address 对象是不是全局单播地址。
返回值:
- Bool - 返回 true 表示是全局单播地址,否则返回 false。
func isIPv4Mapped()
public func isIPv4Mapped(): Bool
功能:判断此 IPv6Address 对象是不是 IPv4 映射地址。
返回值:
- Bool - 返回 true 表示是 IPv4 映射地址,否则返回 false。
func isLinkLocal()
public func isLinkLocal(): Bool
功能:判断此 IPv6Address 对象是不是链路本地地址。
返回值:
- Bool - 返回 true 表示是链路本地地址,否则返回 false。
func isLoopback()
public func isLoopback(): Bool
功能:判断此 IPv6Address 对象是不是环回地址。
返回值:
- Bool - 返回 true 表示是环回地址,否则返回 false。
func isMulticast()
public func isMulticast(): Bool
功能:判断此 IPv6Address 对象是不是多播地址。
返回值:
- Bool - 返回 true 表示是多播地址,否则返回 false。
func isPrivate()
public func isPrivate(): Bool
功能:判断此 IPv6Address 对象是不是私有地址。
返回值:
- Bool - 返回 true 表示是私有地址,否则返回 false。
func isTeredo()
public func isTeredo(): Bool
功能:判断此 IPv6Address 对象是不是 Teredo 地址。Teredo 前缀为 2001::/32。
返回值:
- Bool - 返回 true 表示是
Teredo地址,否则返回 false。
func isUnspecified()
public func isUnspecified(): Bool
功能:判断此 IPv6Address 对象是不是“未指定” IP 地址。
返回值:
- Bool - 返回 true 表示是“未指定” IP 地址,否则返回 false。
func scope(?UInt32)
public func scope(scopeId: ?UInt32): IPv6Address
功能:使用本 IPv6Address 对象的地址值和指定的范围 ID 转换为新的 IPv6Address 对象,如果指定的范围 ID 为 None,则去除已有的范围 ID。
参数:
- scopeId: ?UInt32 - 范围 ID。
返回值:
- IPv6Address - 转换后的 IPv6Address 对象。
func toIPv4()
public func toIPv4(): ?IPv4Address
功能:此 IPv6Address 地址转换为 IPv4 兼容的 IPv4Address 地址。比如 ::a.b.c.d 和 ::ffff:a.b.c.d 转成 a.b.c.d; ::1 转成 0.0.0.1. 所有不以全零或 ::ffff 开头的地址将返回 None。
返回值:
- ?IPv4Address - ?IPv4Address 值。
func toIPv4Mapped()
public func toIPv4Mapped(): ?IPv4Address
功能:此 IPv6Address 地址转换为 IPv4 映射的 IPv4Address 地址。比如 ::ffff:a.b.c.d 转换为 a.b.c.d, 所有不以 ::ffff 开头的地址将返回 None。
返回值:
- ?IPv4Address - ?IPv4Address 值。
func writeBigEndian(Array<Byte>)
public func writeBigEndian(buffer: Array<Byte>): Int64
功能:返回此 IPv6Address 对象以大端序的方式写入字节数组中。
参数:
异常:
- IllegalArgumentException - 当 buffer 太小,不足以写入 IPv6Address 值时,抛出异常。
返回值:
- Int64 - 写入的数据的字节数。
func toString()
public func toString(): String
功能:返回当前 IPv6Address 的文本表示字符串。
返回值:
- String - 当前 IPv6Address 的文本表示字符串,比如
2001:db8:1:2:ffff:ffff:ffff:ffff。
operator func <=(IPv6Address)
public operator func <=(rhs: IPv6Address): Bool
功能:判断本 IPv6Address 对象是否小于等于被比较的 IPv6Address 对象。
参数:
- rhs: IPv6Address - 参与比较的 IPv6Address 对象。
返回值:
- Bool - 如果本 IPv6Address 对象小于等于被比较的 IPv6Address 对象,则返回
true;否则,返回false。
operator func ==(IPv6Address)
public operator func ==(rhs: IPv6Address): Bool
功能:判断两个 IPv6Address 对象是否相等。
参数:
- rhs: IPv6Address - 参与比较的 IPv6Address 对象。
返回值:
- Bool - 如果两个 IPv6Address 对象相等,则返回
true;否则,返回false。
operator func !=(IPv6Address)
public operator func !=(rhs: IPv6Address): Bool
功能:判断两个 IPv6Address 对象是否不等。
参数:
- rhs: IPv6Address - 参与比较的 IPv6Address 对象。
返回值:
- Bool - 如果两个 IPv6Address 对象不等,则返回
true;否则,返回false。
class RawSocket
public class RawSocket {
public init(domain: SocketDomain, `type`: SocketType, protocol: ProtocolType)
}
功能:RawSocket 提供了套接字的基本功能。
可以访问特定通信域(domain)、类型(type)和协议(protocol)组合的套接字。Socket 包已经提供了 TCP、 UDP 等常用网络协议的支持,因此,该类型适用于其他类型的网络编程需求。
注意:
- 当前 RawSocket 已经验证的功能包括 TCP、UDP、UDS 以及 ICMP 协议套接字,其他类型使用上可能存在预期之外的问题。
- 此外,由于接口的开放性,可以使用
connect再listen的组合,部分场景可能存在预期外的问题。建议开发者使用时遵循正常的调用逻辑,避免产生问题。
prop localAddr (deprecated)
public prop localAddr: RawAddress
功能:获取当前 RawSocket 实例的本地地址。
注意:
未来版本即将废弃不再使用,使用 localAddress 替代。
类型:RawAddress
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或无法获取本地地址时,抛出异常。
prop localAddress
public prop localAddress: RawAddress
功能:获取当前 RawSocket 实例的本地地址。
类型:RawAddress
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或无法获取本地地址时,抛出异常。
prop readTimeout
public mut prop readTimeout: ?Duration
功能:获取或设置当前 RawSocket 实例的读超时时间。
类型:?Duration
异常:
- SocketException - 当前 RawSocket 实例已经关闭时,抛出异常。
- IllegalArgumentException - 当设置的读超时时间为负时,抛出异常。
prop remoteAddr (deprecated)
public prop remoteAddr: RawAddress
功能:获取当前 RawSocket 实例的对端地址。
注意:
未来版本即将废弃不再使用,使用 remoteAddress 替代。
类型:RawAddress
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或无法获取对端地址时,抛出异常。
prop remoteAddress
public prop remoteAddress: RawAddress
功能:获取当前 RawSocket 实例的对端地址。
类型:RawAddress
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或无法获取对端地址时,抛出异常。
prop writeTimeout
public mut prop writeTimeout: ?Duration
功能:获取或设置当前 RawSocket 实例的写超时时间。
类型:?Duration
异常:
- SocketException - 当前 RawSocket 实例已经关闭时,抛出异常。
- IllegalArgumentException - 当设置的写超时时间为负时,抛出异常。
init(SocketDomain, SocketType, ProtocolType)
public init(domain: SocketDomain, `type`: SocketType, protocol: ProtocolType)
功能:创建特定通信域、类型、协议组合的套接字。
参数:
- domain: SocketDomain - 通信域。
- `type`: SocketType - 套接字类型。
- protocol: ProtocolType - 协议类型。
异常:
- SocketException - 当通信域、类型、协议组合无法创建套接字时,抛出异常。
func accept(?Duration)
public func accept(timeout!: ?Duration = None): RawSocket
功能:接收当前 RawSocket 实例监听时挂起连接队列上的第一个连接请求,返回一个用于通信的 RawSocket。
参数:
- timeout!: ?Duration - 等待连接请求的最大时间,默认值
None表示一直等待。
返回值:
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或接收失败时,抛出异常。
- SocketTimeoutException - 当等待超时时,抛出异常。
func bind(RawAddress)
public func bind(addr: RawAddress): Unit
功能:将当前 RawSocket 实例与指定的套接字地址进行绑定。
参数:
- addr: RawAddress - 套接字地址。
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或绑定失败时,抛出异常。
func close()
public func close(): Unit
功能:关闭当前 RawSocket 实例。
func connect(RawAddress, ?Duration)
public func connect(addr: RawAddress, timeout!: ?Duration = None): Unit
功能:向目标地址发送连接请求。
参数:
- addr: RawAddress - 发送连接请求的目标地址。
- timeout!: ?Duration - 等待连接接收的最大时间,默认值
None表示一直等待。
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或接收失败时,抛出异常。
- SocketTimeoutException - 当等待超时时,抛出异常。
func getSocketOption(Int32, Int32, CPointer<Byte>, CPointer<Int32>)
public unsafe func getSocketOption(level: Int32, option: Int32, value: CPointer<Byte>, len: CPointer<Int32>): Unit
功能:获取套接字选项的值。
参数:
- level: Int32 - 套接字选项级别。
- option: Int32 - 套接字选项名。
- value: CPointer<Byte> - 套接字选项值。
- len: CPointer<Int32> - 套接字选项值的长度。
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或获取套接字选项失败时,抛出异常。
func listen(Int32)
public func listen(backlog: Int32): Unit
功能:监听当前 RawSocket 实例绑定的地址。
参数:
- backlog: Int32 - 等待队列增长的最大长度。
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或监听失败时,抛出异常。
func receive(Array<Byte>, Int32)
public func receive(buffer: Array<Byte>, flags: Int32): Int64
功能:接收来自连接对端发送的数据。
参数:
返回值:
- Int64 - 数据长度。
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或接收数据失败时,抛出异常。
- SocketTimeoutException - 当超过指定的读超时时间时,抛出异常。
func receiveFrom(Array<Byte>, Int32)
public func receiveFrom(buffer: Array<Byte>, flags: Int32): (RawAddress, Int64)
功能:接收来自其他 RawSocket 实例的数据。
参数:
返回值:
- (RawAddress, Int64) - 数据来源的地址和数据长度。
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或接收数据失败时,抛出异常。
- SocketTimeoutException - 当超过指定的读超时时间时,抛出异常。
func send(Array<Byte>, Int32)
public func send(buffer: Array<Byte>, flags: Int32): Unit
功能:向连接的对端发送数据。
参数:
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或发送数据失败时,抛出异常。
- SocketTimeoutException - 当超过指定的写超时时间时,抛出异常。
func sendTo(RawAddress, Array<Byte>, Int32)
public func sendTo(addr: RawAddress, buffer: Array<Byte>, flags: Int32): Unit
功能:向目标地址发送数据。若 RawSocket 是 DATAGRAM 类型,发送的数据包大小不允许超过 65507 字节。
参数:
- addr: RawAddress - 发送数据的目标地址。
- buffer: Array<Byte> - 数据。
- flags: Int32 - 指定函数行为的标志。
异常:
- SocketException - 当前 RawSocket 实例已经关闭、发送数据失败或者 macOS 平台下
connect被调用后调用sendTo时,抛出异常。 - SocketTimeoutException - 当超过指定的写超时时间时,抛出异常。
func setSocketOption(Int32, Int32, CPointer<Byte>, Int32)
public unsafe func setSocketOption(level: Int32, option: Int32, value: CPointer<Byte>, len: Int32): Unit
功能:设置套接字选项。
参数:
- level: Int32 - 套接字选项级别。
- option: Int32 - 套接字选项名。
- value: CPointer<Byte> - 套接字选项值。
- len: Int32 - 套接字选项值的长度。
异常:
- SocketException - 当前 RawSocket 实例已经关闭,或设置套接字选项失败时,抛出异常。
class SocketAddress
abstract sealed class SocketAddress <: ToString & Equatable<SocketAddress> & Hashable
功能:此类表示协议无关的 Socket 地址。它提供了一个不可变的对象,用于 Socket 的绑定、连接或作为返回值。
父类型:
prop size
public prop size: Int64
功能:当前 SocketAddress 对象的原始字节长度。
类型:Int64
prop family
public prop family: AddressFamily
功能:当前 SocketAddress 对象的地址族。
func getAddressBytes()
public func getAddressBytes(): Array<Byte>
功能:返回此 SocketAddress 对象的原始IP地址。
返回值:
operator func ==(SocketAddress)
public operator func ==(rhs: SocketAddress): Bool
功能:判断两个 SocketAddress 对象是否相等。
参数:
- rhs: SocketAddress - 参与比较的 SocketAddress 对象。
返回值:
- Bool - 如果两个 SocketAddress 对象相等,则返回
true;否则,返回false。
operator func !=(SocketAddress)
public operator func !=(rhs: SocketAddress): Bool
功能:判断两个 SocketAddress 对象是否不等。
参数:
- rhs: SocketAddress - 参与比较的 SocketAddress 对象。
返回值:
- Bool - 如果两个 SocketAddress 对象不等,则返回
true;否则,返回false。
class TcpServerSocket
public class TcpServerSocket <: ServerSocket {
public init(bindAt!: SocketAddress)
public init(bindAt!: UInt16)
}
功能:监听 TCP 连接的服务端。
套接字被创建后,可通过属性和 setSocketOptionXX 接口配置属性。
启动监听需要调用 bind() 将套接字绑定到本地端口。accept() 接口将接受 TCP 连接,阻塞等待连接,若队列中已有连接,则可立即返回。
套接字需要通过 close 显式关闭。
父类型:
prop backlogSize
public mut prop backlogSize: Int64
功能:设置和读取 backlog 大小。
仅可在调用 bind 前调用,否则将抛出异常。
变量是否生效取决于系统行为。
类型:Int64
异常:
- SocketException - 当在
bind后调用时,抛出异常。
prop bindToDevice
public mut prop bindToDevice: ?String
功能:设置和读取绑定网卡。
类型:?String
prop localAddress
public override prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop receiveBufferSize
public mut prop receiveBufferSize: Int64
功能:设置和读取 SO_RCVBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop reuseAddress
public mut prop reuseAddress: Bool
功能:设置和读取 SO_REUSEADDR 属性,默认设置为 true。
属性生效后的行为取决于系统,使用前,请参阅不同系统针对此属性 SO_REUSEADDR/SOCK_REUSEADDR 的说明文档。
类型:Bool
prop reusePort
public mut prop reusePort: Bool
功能:设置和读取 SO_REUSEPORT 属性。
仅可在绑定前被修改。Windows 上可使用 SO_REUSEADDR,无该属性,抛出异常。
属性默认及配置生效后的行为取决于系统,使用前,请参阅不同系统针对此属性 SO_REUSEPORT 的说明文档。
同时开启 SO_REUSEADDR/SO_REUSEPORT 会导致不可预知的系统错误,用户需谨慎配置值。
类型:Bool
异常:
- SocketException - Windows 上不支持此类型,抛出异常。
prop sendBufferSize
public mut prop sendBufferSize: Int64
功能:设置和读取 SO_SNDBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
init(SocketAddress)
public init(bindAt!: SocketAddress)
功能:创建一个 TcpServerSocket 实例,尚未绑定,因此客户端无法连接。
参数:
- bindAt!: SocketAddress - 指定本地绑定地址,端口号设置为 0 表示随机绑定空闲的本地地址。
init(UInt16)
public init(bindAt!: UInt16)
功能:创建一个 TcpServerSocket 实例,尚未绑定,因此客户端无法连接。
参数:
- bindAt!: UInt16 - 指定本地绑定端口,0 表示随机绑定空闲的本地端口。
func accept()
public override func accept(): TcpSocket
功能:监听或接受客户端连接。阻塞等待。
返回值:
- TcpSocket - 客户端套接字。
异常:
- SocketException - 当因系统原因监听失败时,抛出异常。
func accept(?Duration)
public override func accept(timeout!: ?Duration): TcpSocket
功能:监听或接受客户端连接。
参数:
- timeout!: ?Duration - 超时时间。
返回值:
- TcpSocket - 客户端套接字。
异常:
- SocketTimeoutException - 当连接超时,抛出异常。
- SocketException - 当因系统原因监听失败时,抛出异常。
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
func bind()
public override func bind(): Unit
功能:绑定本地端口失败后需要 close 套接字,不支持多次重试。
异常:
- SocketException - 当因系统原因绑定失败时,抛出异常。
func close()
public override func close(): Unit
功能:关闭套接字。接口允许多次调用。
func getSocketOption(Int32, Int32, CPointer<Unit>, CPointer<UIntNative>)
public func getSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: CPointer<UIntNative>
): Unit
功能:获取指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: CPointer<UIntNative> - 参数值长度。
异常:
- SocketException - 当
getsockopt返回失败时,抛出异常。
func getSocketOptionBool(Int32, Int32)
public func getSocketOptionBool(
level: Int32,
option: Int32
): Bool
功能:获取指定的套接字参数。从 IntNative 强转而来。0 => false,非 0 => true。
参数:
返回值:
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func getSocketOptionIntNative(Int32, Int32)
public func getSocketOptionIntNative(
level: Int32,
option: Int32
): IntNative
功能:获取指定的套接字参数。
参数:
返回值:
- IntNative - 获取的套接字参数值。
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func isClosed()
public override func isClosed(): Bool
功能:检查套接字是否关闭。
返回值:
- Bool - 如果已经关闭,返回
true,否则返回false。
func setSocketOption(Int32, Int32, CPointer<Unit>, UIntNative)
public func setSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: UIntNative
): Unit
功能:设置指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: UIntNative - 参数值长度。
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionBool(Int32, Int32,Bool)
public func setSocketOptionBool(
level: Int32,
option: Int32,
value: Bool
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionIntNative(Int32, Int32, IntNative)
public func setSocketOptionIntNative(
level: Int32,
option: Int32,
value: IntNative
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func toString()
public override func toString(): String
功能:返回当前 TcpServerSocket 的状态信息。
返回值:
- String - 包含当前 TcpServerSocket 状态信息的字符串。
class TcpSocket
public class TcpSocket <: StreamingSocket & Equatable<TcpSocket> & Hashable {
public init(address: String, port: UInt16)
public init(address: SocketAddress)
public init(address: SocketAddress, localAddress!: ?SocketAddress)
}
功能:请求 TCP 连接的客户端。
当实例对象被创建后,可使用 connect 函数创建连接,并在结束时显式执行 close 操作。
该类型继承自 StreamingSocket, 可参阅 StreamingSocket 章节获取更多信息。
父类型:
prop bindToDevice
public mut prop bindToDevice: ?String
功能:设置和读取绑定网卡。
类型:?String
prop keepAlive
public mut prop keepAlive: ?SocketKeepAliveConfig
功能:设置和读取保活属性,None 表示关闭保活。
用户未设置时将使用系统默认配置。设置此配置可能会被延迟或被系统忽略,取决于系统的处理能力。
prop linger
public mut prop linger: ?Duration
功能:设置和读取 SO_LINGER 属性,默认值取决于系统,None 表示禁用此选项。
说明:
- 如果
SO_LINGER被设置为Some(v),当套接字关闭时,如果还有等待的字节流,我们将在关闭连接前等待v时间,如果超过时间,字节流还未被发送,连接将会被异常终止(通过 RST 报文关闭)。- 如果
SO_LINGER被设置为None,当套接字关闭时,连接将被立即关闭,如果当前等待发送的字符,使用 FIN-ACK 关闭连接,当还有剩余待发送的字符时,使用 RST 关闭连接。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
prop localAddress
public override prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭或无可用的本地地址(本地地址未配置并且套接字未连接)时,抛出异常。
prop noDelay
public mut prop noDelay: Bool
功能:设置和读取 TCP_NODELAY 属性,默认为 true。
这个选项将禁用 Nagel 算法,所有写入字节被无延迟得转发。当属性设置为 false 时,Nagel 算法将在发包前引入延时时间。
类型:Bool
prop quickAcknowledge
public mut prop quickAcknowledge: Bool
功能:设置和读取 TCP_QUICKACK 属性,默认为 false。
这个选项类似于 noDelay,但仅影响 TCP ACK 和第一次响应。不支持 Windows 和 macOS 系统。
类型:Bool
prop readTimeout
public override mut prop readTimeout: ?Duration
功能:设置和读取读操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
prop receiveBufferSize
public mut prop receiveBufferSize: Int64
功能:设置和读取 SO_RCVBUF 属性,提供一种方式指定收包缓存大小。选项的生效情况取决于系统。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop remoteAddress
public override prop remoteAddress: SocketAddress
功能:读取 Socket 已经或将要连接的远端地址。
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop sendBufferSize
public mut prop sendBufferSize: Int64
功能:设置和读取 SO_SNDBUF 属性,提供一种方式指定发包缓存大小。选项的生效情况取决于系统。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop writeTimeout
public override mut prop writeTimeout: ?Duration
功能:设置和读取写操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
init(SocketAddress)
public init(address: SocketAddress)
功能:创建一个未连接的套接字。
参数:
- address: SocketAddress - 即将要连接的地址。
异常:
- SocketException - 当
address参数不合法或者 Windows 平台下地址为全零地址时,抛出异常。
init(SocketAddress, ?SocketAddress)
public init(address: SocketAddress, localAddress!: ?SocketAddress)
功能:创建一个未连接的套接字,并且绑定到指定本地地址,本地地址为 None 时,将随机选定地址去绑定。
此接口当 localAddress 不为 None 时,将默认设置 SO_REUSEADDR 为 true,否则可能导致 "address already in use" 的错误。如果需要变更此配置,可以通过调用 setSocketOptionBool(SocketOptions.SOL_SOCKET, SocketOptions.SO_REUSEADDR, false)。另外,本地地址和远端地址需要均为 IPv4。
参数:
- address: SocketAddress - 即将要连接的地址。
- localAddress!: ?SocketAddress - 绑定的本地地址。
异常:
- SocketException - 当
address参数不合法或者 Windows 平台下地址为全零地址时,抛出异常。
init(String, UInt16)
public init(address: String, port: UInt16)
功能:创建一个未连接的套接字。
参数:
异常:
- SocketException - 当
address参数不合法或者 Windows 平台下地址为全零地址时,抛出异常。
func close()
public func close(): Unit
功能:关闭套接字,所有操作除了 close/isClosed 之外,均不允许再调用。接口允许多次调用。
func connect(?Duration)
public func connect(timeout!: ?Duration = None): Unit
功能:连接远端套接字,会自动绑定本地地址,因此不需要进行额外的绑定操作。
参数:
- timeout!: ?Duration - 连接超时时间,
None表示无超时时间,并且连接操作无重试,当服务端拒绝连接时,将返回连接失败。并且此操作包含了绑定操作,因此无需重复调用bind接口。
异常:
- IllegalArgumentException - 当远端地址不合法或者连接超时时间小于 0 或者超时时间小于 0 时,抛出异常。
- SocketException - 当连接因系统原因(例如:套接字已关闭,没有访问权限,系统错误等)无法建立时,抛出异常。再次调用可能成功。
- SocketTimeoutException - 当连接超时时,抛出异常。
func getSocketOption(Int32, Int32, CPointer<Unit>, CPointer<UIntNative>)
public func getSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: CPointer<UIntNative>
): Unit
功能:读取指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: CPointer<UIntNative> - 参数值长度。
异常:
- SocketException - 当
getsockopt返回失败时,抛出异常。
func getSocketOptionBool(Int32, Int32)
public func getSocketOptionBool(
level: Int32,
option: Int32
): Bool
功能:读取指定的套接字参数。从 IntNative 强转而来。0 => false,非 0 => true。
参数:
返回值:
- Bool - 读取到的参数值。
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func getSocketOptionIntNative(Int32, Int32)
public func getSocketOptionIntNative(
level: Int32,
option: Int32
): IntNative
功能:读取指定的套接字参数。
参数:
返回值:
- IntNative - 参数值。
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func hashCode()
public override func hashCode(): Int64
功能:获取当前 TcpSocket 实例的哈希值。
返回值:
func isClosed()
public func isClosed(): Bool
功能:判断套接字是否通过调用 close 显式关闭。
返回值:
- Bool - 套接字是否已经调用
close显式关闭。是则返回true;否则返回false。
func read(Array<Byte>)
public override func read(buffer: Array<Byte>): Int64
功能:读取报文。超时情况按 readTimeout 决定,详见 readTimeout。
说明:
- 由于系统底层接口差异,如果连接被对端关闭,
read和write接口的行为也有相应的差异。- Windows 系统上,对端关闭连接后,如果本端调用一次
write,会导致清空缓冲区内容,在此基础上再调用read会抛出连接关闭异常。- Linux/macOS 系统上,对端关闭连接后,先调用
write再调用read函数仍会读出缓冲区中的内容。
参数:
返回值:
- Int64 - 读取的数据长度。
异常:
- SocketException - 当
buffer大小为 0 或者因系统原因读取失败时,抛出异常。
func setSocketOption(Int32, Int32, CPointer<Unit>, UIntNative)
public func setSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: UIntNative
): Unit
功能:设置指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: UIntNative - 参数值长度。
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionBool(Int32, Int32, Bool)
public func setSocketOptionBool(
level: Int32,
option: Int32,
value: Bool
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionIntNative(Int32, Int32, IntNative)
public func setSocketOptionIntNative(
level: Int32,
option: Int32,
value: IntNative
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func toString()
public override func toString(): String
功能:返回当前 TcpSocket 的状态信息。
返回值:
func write(Array<Byte>)
public override func write(payload: Array<Byte>): Unit
功能:写入报文。超时情况按 writeTimeout 决定,详见 writeTimeout。
参数:
异常:
- SocketException - 当
buffer大小为 0 或者当因系统原因写入失败时,抛出异常。
operator func !=(TcpSocket)
public override operator func !=(other: TcpSocket): Bool
功能:判断两个 TcpSocket 实例是否不等。
参数:
返回值:
operator func ==(TcpSocket)
public override operator func ==(other: TcpSocket): Bool
功能:判断两个 TcpSocket 实例是否相等。
参数:
返回值:
class UdpSocket
public class UdpSocket <: DatagramSocket {
public init(bindAt!: SocketAddress)
public init(bindAt!: UInt16)
}
功能:提供 udp 报文通信。
UdpSocket 创建实例后,需要调用 bind() 绑定,可在不与远端建连的前提下接受报文。不过,UdpSocket 也可以通过 connect()/disconnect() 接口进行建连。
UDP 协议要求传输报文大小不可超过 64KB 。
UdpSocket 需要被显式 close() 。可以参阅 DatagramSocket 获取更多信息。
父类型:
prop localAddress
public override prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭或无可用的本地地址(本地地址未配置并且套接字未连接)时,抛出异常。
prop receiveBufferSize
public mut prop receiveBufferSize: Int64
功能:设置和读取 SO_RCVBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop receiveTimeout
public override mut prop receiveTimeout: ?Duration
功能:设置和读取 receive/receiveFrom 操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
prop remoteAddress
public override prop remoteAddress: ?SocketAddress
功能:读取 Socket 已经连接的远端地址,当 Socket 未连接时返回 None。
类型:?SocketAddress
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop reuseAddress
public mut prop reuseAddress: Bool
功能:设置和读取 SO_REUSEADDR 属性。
属性默认以及生效后的行为取决于系统,使用前,请参阅不同系统针对此属性 SO_REUSEADDR/SOCK_REUSEADDR 的说明文档。
类型:Bool
prop reusePort
public mut prop reusePort: Bool
功能:设置和读取 SO_REUSEPORT 属性。
Windows 上可使用 SO_REUSEADDR,但无 SO_REUSEPORT 属性,因此会抛出异常。
属性默认以及配置生效后的行为取决于系统,使用前,请参阅不同系统针对此属性 SO_REUSEPORT 的说明文档。
类型:Bool
异常:
- SocketException - Windows 上不支持此类型,抛出异常。
prop sendBufferSize
public mut prop sendBufferSize: Int64
功能:设置和读取 SO_SNDBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop sendTimeout
public override mut prop sendTimeout: ?Duration
功能:设置和读取 send/sendTo 操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
init(SocketAddress)
public init(bindAt!: SocketAddress)
功能:创建一个未绑定的 UdpSocket 实例。
参数:
- bindAt!: SocketAddress - 绑定地址及端口。
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
init(UInt16)
public init(bindAt!: UInt16)
功能:创建一个未绑定的 UdpSocket 实例。
参数:
- bindAt!: UInt16 - 绑定端口。
func bind()
public func bind(): Unit
功能:绑定本地端口失败后需要 close 套接字,不支持多次重试。
异常:
- SocketException - 当因系统原因绑定失败时,抛出异常。
func close()
public override func close(): Unit
功能:关闭套接字,所有操作除了 close/isClosed 之外,均不允许再调用。接口允许多次调用。
func connect(SocketAddress)
public func connect(remote: SocketAddress): Unit
功能:连接特定远端地址,可通过 disconnect 撤销配置。
仅接受该远端地址的报文。必须在调用 bind 后执行。此操作执行后,端口将开始接收 ICMP 报文,若收到异常报文后,可能导致 send/sendTo 执行失败。
参数:
- remote: SocketAddress - 远端地址。
异常:
- IllegalArgumentException - 当远端地址不合法时,抛出异常。
- SocketException - 当端口未绑定、连接因系统原因无法建立或者 Windows 平台下远端地址为全零地址时,抛出异常。
func disconnect()
public func disconnect(): Unit
功能:停止连接。取消仅收取特定对端报文。可在 connect 前调用,可多次调用。
func getSocketOption(Int32, Int32, CPointer<Unit>, CPointer<UIntNative>)
public func getSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: CPointer<UIntNative>
): Unit
功能:获取指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: CPointer<UIntNative> - 参数值长度。
异常:
- SocketException - 当
getsockopt返回失败时,抛出异常。
func getSocketOptionBool(Int32, Int32)
public func getSocketOptionBool(
level: Int32,
option: Int32
): Bool
功能:获取指定的套接字参数。从 IntNative 强转而来。0 => false,非 0 => true。
参数:
返回值:
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func getSocketOptionIntNative(Int32, Int32)
public func getSocketOptionIntNative(
level: Int32,
option: Int32
): IntNative
功能:获取指定的套接字参数。
参数:
返回值:
- IntNative - 指定的套接字参数值。
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时抛出异常。
func isClosed()
public override func isClosed(): Bool
功能:判断套接字是否通过调用 close 显式关闭。
返回值:
- Bool - 如果该套接字已调用
close显示关闭,则返回true;否则,返回false。
func receive(Array<Byte>)
public func receive(buffer: Array<Byte>): Int64
功能:从 connect 连接到的地址收取报文。
参数:
返回值:
- Int64 - 收取到的报文大小。
func receiveFrom(Array<Byte>)
public override func receiveFrom(buffer: Array<Byte>): (SocketAddress, Int64)
功能:接收报文。
参数:
返回值:
- (SocketAddress, Int64) - 收取到的报文的发送端地址,及实际收取到的报文大小,可能为 0 或者大于参数
buffer的大小。
异常:
- SocketException - 当本机缓存过小无法读取报文时,抛出异常。
- SocketTimeoutException - 当读取超时时,抛出异常。
func send(Array<Byte>)
public func send(payload: Array<Byte>): Unit
功能:发送报文到 connect 连接到的地址。
参数:
异常:
- SocketException - 当
payload的大小超出系统限制或者系统发送失败(例如:当connect被调用,并且收到异常 ICMP 报文时,发送失败)时,抛出异常。
func sendTo(SocketAddress, Array<Byte>)
public override func sendTo(recipient: SocketAddress, payload: Array<Byte>): Unit
功能:发送报文。当没有足够的缓存地址时可能会被阻塞。
参数:
- recipient: SocketAddress - 发送的对端地址。
- payload: Array<Byte> - 发送报文内容。
异常:
- SocketException - 当
payload的大小超出系统限制、系统发送失败(例如:当connect被调用,并且收到异常 ICMP 报文时,发送失败)、Windows 平台下远端地址为全零地址或者 macOS 平台下connect被调用后调用sendTo时,抛出异常。
func setSocketOption(Int32, Int32, CPointer<Unit>, UIntNative)
public func setSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: UIntNative
): Unit
功能:设置指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: UIntNative - 参数值长度。
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionBool(Int32, Int32, Bool)
public func setSocketOptionBool(
level: Int32,
option: Int32,
value: Bool
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionIntNative(Int32, Int32, IntNative)
public func setSocketOptionIntNative(
level: Int32,
option: Int32,
value: IntNative
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func toString()
public override func toString(): String
功能:返回当前 UdpSocket 的状态信息。
返回值:
class UnixDatagramSocket
public class UnixDatagramSocket <: DatagramSocket {
public init(bindAt!: SocketAddress)
public init(bindAt!: String)
}
功能:提供基于数据包的主机通讯能力。
UnixDatagramSocket 实例创建后,应当显式调用 bind() 接口绑定。Unix 数据包套接字不需要连接,不需要与远端握手多次。不过用户也可以通过 connect/disconnect 接口与远端建连和断连。
不同于 UDP,UDS 没有数据包大小限制,限制来源于操作系统和接口实现。
套接字资源需要用 close 接口显式回收。可参阅 DatagramSocket 获取更多信息。
注意:
- 该类型不支持在 Windows 平台上运行。
父类型:
prop localAddress
public override prop localAddress: SocketAddress
功能:读取 socket 将要或已经绑定的本地地址。
异常:
- SocketException - 当
socket已经关闭时,抛出异常。
prop receiveBufferSize
public mut prop receiveBufferSize: Int64
功能:设置和读取 SO_RCVBUF 属性,提供一种方式指定发包缓存大小。选项的生效情况取决于系统。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop receiveTimeout
public override mut prop receiveTimeout: ?Duration
功能:设置和读取 receive/receiveFrom 操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
prop remoteAddress
public override prop remoteAddress: ?SocketAddress
功能:读取 Socket 已经连接的远端地址,当 Socket 未连接时返回 None。
类型:?SocketAddress
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop sendBufferSize
public mut prop sendBufferSize: Int64
功能:设置和读取 SO_SNDBUF 属性,提供一种方式指定发包缓存大小。选项的生效情况取决于系统。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop sendTimeout
public override mut prop sendTimeout: ?Duration
功能:设置和读取 send/sendTo 操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
init(SocketAddress)
public init(bindAt!: SocketAddress)
功能:创建一个未连接的 UnixDatagramSocket 实例。
此文件类型可通过 isSock() 判断是否存在,可通过 unlink() 接口删除。
参数:
- bindAt!: SocketAddress - 连接的套接字地址。地址应当不存在,在
bind时会创建。
异常:
- SocketException - 当路径为空或已存在时,抛出异常。
init(String)
public init(bindAt!: String)
功能:创建一个未连接的 UnixDatagramSocket 实例。
此文件类型可通过 isSock() 判断是否存在,可通过 unlink() 接口删除。
参数:
- bindAt!: String - 连接的文件地址。文件地址应当不存在,在
bind时会创建。
异常:
- IllegalArgumentException - 当文件地址不合法时,抛出异常。
- SocketException - 当文件地址为空或已存在时,抛出异常。
func bind()
public func bind(): Unit
功能:绑定一个 Unix datagram 套接字,并创建监听队列。
此接口自动在本地地址中创建一个套接字文件,如该文件已存在则会绑定失败。此文件类型可通过 isSock 判断是否存在,可通过 unlink() 接口删除,失败后需要 close 套接字,不支持多次重试。
异常:
- SocketException - 当文件地址已存在,或文件创建失败时,抛出异常。
func close()
public override func close(): Unit
功能:关闭套接字,所有操作除了 close/isClosed 之外,均不允许再调用。接口允许多次调用。
func connect(SocketAddress)
public func connect(remote: SocketAddress): Unit
功能:连接特定远端地址,可通过 disconnect 撤销配置。
仅接受该远端地址的报文。默认执行 bind,因此不需额外调用 bind。此操作执行后,端口将开始接收 ICMP 报文,若收到异常报文后,可能导致 send/sendTo 执行失败。
参数:
- remote: SocketAddress - 远端套接字地址。
异常:
- SocketException - 当地址未绑定时,抛出异常。
func connect(String)
public func connect(remotePath: String): Unit
功能:连接特定远端地址,可通过 disconnect 撤销配置。
仅接受该远端地址的报文。必须在 bind 后调用。此操作执行后,端口将开始接收 ICMP 报文,若收到异常报文后,可能导致 send/sendTo 执行失败。
参数:
- remotePath: String - 远端文件地址。
异常:
- SocketException - 当地址未绑定时,抛出异常。
func disconnect()
public func disconnect(): Unit
功能:停止连接。取消仅收取特定对端报文。可在 connect 前调用,可多次调用。
异常:
- SocketException - 当未绑定时,抛出异常。
func getSocketOption(Int32, Int32, CPointer<Unit>, CPointer<UIntNative>)
public func getSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: CPointer<UIntNative>
): Unit
功能:获取指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: CPointer<UIntNative> - 参数值长度。
异常:
- SocketException - 当
getsockopt返回失败时,抛出异常。
func getSocketOptionIntNative(Int32, Int32)
public func getSocketOptionIntNative(
level: Int32,
option: Int32
): IntNative
功能:获取指定的套接字参数。
参数:
返回值:
- IntNative - 返回指定的套接字参数值。
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func isClosed()
public override func isClosed(): Bool
功能:判断套接字是否通过调用 close 显式关闭。
返回值:
- Bool - 返回套接字是否已经通过调用
close显式关闭。是则返回true;否则,返回false。
func receive(Array<Byte>)
public func receive(buffer: Array<Byte>): Int64
功能:从 connect 连接到的地址收取报文。
参数:
返回值:
- Int64 - 收取到的报文大小。
func receiveFrom(Array<Byte>)
public override func receiveFrom(buffer: Array<Byte>): (SocketAddress, Int64)
功能:收取报文。
参数:
返回值:
- (SocketAddress, Int64) - 收取到的报文的发送端地址,及实际收取到的报文大小,可能为 0 或者大于参数
buffer的大小。
异常:
- SocketException - 本机缓存过小无法读取报文时,抛出异常。
- SocketTimeoutException - 当读取超时时,抛出异常。
func send(Array<Byte>)
public func send(payload: Array<Byte>): Unit
功能:发送报文到 connect 连接到的地址。
参数:
异常:
- SocketException - 当
payload的大小超出系统限制或者系统发送失败时,抛出异常。
func sendTo(SocketAddress, Array<Byte>)
public override func sendTo(recipient: SocketAddress, payload: Array<Byte>): Unit
功能:发送报文。当没有足够的缓存地址时可能会被阻塞。
参数:
- recipient: SocketAddress - 发送的对端地址。
- payload: Array<Byte> - 发送报文内容。
异常:
- SocketException - 当
payload的大小超出系统限制、系统发送失败(例如:当connect被调用,并且收到异常 ICMP 报文时,发送将失败)或者 macOS 平台下connect被调用后调用sendTo时,抛出异常。
func setSocketOption(Int32, Int32, CPointer<Unit>, UIntNative)
public func setSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: UIntNative
): Unit
功能:设置指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: UIntNative - 参数值长度。
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionBool(Int32, Int32, Bool)
public func setSocketOptionBool(
level: Int32,
option: Int32,
value: Bool
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionIntNative(Int32, Int32,IntNative)
public func setSocketOptionIntNative(
level: Int32,
option: Int32,
value: IntNative
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时抛出异常。
func getSocketOptionBool(Int32, Int32)
public func getSocketOptionBool(
level: Int32,
option: Int32
): Bool
功能:获取指定的套接字参数。从 IntNative 强转而来。0 => false,非 0 => true。
参数:
返回值:
异常:
- SocketException - 当
getsockopt返回失败时,抛出异常。
func toString()
public override func toString(): String
功能:返回当前 UDS 的状态信息。
返回值:
- String - 包含当前
UDS状态信息的字符串。
class UnixServerSocket
public class UnixServerSocket <: ServerSocket {
public init(bindAt!: String)
public init(bindAt!: SocketAddress)
}
功能:提供基于双工流的主机通讯服务端。
UnixServerSocket 监听连接,创建后可以通过属性和 setSocketOptionXX 接口配置属性值。需要调用 bind() 接口绑定本地地址开始监听连接。可以通过 accept() 接口接受连接。
注意:
- 该类型不支持在 Windows 平台上运行。
父类型:
prop backlogSize
public mut prop backlogSize: Int64
功能:设置和读取 backlog 大小。仅可在调用 bind 前调用,否则将抛出异常。
变量是否生效取决于系统行为。
类型:Int64
异常:
- SocketException - 当在
bind后调用,将抛出异常。
prop localAddress
public override prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop receiveBufferSize
public mut prop receiveBufferSize: Int64
功能:设置和读取 SO_RCVBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop sendBufferSize
public mut prop sendBufferSize: Int64
功能:设置和读取 SO_SNDBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
init(SocketAddress)
public init(bindAt!: SocketAddress)
功能:创建一个未连接的 UnixServerSocket 实例。
参数:
- bindAt!: SocketAddress - 连接的套接字地址。
init(String)
public init(bindAt!: String)
功能:创建一个未连接的 UnixServerSocket 实例。
此文件类型可通过 isSock 判断是否存在,可通过 unlink() 接口删除。
参数:
- bindAt!: String - 连接的文件地址。
异常:
- IllegalArgumentException - 当文件地址不合法时,抛出异常。
func accept()
public override func accept(): UnixSocket
功能:等待接受一个客户端的连接,或从队列中读取连接。
返回值:
- UnixSocket - 连接的客户端套接字。
func accept(?Duration)
public override func accept(timeout!: ?Duration): UnixSocket
功能:等待接受一个客户端的连接,或从队列中读取连接。
参数:
- timeout!: ?Duration - 超时时间。
返回值:
- UnixSocket - 连接的客户端套接字。
异常:
- SocketTimeoutException - 当连接超时时,抛出异常。
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
func bind()
public override func bind(): Unit
功能:绑定一个 Unix domain 套接字,并创建监听队列。
此接口自动在本地地址中创建一个套接字文件,如该文件已存在则会绑定失败。此文件类型可通过 isSock 接口判断是否存在,可通过 unlink() 接口删除,失败后需要 close 套接字,不支持多次重试。
异常:
- SocketException - 当因系统原因绑定失败时,抛出异常。
func close()
public override func close(): Unit
功能:关闭套接字,该套接字的所有操作除了 close/isClosed 之外,均不允许再调用。此接口允许多次调用。
func getSocketOption(Int32, Int32, CPointer<Unit>, CPointer<UIntNative>)
public func getSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: CPointer<UIntNative>
): Unit
功能:获取指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: CPointer<UIntNative> - 参数值长度。
异常:
- SocketException - 当
getsockopt返回失败时,抛出异常。
func getSocketOptionBool(Int32, Int32)
public func getSocketOptionBool(
level: Int32,
option: Int32
): Bool
功能:获取指定的套接字参数。从 IntNative 强转而来。0 => false,非 0 => true。
参数:
返回值:
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func getSocketOptionIntNative(Int32, Int32)
public func getSocketOptionIntNative(
level: Int32,
option: Int32
): IntNative
功能:获取返回值为整型的套接字参数。
参数:
返回值:
- IntNative - 指定的套接字参数值。
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func isClosed()
public override func isClosed(): Bool
功能:判断套接字是否通过调用 close 显式关闭。
返回值:
- Bool - 如果套接字是通过调用
close显式关闭,则返回 true;否则,返回 false。
func setSocketOption(Int32, Int32, CPointer<Unit>, UIntNative)
public func setSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: UIntNative
): Unit
功能:设置返回值为整型的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: UIntNative - 参数值长度。
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionBool(Int32, Int32, Bool)
public func setSocketOptionBool(
level: Int32,
option: Int32,
value: Bool
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionIntNative(Int32, Int32, IntNative)
public func setSocketOptionIntNative(
level: Int32,
option: Int32,
value: IntNative
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func toString()
public override func toString(): String
功能:返回当前 UnixServerSocket 的状态信息。
返回值:
- String - 包含当前 UnixServerSocket 状态信息的字符串。
class UnixSocket
public class UnixSocket <: StreamingSocket {
public init(address: SocketAddress, localAddress!: ?SocketAddress = None)
public init(path: String, localPath!: ?String = None)
}
功能:提供基于双工流的主机通讯客户端。
UnixSocket 实例创建后应调用 connect() 接口创建连接,并且在结束时显式调用 close() 回收资源。可参阅 StreamingSocket 获取更多信息。
注意:
- 该类型不支持在 Windows 平台上运行。
父类型:
prop localAddress
public override prop localAddress: SocketAddress
功能:读取 Socket 将要或已经被绑定的本地地址。
异常:
- SocketException - 当
Socket已经被关闭或无可用的本地地址(本地地址未配置并且套接字未连接)时,抛出异常。
prop readTimeout
public override mut prop readTimeout: ?Duration
功能:设置和读取读操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值,过大时将设置为None,默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
prop receiveBufferSize
public mut prop receiveBufferSize: Int64
功能:设置和读取 SO_RCVBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop remoteAddress
public override prop remoteAddress: SocketAddress
功能:读取 Socket 已经或将要连接的远端地址。
异常:
- SocketException - 当
Socket已经被关闭时,抛出异常。
prop sendBufferSize
public mut prop sendBufferSize: Int64
功能:设置和读取 SO_SNDBUF 属性。
类型:Int64
异常:
- IllegalArgumentException - 当
size小于等于 0 时,抛出异常。 - SocketException - 当
Socket已关闭时,抛出异常。
prop writeTimeout
public override mut prop writeTimeout: ?Duration
功能:设置和读取写操作超时时间。
如果设置的时间过小将会设置为最小时钟周期值;过大时将设置为最大超时时间(263-1 纳秒);默认值为 None。
类型:?Duration
异常:
- IllegalArgumentException - 当超时时间小于 0 时,抛出异常。
init(SocketAddress, ?SocketAddress)
public init(address: SocketAddress, localAddress!: ?SocketAddress = None)
功能:创建一个未连接的 UnixSocket 实例。
参数:
- address: SocketAddress - 连接的套接字地址。
- localAddress!: ?SocketAddress - 需要 bind 的本地套接字地址;默认值为
None。
init(String, ?String)
public init(path: String, localPath!: ?String = None)
功能:创建一个未连接的 UnixSocket 实例。
此文件类型可通过 isSock 判断是否存在,可通过 unlink() 接口删除。
参数:
异常:
- IllegalArgumentException - 当文件地址不合法时,抛出异常。
func close()
public func close(): Unit
功能:关闭套接字,所有操作除了 close/isClosed 之外,均不允许再调用。接口允许多次调用。
func connect(?Duration)
public func connect(timeout!: ?Duration = None): Unit
功能:建立远端连接,对端拒绝时连接失败,会自动绑定本地地址,因此不需要进行额外的绑定操作。
参数:
- timeout!: ?Duration - 超时时间,
None表示无超时时间。Unix 与 Tcp 不同,队列已满时,调用立即返回错误,而非重试阻塞等待。
异常:
- IllegalArgumentException - 当远端地址不合法或者超时时间小于 0 时,抛出异常。
- SocketException - 当连接因系统原因无法建立时。抛出异常。
- SocketTimeoutException - 当连接超时时。抛出异常。
func getSocketOption(Int32, Int32, CPointer<Unit>, CPointer<UIntNative>)
public func getSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: CPointer<UIntNative>
): Unit
功能:获取指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: CPointer<UIntNative> - 参数值长度。
异常:
- SocketException - 当
getsockopt返回失败时,抛出异常。
func getSocketOptionBool(Int32, Int32)
public func getSocketOptionBool(
level: Int32,
option: Int32
): Bool
功能:获取指定的套接字参数。从 IntNative 强转而来。0 => false,非 0 => true。
参数:
返回值:
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func getSocketOptionIntNative(Int32, Int32)
public func getSocketOptionIntNative(
level: Int32,
option: Int32
): IntNative
功能:获取指定的套接字参数。
参数:
返回值:
- IntNative - 指定的套接字参数值。
异常:
- SocketException - 当
getsockopt返回失败时或参数大小超过 IntNative 的阈值时,抛出异常。
func isClosed()
public func isClosed(): Bool
功能:判断套接字是否通过调用 close 显式关闭。
返回值:
- Bool - 返回套接字是否已经调用
close显示关闭。是则返回true;否则,返回false。
func read(Array<Byte>)
public override func read(buffer: Array<Byte>): Int64
功能:读取报文。超时情况按 readTimeout 决定,详见 readTimeout。
参数:
返回值:
- Int64 - 读取的数据长度。
异常:
- SocketException - 当
buffer大小为 0 或者因系统原因读取失败时,抛出异常。
func setSocketOption(Int32, Int32, CPointer<Unit>, UIntNative)
public func setSocketOption(
level: Int32,
option: Int32,
value: CPointer<Unit>,
valueLength: UIntNative
): Unit
功能:设置指定的套接字参数。
参数:
- level: Int32 - 层级,例如
SOL_SOCKET。 - option: Int32 - 参数,例如
SO_KEEPALIVE。 - value: CPointer<Unit> - 参数值。
- valueLength: UIntNative - 参数值长度。
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionBool(Int32, Int32, Bool)
public func setSocketOptionBool(
level: Int32,
option: Int32,
value: Bool
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func setSocketOptionIntNative(Int32, Int32, IntNative)
public func setSocketOptionIntNative(
level: Int32,
option: Int32,
value: IntNative
): Unit
功能:设置指定的套接字参数。
参数:
异常:
- SocketException - 当
setsockopt返回失败时,抛出异常。
func toString()
public override func toString(): String
功能:返回当前 UnixSocket 的状态信息。
返回值:
- String - 包含当前 UnixSocket 状态信息的字符串。
func write(Array<Byte>)
public override func write(buffer: Array<Byte>): Unit
功能:读取写入。超时情况按 writeTimeout 决定,详见 writeTimeout。
参数:
异常:
- SocketException - 当
buffer大小为 0 时抛出异常,当因系统原因写入失败时,抛出异常。
class UnixSocketAddress
public class UnixSocketAddress <: SocketAddress & Equatable<UnixSocketAddress> {
public init(path: Array<Byte>)
public init(path: String)
}
功能:此类实现了 Unix Domain Socket 地址,Unix Domain Socket 地址封装了Unix Domain Socket 绑定或连接到的文件系统路径,路径长度不可超过 108。
如果路径是空字符串,那么表示它是 unnamed 地址,如果路径以\0 开头,那么它是 abstract 地址。路径中间不可包含 \0。
父类型:
prop family
public prop family: AddressFamily
功能:获取当前 UnixSocketAddress 对象的地址族,总是 AddressFamily.UNIX。
prop size
public prop size: Int64
功能:获取当前 UnixSocketAddress 对象的原始字节长度。
类型:Int64
init(Array<Byte>)
public init(path: Array<Byte>)
功能:根据 Array<Byte> 表示的文件系统路径构造 UnixSocketAddress 地址。
参数:
异常:
- IllegalArgumentException - 如果 address 不合法,抛出异常。
init(String)
public init(path: String)
功能:根据字符串表示的文件系统路径构造 UnixSocketAddress 地址。
参数:
- path: String - 文件系统路径字符串。
异常:
- IllegalArgumentException - 如果 address 不合法,抛出异常。
func getAddressBytes()
public func getAddressBytes(): Array<Byte>
功能:返回此 UnixSocketAddress 对象的原始IP地址,内容布局与 sockaddr_un 形式一致。
返回值:
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let udsa1_1: UnixSocketAddress = UnixSocketAddress("/tmp/server1.sock")
@Assert(udsa1_1.getAddressBytes(), "\u{1}\u{0}/tmp/server1.sock".toArray())
}
func hashCode()
public func hashCode(): Int64
功能:获取 hashcode 值。
返回值:
- Int64 -
hashcode值。
func toString()
public func toString(): String
功能:返回当前 UnixSocketAddress 的文本表示字符串。
返回值:
- String - 当前 UnixSocketAddress 的文本表示字符串,比如
/tmp/socket1。
示例:
import std.net.*
import std.unittest.*
import std.unittest.testmacro.*
main () {
let expect1 = "/tmp/server1.sock"
let expect2 = "\u{0}/tmp/server1.sock"
let udsa1_1: UnixSocketAddress = UnixSocketAddress("/tmp/server1.sock")
let udsa2_1: UnixSocketAddress = UnixSocketAddress("/tmp/server1.sock".toArray())
let udsa2_2: UnixSocketAddress = UnixSocketAddress("/tmp/server1.sock\u{0}\u{0}".toArray())
let udsa3_1: UnixSocketAddress = UnixSocketAddress("\u{0}/tmp/server1.sock")
let udsa4_1: UnixSocketAddress = UnixSocketAddress("\u{0}/tmp/server1.sock".toArray())
let udsa4_2: UnixSocketAddress = UnixSocketAddress("\u{0}/tmp/server1.sock\u{0}\u{0}".toArray())
@Assert(udsa1_1.toString(), expect1)
@Assert(udsa2_1.toString(), expect1)
@Assert(udsa2_2.toString(), expect1)
@Assert(udsa3_1.toString(), expect2)
@Assert(udsa1_1, udsa2_1)
@Assert(udsa1_1, udsa2_2)
@Assert(udsa3_1, udsa4_1)
@Assert(udsa3_1, udsa4_2)
@Assert(udsa4_1.toString(), expect2)
@Assert(udsa4_2.toString(), expect2)
try {
UnixSocketAddress("/tmp/server1\u{0}.sock")
} catch (e: IllegalArgumentException) {
@Assert(true)
}
try {
UnixSocketAddress("/tmp/server1.sock\u{0}\u{0}")
} catch (e: IllegalArgumentException) {
@Assert(true)
}
try {
UnixSocketAddress("\u{0}/tmp/server1.sock\u{0}\u{0}")
} catch (e: IllegalArgumentException) {
@Assert(true)
}
try {
UnixSocketAddress("/tmp/server1\u{0}.sock".toArray())
} catch (e: IllegalArgumentException) {
@Assert(true)
}
return
}
operator func ==(UnixSocketAddress)
public operator func ==(rhs: UnixSocketAddress): Bool
功能:判断两个 UnixSocketAddress 对象是否相等。
参数:
- rhs: UnixSocketAddress - 参与比较的 UnixSocketAddress 对象。
返回值:
- Bool - 如果两个 UnixSocketAddress 对象相等,则返回
true;否则,返回false。
operator func !=(UnixSocketAddress)
public operator func !=(rhs: UnixSocketAddress): Bool
功能:判断两个 UnixSocketAddress 对象是否不等。
参数:
- rhs: UnixSocketAddress - 参与比较的 UnixSocketAddress 对象。
返回值:
- Bool - 如果两个 UnixSocketAddress 对象不等,则返回
true;否则,返回false。
枚举
enum SocketNet
public enum SocketNet <: ToString & Equatable<SocketNet> {
| TCP
| UDP
| UNIX
}
功能:传输层协议类型。
父类型:
TCP
TCP
功能:代表 TCP 协议。
UDP
UDP
功能:代表 UDP 协议。
UNIX
UNIX
功能:代表 UNIX 协议。
func toString()
public func toString(): String
功能:将枚举值转换为字符串。
返回值:
- String - 转换后的字符串。
operator func !=(SocketNet)
public operator func !=(that: SocketNet): Bool
功能:判断两个 SocketNet 是否不相等。
参数:
返回值:
- Bool - 如果不相等,则返回
true;否则,返回false。
operator func ==(SocketNet)
public operator func ==(that: SocketNet): Bool
功能:判断两个 SocketNet 是否相等。
参数:
返回值:
- Bool - 如果相等,则返回
true;否则,返回false。
结构体
struct AddressFamily
public struct AddressFamily <: ToString & Equatable<AddressFamily> {
public static const INET = AddressFamily("INET", 2)
public static const INET6: AddressFamily
public static const NETLINK: AddressFamily
public static const UNIX = AddressFamily("UNIX", 1)
public static const UNSPEC = AddressFamily("UNSPEC", 0)
public let name: String
public let value: Int32
public const init(name: String, value: UInt16)
}
功能:AddressFamily 地址族用于指示 Socket 的寻址方案,常用的有 INET / INET6 / UNIX 地址族。地址族标识符最初在 RFC 2453 中定义。
父类型:
static const INET
public static const INET = AddressFamily("INET", 2)
功能:IPv4 地址族。
static const INET6
public static const INET6: AddressFamily
功能:IPv6 地址族。不同系统下的值分别为:
- macOS: AddressFamily("INET6", 30)
- Windows: AddressFamily("INET6", 23)
- 其他情况:AddressFamily("INET6", 10)
static const NETLINK
public static const NETLINK: AddressFamily
功能:NetLink 地址族,仅 Linux 下支持,其值为:
- Linux: AddressFamily("NETLINK", 16)
static const UNIX
public static const UNIX = AddressFamily("UNIX", 1)
功能:unix domain socket 地址族。
static const UNSPEC
public static const UNSPEC = AddressFamily("UNSPEC", 0)
功能:未指定的地址族。
let name: String
public let name: String
功能:地址族名。
类型:String
let value: UInt16
public let value: UInt16
功能:地址族值。
类型:UInt16
init(String, UInt16)
public const init(name: String, value: UInt16)
功能:常量构造函数,创建 AddressFamily 对象。
参数:
func toString()
public func toString(): String
功能:获取地址族对应的名称。
返回值:
- String - 当前地址族的名称。
operator func ==(AddressFamily)
public operator func ==(rhs: AddressFamily): Bool
功能:比较地址族值是否相等。
参数:
- rhs: AddressFamily - 参与比较的 AddressFamily 对象。
返回值:
- Bool - 如果两个 AddressFamily 对象相等,则返回
true;否则,返回false。
operator func !=(AddressFamily)
public operator func !=(rhs: AddressFamily): Bool
功能:比较地址族值是否不等。
参数:
- rhs: AddressFamily - 参与比较的 AddressFamily 对象。
返回值:
- Bool - 如果两个 AddressFamily 对象不等,则返回
true;否则,返回false。
struct OptionLevel
public struct OptionLevel {
public static const ICMP: Int32 = 1
public static const IP: Int32 = 0
public static const RAW: Int32 = 255
public static const SOCKET: Int32
public static const TCP: Int32 = 6
public static const UDP: Int32 = 17
}
功能:提供了常用的套接字选项级别。
static const ICMP
public static const ICMP: Int32 = 1
功能:控制 ICMP 协议行为的套接字选项级别。
类型:Int32
static const IP
public static const IP: Int32 = 0
功能:控制 IP 协议行为的套接字选项级别。
类型:Int32
static const RAW
public static const RAW: Int32 = 255
功能:控制 RAW 协议行为的套接字选项级别。
类型:Int32
static const SOCKET
public static const SOCKET: Int32
功能:控制基本套接字行为的套接字选项级别。不同系统下的值分别为:
- macOS: 0xFFFF
- Windows: 0xFFFF
- 其他情况:1
类型:Int32
static const TCP
public static const TCP: Int32 = 6
功能:控制 TCP 协议行为的套接字选项级别。
类型:Int32
static const UDP
public static const UDP: Int32 = 17
功能:控制 UDP 协议行为的套接字选项级别。
类型:Int32
struct OptionName
public struct OptionName {
public static const IP_HDRINCL: Int32
public static const IP_TOS: Int32
public static const IP_TTL: Int32
public static const SO_ACCEPTCONN: Int32
public static const SO_BROADCAST: Int32
public static const SO_DEBUG: Int32 = 0x0001
public static const SO_DONTROUTE: Int32
public static const SO_ERROR: Int32
public static const SO_KEEPALIVE: Int32
public static const SO_LINGER: Int32
public static const SO_OOBINLINE: Int32
public static const SO_RCVBUF: Int32
public static const SO_RCVTIMEO: Int32
public static const SO_REUSEADDR: Int32
public static const SO_SNDBUF: Int32
public static const SO_SNDTIMEO: Int32
public static const TCP_KEEPCNT: Int32
public static const TCP_KEEPIDLE: Int32
public static const TCP_KEEPINTVL: Int32
public static const TCP_NODELAY: Int32 = 0x0001
}
功能:提供了常用的套接字选项。
static const IP_HDRINCL
public static const IP_HDRINCL: Int32
功能:用于在发送数据包时指定 IP 头部是否由应用程序提供的套接字选项。不同系统下的值分别为:
- macOS: 0x0002
- Windows: 0x0002
- 其他情况:0x0003
类型:Int32
static const IP_TOS
public static const IP_TOS: Int32
功能:用于指定数据包服务类型和优先级的套接字选项。不同系统下的值分别为:
- macOS: 0x0003
- Windows: 0x0003
- 其他情况:0x0001
类型:Int32
static const IP_TTL
public static const IP_TTL: Int32
功能:用于限制IP数据包在网络中传输最大跳数的套接字选项。不同系统下的值分别为:
- macOS: 0x0004
- Windows: 0x0004
- 其他情况:0x0002
类型:Int32
static const SO_ACCEPTCONN
public static const SO_ACCEPTCONN: Int32
功能:用于查询套接字是否处于监听状态的套接字选项。不同系统下的值分别为:
- macOS: 0x0002
- Windows: 0x0002
- 其他情况:0x001E
类型:Int32
static const SO_BROADCAST
public static const SO_BROADCAST: Int32
功能:用于设置套接字是否允许发送广播消息的套接字选项。不同系统下的值分别为:
- macOS: 0x0020
- Windows: 0x0020
- 其他情况:0x0006
类型:Int32
static const SO_DEBUG
public static const SO_DEBUG: Int32 = 0x0001
功能:用于启用或禁用调试模式的套接字选项。
类型:Int32
static const SO_DONTROUTE
public static const SO_DONTROUTE: Int32
功能:用于在连接套接字时,不路由套接字数据包的套接字选项。不同系统下的值分别为:
- macOS: 0x0010
- Windows: 0x0010
- 其他情况:0x0005
类型:Int32
static const SO_ERROR
public static const SO_ERROR: Int32
功能:获取和清除套接字上错误状态的套接字选项。不同系统下的值分别为:
- macOS: 0x1007
- Windows: 0x1007
- 其他情况:0x0004
类型:Int32
static const SO_KEEPALIVE
public static const SO_KEEPALIVE: Int32
功能:用于检测 TCP 连接是否仍然处于活动状态的套接字选项。不同系统下的值分别为:
- macOS: 0x0008
- Windows: 0x0008
- 其他情况:0x0009
类型:Int32
static const SO_LINGER
public static const SO_LINGER: Int32
功能:用于设置套接字关闭时行为的套接字选项。不同系统下的值分别为:
- macOS: 0x0080
- Windows: 0x0080
- 其他情况:0x000D
类型:Int32
static const SO_OOBINLINE
public static const SO_OOBINLINE: Int32
功能:用于控制接收带外数据方式的套接字选项。不同系统下的值分别为:
- macOS: 0x0100
- Windows: 0x0100
- 其他情况:0x000A
类型:Int32
static const SO_RCVBUF
public static const SO_RCVBUF: Int32
功能:用于设置套接字接收缓冲区大小的套接字选项。不同系统下的值分别为:
- macOS: 0x1002
- Windows: 0x1002
- 其他情况:0x0008
类型:Int32
static const SO_RCVTIMEO
public static const SO_RCVTIMEO: Int32
功能:用于设置套接字接收数据超时时间的套接字选项。不同系统下的值分别为:
- macOS: 0x1006
- Windows: 0x1006
- 其他情况:0x0014
类型:Int32
static const SO_REUSEADDR
public static const SO_REUSEADDR: Int32
功能:用于在套接字关闭后立即释放其绑定端口,以便其他套接字可以立即绑定该端口的套接字选项。不同系统下的值分别为:
- macOS: 0x0004
- Windows: 0x0004
- 其他情况:0x0002
类型:Int32
static const SO_SNDBUF
public static const SO_SNDBUF: Int32
功能:用于设置套接字发送缓冲区大小的套接字选项。不同系统下的值分别为:
- macOS: 0x1001
- Windows: 0x1001
- 其他情况:0x0007
类型:Int32
static const SO_SNDTIMEO
public static const SO_SNDTIMEO: Int32
功能:用于设置套接字发送数据超时时间的套接字选项。不同系统下的值分别为:
- macOS: 0x1005
- Windows: 0x1005
- 其他情况:0x0015
类型:Int32
static const TCP_KEEPCNT
public static const TCP_KEEPCNT: Int32
功能:用于控制 TCP 连接中发送保持存活探测报文次数的套接字选项。不同系统下的值分别为:
- macOS: 0x0102
- Windows: 0x0010
- 其他情况:0x0006
类型:Int32
static const TCP_KEEPIDLE
public static const TCP_KEEPIDLE: Int32
功能:用于设置在没有收到对端确认的情况下,TCP 保持连接最大次数的套接字选项。不同系统下的值分别为:
- macOS: 0x0010
- Windows: 0x0003
- 其他情况:0x0004
类型:Int32
static const TCP_KEEPINTVL
public static const TCP_KEEPINTVL: Int32
功能:用于设置 TCP 保持连接时发送探测报文时间间隔的套接字选项。不同系统下的值分别为:
- macOS: 0x0101
- Windows: 0x0011
- 其他情况:0x0005
类型:Int32
static const TCP_NODELAY
public static const TCP_NODELAY: Int32 = 0x0001
功能:用于控制 TCP 协议延迟行为的套接字选项。
类型:Int32
struct ProtocolType
public struct ProtocolType <: Equatable<ProtocolType> & ToString & Hashable {
public static let ICMP: ProtocolType = ProtocolType(1)
public static let IPV4: ProtocolType = ProtocolType(4)
public static let IPV6: ProtocolType = ProtocolType(41)
public static let RAW: ProtocolType = ProtocolType(255)
public static let TCP: ProtocolType = ProtocolType(6)
public static let UDP: ProtocolType = ProtocolType(17)
public static let Unspecified: ProtocolType = ProtocolType(0)
public init(protocol: Int32)
}
功能:提供了常用的套接字协议,以及通过指定 Int32 值来构建套接字协议的功能。
父类型:
static let ICMP
public static let ICMP: ProtocolType = ProtocolType(1)
功能:指定协议类型为 ICMP。
类型:ProtocolType
static let IPV4
public static let IPV4: ProtocolType = ProtocolType(4)
功能:指定协议类型为 IPv4 。
类型:ProtocolType
static let IPV6
public static let IPV6: ProtocolType = ProtocolType(41)
功能:指定协议类型为 IPv6。
类型:ProtocolType
static let RAW
public static let RAW: ProtocolType = ProtocolType(255)
功能:指定协议类型为 RAW。
类型:ProtocolType
static let TCP
public static let TCP: ProtocolType = ProtocolType(6)
功能:指定协议类型为 TCP。
类型:ProtocolType
static let UDP
public static let UDP: ProtocolType = ProtocolType(17)
功能:指定协议类型为 UDP。
类型:ProtocolType
static let Unspecified
public static let Unspecified: ProtocolType = ProtocolType(0)
功能:不指定协议类型。
类型:ProtocolType
init(Int32)
public init(protocol: Int32)
功能:通过指定套接字协议值创建协议。
参数:
- protocol: Int32 - 套接字协议值。
func hashCode()
public func hashCode(): Int64
功能:返回当前 ProtocolType 实例的哈希值。
返回值:
- Int64 - 当前 ProtocolType 实例的哈希值。
func toString()
public func toString(): String
功能:返回当前 ProtocolType 实例的字符串表示。
返回值:
- String - 当前 ProtocolType 实例的字符串表示。
operator func !=(ProtocolType)
public operator func !=(r: ProtocolType): Bool
功能:判断两个 ProtocolType 实例是否不等。
参数:
- r: ProtocolType - 参与比较的 ProtocolType 实例。
返回值:
operator func ==(ProtocolType)
public operator func ==(r: ProtocolType): Bool
功能:判断两个 ProtocolType 实例是否相等。
参数:
- r: ProtocolType - 参与比较的 ProtocolType 实例。
返回值:
struct RawAddress
public struct RawAddress {
public init(addr: Array<Byte>)
}
功能:提供了 RawSocket 的通信地址创建和获取功能。
prop addr
public prop addr: Array<Byte>
功能:获取地址。
init(Array<Byte>)
public init(addr: Array<Byte>)
功能:根据字节数组创建地址。
参数:
struct SocketDomain
public struct SocketDomain <: Equatable<SocketDomain> & ToString & Hashable {
public static let IPV4: SocketDomain = SocketDomain(2)
public static let IPV6: SocketDomain
public static let NETLINK: SocketDomain = SocketDomain(16)
public static let PACKET: SocketDomain = SocketDomain(17)
public static let UNIX: SocketDomain
public init(domain: Int32)
}
功能:提供了常用的套接字通信域,以及通过指定 Int32 值来构建套接字通信域的功能。
父类型:
static let IPV4
public static let IPV4: SocketDomain = SocketDomain(2)
功能:IPv4 通信域。
类型:SocketDomain
static let IPV6
public static let IPV6: SocketDomain
功能:IPv6 通信域。不同系统下的值分别为:
- macOS: SocketDomain(30)
- Windows: SocketDomain(23)
- 其他情况:SocketDomain(10)
类型:SocketDomain
static let NETLINK
public static let NETLINK: SocketDomain = SocketDomain(16)
功能:内核和用户空间进程之间通信。
注意:
- 该常量在 Windows 和 macOS 平台不提供。
类型:SocketDomain
static let PACKET
public static let PACKET: SocketDomain = SocketDomain(17)
功能:允许用户空间程序直接访问网络数据包。
注意:
- 该常量在 Windows 和 macOS 平台不提供。
类型:SocketDomain
static let UNIX
public static let UNIX: SocketDomain
功能:本机通信。不同系统下的值分别为:
- Windows: SocketDomain(0)
- 其他情况:SocketDomain(1)
类型:SocketDomain
init(Int32)
public init(domain: Int32)
功能:根据指定通信域值创建套接字通信域。
参数:
- domain: Int32 - 通信域值。
func hashCode()
public func hashCode(): Int64
功能:返回当前 SocketDomain 实例的哈希值。
返回值:
- Int64 - 当前 SocketDomain 实例的哈希值。
func toString()
public func toString(): String
功能:返回当前 SocketDomain 实例的字符串表示。
返回值:
- String - 当前 SocketDomain 实例的字符串表示。
operator func !=(SocketDomain)
public operator func !=(r: SocketDomain): Bool
功能:比较两个 SocketDomain 实例是否不等。
参数:
- r: SocketDomain - 参与比较的 SocketDomain 实例。
返回值:
operator func ==(SocketDomain)
public operator func ==(r: SocketDomain): Bool
功能:比较两个 SocketDomain 实例是否相等。
参数:
- r: SocketDomain - 参与比较的 SocketDomain 实例。
返回值:
struct SocketKeepAliveConfig
public struct SocketKeepAliveConfig <: ToString & Equatable<SocketKeepAliveConfig> {
public let count: UInt32
public let idle: Duration
public let interval: Duration
public init(idle!: Duration = Duration.second * 45, interval!: Duration = Duration.second * 5, count!: UInt32 = 5)
}
功能:TCP KeepAlive 属性配置。
父类型:
let count
public let count: UInt32
功能:查询连接是否失效的报文个数。
类型:UInt32
let idle
public let idle: Duration
功能:允许连接空闲的时长,空闲超长将关闭连接。
类型:Duration
let interval
public let interval: Duration
功能:保活报文发送周期。
类型:Duration
init(Duration, Duration, UInt32)
public init(idle!: Duration = Duration.second * 45, interval!: Duration = Duration.second * 5, count!: UInt32 = 5)
功能:初始化 SocketKeepAliveConfig 实例对象。
参数:
- idle!: Duration - 允许空闲的时长,默认 45 秒。
- interval!: Duration - 保活报文发送周期,默认 45 秒。
- count!: UInt32 - 查询连接是否失效的报文个数, 默认 5 个。
异常:
- IllegalArgumentException - 当配置为空闲状态或设置间隔小于 0 时,抛出异常。
func toString()
public override func toString(): String
功能:将 TCP KeepAlive 属性配置转换为字符串。
返回值:
- String - 转换后的字符串。
operator func !=(SocketKeepAliveConfig)
public override operator func !=(other: SocketKeepAliveConfig): Bool
功能:判断两个 SocketKeepAliveConfig 实例是否不等。
参数:
- other: SocketKeepAliveConfig - 参与比较的 SocketKeepAliveConfig 实例。
返回值:
- Bool - 如果不等,则返回
true;否则,返回false。
operator func ==(SocketKeepAliveConfig)
public override operator func ==(other: SocketKeepAliveConfig): Bool
功能:判断两个 SocketKeepAliveConfig 实例是否相等。
参数:
- other: SocketKeepAliveConfig - 参与比较的 SocketKeepAliveConfig 实例。
返回值:
- Bool - 如果相等,则返回
true;否则,返回false。
struct SocketOptions
public struct SocketOptions {
public static const IPPROTO_TCP: Int32 = 6
public static const IPPROTO_UDP: Int32 = 17
public static const SOL_SOCKET: Int32
public static const SO_BINDTODEVICE: Int32
public static const SO_KEEPALIVE: Int32
public static const SO_LINGER: Int32
public static const SO_RCVBUF: Int32
public static const SO_REUSEADDR: Int32
public static const SO_REUSEPORT: Int32
public static const SO_SNDBUF: Int32
public static const TCP_NODELAY: Int32 = 0x0001
public static const TCP_QUICKACK: Int32
}
功能:SocketOptions 存储了设置套接字选项的一些参数常量方便后续调用。
const IPPROTO_TCP (deprecated)
public static const IPPROTO_TCP: Int32 = 6
功能:常数,用于将套接字选项的 level 层级设为 IPPROTO_TCP。
注意:
未来版本即将废弃不再使用,使用 OptionLevel.TCP 替代。
类型:Int32
const IPPROTO_UDP (deprecated)
public static const IPPROTO_UDP: Int32 = 17
功能:常数,用于将套接字选项的 level 层级设为 IPPROTO_UDP。
注意:
未来版本即将废弃不再使用,使用 OptionLevel.UDP 替代。
类型:Int32
const SOL_SOCKET (deprecated)
public static const SOL_SOCKET: Int32
功能:常数,用于将套接字选项的 level 层级设为 SOL_SOCKET。不同系统下的值分别为:
- macOS: 0xFFFF
- Windows: 0xFFFF
- 其他情况:1
注意:
未来版本即将废弃不再使用,使用 OptionLevel.SOCKET 替代。
类型:Int32
const SO_BINDTODEVICE
public static const SO_BINDTODEVICE: Int32
功能:常数,用于将套接字选项的 optname 设为 SO_BINDTODEVICE。不同系统下的值分别为:
- macOS: 0xFFFF
- Windows: 0xFFFF
- 其他情况:0x0019
类型:Int32
const SO_KEEPALIVE
public static const SO_KEEPALIVE: Int32
功能:常数,用于将套接字选项的 optname 设为 SO_KEEPALIVE。不同系统下的值分别为:
- macOS: 0x0008
- Windows: 0x0008
- 其他情况:0x0009
类型:Int32
const SO_LINGER
public static const SO_LINGER: Int32
功能:常数,用于将套接字选项的 optname 设为 SO_LINGER。不同系统下的值分别为:
- macOS: 0x0080
- Windows: 0x0080
- 其他情况:0x000D
类型:Int32
const SO_RCVBUF
public static const SO_RCVBUF: Int32
功能:常数,用于将套接字选项的 optname 设为 SO_RCVBUF。不同系统下的值分别为:
- macOS: 0x1002
- Windows: 0x1002
- 其他情况:0x0008
类型:Int32
const SO_REUSEADDR
public static const SO_REUSEADDR: Int32
功能:常数,用于将套接字选项的 optname 设为 SO_REUSEADDR。不同系统下的值分别为:
- macOS: 0x0004
- Windows: 0x0004
- 其他情况:0x0002
类型:Int32
const SO_REUSEPORT
public static const SO_REUSEPORT: Int32
功能:常数,用于将套接字选项的 optname 设为 SO_REUSEPORT。不同系统下的值分别为:
- macOS: 0x0200
- Windows: 0xFFFF
- 其他情况:0x000F
类型:Int32
const SO_SNDBUF
public static const SO_SNDBUF: Int32
功能:常数,用于将套接字选项的 optname 设为 SO_SNDBUF。不同系统下的值分别为:
- macOS: 0x1001
- Windows: 0x1001
- 其他情况:0x0007
类型:Int32
const TCP_NODELAY
public static const TCP_NODELAY: Int32 = 0x0001
功能:常数,用于将套接字选项的 optname 设为 TCP_NODELAY。
类型:Int32
const TCP_QUICKACK
public static const TCP_QUICKACK: Int32
功能:常数,用于将套接字选项的 optname 设为 TCP_QUICKACK。不同系统下的值分别为:
- macOS: 0xFFFF
- Windows: 0xFFFF
- 其他情况:0x000C
类型:Int32
struct SocketType
public struct SocketType <: Equatable<SocketType> & ToString & Hashable {
public static let DATAGRAM: SocketType = SocketType(2)
public static let RAW: SocketType = SocketType(3)
public static let SEQPACKET: SocketType = SocketType(5)
public static let STREAM: SocketType = SocketType(1)
public init(`type`: Int32)
}
功能:提供了常用的套接字类型,以及通过指定 Int32 值来构建套接字类型的功能。
父类型:
static let DATAGRAM
public static let DATAGRAM: SocketType = SocketType(2)
功能:数据报套接字类型。
类型:SocketType
static let RAW
public static let RAW: SocketType = SocketType(3)
功能:原始套接字类型。
类型:SocketType
static let SEQPACKET
public static let SEQPACKET: SocketType = SocketType(5)
功能:有序数据包套接字类型。
类型:SocketType
static let STREAM
public static let STREAM: SocketType = SocketType(1)
功能:流式套接字类型。
类型:SocketType
init(Int32)
public init(`type`: Int32)
功能:通过指定套接字类型值创建套接字类型。
参数:
- `type`: Int32 - 套接字类型值。
func hashCode()
public func hashCode(): Int64
功能:返回当前 SocketType 实例的哈希值。
返回值:
- Int64 - 当前 SocketType 实例的哈希值。
func toString()
public func toString(): String
功能:返回当前 SocketType 实例的字符串表示。
返回值:
- String - 当前 SocketType 实例的字符串表示。
operator func !=(SocketType)
public operator func !=(r: SocketType): Bool
功能:判断两个 SocketType 实例是否不等。
参数:
- r: SocketType - 参与比较的 SocketType 实例。
返回值:
operator func ==(SocketType)
public operator func ==(r: SocketType): Bool
功能:判断两个 SocketType 实例是否相等。
参数:
- r: SocketType - 参与比较的 SocketType 实例。
返回值:
异常类
class SocketException
public class SocketException <: IOException {
public init()
public init(message: String)
}
功能:提供套接字相关的异常处理。
父类型:
init()
public init()
功能:创建 SocketException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 SocketException 实例。
参数:
- message: String - 异常提示信息。
class SocketTimeoutException
public class SocketTimeoutException <: Exception {
public init()
public init(message: String)
}
功能:提供套接字操作超时相关的异常处理。
父类型:
init()
public init()
功能:创建 SocketTimeoutException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 SocketTimeoutException 实例。
参数:
- message: String - 异常提示信息。
属性配置使用用例
属性配置
import std.net.*
import std.time.*
import std.sync.*
main (){
try (tcpSocket = TcpSocket("127.0.0.1", 80)) {
tcpSocket.readTimeout = Duration.second
tcpSocket.noDelay = false
tcpSocket.linger = Duration.minute
tcpSocket.keepAlive = SocketKeepAliveConfig(
interval: Duration.second * 7,
count: 15
)
}
}
增加自定义属性
import std.net.*
extend TcpSocket {
public mut prop customNoDelay: Int64 {
get() {
Int64(getSocketOptionIntNative(OptionLevel.TCP, SocketOptions.TCP_NODELAY))
}
set(value) {
setSocketOptionIntNative(OptionLevel.TCP, SocketOptions.TCP_NODELAY, IntNative(value))
}
}
}
main() {
let socket = TcpSocket("127.0.0.1", 0)
socket.customNoDelay = 1
println(socket.customNoDelay)
}
运行结果:
1
TCP 使用示例
import std.net.*
import std.sync.*
let SERVER_PORT: UInt16 = 33333
let syncCounter = SyncCounter(1)
func runTcpServer() {
try (serverSocket = TcpServerSocket(bindAt: SERVER_PORT)) {
serverSocket.bind()
syncCounter.dec()
try (client = serverSocket.accept()) {
let buf = Array<Byte>(10, repeat: 0)
let count = client.read(buf)
// Server read 3 bytes: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
println("Server read ${count} bytes: ${buf}")
}
}
}
main(): Int64 {
let fut = spawn {
runTcpServer()
}
syncCounter.waitUntilZero()
try (socket = TcpSocket("127.0.0.1", SERVER_PORT)) {
socket.connect()
socket.write([1, 2, 3])
}
fut.get()
return 0
}
运行结果:
Server read 3 bytes: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
UDP 使用示例
import std.net.*
import std.sync.*
let SERVER_PORT: UInt16 = 33333
let barrier = Barrier(2)
func runUdpServer() {
try (serverSocket = UdpSocket(bindAt: SERVER_PORT)) {
serverSocket.bind()
barrier.wait()
let buf = Array<Byte>(3, repeat: 0)
let (clientAddr, count) = serverSocket.receiveFrom(buf)
let sender = (clientAddr as IPSocketAddress)?.address.toString() ?? ""
// Server receive 3 bytes: [1, 2, 3] from 127.0.0.1
println("Server receive ${count} bytes: ${buf} from ${sender}")
}
}
main(): Int64 {
let fut = spawn {
runUdpServer()
}
barrier.wait()
try (udpSocket = UdpSocket(bindAt: 0)) { // random port
udpSocket.sendTimeout = Duration.second * 2
udpSocket.bind()
udpSocket.sendTo(
IPSocketAddress("127.0.0.1", SERVER_PORT),
[1, 2, 3]
)
}
fut.get()
return 0
}
运行结果:
Server receive 3 bytes: [1, 2, 3] from 127.0.0.1
UNIX 使用示例
import std.net.*
import std.sync.*
import std.fs.*
let SOCKET_PATH = "/tmp/tmpsock"
let barrier = Barrier(2)
func runUnixServer() {
remove(SOCKET_PATH)
try (serverSocket = UnixServerSocket(bindAt: SOCKET_PATH)) {
serverSocket.bind()
barrier.wait()
try (client = serverSocket.accept()) {
client.write("hello".toArray())
}
}
}
main(): Int64 {
let fut = spawn {
runUnixServer()
}
barrier.wait()
try (socket = UnixSocket(SOCKET_PATH)) {
socket.connect()
let buf = Array<Byte>(10, repeat: 0)
socket.read(buf)
println(String.fromUtf8(buf)) // hello
}
fut.get()
return 0
}
运行结果:
hello
UnixDatagram 使用示例
import std.net.*
import std.sync.*
import std.fs.*
import std.random.*
import std.env.*
let barrier = Barrier(2)
func createTempFile(): String {
let tempDir: Path = getTempDirectory()
let index: String = Random().nextUInt64().toString()
return tempDir.join("tmp${index}").toString()
}
func runUnixDatagramServer(serverPath: String, clientPath: String) {
try (serverSocket = UnixDatagramSocket(bindAt: serverPath)) {
serverSocket.bind()
barrier.wait()
let buf = Array<Byte>(3, repeat: 0)
let (clientAddr, read) = serverSocket.receiveFrom(buf)
if (read == 3 && buf == [1, 2, 3]) {
println("server received")
}
if (clientAddr.toString() == clientPath) {
println("client address correct")
}
}
}
main(): Int64 {
let clientPath = createTempFile()
let serverPath = createTempFile()
let fut = spawn {
runUnixDatagramServer(serverPath, clientPath)
}
barrier.wait()
try (unixSocket = UnixDatagramSocket(bindAt: clientPath)) {
unixSocket.sendTimeout = Duration.second * 2
unixSocket.bind()
unixSocket.connect(serverPath)
unixSocket.send([1, 2, 3])
}
fut.get()
return 0
}
运行结果:
server received
client address correct
std.objectpool
功能介绍
objectpool 包提供了对象缓存和复用的功能。
在面向对象语言中,对象的申请和释放普遍实现复杂,耗时较长,很可能成为应用程序的性能瓶颈。仓颉对象的申请和释放也面临同样的问题。对象池通过缓存、复用对象,减少对象的申请和释放,有效提高程序性能。
本包 ObjectPool 类实现了将指定类型的对象进行缓存和复用,调用 put 方法可将使用完毕的对象放入对象池缓存,调用 get 方法可从对象池缓存中取出待使用的对象。
此外,为了减少竞争,进一步提升对象存取的效率,ObjectPool 在实现中根据当前所在仓颉线程的 id 在不同数组中进行对象存取。
注意:
1、由于
ObjectPool在实现中根据仓颉线程id进行存取,将导致存和取分布在不同仓颉线程的情况下,存入的对象难以被取到。因此应该在存和取均匀分布在各个仓颉线程的场景下使用该对象池。2、暂不支持自动缩减容量。
API列表
类
| 类名 | 功能 |
|---|---|
| ObjectPool (deprecated) | 此类提供了一个并发安全的对象缓存类型,该类型可以储存已经分配内存但未使用的对象。 |
类
class ObjectPool<T> where T <: Object (deprecated)
public class ObjectPool<T> where T <: Object {
public init(newFunc: () -> T, resetFunc!: Option<(T) -> T> = None)
}
功能:此类提供了一个并发安全的对象缓存类型,该类型可以储存已经分配内存但未使用的对象。
当一个对象不需要使用时可以将对象存入 ObjectPool,当需要使用对象时再从该 ObjectPool 中取出。
储存在一个 ObjectPool 中的对象只能是同一种类型。
在一个 ObjectPool 对象的生命周期结束前,该 ObjectPool 对象中存储的对象不会被释放。
注意:
未来版本即将废弃。
示例:
import std.objectpool.*
class City {
var id: Int64 = 0
var name: String = ""
}
func resetCity(c: City): City {
let city = c
city.id = 0
city.name = ""
return city
}
main() {
let cityPool = ObjectPool({ => City()}, resetFunc: resetCity)
let cityA = cityPool.get()
cityA.id = 30
cityA.name = "A"
println("id: ${cityA.id}, name: ${cityA.name}")
cityPool.put(cityA)
}
运行结果:
id: 30, name: A
init(() -> T, Option<(T) -> T>)
public init(newFunc: () -> T, resetFunc!: Option<(T) -> T> = None)
功能:创建新的 ObjectPool 对象。
参数:
- newFunc: () ->T - 当调用 get 方法时,若从 ObjectPool 中获取对象失败,则调用 newFn 创建一个新对象, newFunc 应保证并发安全。
- resetFunc!: Option<(T) ->T> - 调用 get 方法时会调用 resetFunc 重置对象状态,resetFunc 为 None 表示不重置, resetFunc 应保证并发安全。
func get()
public func get(): T
功能:尝试从 ObjectPool 中获取对象, 若从 ObjectPool 中获取对象失败,则调用 newFunc 创建新的对象并返回该对象get 的对象不使用之后应该通过 put 归还给 ObjectPool。
返回值:
- T - 从 ObjectPool 中获取到的对象或调用 newFunc 新建的对象。
func put(T)
public func put(item: T): Unit
功能:尝试将对象放入 ObjectPool 中,不保证一定会将对象放入 ObjectPool在对一个对象调用 put 后不应该再对该对象进行任何操作,否则可能导致不可期问题。
参数:
- item: T - 需要放入 ObjectPool 的对象。
std.overflow
功能介绍
overflow 包提供了整数运算溢出时的处理能力。
在整数运算时,若运算结果大于其类型最大值或小于其类型最小值即是溢出。默认情况下,出现溢出时会抛出异常。
overflow 包提供了四种溢出处理策略,并定义了对应的接口,列举如下:
| 策略 | 接口 | 描述 |
|---|---|---|
| 返回 Option | CheckedOp | 当整数运算出现溢出,返回 None。 |
| 饱和 | SaturatingOp | 当计算结果大于目标类型的 MAX 值,返回 MAX 值;当计算结果小于目标类型的 MIN 值,返回 MIN 值。 |
| 抛出异常 | ThrowingOp | 当整数运算出现溢出,抛出异常。 |
| 高位截断 | WrappingOp | 当整数运算出现溢出,将运算结果中超出目标类型位数的高位截断。 |
overflow 包中通过扩展为所有的整数类型提供了这些接口的实现,用户可以用同样的方式为其他类型实现 overflow 接口。
API 列表
接口
| 接口名 | 功能 |
|---|---|
| CarryingOp | 提供返回整数运算是否发生了截断以及运算结果的接口。 |
| CarryingPow | 提供使用 wrapping 策略的幂运算接口。 |
| CheckedOp | 当整数运算出现溢出,返回 None。 |
| CheckedPow | 提供返回 Option 策略的幂运算接口。 |
| SaturatingOp | 当整数运算出现溢出,饱和处理。 |
| SaturatingPow | 提供饱和策略的幂运算接口。 |
| ThrowingOp | 当整数运算出现溢出,抛出异常。 |
| ThrowingPow | 提供使用抛出异常策略的幂运算接口。 |
| WrappingOp | 当整数运算出现溢出,将运算结果中超出目标类型位数的高位截断。 |
| WrappingPow | 提供使用高位截断策略的幂运算接口。 |
异常类
| 类名 | 功能 |
|---|---|
| OvershiftException | 移位运算时移位位数超过操作数位数时抛出的异常。 |
| UndershiftException | 移位运算时移位位数小于 0 时抛出的异常。 |
接口
interface CarryingOp<T>
public interface CarryingOp<T> {
func carryingAdd(y: T): (Bool, T)
func carryingSub(y: T): (Bool, T)
func carryingMul(y: T): (Bool, T)
func carryingDiv(y: T): (Bool, T)
func carryingMod(y: T): (Bool, T)
func carryingInc(): (Bool, T)
func carryingDec(): (Bool, T)
func carryingNeg(): (Bool, T)
func carryingShl(y: UInt64): (Bool, T)
func carryingShr(y: UInt64): (Bool, T)
}
功能:提供返回整数运算是否发生了截断以及运算结果的接口。
func carryingAdd(T)
func carryingAdd(y: T): (Bool, T)
功能:返回一个元组,元组的第一个元素表示加法运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
参数:
- y: T - 加数。
返回值:
- (Bool, T) - 加法运算是否发生截断以及运算的结果。
func carryingDec()
func carryingDec(): (Bool, T)
功能:返回一个元组,元组的第一个元素表示自减运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
返回值:
- (Bool, T) - 自减运算是否发生截断以及运算的结果。
func carryingDiv(T)
func carryingDiv(y: T): (Bool, T)
功能:返回一个元组,元组的第一个元素表示除法运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
参数:
- y: T - 除数。
返回值:
- (Bool, T) - 除法运算是否发生截断以及运算的结果。
func carryingInc()
func carryingInc(): (Bool, T)
功能:返回一个元组,元组的第一个元素表示自增运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
返回值:
- (Bool, T) - 自增运算是否发生截断以及运算的结果。
func carryingMod(T)
func carryingMod(y: T): (Bool, T)
功能:返回一个元组,元组的第一个元素表示取余运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
参数:
- y: T - 除数。
返回值:
- (Bool, T) - 取余运算是否发生截断以及运算的结果。
func carryingMul(T)
func carryingMul(y: T): (Bool, T)
功能:返回一个元组,元组的第一个元素表示乘法运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
参数:
- y: T - 乘数。
返回值:
- (Bool, T) - 乘法运算是否发生截断以及运算的结果。
func carryingNeg()
func carryingNeg(): (Bool, T)
功能:返回一个元组,元组的第一个元素表示负号运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
返回值:
- (Bool, T) - 负号运算是否发生截断以及运算的结果。
func carryingShl(UInt64)
func carryingShl(y: UInt64): (Bool, T)
功能:返回一个元组,元组的第一个元素表示左移运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- (Bool, T) - 左移运算是否发生截断以及运算的结果。
func carryingShr(UInt64)
func carryingShr(y: UInt64): (Bool, T)
功能:返回一个元组,元组的第一个元素表示右移运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- (Bool, T) - 右移运算是否发生截断以及运算的结果。
func carryingSub(T)
func carryingSub(y: T): (Bool, T)
功能:返回一个元组,元组的第一个元素表示减法运算是否发生了截断,发生截断时为 true,元组的第二个元素是运算的结果。
参数:
- y: T - 减数。
返回值:
- (Bool, T) - 减法运算是否发生截断以及运算的结果。
extend Int16 <: CarryingOp<Int16>
extend Int16 <: CarryingOp<Int16>
功能:为 Int16 实现 CarryingOp 接口。
父类型:
func carryingAdd(Int16)
public func carryingAdd(y: Int16): (Bool, Int16)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int16 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, Int16)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(Int16)
public func carryingDiv(y: Int16): (Bool, Int16)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int16 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, Int16)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(Int16)
public func carryingMod(y: Int16): (Bool, Int16)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int16 - 除数。
返回值:
func carryingMul(Int16)
public func carryingMul(y: Int16): (Bool, Int16)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int16 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, Int16)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, Int16)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, Int16)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(Int16)
public func carryingSub(y: Int16): (Bool, Int16)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int16 - 减数。
返回值:
extend Int32 <: CarryingOp<Int32>
extend Int32 <: CarryingOp<Int32>
功能:为 Int32 实现 CarryingOp 接口。
父类型:
func carryingAdd(Int32)
public func carryingAdd(y: Int32): (Bool, Int32)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int32 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, Int32)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(Int32)
public func carryingDiv(y: Int32): (Bool, Int32)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int32 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, Int32)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(Int32)
public func carryingMod(y: Int32): (Bool, Int32)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int32 - 除数。
返回值:
func carryingMul(Int32)
public func carryingMul(y: Int32): (Bool, Int32)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int32 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, Int32)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, Int32)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, Int32)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(Int32)
public func carryingSub(y: Int32): (Bool, Int32)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int32 - 减数。
返回值:
extend Int64 <: CarryingOp<Int64> & CarryingPow
extend Int64 <: CarryingOp<Int64> & CarryingPow
功能:为 Int64 实现 CarryingOp 接口和 CarryingPow 接口。
父类型:
func carryingAdd(Int64)
public func carryingAdd(y: Int64): (Bool, Int64)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int64 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, Int64)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(Int64)
public func carryingDiv(y: Int64): (Bool, Int64)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int64 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, Int64)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(Int64)
public func carryingMod(y: Int64): (Bool, Int64)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int64 - 除数。
返回值:
func carryingMul(Int64)
public func carryingMul(y: Int64): (Bool, Int64)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int64 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, Int64)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingPow(UInt64)
public func carryingPow(y: UInt64): (Bool, Int64)
功能:使用 wrapping 策略的幂运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 指数。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, Int64)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, Int64)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(Int64)
public func carryingSub(y: Int64): (Bool, Int64)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int64 - 减数。
返回值:
extend Int8 <: CarryingOp<Int8>
extend Int8 <: CarryingOp<Int8>
功能:为 Int8 实现 CarryingOp 接口。
父类型:
func carryingAdd(Int8)
public func carryingAdd(y: Int8): (Bool, Int8)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int8 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, Int8)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(Int8)
public func carryingDiv(y: Int8): (Bool, Int8)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int8 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, Int8)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(Int8)
public func carryingMod(y: Int8): (Bool, Int8)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int8 - 除数。
返回值:
func carryingMul(Int8)
public func carryingMul(y: Int8): (Bool, Int8)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int8 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, Int8)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, Int8)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, Int8)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(Int8)
public func carryingSub(y: Int8):(Bool, Int8)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: Int8 - 减数。
返回值:
extend IntNative <: CarryingOp<IntNative>
extend IntNative <: CarryingOp<IntNative>
功能:为 IntNative 实现 CarryingOp 接口。
父类型:
func carryingAdd(IntNative)
public func carryingAdd(y: IntNative): (Bool, IntNative)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: IntNative - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, IntNative)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(IntNative)
public func carryingDiv(y: IntNative): (Bool, IntNative)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: IntNative - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, IntNative)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(IntNative)
public func carryingMod(y: IntNative): (Bool, IntNative)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: IntNative - 除数。
返回值:
func carryingMul(IntNative)
public func carryingMul(y: IntNative): (Bool, IntNative)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: IntNative - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, IntNative)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, IntNative)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, IntNative)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(IntNative)
public func carryingSub(y: IntNative): (Bool, IntNative)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: IntNative - 减数。
返回值:
extend UInt16 <: CarryingOp<UInt16>
extend UInt16 <: CarryingOp<UInt16>
功能:为 UInt16 实现 CarryingOp 接口。
父类型:
func carryingAdd(UInt16)
public func carryingAdd(y: UInt16): (Bool, UInt16)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt16 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, UInt16)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(UInt16)
public func carryingDiv(y: UInt16): (Bool, UInt16)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt16 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, UInt16)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(UInt16)
public func carryingMod(y: UInt16): (Bool, UInt16)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt16 - 除数。
返回值:
func carryingMul(UInt16)
public func carryingMul(y: UInt16): (Bool, UInt16)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt16 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, UInt16)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, UInt16)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, UInt16)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(UInt16)
public func carryingSub(y: UInt16): (Bool, UInt16)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt16 - 减数。
返回值:
extend UInt32 <: CarryingOp<UInt32>
extend UInt32 <: CarryingOp<UInt32>
功能:为 UInt32 实现 CarryingOp 接口。
父类型:
func carryingAdd(UInt32)
public func carryingAdd(y: UInt32): (Bool, UInt32)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt32 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, UInt32)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(UInt32)
public func carryingDiv(y: UInt32): (Bool, UInt32)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt32 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, UInt32)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(UInt32)
public func carryingMod(y: UInt32): (Bool, UInt32)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt32 - 除数。
返回值:
func carryingMul(UInt32)
public func carryingMul(y: UInt32): (Bool, UInt32)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt32 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, UInt32)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, UInt32)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, UInt32)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(UInt32)
public func carryingSub(y: UInt32): (Bool, UInt32)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt32 - 减数。
返回值:
extend UInt64 <: CarryingOp<UInt64>
extend UInt64 <: CarryingOp<UInt64>
功能:为 UInt64 实现 CarryingOp 接口。
父类型:
func carryingAdd(UInt64)
public func carryingAdd(y: UInt64): (Bool, UInt64)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, UInt64)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(UInt64)
public func carryingDiv(y: UInt64): (Bool, UInt64)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, UInt64)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(UInt64)
public func carryingMod(y: UInt64): (Bool, UInt64)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 除数。
返回值:
func carryingMul(UInt64)
public func carryingMul(y: UInt64): (Bool, UInt64)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, UInt64)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, UInt64)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, UInt64)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(UInt64)
public func carryingSub(y: UInt64): (Bool, UInt64)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 减数。
返回值:
extend UInt8 <: CarryingOp<UInt8>
extend UInt8 <: CarryingOp<UInt8>
功能:为 UInt8 实现 CarryingOp 接口。
父类型:
func carryingAdd(UInt8)
public func carryingAdd(y: UInt8): (Bool, UInt8)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt8 - 加数。
返回值:
func carryingDec()
public func carryingDec(): (Bool, UInt8)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingDiv(UInt8)
public func carryingDiv(y: UInt8): (Bool, UInt8)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt8 - 除数。
返回值:
func carryingInc()
public func carryingInc(): (Bool, UInt8)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingMod(UInt8)
public func carryingMod(y: UInt8): (Bool, UInt8)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt8 - 除数。
返回值:
func carryingMul(UInt8)
public func carryingMul(y: UInt8): (Bool, UInt8)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt8 - 乘数。
返回值:
func carryingNeg()
public func carryingNeg(): (Bool, UInt8)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, UInt8)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, UInt8)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
func carryingSub(UInt8)
public func carryingSub(y: UInt8): (Bool, UInt8)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt8 - 减数。
返回值:
extend UIntNative <: CarryingOp<UIntNative>
extend UIntNative <: CarryingOp<UIntNative>
功能:为 UIntNative 实现 CarryingOp 接口。
父类型:
func carryingAdd(UIntNative)
public func carryingAdd(y: UIntNative): (Bool, UIntNative)
功能:使用 wrapping 策略的加法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UIntNative - 加数。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingDec()
public func carryingDec(): (Bool, UIntNative)
功能:使用 wrapping 策略的自减运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingDiv(UIntNative)
public func carryingDiv(y: UIntNative): (Bool, UIntNative)
功能:使用 wrapping 策略的除法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingInc()
public func carryingInc(): (Bool, UIntNative)
功能:使用 wrapping 策略的自增运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingMod(UIntNative)
public func carryingMod(y: UIntNative): (Bool, UIntNative)
功能:使用 wrapping 策略的取余运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingMul(UIntNative)
public func carryingMul(y: UIntNative): (Bool, UIntNative)
功能:使用 wrapping 策略的乘法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UIntNative - 乘数。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingNeg()
public func carryingNeg(): (Bool, UIntNative)
功能:使用 wrapping 策略的负号运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingShl(UInt64)
public func carryingShl(y: UInt64): (Bool, UIntNative)
功能:使用 wrapping 策略的左移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingShr(UInt64)
public func carryingShr(y: UInt64): (Bool, UIntNative)
功能:使用 wrapping 策略的右移运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
func carryingSub(UIntNative)
public func carryingSub(y: UIntNative): (Bool, UIntNative)
功能:使用 wrapping 策略的减法运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UIntNative - 减数。
返回值:
- (Bool, UIntNative) - 返回一个元组,元组的第一个元素表示运算是否发生了截断,发生截断时为
true,元组的第二个元素是运算的结果。
interface CarryingPow
public interface CarryingPow {
func carryingPow(y: UInt64): (Bool, Int64)
}
功能:提供使用 wrapping 策略的幂运算接口。
func carryingPow(UInt64)
func carryingPow(y: UInt64): (Bool, Int64)
功能:使用 wrapping 策略的幂运算。
当运算出现溢出时,返回 true 和运算结果,否则返回 false 和运算结果。
参数:
- y: UInt64 - 指数。
返回值:
interface CheckedOp<T>
public interface CheckedOp<T> {
func checkedAdd(y: T): ?T
func checkedDec(): ?T
func checkedDiv(y: T): ?T
func checkedInc(): ?T
func checkedMod(y: T): ?T
func checkedMul(y: T): ?T
func checkedNeg(): ?T
func checkedShl(y: UInt64): ?T
func checkedShr(y: UInt64): ?T
func checkedSub(y: T): ?T
}
功能:当整数运算出现溢出,返回 None。
func checkedAdd(T)
func checkedAdd(y: T): ?T
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
参数:
- y: T - 加数。
返回值:
- ?T - 加法运算结果。
func checkedDec()
func checkedDec(): ?T
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
返回值:
- ?T - 自减运算结果。
func checkedDiv(T)
func checkedDiv(y: T): ?T
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- ?T - 除法运算结果。
func checkedInc()
func checkedInc(): ?T
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
返回值:
- ?T - 自增运算结果。
func checkedMod(T)
func checkedMod(y: T): ?T
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- ?T - 取余运算结果。
func checkedMul(T)
func checkedMul(y: T): ?T
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
参数:
- y: T - 乘数。
返回值:
- ?T - 乘法运算结果。
func checkedNeg()
func checkedNeg(): ?T
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
返回值:
- ?T - 负号运算结果。
func checkedShl(UInt64)
func checkedShl(y: UInt64): ?T
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?T.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?T - 左移运算结果。
func checkedShr(UInt64)
func checkedShr(y: UInt64): ?T
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?T.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?T - 右移运算结果。
func checkedSub(T)
func checkedSub(y: T): ?T
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?T.None,否则返回运算结果。
参数:
- y: T - 减数。
返回值:
- ?T - 减法运算结果。
extend Int16 <: CheckedOp<Int16>
extend Int16 <: CheckedOp<Int16>
父类型:
func checkedAdd(Int16)
public func checkedAdd(y: Int16): ?Int16
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
参数:
- y: Int16 - 加数。
返回值:
- ?Int16 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?Int16
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
返回值:
- ?Int16 - 自减运算结果。
func checkedDiv(Int16)
public func checkedDiv(y: Int16): ?Int16
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- ?Int16 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?Int16
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
返回值:
- ?Int16 - 自增运算结果。
func checkedMod(Int16)
public func checkedMod(y: Int16): ?Int16
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- ?Int16 - 取余运算结果。
func checkedMul(Int16)
public func checkedMul(y: Int16): ?Int16
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
参数:
- y: Int16 - 乘数。
返回值:
- ?Int16 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?Int16
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
返回值:
- ?Int16 - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?Int16
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?Int16.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int16 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?Int16
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?Int16.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int16 - 右移运算结果。
func checkedSub(Int16)
public func checkedSub(y: Int16): ?Int16
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?Int16.None,否则返回运算结果。
参数:
- y: Int16 - 减数。
返回值:
- ?Int16 - 减法运算结果。
extend Int32 <: CheckedOp<Int32>
extend Int32 <: CheckedOp<Int32>
父类型:
func checkedAdd(Int32)
public func checkedAdd(y: Int32): ?Int32
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
参数:
- y: Int32 - 加数。
返回值:
- ?Int32 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?Int32
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
返回值:
- ?Int32 - 自减运算结果。
func checkedDiv(Int32)
public func checkedDiv(y: Int32): ?Int32
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- ?Int32 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?Int32
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
返回值:
- ?Int32 - 自增运算结果。
func checkedMod(Int32)
public func checkedMod(y: Int32): ?Int32
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- ?Int32 - 取余运算结果。
func checkedMul(Int32)
public func checkedMul(y: Int32): ?Int32
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
参数:
- y: Int32 - 乘数。
返回值:
- ?Int32 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?Int32
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
返回值:
- ?Int32 - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?Int32
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?Int32.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int32 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?Int32
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?Int32.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int32 - 右移运算结果。
func checkedSub(Int32)
public func checkedSub(y: Int32): ?Int32
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?Int32.None,否则返回运算结果。
参数:
- y: Int32 - 减数。
返回值:
- ?Int32 - 减法运算结果。
extend Int64 <: CheckedOp<Int64> & CheckedPow
extend Int64 <: CheckedOp<Int64> & CheckedPow
功能:为 Int64 实现 CheckedOp 和 CheckedPow 接口。
父类型:
func checkedAdd(Int64)
public func checkedAdd(y: Int64): ?Int64
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: Int64 - 加数。
返回值:
- ?Int64 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?Int64
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
返回值:
- ?Int64 - 自减运算结果。
func checkedDiv(Int64)
public func checkedDiv(y: Int64): ?Int64
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- ?Int64 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?Int64
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
返回值:
- ?Int64 - 自增运算结果。
func checkedMod(Int64)
public func checkedMod(y: Int64): ?Int64
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- ?Int64 - 取余运算结果。
func checkedMul(Int64)
public func checkedMul(y: Int64): ?Int64
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: Int64 - 乘数。
返回值:
- ?Int64 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?Int64
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
返回值:
- ?Int64 - 负号运算结果。
func checkedPow(UInt64)
public func checkedPow(y: UInt64): ?Int64
功能:使用返回 Option 策略的幂运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- ?Int64 - 幂运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?Int64
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int64 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?Int64
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int64 - 右移运算结果。
func checkedSub(Int64)
public func checkedSub(y: Int64): ?Int64
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: Int64 - 减数。
返回值:
- ?Int64 - 减法运算结果。
extend Int8 <: CheckedOp<Int8>
extend Int8 <: CheckedOp<Int8>
父类型:
func checkedAdd(Int8)
public func checkedAdd(y: Int8): ?Int8
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
参数:
- y: Int8 - 加数。
返回值:
- ?Int8 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?Int8
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
返回值:
- ?Int8 - 自减运算结果。
func checkedDiv(Int8)
public func checkedDiv(y: Int8): ?Int8
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- ?Int8 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?Int8
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
返回值:
- ?Int8 - 自增运算结果。
func checkedMod(Int8)
public func checkedMod(y: Int8): ?Int8
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- ?Int8 - 取余运算结果。
func checkedMul(Int8)
public func checkedMul(y: Int8): ?Int8
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
参数:
- y: Int8 - 乘数。
返回值:
- ?Int8 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?Int8
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
返回值:
- ?Int8 - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?Int8
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?Int8.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int8 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?Int8
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?Int8.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?Int8 - 右移运算结果。
func checkedSub(Int8)
public func checkedSub(y: Int8): ?Int8
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?Int8.None,否则返回运算结果。
参数:
- y: Int8 - 减数。
返回值:
- ?Int8 - 减法运算结果。
extend IntNative <: CheckedOp<IntNative>
extend IntNative <: CheckedOp<IntNative>
功能:为 IntNative 实现 CheckedOp 接口。
父类型:
func checkedAdd(IntNative)
public func checkedAdd(y: IntNative): ?IntNative
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
参数:
- y: IntNative - 加数。
返回值:
- ?IntNative - 加法运算结果。
func checkedDec()
public func checkedDec(): ?IntNative
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
返回值:
- ?IntNative - 自减运算结果。
func checkedDiv(IntNative)
public func checkedDiv(y: IntNative): ?IntNative
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- ?IntNative - 除法运算结果。
func checkedInc()
public func checkedInc(): ?IntNative
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
返回值:
- ?IntNative - 自增运算结果。
func checkedMod(IntNative)
public func checkedMod(y: IntNative): ?IntNative
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- ?IntNative - 取余运算结果。
func checkedMul(IntNative)
public func checkedMul(y: IntNative): ?IntNative
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
参数:
- y: IntNative - 乘数。
返回值:
- ?IntNative - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?IntNative
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
返回值:
- ?IntNative - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?IntNative
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?IntNative.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?IntNative - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?IntNative
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?IntNative.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?IntNative - 右移运算结果。
func checkedSub(IntNative)
public func checkedSub(y: IntNative): ?IntNative
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?IntNative.None,否则返回运算结果。
参数:
- y: IntNative - 减数。
返回值:
- ?IntNative - 减法运算结果。
extend UInt16 <: CheckedOp<UInt16>
extend UInt16 <: CheckedOp<UInt16>
父类型:
func checkedAdd(UInt16)
public func checkedAdd(y: UInt16): ?UInt16
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
参数:
- y: UInt16 - 加数。
返回值:
- ?UInt16 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?UInt16
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
返回值:
- ?UInt16 - 自减运算结果。
func checkedDiv(UInt16)
public func checkedDiv(y: UInt16): ?UInt16
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- ?UInt16 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?UInt16
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
返回值:
- ?UInt16 - 自增运算结果。
func checkedMod(UInt16)
public func checkedMod(y: UInt16): ?UInt16
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- ?UInt16 - 取余运算结果。
func checkedMul(UInt16)
public func checkedMul(y: UInt16): ?UInt16
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
参数:
- y: UInt16 - 乘数。
返回值:
- ?UInt16 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?UInt16
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
返回值:
- ?UInt16 - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?UInt16
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?UInt16.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt16 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?UInt16
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?UInt16.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt16 - 右移运算结果。
func checkedSub(UInt16)
public func checkedSub(y: UInt16): ?UInt16
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?UInt16.None,否则返回运算结果。
参数:
- y: UInt16 - 减数。
返回值:
- ?UInt16 - 减法运算结果。
extend UInt32 <: CheckedOp<UInt32>
extend UInt32 <: CheckedOp<UInt32>
父类型:
func checkedAdd(UInt32)
public func checkedAdd(y: UInt32): ?UInt32
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
参数:
- y: UInt32 - 加数。
返回值:
- ?UInt32 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?UInt32
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
返回值:
- ?UInt32 - 自减运算结果。
func checkedDiv(UInt32)
public func checkedDiv(y: UInt32): ?UInt32
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- ?UInt32 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?UInt32
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
返回值:
- ?UInt32 - 自增运算结果。
func checkedMod(UInt32)
public func checkedMod(y: UInt32): ?UInt32
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- ?UInt32 - 取余运算结果。
func checkedMul(UInt32)
public func checkedMul(y: UInt32): ?UInt32
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
参数:
- y: UInt32 - 乘数。
返回值:
- ?UInt32 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?UInt32
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
返回值:
- ?UInt32 - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?UInt32
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?UInt32.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt32 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?UInt32
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?UInt32.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt32 - 右移运算结果。
func checkedSub(UInt32)
public func checkedSub(y: UInt32): ?UInt32
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?UInt32.None,否则返回运算结果。
参数:
- y: UInt32 - 减数。
返回值:
- ?UInt32 - 减法运算结果。
extend UInt64 <: CheckedOp<UInt64>
extend UInt64 <: CheckedOp<UInt64>
父类型:
func checkedAdd(UInt64)
public func checkedAdd(y: UInt64): ?UInt64
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
参数:
- y: UInt64 - 加数。
返回值:
- ?UInt64 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?UInt64
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
返回值:
- ?UInt64 - 自减运算结果。
func checkedDiv(UInt64)
public func checkedDiv(y: UInt64): ?UInt64
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- ?UInt64 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?UInt64
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
返回值:
- ?UInt64 - 自增运算结果。
func checkedMod(UInt64)
public func checkedMod(y: UInt64): ?UInt64
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- ?UInt64 - 取余运算结果。
func checkedMul(UInt64)
public func checkedMul(y: UInt64): ?UInt64
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
参数:
- y: UInt64 - 乘数。
返回值:
- ?UInt64 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?UInt64
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
返回值:
- ?UInt64 - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?UInt64
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?UInt64.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt64 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?UInt64
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?UInt64.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt64 - 右移运算结果。
func checkedSub(UInt64)
public func checkedSub(y: UInt64): ?UInt64
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?UInt64.None,否则返回运算结果。
参数:
- y: UInt64 - 减数。
返回值:
- ?UInt64 - 减法运算结果。
extend UInt8 <: CheckedOp<UInt8>
extend UInt8 <: CheckedOp<UInt8>
父类型:
func checkedAdd(UInt8)
public func checkedAdd(y: UInt8): ?UInt8
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
参数:
- y: UInt8 - 加数。
返回值:
- ?UInt8 - 加法运算结果。
func checkedDec()
public func checkedDec(): ?UInt8
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
返回值:
- ?UInt8 - 自减运算结果。
func checkedDiv(UInt8)
public func checkedDiv(y: UInt8): ?UInt8
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- ?UInt8 - 除法运算结果。
func checkedInc()
public func checkedInc(): ?UInt8
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
返回值:
- ?UInt8 - 自增运算结果。
func checkedMod(UInt8)
public func checkedMod(y: UInt8): ?UInt8
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- ?UInt8 - 取余运算结果。
func checkedMul(UInt8)
public func checkedMul(y: UInt8): ?UInt8
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
参数:
- y: UInt8 - 乘数。
返回值:
- ?UInt8 - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?UInt8
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
返回值:
- ?UInt8 - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?UInt8
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?UInt8.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt8 - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?UInt8
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?UInt8.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UInt8 - 右移运算结果。
func checkedSub(UInt8)
public func checkedSub(y: UInt8): ?UInt8
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?UInt8.None,否则返回运算结果。
参数:
- y: UInt8 - 减数。
返回值:
- ?UInt8 - 减法运算结果。
extend UIntNative <: CheckedOp<UIntNative>
extend UIntNative <: CheckedOp<UIntNative>
功能:为 UIntNative 实现 CheckedOp 接口。
父类型:
func checkedAdd(UIntNative)
public func checkedAdd(y: UIntNative): ?UIntNative
功能:使用返回 Option 策略的加法运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
参数:
- y: UIntNative - 加数。
返回值:
- ?UIntNative - 加法运算结果。
func checkedDec()
public func checkedDec(): ?UIntNative
功能:使用返回 Option 策略的自减运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
返回值:
- ?UIntNative - 自减运算结果。
func checkedDiv(UIntNative)
public func checkedDiv(y: UIntNative): ?UIntNative
功能:使用返回 Option 策略的除法运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- ?UIntNative - 除法运算结果。
func checkedInc()
public func checkedInc(): ?UIntNative
功能:使用返回 Option 策略的自增运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
返回值:
- ?UIntNative - 自增运算结果。
func checkedMod(UIntNative)
public func checkedMod(y: UIntNative): ?UIntNative
功能:使用返回 Option 策略的取余运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- ?UIntNative - 取余运算结果。
func checkedMul(UIntNative)
public func checkedMul(y: UIntNative): ?UIntNative
功能:使用返回 Option 策略的乘法运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
参数:
- y: UIntNative - 乘数。
返回值:
- ?UIntNative - 乘法运算结果。
func checkedNeg()
public func checkedNeg(): ?UIntNative
功能:使用返回 Option 策略的负号运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
返回值:
- ?UIntNative - 负号运算结果。
func checkedShl(UInt64)
public func checkedShl(y: UInt64): ?UIntNative
功能:使用返回 Option 策略的左移运算。
当移位位数大于等于操作数位数时,返回 ?UIntNative.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UIntNative - 左移运算结果。
func checkedShr(UInt64)
public func checkedShr(y: UInt64): ?UIntNative
功能:使用返回 Option 策略的右移运算。
当移位位数大于等于操作数位数时,返回 ?UIntNative.None,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- ?UIntNative - 右移运算结果。
func checkedSub(UIntNative)
public func checkedSub(y: UIntNative): ?UIntNative
功能:使用返回 Option 策略的减法运算。
当运算出现溢出时,返回 ?UIntNative.None,否则返回运算结果。
参数:
- y: UIntNative - 减数。
返回值:
- ?UIntNative - 减法运算结果。
interface CheckedPow
public interface CheckedPow {
func checkedPow(y: UInt64): ?Int64
}
功能:提供返回 Option 策略的幂运算接口。
func checkedPow(UInt64)
func checkedPow(y: UInt64): ?Int64
功能:使用返回 Option 策略的幂运算。
当运算出现溢出时,返回 ?Int64.None,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- ?Int64 - 幂运算结果。
interface SaturatingOp<T>
public interface SaturatingOp<T> {
func saturatingAdd(y: T): T
func saturatingDec(): T
func saturatingDiv(y: T): T
func saturatingInc(): T
func saturatingMod(y: T): T
func saturatingMul(y: T): T
func saturatingNeg(): T
func saturatingShl(y: UInt64): T
func saturatingShr(y: UInt64): T
func saturatingSub(y: T): T
}
功能:当整数运算出现溢出,饱和处理。
func saturatingAdd(T)
func saturatingAdd(y: T): T
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: T - 加数。
返回值:
- T - 加法运算结果。
func saturatingDec()
func saturatingDec(): T
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- T - 自减运算结果。
func saturatingDiv(T)
func saturatingDiv(y: T): T
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- T - 除法运算结果。
func saturatingInc()
func saturatingInc(): T
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- T - 自增运算结果。
func saturatingMod(T)
func saturatingMod(y: T): T
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- T - 取余运算结果。
func saturatingMul(T)
func saturatingMul(y: T): T
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: T - 乘数。
返回值:
- T - 乘法运算结果。
func saturatingNeg()
func saturatingNeg(): T
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- T - 负号运算结果。
func saturatingShl(UInt64)
func saturatingShl(y: UInt64): T
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- T - 左移运算结果。
func saturatingShr(UInt64)
func saturatingShr(y: UInt64): T
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- T - 右移运算结果。
func saturatingSub(T)
func saturatingSub(y: T): T
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: T - 减数。
返回值:
- T - 减法运算结果。
extend Int16 <: SaturatingOp<Int16>
extend Int16 <: SaturatingOp<Int16>
功能:为 Int16 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(Int16)
public func saturatingAdd(y: Int16): Int16
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int16 - 加数。
返回值:
- Int16 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): Int16
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int16 - 自减运算结果。
func saturatingDiv(Int16)
public func saturatingDiv(y: Int16): Int16
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- Int16 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): Int16
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- Int16 - 自增运算结果。
func saturatingMod(Int16)
public func saturatingMod(y: Int16): Int16
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- Int16 - 取余运算结果。
func saturatingMul(Int16)
public func saturatingMul(y: Int16): Int16
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int16 - 乘数。
返回值:
- Int16 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): Int16
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int16 - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): Int16
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int16 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): Int16
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int16 - 右移运算结果。
func saturatingSub(Int16)
public func saturatingSub(y: Int16): Int16
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int16 - 减数。
返回值:
- Int16 - 减法运算结果。
extend Int32 <: SaturatingOp<Int32>
extend Int32 <: SaturatingOp<Int32>
功能:为 Int32 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(Int32)
public func saturatingAdd(y: Int32): Int32
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int32 - 加数。
返回值:
- Int32 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): Int32
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int32 - 自减运算结果。
func saturatingDiv(Int32)
public func saturatingDiv(y: Int32): Int32
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- Int32 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): Int32
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- Int32 - 自增运算结果。
func saturatingMod(Int32)
public func saturatingMod(y: Int32): Int32
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- Int32 - 取余运算结果。
func saturatingMul(Int32)
public func saturatingMul(y: Int32): Int32
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int32 - 乘数。
返回值:
- Int32 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): Int32
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int32 - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): Int32
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int32 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): Int32
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int32 - 右移运算结果。
func saturatingSub(Int32)
public func saturatingSub(y: Int32): Int32
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int32 - 减数。
返回值:
- Int32 - 减法运算结果。
extend Int64 <: SaturatingOp<Int64> & SaturatingPow
extend Int64 <: SaturatingOp<Int64> & SaturatingPow
功能:为 Int64 实现 SaturatingOp 和 SaturatingPow 接口。
父类型:
func saturatingAdd(Int64)
public func saturatingAdd(y: Int64): Int64
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int64 - 加数。
返回值:
- Int64 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): Int64
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int64 - 自减运算结果。
func saturatingDiv(Int64)
public func saturatingDiv(y: Int64): Int64
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- Int64 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): Int64
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- Int64 - 自增运算结果。
func saturatingMod(Int64)
public func saturatingMod(y: Int64): Int64
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- Int64 - 取余运算结果。
func saturatingMul(Int64)
public func saturatingMul(y: Int64): Int64
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int64 - 乘数。
返回值:
- Int64 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): Int64
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int64 - 负号运算结果。
func saturatingPow(UInt64)
public func saturatingPow(y: UInt64): Int64
功能:使用饱和策略的幂运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- Int64 - 幂运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): Int64
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int64 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): Int64
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int64 - 右移运算结果。
func saturatingSub(Int64)
public func saturatingSub(y: Int64): Int64
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int64 - 减数。
返回值:
- Int64 - 减法运算结果。
extend Int8 <: SaturatingOp<Int8>
extend Int8 <: SaturatingOp<Int8>
功能:为 Int8 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(Int8)
public func saturatingAdd(y: Int8): Int8
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int8 - 加数。
返回值:
- Int8 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): Int8
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int8 - 自减运算结果。
func saturatingDiv(Int8)
public func saturatingDiv(y: Int8): Int8
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- Int8 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): Int8
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- Int8 - 自增运算结果。
func saturatingMod(Int8)
public func saturatingMod(y: Int8): Int8
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- Int8 - 取余运算结果。
func saturatingMul(Int8)
public func saturatingMul(y: Int8): Int8
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int8 - 乘数。
返回值:
- Int8 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): Int8
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- Int8 - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): Int8
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int8 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): Int8
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int8 - 右移运算结果。
func saturatingSub(Int8)
public func saturatingSub(y: Int8): Int8
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: Int8 - 减数。
返回值:
- Int8 - 减法运算结果。
extend IntNative <: SaturatingOp<IntNative>
extend IntNative <: SaturatingOp<IntNative>
功能:为 IntNative 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(IntNative)
public func saturatingAdd(y: IntNative): IntNative
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: IntNative - 加数。
返回值:
- IntNative - 加法运算结果。
func saturatingDec()
public func saturatingDec(): IntNative
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- IntNative - 自减运算结果。
func saturatingDiv(IntNative)
public func saturatingDiv(y: IntNative): IntNative
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- IntNative - 除法运算结果。
func saturatingInc()
public func saturatingInc(): IntNative
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- IntNative - 自增运算结果。
func saturatingMod(IntNative)
public func saturatingMod(y: IntNative): IntNative
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- IntNative - 取余运算结果。
func saturatingMul(IntNative)
public func saturatingMul(y: IntNative): IntNative
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: IntNative - 乘数。
返回值:
- IntNative - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): IntNative
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- IntNative - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): IntNative
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- IntNative - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): IntNative
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- IntNative - 右移运算结果。
func saturatingSub(IntNative)
public func saturatingSub(y: IntNative): IntNative
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: IntNative - 减数。
返回值:
- IntNative - 减法运算结果。
extend UInt16 <: SaturatingOp<UInt16>
extend UInt16 <: SaturatingOp<UInt16>
功能:为 UInt16 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(UInt16)
public func saturatingAdd(y: UInt16): UInt16
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt16 - 加数。
返回值:
- UInt16 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): UInt16
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt16 - 自减运算结果。
func saturatingDiv(UInt16)
public func saturatingDiv(y: UInt16): UInt16
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- UInt16 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): UInt16
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- UInt16 - 自增运算结果。
func saturatingMod(UInt16)
public func saturatingMod(y: UInt16): UInt16
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- UInt16 - 取余运算结果。
func saturatingMul(UInt16)
public func saturatingMul(y: UInt16): UInt16
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt16 - 乘数。
返回值:
- UInt16 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): UInt16
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt16 - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): UInt16
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt16 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): UInt16
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt16 - 右移运算结果。
func saturatingSub(UInt16)
public func saturatingSub(y: UInt16): UInt16
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt16 - 减数。
返回值:
- UInt16 - 减法运算结果。
extend UInt32 <: SaturatingOp<UInt32>
extend UInt32 <: SaturatingOp<UInt32>
功能:为 UInt32 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(UInt32)
public func saturatingAdd(y: UInt32): UInt32
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt32 - 加数。
返回值:
- UInt32 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): UInt32
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt32 - 自减运算结果。
func saturatingDiv(UInt32)
public func saturatingDiv(y: UInt32): UInt32
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- UInt32 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): UInt32
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- UInt32 - 自增运算结果。
func saturatingMod(UInt32)
public func saturatingMod(y: UInt32): UInt32
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- UInt32 - 取余运算结果。
func saturatingMul(UInt32)
public func saturatingMul(y: UInt32): UInt32
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt32 - 乘数。
返回值:
- UInt32 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): UInt32
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt32 - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): UInt32
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt32 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): UInt32
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt32 - 右移运算结果。
func saturatingSub(UInt32)
public func saturatingSub(y: UInt32): UInt32
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt32 - 减数。
返回值:
- UInt32 - 减法运算结果。
extend UInt64 <: SaturatingOp<UInt64>
extend UInt64 <: SaturatingOp<UInt64>
功能:为 UInt64 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(UInt64)
public func saturatingAdd(y: UInt64): UInt64
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt64 - 加数。
返回值:
- UInt64 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): UInt64
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt64 - 自减运算结果。
func saturatingDiv(UInt64)
public func saturatingDiv(y: UInt64): UInt64
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- UInt64 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): UInt64
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- UInt64 - 自增运算结果。
func saturatingMod(UInt64)
public func saturatingMod(y: UInt64): UInt64
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- UInt64 - 取余运算结果。
func saturatingMul(UInt64)
public func saturatingMul(y: UInt64): UInt64
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt64 - 乘数。
返回值:
- UInt64 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): UInt64
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt64 - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): UInt64
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt64 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): UInt64
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt64 - 右移运算结果。
func saturatingSub(UInt64)
public func saturatingSub(y: UInt64): UInt64
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt64 - 减数。
返回值:
- UInt64 - 减法运算结果。
extend UInt8 <: SaturatingOp<UInt8>
extend UInt8 <: SaturatingOp<UInt8>
功能:为 UInt8 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(UInt8)
public func saturatingAdd(y: UInt8): UInt8
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt8 - 加数。
返回值:
- UInt8 - 加法运算结果。
func saturatingDec()
public func saturatingDec(): UInt8
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt8 - 自减运算结果。
func saturatingDiv(UInt8)
public func saturatingDiv(y: UInt8): UInt8
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- UInt8 - 除法运算结果。
func saturatingInc()
public func saturatingInc(): UInt8
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- UInt8 - 自增运算结果。
func saturatingMod(UInt8)
public func saturatingMod(y: UInt8): UInt8
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- UInt8 - 取余运算结果。
func saturatingMul(UInt8)
public func saturatingMul(y: UInt8): UInt8
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt8 - 乘数。
返回值:
- UInt8 - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): UInt8
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UInt8 - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): UInt8
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt8 - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): UInt8
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt8 - 右移运算结果。
func saturatingSub(UInt8)
public func saturatingSub(y: UInt8): UInt8
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt8 - 减数。
返回值:
- UInt8 - 减法运算结果。
extend UIntNative <: SaturatingOp<UIntNative>
extend UIntNative <: SaturatingOp<UIntNative>
功能:为 UIntNative 实现 SaturatingOp 接口。
父类型:
func saturatingAdd(UIntNative)
public func saturatingAdd(y: UIntNative): UIntNative
功能:使用饱和策略的加法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UIntNative - 加数。
返回值:
- UIntNative - 加法运算结果。
func saturatingDec()
public func saturatingDec(): UIntNative
功能:使用饱和策略的自减运算。
当运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UIntNative - 自减运算结果。
func saturatingDiv(UIntNative)
public func saturatingDiv(y: UIntNative): UIntNative
功能:使用饱和策略的除法运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- UIntNative - 除法运算结果。
func saturatingInc()
public func saturatingInc(): UIntNative
功能:使用饱和策略的自增运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
返回值:
- UIntNative - 自增运算结果。
func saturatingMod(UIntNative)
public func saturatingMod(y: UIntNative): UIntNative
功能:使用饱和策略的取余运算。
当运算出现上溢时,返回操作数类型的最大值,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- UIntNative - 取余运算结果。
func saturatingMul(UIntNative)
public func saturatingMul(y: UIntNative): UIntNative
功能:使用饱和策略的乘法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UIntNative - 乘数。
返回值:
- UIntNative - 乘法运算结果。
func saturatingNeg()
public func saturatingNeg(): UIntNative
功能:使用饱和策略的负号运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
返回值:
- UIntNative - 负号运算结果。
func saturatingShl(UInt64)
public func saturatingShl(y: UInt64): UIntNative
功能:使用饱和策略的左移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UIntNative - 左移运算结果。
func saturatingShr(UInt64)
public func saturatingShr(y: UInt64): UIntNative
功能:使用饱和策略的右移运算。
当移位位数大于等于操作数位数时,将移位位数置为操作数位数 - 1,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UIntNative - 右移运算结果。
func saturatingSub(UIntNative)
public func saturatingSub(y: UIntNative): UIntNative
功能:使用饱和策略的减法运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UIntNative - 减数。
返回值:
- UIntNative - 减法运算结果。
interface SaturatingPow
public interface SaturatingPow {
public func saturatingPow(y: UInt64): Int64
}
功能:提供饱和策略的幂运算接口。
func saturatingPow(UInt64)
public func saturatingPow(y: UInt64): Int64
功能:使用饱和策略的幂运算。
当运算出现上溢时,返回操作数类型的最大值,运算出现下溢时,返回操作数类型的最小值,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- Int64 - 幂运算结果。
interface ThrowingOp<T>
public interface ThrowingOp<T> {
func throwingAdd(y: T): T
func throwingSub(y: T): T
func throwingMul(y: T): T
func throwingDiv(y: T): T
func throwingMod(y: T): T
func throwingInc(): T
func throwingDec(): T
func throwingNeg(): T
func throwingShl(y: UInt64): T
func throwingShr(y: UInt64): T
}
功能:当整数运算出现溢出,抛出异常。
func throwingAdd(T)
func throwingAdd(y: T): T
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: T - 加数。
返回值:
- T - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
func throwingDec(): T
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- T - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(T)
func throwingDiv(y: T): T
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- T - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
func throwingInc(): T
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- T - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(T)
func throwingMod(y: T): T
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- T - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(T)
func throwingMul(y: T): T
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: T - 乘数。
返回值:
- T - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
func throwingNeg(): T
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- T - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
func throwingShl(y: UInt64): T
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- T - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
func throwingShr(y: UInt64): T
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- T - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(T)
func throwingSub(y: T): T
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: T - 减数。
返回值:
- T - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend Int16 <: ThrowingOp<Int16>
extend Int16 <: ThrowingOp<Int16>
功能:为 Int16 实现 ThrowingOp 接口。
父类型:
func throwingAdd(Int16)
public func throwingAdd(y: Int16): Int16
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int16 - 加数。
返回值:
- Int16 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): Int16
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int16 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(Int16)
public func throwingDiv(y: Int16): Int16
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- Int16 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): Int16
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int16 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(Int16)
public func throwingMod(y: Int16): Int16
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- Int16 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(Int16)
public func throwingMul(y: Int16): Int16
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int16 - 乘数。
返回值:
- Int16 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): Int16
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int16 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): Int16
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int16 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): Int16
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int16 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(Int16)
public func throwingSub(y: Int16): Int16
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int16 - 减数。
返回值:
- Int16 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend Int32 <: ThrowingOp<Int32>
extend Int32 <: ThrowingOp<Int32>
功能:为 Int32 实现 ThrowingOp 接口。
父类型:
func throwingAdd(Int32)
public func throwingAdd(y: Int32): Int32
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int32 - 加数。
返回值:
- Int32 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): Int32
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int32 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(Int32)
public func throwingDiv(y: Int32): Int32
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- Int32 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): Int32
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int32 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(Int32)
public func throwingMod(y: Int32): Int32
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- Int32 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(Int32)
public func throwingMul(y: Int32): Int32
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int32 - 乘数。
返回值:
- Int32 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): Int32
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int32 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): Int32
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int32 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): Int32
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int32 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(Int32)
public func throwingSub(y: Int32): Int32
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int32 - 减数。
返回值:
- Int32 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend Int64 <: ThrowingOp<Int64> & ThrowingPow
extend Int64 <: ThrowingOp<Int64> & ThrowingPow
功能:为 Int64 实现 ThrowingOp 和 ThrowingPow 接口。
父类型:
func throwingAdd(Int64)
public func throwingAdd(y: Int64): Int64
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int64 - 加数。
返回值:
- Int64 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): Int64
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int64 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(Int64)
public func throwingDiv(y: Int64): Int64
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- Int64 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): Int64
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int64 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(Int64)
public func throwingMod(y: Int64): Int64
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- Int64 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(Int64)
public func throwingMul(y: Int64): Int64
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int64 - 乘数。
返回值:
- Int64 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): Int64
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int64 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingPow(UInt64)
public func throwingPow(y: UInt64): Int64
功能:使用抛出异常策略的幂运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- Int64 - 幂运算结果。
异常:
- OverflowException - 当幂运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): Int64
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int64 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): Int64
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int64 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(Int64)
public func throwingSub(y: Int64): Int64
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int64 - 减数。
返回值:
- Int64 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend Int8 <: ThrowingOp<Int8>
extend Int8 <: ThrowingOp<Int8>
功能:为 Int8 实现 ThrowingOp 接口。
父类型:
func throwingAdd(Int8)
public func throwingAdd(y: Int8): Int8
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int8 - 加数。
返回值:
- Int8 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): Int8
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int8 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(Int8)
public func throwingDiv(y: Int8): Int8
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- Int8 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): Int8
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int8 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(Int8)
public func throwingMod(y: Int8): Int8
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- Int8 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(Int8)
public func throwingMul(y: Int8): Int8
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int8 - 乘数。
返回值:
- Int8 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): Int8
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- Int8 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): Int8
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int8 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): Int8
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int8 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(Int8)
public func throwingSub(y: Int8): Int8
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: Int8 - 减数。
返回值:
- Int8 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend IntNative <: ThrowingOp<IntNative>
extend IntNative <: ThrowingOp<IntNative>
功能:为 IntNative 实现 ThrowingOp 接口。
父类型:
func throwingAdd(IntNative)
public func throwingAdd(y: IntNative): IntNative
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: IntNative - 加数。
返回值:
- IntNative - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): IntNative
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- IntNative - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(IntNative)
public func throwingDiv(y: IntNative): IntNative
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- IntNative - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): IntNative
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- IntNative - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(IntNative)
public func throwingMod(y: IntNative): IntNative
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- IntNative - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(IntNative)
public func throwingMul(y: IntNative): IntNative
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: IntNative - 乘数。
返回值:
- IntNative - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): IntNative
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- IntNative - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): IntNative
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- IntNative - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): IntNative
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- IntNative - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(IntNative)
public func throwingSub(y: IntNative): IntNative
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: IntNative - 减数。
返回值:
- IntNative - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend UInt16 <: ThrowingOp<UInt16>
extend UInt16 <: ThrowingOp<UInt16>
功能:为 UInt16 实现 ThrowingOp 接口。
父类型:
func throwingAdd(UInt16)
public func throwingAdd(y: UInt16): UInt16
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt16 - 加数。
返回值:
- UInt16 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): UInt16
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt16 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(UInt16)
public func throwingDiv(y: UInt16): UInt16
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- UInt16 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): UInt16
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt16 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(UInt16)
public func throwingMod(y: UInt16): UInt16
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- UInt16 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(UInt16)
public func throwingMul(y: UInt16): UInt16
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt16 - 乘数。
返回值:
- UInt16 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): UInt16
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt16 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): UInt16
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt16 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): UInt16
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt16 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(UInt16)
public func throwingSub(y: UInt16): UInt16
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt16 - 减数。
返回值:
- UInt16 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend UInt32 <: ThrowingOp<UInt32>
extend UInt32 <: ThrowingOp<UInt32>
功能:为 UInt32 实现 ThrowingOp 接口。
父类型:
func throwingAdd(UInt32)
public func throwingAdd(y: UInt32): UInt32
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt32 - 加数。
返回值:
- UInt32 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): UInt32
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt32 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(UInt32)
public func throwingDiv(y: UInt32): UInt32
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- UInt32 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): UInt32
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt32 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(UInt32)
public func throwingMod(y: UInt32): UInt32
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- UInt32 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(UInt32)
public func throwingMul(y: UInt32): UInt32
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt32 - 乘数。
返回值:
- UInt32 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): UInt32
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt32 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): UInt32
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt32 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): UInt32
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt32 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(UInt32)
public func throwingSub(y: UInt32): UInt32
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt32 - 减数。
返回值:
- UInt32 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend UInt64 <: ThrowingOp<UInt64>
extend UInt64 <: ThrowingOp<UInt64>
功能:为 UInt64 实现 ThrowingOp 接口。
父类型:
func throwingAdd(UInt64)
public func throwingAdd(y: UInt64): UInt64
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 加数。
返回值:
- UInt64 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): UInt64
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt64 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(UInt64)
public func throwingDiv(y: UInt64): UInt64
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- UInt64 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): UInt64
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt64 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(UInt64)
public func throwingMod(y: UInt64): UInt64
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- UInt64 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(UInt64)
public func throwingMul(y: UInt64): UInt64
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 乘数。
返回值:
- UInt64 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): UInt64
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt64 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): UInt64
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt64 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): UInt64
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt64 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(UInt64)
public func throwingSub(y: UInt64): UInt64
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 减数。
返回值:
- UInt64 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend UInt8 <: ThrowingOp<UInt8>
extend UInt8 <: ThrowingOp<UInt8>
功能:为 UInt8 实现 ThrowingOp 接口。
父类型:
func throwingAdd(UInt8)
public func throwingAdd(y: UInt8): UInt8
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt8 - 加数。
返回值:
- UInt8 - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): UInt8
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt8 - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(UInt8)
public func throwingDiv(y: UInt8): UInt8
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- UInt8 - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): UInt8
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt8 - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(UInt8)
public func throwingMod(y: UInt8): UInt8
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- UInt8 - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(UInt8)
public func throwingMul(y: UInt8): UInt8
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt8 - 乘数。
返回值:
- UInt8 - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): UInt8
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UInt8 - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): UInt8
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt8 - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): UInt8
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt8 - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(UInt8)
public func throwingSub(y: UInt8): UInt8
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt8 - 减数。
返回值:
- UInt8 - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
extend UIntNative <: ThrowingOp<UIntNative>
extend UIntNative <: ThrowingOp<UIntNative>
功能:为 UIntNative 实现 ThrowingOp 接口。
父类型:
func throwingAdd(UIntNative)
public func throwingAdd(y: UIntNative): UIntNative
功能:使用抛出异常策略的加法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UIntNative - 加数。
返回值:
- UIntNative - 加法运算结果。
异常:
- OverflowException - 当加法运算出现溢出时,抛出异常。
func throwingDec()
public func throwingDec(): UIntNative
功能:使用抛出异常策略的自减运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UIntNative - 自减运算结果。
异常:
- OverflowException - 当自减运算出现溢出时,抛出异常。
func throwingDiv(UIntNative)
public func throwingDiv(y: UIntNative): UIntNative
功能:使用抛出异常策略的除法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- UIntNative - 除法运算结果。
异常:
- OverflowException - 当除法运算出现溢出时,抛出异常。
func throwingInc()
public func throwingInc(): UIntNative
功能:使用抛出异常策略的自增运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UIntNative - 自增运算结果。
异常:
- OverflowException - 当自增运算出现溢出时,抛出异常。
func throwingMod(UIntNative)
public func throwingMod(y: UIntNative): UIntNative
功能:使用抛出异常策略的取余运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- UIntNative - 取余运算结果。
异常:
- OverflowException - 当取余运算出现溢出时,抛出异常。
func throwingMul(UIntNative)
public func throwingMul(y: UIntNative): UIntNative
功能:使用抛出异常策略的乘法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UIntNative - 乘数。
返回值:
- UIntNative - 乘法运算结果。
异常:
- OverflowException - 当乘法运算出现溢出时,抛出异常。
func throwingNeg()
public func throwingNeg(): UIntNative
功能:使用抛出异常策略的负号运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
返回值:
- UIntNative - 负号运算结果。
异常:
- OverflowException - 当负号运算出现溢出时,抛出异常。
func throwingShl(UInt64)
public func throwingShl(y: UInt64): UIntNative
功能:使用抛出异常策略的左移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UIntNative - 左移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingShr(UInt64)
public func throwingShr(y: UInt64): UIntNative
功能:右移运算。
当移位位数大于等于操作数位数时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 移位位数。
返回值:
- UIntNative - 右移运算结果。
异常:
- OvershiftException - 当移位位数大于等于操作数位数时,抛出异常。
func throwingSub(UIntNative)
public func throwingSub(y: UIntNative): UIntNative
功能:使用抛出异常策略的减法运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UIntNative - 减数。
返回值:
- UIntNative - 减法运算结果。
异常:
- OverflowException - 当减法运算出现溢出时,抛出异常。
interface ThrowingPow
public interface ThrowingPow {
public func throwingPow(y: UInt64): Int64
}
功能:提供使用抛出异常策略的幂运算接口。
func throwingPow(UInt64)
public func throwingPow(y: UInt64): Int64
功能:使用抛出异常策略的幂运算。
当运算出现溢出时,抛出异常,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- Int64 - 幂运算结果。
异常:
- OverflowException - 当幂运算出现溢出时,抛出异常。
interface WrappingOp<T>
public interface WrappingOp<T> {
func wrappingAdd(y: T): T
func wrappingDec(): T
func wrappingDiv(y: T): T
func wrappingInc(): T
func wrappingMod(y: T): T
func wrappingMul(y: T): T
func wrappingNeg(): T
func wrappingShl(y: UInt64): T
func wrappingShr(y: UInt64): T
func wrappingSub(y: T): T
}
功能:当整数运算出现溢出,高位截断。
func wrappingAdd(T)
func wrappingAdd(y: T): T
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: T - 加数。
返回值:
- T - 加法运算结果。
func wrappingDec()
func wrappingDec(): T
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- T - 自减运算结果。
func wrappingDiv(T)
func wrappingDiv(y: T): T
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- T - 除法运算结果。
func wrappingInc()
func wrappingInc(): T
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- T - 自增运算结果。
func wrappingMod(T)
func wrappingMod(y: T): T
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: T - 除数。
返回值:
- T - 取余运算结果。
func wrappingMul(T)
func wrappingMul(y: T): T
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: T - 乘数。
返回值:
- T - 乘法运算结果。
func wrappingNeg()
func wrappingNeg(): T
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- T - 负号运算结果。
func wrappingShl(UInt64)
func wrappingShl(y: UInt64): T
功能:使用高位截断策略的左移运算。
当移位位数大于等于操作数位数时,高位截断。例如,对 Int8 类型的数进行移位,当 y (移位位数)超大于等于 8时,仅取 y 的低 3 位作为移位位数,以此保证移位位数在 0 到 7 之间。
参数:
- y: UInt64 - 移位位数。
返回值:
- T - 左移运算结果。
func wrappingShr(UInt64)
func wrappingShr(y: UInt64): T
功能:使用高位截断策略的右移运算。
当移位位数大于等于操作数位数时,高位截断。例如,对 Int8 类型的数进行移位,当 y (移位位数)超大于等于 8时,仅取 y 的低 3 位作为移位位数,以此保证移位位数在 0 到 7 之间。
参数:
- y: UInt64 - 移位位数。
返回值:
- T - 右移运算结果。
func wrappingSub(T)
func wrappingSub(y: T): T
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: T - 减数。
返回值:
- T - 减法运算结果。
extend Int16 <: WrappingOp<Int16>
extend Int16 <: WrappingOp<Int16>
功能:为 Int16 实现 WrappingOp 接口。
父类型:
func wrappingAdd(Int16)
public func wrappingAdd(y: Int16): Int16
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int16 - 加数。
返回值:
- Int16 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): Int16
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int16 - 自减运算结果。
func wrappingDiv(Int16)
public func wrappingDiv(y: Int16): Int16
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- Int16 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): Int16
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int16 - 自增运算结果。
func wrappingMod(Int16)
public func wrappingMod(y: Int16): Int16
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int16 - 除数。
返回值:
- Int16 - 取余运算结果。
func wrappingMul(Int16)
public func wrappingMul(y: Int16): Int16
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int16 - 乘数。
返回值:
- Int16 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): Int16
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int16 - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): Int16
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 4 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int16 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): Int16
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 4 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int16 - 右移运算结果。
func wrappingSub(Int16)
public func wrappingSub(y: Int16): Int16
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int16 - 减数。
返回值:
- Int16 - 减法运算结果。
extend Int32 <: WrappingOp<Int32>
extend Int32 <: WrappingOp<Int32>
功能:为 Int32 实现 WrappingOp 接口。
父类型:
func wrappingAdd(Int32)
public func wrappingAdd(y: Int32): Int32
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int32 - 加数。
返回值:
- Int32 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): Int32
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int32 - 自减运算结果。
func wrappingDiv(Int32)
public func wrappingDiv(y: Int32): Int32
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- Int32 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): Int32
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int32 - 自增运算结果。
func wrappingMod(Int32)
public func wrappingMod(y: Int32): Int32
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int32 - 除数。
返回值:
- Int32 - 取余运算结果。
func wrappingMul(Int32)
public func wrappingMul(y: Int32): Int32
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int32 - 乘数。
返回值:
- Int32 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): Int32
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int32 - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): Int32
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 5 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int32 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): Int32
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 5 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int32 - 右移运算结果。
func wrappingSub(Int32)
public func wrappingSub(y: Int32): Int32
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int32 - 减数。
返回值:
- Int32 - 减法运算结果。
extend Int64 <: WrappingOp<Int64> & WrappingPow
extend Int64 <: WrappingOp<Int64> & WrappingPow
功能:为 Int64 实现 WrappingOp 和 WrappingPow 接口。
父类型:
func wrappingAdd(Int64)
public func wrappingAdd(y: Int64): Int64
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int64 - 加数。
返回值:
- Int64 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): Int64
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int64 - 自减运算结果。
func wrappingDiv(Int64)
public func wrappingDiv(y: Int64): Int64
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- Int64 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): Int64
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int64 - 自增运算结果。
func wrappingMod(Int64)
public func wrappingMod(y: Int64): Int64
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int64 - 除数。
返回值:
- Int64 - 取余运算结果。
func wrappingMul(Int64)
public func wrappingMul(y: Int64): Int64
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int64 - 乘数。
返回值:
- Int64 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): Int64
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int64 - 负号运算结果。
func wrappingPow(UInt64)
public func wrappingPow(y: UInt64): Int64
功能:使用高位截断策略的幂运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- Int64 - 幂运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): Int64
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 6 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int64 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): Int64
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 6 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int64 - 右移运算结果。
func wrappingSub(Int64)
public func wrappingSub(y: Int64): Int64
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int64 - 减数。
返回值:
- Int64 - 减法运算结果。
extend Int8 <: WrappingOp<Int8>
extend Int8 <: WrappingOp<Int8>
功能:为 Int8 实现 WrappingOp 接口。
父类型:
func wrappingAdd(Int8)
public func wrappingAdd(y: Int8): Int8
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int8 - 加数。
返回值:
- Int8 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): Int8
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int8 - 自减运算结果。
func wrappingDiv(Int8)
public func wrappingDiv(y: Int8): Int8
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- Int8 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): Int8
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int8 - 自增运算结果。
func wrappingMod(Int8)
public func wrappingMod(y: Int8): Int8
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int8 - 除数。
返回值:
- Int8 - 取余运算结果。
func wrappingMul(Int8)
public func wrappingMul(y: Int8): Int8
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int8 - 乘数。
返回值:
- Int8 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): Int8
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- Int8 - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): Int8
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 3 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int8 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): Int8
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 3 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- Int8 - 右移运算结果。
func wrappingSub(Int8)
public func wrappingSub(y: Int8): Int8
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: Int8 - 减数。
返回值:
- Int8 - 减法运算结果。
extend IntNative <: WrappingOp<IntNative>
extend IntNative <: WrappingOp<IntNative>
功能:为 IntNative 实现 WrappingOp 接口。
父类型:
func wrappingAdd(IntNative)
public func wrappingAdd(y: IntNative): IntNative
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: IntNative - 加数。
返回值:
- IntNative - 加法运算结果。
func wrappingDec()
public func wrappingDec(): IntNative
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- IntNative - 自减运算结果。
func wrappingDiv(IntNative)
public func wrappingDiv(y: IntNative): IntNative
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- IntNative - 除法运算结果。
func wrappingInc()
public func wrappingInc(): IntNative
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- IntNative - 自增运算结果。
func wrappingMod(IntNative)
public func wrappingMod(y: IntNative): IntNative
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: IntNative - 除数。
返回值:
- IntNative - 取余运算结果。
func wrappingMul(IntNative)
public func wrappingMul(y: IntNative): IntNative
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: IntNative - 乘数。
返回值:
- IntNative - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): IntNative
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- IntNative - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): IntNative
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低位作为移位位数,具体取的位数取决于当前系统下 IntNative 的位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- IntNative - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): IntNative
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低位作为移位位数,具体取的位数取决于当前系统下 IntNative 的位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- IntNative - 右移运算结果。
func wrappingSub(IntNative)
public func wrappingSub(y: IntNative): IntNative
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: IntNative - 减数。
返回值:
- IntNative - 减法运算结果。
extend UInt16 <: WrappingOp<UInt16>
extend UInt16 <: WrappingOp<UInt16>
功能:为 UInt16 实现 WrappingOp 接口。
父类型:
func wrappingAdd(UInt16)
public func wrappingAdd(y: UInt16): UInt16
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt16 - 加数。
返回值:
- UInt16 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): UInt16
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt16 - 自减运算结果。
func wrappingDiv(UInt16)
public func wrappingDiv(y: UInt16): UInt16
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- UInt16 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): UInt16
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt16 - 自增运算结果。
func wrappingMod(UInt16)
public func wrappingMod(y: UInt16): UInt16
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt16 - 除数。
返回值:
- UInt16 - 取余运算结果。
func wrappingMul(UInt16)
public func wrappingMul(y: UInt16): UInt16
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt16 - 乘数。
返回值:
- UInt16 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): UInt16
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt16 - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): UInt16
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 4 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt16 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): UInt16
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 4 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt16 - 右移运算结果。
func wrappingSub(UInt16)
public func wrappingSub(y: UInt16): UInt16
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt16 - 减数。
返回值:
- UInt16 - 减法运算结果。
extend UInt32 <: WrappingOp<UInt32>
extend UInt32 <: WrappingOp<UInt32>
功能:为 UInt32 实现 WrappingOp 接口。
父类型:
func wrappingAdd(UInt32)
public func wrappingAdd(y: UInt32): UInt32
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt32 - 加数。
返回值:
- UInt32 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): UInt32
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt32 - 自减运算结果。
func wrappingDiv(UInt32)
public func wrappingDiv(y: UInt32): UInt32
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- UInt32 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): UInt32
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt32 - 自增运算结果。
func wrappingMod(UInt32)
public func wrappingMod(y: UInt32): UInt32
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt32 - 除数。
返回值:
- UInt32 - 取余运算结果。
func wrappingMul(UInt32)
public func wrappingMul(y: UInt32): UInt32
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt32 - 乘数。
返回值:
- UInt32 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): UInt32
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt32 - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): UInt32
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 5 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt32 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): UInt32
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 5 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt32 - 右移运算结果。
func wrappingSub(UInt32)
public func wrappingSub(y: UInt32): UInt32
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt32 - 减数。
返回值:
- UInt32 - 减法运算结果。
extend UInt64 <: WrappingOp<UInt64>
extend UInt64 <: WrappingOp<UInt64>
功能:为 UInt64 实现 WrappingOp 接口。
父类型:
func wrappingAdd(UInt64)
public func wrappingAdd(y: UInt64): UInt64
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt64 - 加数。
返回值:
- UInt64 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): UInt64
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt64 - 自减运算结果。
func wrappingDiv(UInt64)
public func wrappingDiv(y: UInt64): UInt64
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- UInt64 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): UInt64
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt64 - 自增运算结果。
func wrappingMod(UInt64)
public func wrappingMod(y: UInt64): UInt64
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt64 - 除数。
返回值:
- UInt64 - 取余运算结果。
func wrappingMul(UInt64)
public func wrappingMul(y: UInt64): UInt64
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt64 - 乘数。
返回值:
- UInt64 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): UInt64
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt64 - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): UInt64
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 6 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt64 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): UInt64
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 6 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt64 - 右移运算结果。
func wrappingSub(UInt64)
public func wrappingSub(y: UInt64): UInt64
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt64 - 减数。
返回值:
- UInt64 - 减法运算结果。
extend UInt8 <: WrappingOp<UInt8>
extend UInt8 <: WrappingOp<UInt8>
功能:为 UInt8 实现 WrappingOp 接口。
父类型:
func wrappingAdd(UInt8)
public func wrappingAdd(y: UInt8): UInt8
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt8 - 加数。
返回值:
- UInt8 - 加法运算结果。
func wrappingDec()
public func wrappingDec(): UInt8
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt8 - 自减运算结果。
func wrappingDiv(UInt8)
public func wrappingDiv(y: UInt8): UInt8
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- UInt8 - 除法运算结果。
func wrappingInc()
public func wrappingInc(): UInt8
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt8 - 自增运算结果。
func wrappingMod(UInt8)
public func wrappingMod(y: UInt8): UInt8
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt8 - 除数。
返回值:
- UInt8 - 取余运算结果。
func wrappingMul(UInt8)
public func wrappingMul(y: UInt8): UInt8
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt8 - 乘数。
返回值:
- UInt8 - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): UInt8
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UInt8 - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): UInt8
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 3 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt8 - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): UInt8
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低 3 位作为移位位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UInt8 - 右移运算结果。
func wrappingSub(UInt8)
public func wrappingSub(y: UInt8): UInt8
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt8 - 减数。
返回值:
- UInt8 - 减法运算结果。
extend UIntNative <: WrappingOp<UIntNative>
extend UIntNative <: WrappingOp<UIntNative>
功能:为 UIntNative 实现 WrappingOp 接口。
父类型:
func wrappingAdd(UIntNative)
public func wrappingAdd(y: UIntNative): UIntNative
功能:使用高位截断策略的加法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UIntNative - 加数。
返回值:
- UIntNative - 加法运算结果。
func wrappingDec()
public func wrappingDec(): UIntNative
功能:使用高位截断策略的自减运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UIntNative - 自减运算结果。
func wrappingDiv(UIntNative)
public func wrappingDiv(y: UIntNative): UIntNative
功能:使用高位截断策略的除法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- UIntNative - 除法运算结果。
func wrappingInc()
public func wrappingInc(): UIntNative
功能:使用高位截断策略的自增运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UIntNative - 自增运算结果。
func wrappingMod(UIntNative)
public func wrappingMod(y: UIntNative): UIntNative
功能:使用高位截断策略的取余运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UIntNative - 除数。
返回值:
- UIntNative - 取余运算结果。
func wrappingMul(UIntNative)
public func wrappingMul(y: UIntNative): UIntNative
功能:使用高位截断策略的乘法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UIntNative - 乘数。
返回值:
- UIntNative - 乘法运算结果。
func wrappingNeg()
public func wrappingNeg(): UIntNative
功能:使用高位截断策略的负号运算。
当运算出现溢出时,高位截断,否则返回运算结果。
返回值:
- UIntNative - 负号运算结果。
func wrappingShl(UInt64)
public func wrappingShl(y: UInt64): UIntNative
功能:使用高位截断策略的左移运算。
当右操作数大于等于左操作数位数时,取右操作数的低位作为移位位数,具体取的位数取决于当前系统下 UIntNative 的位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UIntNative - 左移运算结果。
func wrappingShr(UInt64)
public func wrappingShr(y: UInt64): UIntNative
功能:使用高位截断策略的右移运算。
当右操作数大于等于左操作数位数时,取右操作数的低位作为移位位数,具体取的位数取决于当前系统下 UIntNative 的位数。
参数:
- y: UInt64 - 移位位数。
返回值:
- UIntNative - 右移运算结果。
func wrappingSub(UIntNative)
public func wrappingSub(y: UIntNative): UIntNative
功能:使用高位截断策略的减法运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UIntNative - 减数。
返回值:
- UIntNative - 减法运算结果。
interface WrappingPow
public interface WrappingPow {
public func wrappingPow(y: UInt64): Int64
}
功能:提供使用高位截断策略的幂运算接口。
func wrappingPow(UInt64)
public func wrappingPow(y: UInt64): Int64
功能:使用高位截断策略的幂运算。
当运算出现溢出时,高位截断,否则返回运算结果。
参数:
- y: UInt64 - 指数。
返回值:
- Int64 - 幂运算结果。
异常类
class OvershiftException
public class OvershiftException <: Exception {
public init()
public init(message: String)
}
功能:移位运算中,当移位位数超过操作数位数时抛出的异常。
父类型:
init()
public init()
功能:创建 OvershiftException 实例。
init(String)
public init(message: String)
功能:创建带有异常信息 message 的 OvershiftException 实例。
参数:
- message: String - 异常信息。
class UndershiftException
public class UndershiftException <: Exception {
public init()
public init(message: String)
}
功能:移位运算中,当移位位数小于 0 时抛出的异常。
父类型:
init()
public init()
功能:创建 UndershiftException 实例。
init(String)
public init(message: String)
功能:创建带有异常信息 message 的 UndershiftException 实例。
参数:
- message: String - 异常信息。
返回 Option 策略的示例
下面是返回 Option 策略的示例,示例中尝试运算 Int64.Max 的平方,发生溢出,返回 None。
import std.overflow.*
import std.math.*
main() {
let a: Int64 = Int64.Max
println(a.checkedPow(UInt64(2)))
}
运行结果:
None
饱和策略的示例
下面是饱和策略的示例,示例中尝试运算 UInt16.Max 乘 16,运算结果超过 UInt16 的最大值,发生上溢,故返回 UInt16 的最大值。
import std.overflow.*
import std.math.*
main() {
let a: UInt16 = UInt16.Max
println(a.saturatingMul(16))
}
运行结果:
65535
抛出异常策略的示例
下面是抛出异常策略的示例,示例中尝试运算 Int64.Max + 1,发生溢出,抛出 OverflowException。
import std.overflow.*
import std.math.*
main() {
let a: Int64 = Int64.Max
println(a.throwingAdd(1))
}
运行结果:
An exception has occurred:
OverflowException: add
高位截断策略的示例
下面是高位截断策略的示例,示例中尝试运算 UInt8.Max + 1,UInt8.Max 二进制表示为 0b11111111,UInt8.Max + 1 为 0b100000000,由于 UInt8 只能储存 8 位,高位截断后结果为 0。
import std.overflow.*
import std.math.*
main() {
let a: UInt8 = UInt8.Max
println(a.wrappingAdd(1))
}
运行结果:
0
std.posix
功能介绍
posix 包封装 POSIX 系统调用,提供跨平台的系统操作接口。
本包提供多平台统一操控能力,目前支持 Linux 平台,macOS 平台与Windows 平台。
注意:
未来版本即将废弃本包全部内容。
API 列表
函数
| 函数名 | 功能 | 支持平台 |
|---|---|---|
| open(String, Int32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux Windows macOS |
| open(String, Int32, UInt32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux Windows macOS |
| access(String, Int32) (deprecated) | 判断某个文件是否具有某种权限,具有返回 0,否则返回 -1。 | Linux Windows macOS |
| chdir(String) (deprecated) | 通过指定路径的方式,更改调用进程的当前工作目录。 | Linux Windows macOS |
| chmod(String, UInt32) (deprecated) | 修改文件访问权限。 | Linux Windows macOS |
| chown(String, UInt32, UInt32) (deprecated) | 修改文件所有者和文件所有者所属组。 | Linux macOS |
| close(Int32) (deprecated) | 关闭文件,close 将会触发数据写回磁盘,并释放文件占用的资源。 | Linux Windows macOS |
| creat(String, UInt32) (deprecated) | 创建文件并为其返回文件描述符,或在失败时返回 -1。 | Linux Windows macOS |
| dup(Int32) (deprecated) | 用于复制旧 fd 参数指定的文件描述符并返回。 | Linux Windows macOS |
| dup2(Int32, Int32) (deprecated) | 用于复制 oldfd 参数指定的文件描述符,并将其返回到 newfd 参数。 | Linux Windows macOS |
| faccessat(Int32, String, Int32, Int32) (deprecated) | 判断 fd 对应的文件是否具有某种权限,具有返回 0,否则返回 -1。 | Linux macOS |
| fchdir(Int32) (deprecated) | 通过指定文件路径的描述符,更改调用进程的当前工作目录。 | Linux macOS |
| fchmod(Int32, UInt32) (deprecated) | 修改文件描述符对应的文件访问权限。 | Linux Windows macOS |
| fchmodat(Int32, String, UInt32, Int32) (deprecated) | 修改文件描述符对应的文件访问权限。 | Linux Windows macOS |
| fchown(Int32, UInt32, UInt32) (deprecated) | 修改 fd 对应的文件所有者和文件所有者所属组。 | Linux macOS |
| fchownat(Int32, String, UInt32, UInt32, Int32) (deprecated) | 修改文件描述符对应的文件所有者和文件所有者所属组。 | Linux macOS |
| getcwd() (deprecated) | 获取当前执行进程工作目录的绝对路径。 | Linux Windows macOS |
| getgid() (deprecated) | 获取用户组 ID。 | Linux macOS |
| getgroups(Int32, CPointer<UInt32>) (deprecated) | 获取当前用户所属组的代码。 | Linux macOS |
| gethostname() (deprecated) | 获取主机名称,此名称通常是 TCP/IP 网络上主机的名称。 | Linux macOS |
| getlogin() (deprecated) | 获取当前登录名。 | Linux macOS |
| getos() (deprecated) | 从 /proc/version 文件中获取 Linux 系统的信息。 | Linux |
| getpgid(Int32) (deprecated) | 获取 pid 指定的进程的 PGID,如果 pid 为零,返回调用进程的进程 ID。 | Linux macOS |
| getpgrp() (deprecated) | 获取调用进程的父进程 ID。 | Linux macOS |
| getpid() (deprecated) | 获取调用进程的进程 ID(PID)。 | Linux Windows macOS |
| getppid() (deprecated) | 获取调用进程的父进程 ID。 | Linux macOS |
| getuid() (deprecated) | 获取调用进程的真实用户 ID。 | Linux macOS |
| isBlk(String) (deprecated) | 检查传入对象是否为块设备,并返回布尔类型。 | Linux Windows macOS |
| isChr(String) (deprecated) | 检查传入对象是否为字符设备,返回布尔类型。 | Linux Windows macOS |
| isDir(String) (deprecated) | 检查传入对象是否为文件夹,返回布尔类型。 | Linux Windows macOS |
| isFIFO(String) (deprecated) | 检查传入对象是否为 FIFO 文件,返回布尔类型。 | Linux macOS |
| isLnk(String) (deprecated) | 检查传入对象是否为软链路,返回布尔类型。 | Linux macOS |
| isReg(String) (deprecated) | 检查传入对象是否为普通文件,返回布尔类型。 | Linux Windows macOS |
| isSock(String) (deprecated) | 检查传入对象是否为套接字文件,返回布尔类型。 | Linux macOS |
| isType(String, UInt32) (deprecated) | 检查文件是否为指定模式的文件。 | Linux macOS |
| isatty(Int32) (deprecated) | 用于测试文件描述符是否引用终端,成功时返回 true,否则返回 false。 | Linux Windows macOS |
| kill(Int32, Int32) (deprecated) | 系统调用可用于向任何进程组或进程发送任何信号。 | Linux macOS |
| killpg(Int32, Int32) (deprecated) | 将信号 sig 发送到进程组 pgrp,如果 pgrp 为 0,则 killpg() 将信号发送到调用进程的进程组。 | Linux macOS |
| lchown(String, UInt32, UInt32) (deprecated) | 修改文件链接本身所有者和所有者所属组。 | Linux macOS |
| link(String, String) (deprecated) | 为存在的文件创建链接,一个文件可以有多个指向其 i-node 的目录条目。 | Linux macOS |
| linkat(Int32, String, Int32, String, Int32) (deprecated) | 创建相对于目录文件描述符的文件链接。 | Linux macOS |
| lseek(Int32, Int64, Int32) (deprecated) | 当文件进行读或写时,读或写位置相应增加。 | Linux Windows macOS |
| nice(Int32) (deprecated) | 更改当前线程的优先级。 | Linux macOS |
| open64(String, Int32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux |
| open64(String, Int32, UInt32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux |
| openat(Int32, String, Int32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux macOS |
| openat(Int32, String, Int32, UInt32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux macOS |
| openat64(Int32, String, Int32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux macOS |
| openat64(Int32, String, Int32, UInt32) (deprecated) | 打开文件并为其返回新的文件描述符,或在失败时返回 -1。 | Linux macOS |
| pread(Int32, CPointer<UInt8>, UIntNative, Int32) (deprecated) | 将 fd 指向的文件的 nbyte 字节传输到 buffer 指向的内存中。 | Linux macOS |
| pwrite(Int32, CPointer<UInt8>, UIntNative, Int32) (deprecated) | 将 buffer 指向的内存中 nbyte 字节从指定偏移位置开始写入到 fd 指向的文件。 | Linux macOS |
| read(Int32, CPointer<UInt8>, UIntNative) (deprecated) | 将 fd 指向的文件的 nbyte 字节传输到 buffer 指向的内存中。 | Linux Windows macOS |
| remove(String) (deprecated) | 删除文件或目录。 | Linux Windows macOS |
| rename(String, String) (deprecated) | 重命名文件,如果需要将会移动文件所在目录。 | Linux Windows macOS |
| renameat(Int32, String, Int32, String) (deprecated) | 重命名文件,如果需要将会移动文件所在目录。 | Linux macOS |
| setgid(UInt32) (deprecated) | 设置调用进程的有效组 ID,需要适当的权限。 | Linux macOS |
| sethostname(String) (deprecated) | 设置主机名,仅超级用户可以调用。 | Linux macOS |
| setpgid(Int32, Int32) (deprecated) | 此函数将参数 pid 指定的组 ID 设置为参数 pgrp 指定的组 ID。 | Linux macOS |
| setpgrp() (deprecated) | 将当前进程所属的组 ID 设置为当前进程的进程 ID,此函数等同于调用 setpgid(0, 0)。 | Linux macOS |
| setuid(UInt32) (deprecated) | 设置调用进程的有效用户 ID,需要适当的权限。 | Linux macOS |
| symlink(String, String) (deprecated) | 创建一个名为 symPath 链接到 path 所指定的文件。 | Linux macOS |
| symlinkat(String, Int32, String) (deprecated) | 创建一个名为 symPath 链接到 path 与 fd 所指定的文件。 | Linux macOS |
| ttyname(Int32) (deprecated) | 返回终端名称。 | Linux Windows macOS |
| umask(UInt32) (deprecated) | 设置权限掩码。 | Linux Windows macOS |
| unlink(String) (deprecated) | 从文件系统中删除文件。 | Linux macOS |
| unlinkat(Int32, String, Int32) (deprecated) | 从文件系统中删除文件。 | Linux macOS |
| write(Int32, CPointer<UInt8>, UIntNative) (deprecated) | 将 buffer 指向的内存中 nbyte 字节写入到 fd 指向的文件。 | Linux Windows macOS |
常量
| 常量名 | 功能 | 支持平台 |
|---|---|---|
| AT_EMPTY_PATH (deprecated) | 表示在文件系统中空路径(即没有指定任何文件或目录)时返回的文件描述符,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows |
| AT_FDCWD (deprecated) | 表示在文件系统中相对路径操作的特殊文件描述符常量,用于在使用 *at() 系列系统调用时指定相对路径的解析起点。主要用于 fchmodat、fchownat、linkat、renameat、symlinkat、unlinkat等函数,所属函数参数 fd。 | Linux Windows |
| AT_REMOVEDIR (deprecated) | 如果指定了 AT_REMOVEDIR 标志,则对 pathname 执行等效于 rmdir(2) 的操作,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| AT_SYMLINK_FOLLOW (deprecated) | 表示一个用于控制符号链接解析行为的标志,指定在操作符号链接时是否跟随链接指向的目标文件。通常与 AT_FDCWD 结合使用。若无该标志,大多数系统调用会直接操作符号链接本身(如读取链接路径)。使用该标志后,系统调用会先解析符号链接,然后操作其指向的目标文件。主要用于 linkat、unlinkat 等函数,所属函数参数 fd。 | Linux Windows macOS |
| O_CLOEXEC (deprecated) | 在某些多线程程序中,使用此标志是必不可少的。因为在一个线程同时打开文件描述符,而另一个线程执行 fork(2) 加 execve(2) 场景下使用单独的 fcntl(2) F_SETFD 操作设置 FD_CLOEXEC 标志并不足以避免竞争条件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux macOS |
| O_DIRECTORY (deprecated) | 如果 pathname 指定的文件不是目录,则打开文件失败,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux macOS |
| O_CREAT (deprecated) | 如果要打开的文件不存在,则自动创建该文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| O_DSYNC (deprecated) | 每次写入都会等待物理 I/O 完成,但如果写操作不影响读取刚写入的数据,则不等待文件属性更新,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux macOS |
| O_EXCL (deprecated) | 如同时设置 O_CREAT,则此指令检查文件是否存在。如果文件不存在,则创建文件。否则,打开文件出错。此外,如果同时设置了 O_CREAT 和 O_EXCL,并且要打开的文件是符号链接,则打开文件失败,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| O_NOCTTY (deprecated) | 如要打开的文件是终端设备,则该文件不会成为这个进程的控制终端,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux macOS |
| O_NOFOLLOW (deprecated) | 如 pathname 指定的文件是单符号链接,则打开文件失败,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux macOS |
| O_NONBLOCK (deprecated) | 以非阻塞的方式打开文件,即 I/O 操作不会导致调用进程等待,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux macOS |
| O_SYNC (deprecated) | 同步打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux macOS |
| O_RDONLY (deprecated) | 以只读方式打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| O_RDWR (deprecated) | 以读写模式打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| O_WRONLY (deprecated) | 以只写方式打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| O_APPEND (deprecated) | 读取或写入文件时,数据将从文件末尾移动。即写入的数据将附加到文件的末尾,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| O_RSYNC (deprecated) | 此标志仅影响读取操作,必须与 O_SYNC 或 O_DSYNC 结合使用。如果有必要,它将导致读取调用阻塞,直到正在读取的数据(可能还有元数据)刷新到磁盘,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux |
| O_TRUNC (deprecated) | 如果文件存在且打开可写,则此标志将文件长度清除为 0,文件中以前存储的数据消失,适用函数 open、open64、openat、openat64,所属函数参数 oflag。 | Linux Windows macOS |
| R_OK (deprecated) | 测试文件读权限,适用函数 access,faccessat,所属函数参数 mode。 | Linux Windows macOS |
| W_OK (deprecated) | 测试文件写权限,适用函数 access,faccessat,所属函数参数 mode。 | Linux Windows macOS |
| X_OK (deprecated) | 测试文件执行权限,适用函数 access,faccessat,所属函数参数 mode。 | Linux Windows macOS |
| F_OK (deprecated) | 测试文件是否存在,适用函数 access,faccessat,所属函数参数 mode。 | Linux Windows macOS |
| SEEK_SET (deprecated) | 偏移参数表示新的读写位置,适用函数 lseek,所属函数参数 whence。 | Linux Windows macOS |
| SEEK_CUR (deprecated) | 向当前读或写位置添加偏移量,适用函数 lseek,所属函数参数 whence。 | Linux Windows macOS |
| SEEK_END (deprecated) | 将读写位置设置为文件末尾,并添加偏移量,适用函数 lseek,所属函数参数 whence。 | Linux Windows macOS |
| SIGABRT (deprecated) | 异常终止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGBUS (deprecated) | 硬件故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGFPE (deprecated) | 算术错误,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGKILL (deprecated) | 终止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGCONT (deprecated) | 暂停过程的继续,默认操作继续或忽略,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGHUP (deprecated) | 连接已断开,默认操作已终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGINT (deprecated) | 终端中断字符,默认动作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGQUIT (deprecated) | 终端退出字符,默认动作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGILL (deprecated) | 硬件指令无效,默认动作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGTRAP (deprecated) | 硬件故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGIOT (deprecated) | 硬件故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGIO (deprecated) | 异步 IO,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGPIPE (deprecated) | 写入未读进程的管道,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGALRM (deprecated) | 计时器到期,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGPWR (deprecated) | 电源故障或重启,系统调用无效,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows |
| SIGSEGV (deprecated) | 内存引用无效,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGSTOP (deprecated) | 停止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGSYS (deprecated) | 终止,默认操作终止进程并生成核心转储文件(core dump),用于调试分析,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGTERM (deprecated) | 终止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGSTKFLT (deprecated) | 协处理器堆栈故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows |
| SIGCHLD (deprecated) | 子进程状态更改,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGTSTP (deprecated) | 终端停止符号,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGTTIN (deprecated) | 后台读取控件 tty,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGTTOU (deprecated) | 后台写控制 tty,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGURG (deprecated) | 紧急情况(套接字),忽略默认操作,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGUSR1 (deprecated) | 用户定义的信号,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGUSR2 (deprecated) | 用户定义的信号,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGVTALRM (deprecated) | 虚拟时间警报,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGPROF (deprecated) | 摘要超时,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGWINCH (deprecated) | 终端窗口大小更改,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGXCPU (deprecated) | CPU 占用率超过上限,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| SIGXFSZ (deprecated) | 文件长度超过上限,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。 | Linux Windows macOS |
| S_IRUSR (deprecated) | 表示文件所有者具有读权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IWUSR (deprecated) | 表示文件所有者具有写权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IRGRP (deprecated) | 表示文件用户组具有读权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IWGRP (deprecated) | 表示文件用户组具有写权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IFREG (deprecated) | 文件类型为一般文件,适用函数 isType, 所属函数参数 mode。 | Linux Windows macOS |
| S_IFBLK (deprecated) | 文件类型为块设备,适用函数 isType, 所属函数参数 mode。 | Linux Windows macOS |
| S_IFDIR (deprecated) | 文件类型为目录,适用函数 isType, 所属函数参数 mode。 | Linux Windows macOS |
| S_IFCHR (deprecated) | 文件类型为字符设备,适用函数 isType, 所属函数参数 mode。 | Linux Windows macOS |
| S_IFIFO (deprecated) | 文件类型为 FIFO 文件,适用函数 isType, 所属函数参数 mode。 | Linux Windows macOS |
| S_IFLNK (deprecated) | 文件类型为软连接,适用函数 isType, 所属函数参数 mode。 | Linux Windows macOS |
| S_IFSOCK (deprecated) | 文件类型为套接字文件,适用函数 isType, 所属函数参数 mode。 | Linux Windows macOS |
| S_IROTH (deprecated) | 表示其他用户对文件具有读权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IRWXG (deprecated) | 表示文件用户组具有读、写、执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IRWXU (deprecated) | 表示文件所有者具有读、写和执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IWOTH (deprecated) | 表示其他用户对文件具有写权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IXOTH (deprecated) | 表示其他用户对文件具有执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IRWXO (deprecated) | 表示其他用户对文件具有读、写和执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IXGRP (deprecated) | 表示文件用户组具有执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
| S_IXUSR (deprecated) | 表示文件所有者具有执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。 | Linux Windows macOS |
常量&变量
const AT_EMPTY_PATH (deprecated)
public const AT_EMPTY_PATH: Int32 = 0x1000
功能:表示在文件系统中空路径(即没有指定任何文件或目录)时返回的文件描述符,适用函数 open、open64、openat、openat64,所属函数参数 oflag。
注意:
未来版本即将废弃。
类型:Int32
const AT_FDCWD (deprecated)
public const AT_FDCWD: Int32
功能:表示在文件系统中相对路径操作的特殊文件描述符常量,用于在使用 *at() 系列系统调用时指定相对路径的解析起点。主要用于 fchmodat、fchownat、linkat、renameat、symlinkat、unlinkat等函数,所属函数参数 fd。不同系统下的值分别为:
- macOS:-0x2
- 其他情况:-0x64
注意
未来版本即将废弃。
类型:Int32
const AT_REMOVEDIR (deprecated)
public const AT_REMOVEDIR: Int32 = 0x200
功能:如果指定了 AT_REMOVEDIR 标志,则对 pathname 执行等效于 rmdir(2) 的操作,适用函数 open、open64、openat、openat64,所属函数参数 oflag。
注意:
未来版本即将废弃。
类型:Int32
const AT_SYMLINK_FOLLOW (deprecated)
public const AT_SYMLINK_FOLLOW: Int32
功能:表示一个用于控制符号链接解析行为的标志,指定在操作符号链接时是否跟随链接指向的目标文件。通常与 AT_FDCWD 结合使用。若无该标志,大多数系统调用会直接操作符号链接本身(如读取链接路径)。使用该标志后,系统调用会先解析符号链接,然后操作其指向的目标文件。主要用于 linkat、unlinkat 等函数,所属函数参数 fd。不同系统下的值分别为:
- macOS:0x040
- 其他情况:0x400
注意
未来版本即将废弃。
类型:Int32
const F_OK (deprecated)
public const F_OK: Int32 = 0x0
功能:测试文件是否存在,适用函数 access,faccessat,所属函数参数 mode。
注意:
未来版本即将废弃。
类型:Int32
const O_APPEND (deprecated)
public const O_APPEND: Int32
功能:读取或写入文件时,数据将从文件末尾移动。即写入的数据将附加到文件的末尾,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00000008
- Windows: 0x8
- 其他情况:0x400
注意:
未来版本即将废弃。
类型:Int32
const O_CLOEXEC (deprecated)
public const O_CLOEXEC: Int32
功能:在某些多线程程序中,使用此标志是必不可少的。因为在一个线程同时打开文件描述符,而另一个线程执行 fork(2) 加 execve(2) 场景下使用单独的 fcntl(2) F_SETFD 操作设置 FD_CLOEXEC 标志并不足以避免竞争条件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x01000000
- 其他情况:0x80000
注意:
未来版本即将废弃。
类型:Int32
const O_CREAT (deprecated)
public const O_CREAT: Int32
功能:如果要打开的文件不存在,则自动创建该文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00000200
- Windows: 0x100
- 其他情况:0x40
注意:
未来版本即将废弃。
类型:Int32
const O_DIRECTORY (deprecated)
public const O_DIRECTORY: Int32
功能:如果 pathname 指定的文件不是目录,则打开文件失败,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00100000
- 其他情况:0x80000
注意:
未来版本即将废弃。
类型:Int32
const O_DSYNC (deprecated)
public const O_DSYNC: Int32
功能:每次写入都会等待物理 I/O 完成,但如果写操作不影响读取刚写入的数据,则不等待文件属性更新,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x400000
- 其他情况:0x1000
注意:
未来版本即将废弃。
类型:Int32
const O_EXCL (deprecated)
public const O_EXCL: Int32
功能:如同时设置 O_CREAT,则此指令检查文件是否存在。如果文件不存在,则创建文件。否则,打开文件出错。此外,如果同时设置了 O_CREAT 和 O_EXCL,并且要打开的文件是符号链接,则打开文件失败,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00000800
- Windows: 0x400
- 其他情况:0x80
注意:
未来版本即将废弃。
类型:Int32
const O_NOCTTY (deprecated)
public const O_NOCTTY: Int32
功能:如要打开的文件是终端设备,则该文件不会成为这个进程的控制终端,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00020000
- 其他情况:0x100
注意:
未来版本即将废弃。
类型:Int32
const O_NOFOLLOW (deprecated)
public const O_NOFOLLOW: Int32
功能:如 pathname 指定的文件是单符号连接,则打开文件失败,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00000100
- 其他情况:0x20000
注意:
未来版本即将废弃。
类型:Int32
const O_NONBLOCK (deprecated)
public const O_NONBLOCK: Int32
功能:以非阻塞的方式打开文件,即 I/O 操作不会导致调用进程等待,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00000004
- 其他情况:0x800
注意:
未来版本即将废弃。
类型:Int32
const O_RDONLY (deprecated)
public const O_RDONLY: Int32 = 0x0
功能:以只读方式打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。
注意:
未来版本即将废弃。
类型:Int32
const O_RDWR (deprecated)
public const O_RDWR: Int32 = 0x2
功能:以读写模式打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。
注意:
未来版本即将废弃。
类型:Int32
const O_RSYNC (deprecated)
public const O_RSYNC: Int32 = 0x101000
功能:此标志仅影响读取操作,必须与 O_SYNC 或 O_DSYNC 结合使用。如果有必要,它将导致读取调用阻塞,直到正在读取的数据(可能还有元数据)刷新到磁盘,适用函数 open、open64、openat、openat64,所属函数参数 oflag。
注意:
未来版本即将废弃。
类型:Int32
const O_SYNC (deprecated)
public const O_SYNC: Int32
功能:同步打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x0080
- 其他情况:0x101000
注意:
未来版本即将废弃。
类型:Int32
const O_TRUNC (deprecated)
public const O_TRUNC: Int32
功能:如果文件存在且打开可写,则此标志将文件长度清除为 0,文件中以前存储的数据消失,适用函数 open、open64、openat、openat64,所属函数参数 oflag。不同系统下的值分别为:
- macOS: 0x00000400
- 其他情况:0x200
注意:
未来版本即将废弃。
类型:Int32
const O_WRONLY (deprecated)
public const O_WRONLY: Int32 = 0x1
功能:以只写方式打开文件,适用函数 open、open64、openat、openat64,所属函数参数 oflag。
注意:
未来版本即将废弃。
类型:Int32
const R_OK (deprecated)
public const R_OK: Int32 = 0x4
功能:测试文件读权限,适用函数 access,faccessat,所属函数参数 mode。
注意:
未来版本即将废弃。
类型:Int32
const SEEK_CUR (deprecated)
public const SEEK_CUR: Int32 = 0x1
功能:向当前读或写位置添加偏移量,适用函数 lseek,所属函数参数 whence。
注意:
未来版本即将废弃。
类型:Int32
const SEEK_END (deprecated)
public const SEEK_END: Int32 = 0x2
功能:将读写位置设置为文件末尾,并添加偏移量,适用函数 lseek,所属函数参数 whence。
注意:
未来版本即将废弃。
类型:Int32
const SEEK_SET (deprecated)
public const SEEK_SET: Int32 = 0x0
功能:偏移参数表示新的读写位置,适用函数 lseek,所属函数参数 whence。
注意:
未来版本即将废弃。
类型:Int32
const SIGABRT (deprecated)
public const SIGABRT: Int32 = 0x6
功能:异常终止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGALRM (deprecated)
public const SIGALRM: Int32 = 0xE
功能:计时器到期,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGBUS (deprecated)
public const SIGBUS: Int32
功能:硬件故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0xA
- 其他情况:0x7
注意:
未来版本即将废弃。
类型:Int32
const SIGCHLD (deprecated)
public const SIGCHLD: Int32
功能:子进程状态更改,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x14
- 其他情况:0x11
注意:
未来版本即将废弃。
类型:Int32
const SIGCONT (deprecated)
public const SIGCONT: Int32
功能:暂停过程的继续,默认操作继续或忽略,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x13
- 其他情况:0x12
注意:
未来版本即将废弃。
类型:Int32
const SIGFPE (deprecated)
public const SIGFPE: Int32 = 0x8
功能:算术错误,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGHUP (deprecated)
public const SIGHUP: Int32 = 0x1
功能:连接已断开,默认操作已终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGILL (deprecated)
public const SIGILL: Int32 = 0x4
功能:硬件指令无效,默认动作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGINT (deprecated)
public const SIGINT: Int32 = 0x2
功能:终端中断字符,默认动作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGIO (deprecated)
public const SIGIO: Int32
功能:异步 IO,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x17
- 其他情况:0x1D
注意:
未来版本即将废弃。
类型:Int32
const SIGIOT (deprecated)
public const SIGIOT: Int32 = 0x6
功能:硬件故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGKILL (deprecated)
public const SIGKILL: Int32 = 0x9
功能:终止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGPIPE (deprecated)
public const SIGPIPE: Int32 = 0xD
功能:写入未读进程的管道,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGPROF (deprecated)
public const SIGPROF: Int32 = 0x1B
功能:摘要超时,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGPWR (deprecated)
public const SIGPWR: Int32 = 0x1E
功能:电源故障或重启,系统调用无效,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGQUIT (deprecated)
public const SIGQUIT: Int32 = 0x3
功能:终端退出字符,默认动作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGSEGV (deprecated)
public const SIGSEGV: Int32 = 0xB
功能:内存引用无效,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGSTKFLT (deprecated)
public const SIGSTKFLT: Int32 = 0x10
功能:协处理器堆栈故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGSTOP (deprecated)
public const SIGSTOP: Int32
功能:停止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x11
- 其他情况:0x13
注意:
未来版本即将废弃。
类型:Int32
const SIGSYS (deprecated)
public const SIGSYS: Int32
功能:终止,默认操作终止进程并生成核心转储文件(core dump),用于调试分析,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS:0xC
- 其他情况:0x1F
注意
未来版本即将废弃。
类型:Int32
const SIGTERM (deprecated)
public const SIGTERM: Int32 = 0xF
功能:终止,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGTRAP (deprecated)
public const SIGTRAP: Int32 = 0x5
功能:硬件故障,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGTSTP (deprecated)
public const SIGTSTP: Int32
功能:终端停止符号,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x12
- 其他情况:0x14
注意:
未来版本即将废弃。
类型:Int32
const SIGTTIN (deprecated)
public const SIGTTIN: Int32 = 0x15
功能:后台读取控件 tty,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGTTOU (deprecated)
public const SIGTTOU: Int32 = 0x16
功能:后台写控制 tty,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGURG (deprecated)
public const SIGURG: Int32
功能:紧急情况(套接字),忽略默认操作,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x10
- 其他情况:0x17
注意:
未来版本即将废弃。
类型:Int32
const SIGUSR1 (deprecated)
public const SIGUSR1: Int32
功能:用户定义的信号,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x1E
- 其他情况:0xA
注意:
未来版本即将废弃。
类型:Int32
const SIGUSR2 (deprecated)
public const SIGUSR2: Int32
功能:用户定义的信号,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。不同系统下的值分别为:
- macOS: 0x1F
- 其他情况:0xC
注意:
未来版本即将废弃。
类型:Int32
const SIGVTALRM (deprecated)
public const SIGVTALRM: Int32 = 0x1A
功能:虚拟时间警报,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGWINCH (deprecated)
public const SIGWINCH: Int32 = 0x1C
功能:终端窗口大小更改,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGXCPU (deprecated)
public const SIGXCPU: Int32 = 0x18
功能:CPU 占用率超过上限,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const SIGXFSZ (deprecated)
public const SIGXFSZ: Int32 = 0x19
功能:文件长度超过上限,默认操作终止,适用函数 kill,killpg,所属函数参数 sig。
注意:
未来版本即将废弃。
类型:Int32
const S_IFBLK (deprecated)
public const S_IFBLK: UInt32 = 0x6000
功能:文件类型为块设备,适用函数 isType, 所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const S_IFCHR (deprecated)
public const S_IFCHR: UInt32 = 0x2000
功能:文件类型为字符设备,适用函数 isType, 所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const S_IFDIR (deprecated)
public const S_IFDIR: UInt32 = 0x4000
功能:文件类型为目录,适用函数 isType, 所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const S_IFIFO (deprecated)
public const S_IFIFO: UInt32 = 0x1000
功能:文件类型为 FIFO 文件,适用函数 isType, 所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const S_IFLNK (deprecated)
public const S_IFLNK: UInt32 = 0xA000
功能:文件类型为软连接,适用函数 isType, 所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const S_IFREG (deprecated)
public const S_IFREG: UInt32 = 0x8000
功能:文件类型为一般文件,适用函数 isType, 所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const S_IFSOCK (deprecated)
public const S_IFSOCK: UInt32 = 0xC000
功能:文件类型为套接字文件,适用函数 isType, 所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const S_IRGRP (deprecated)
public const S_IRGRP: UInt32 = 0x20
功能:表示文件用户组具有读权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IROTH (deprecated)
public const S_IROTH: UInt32 = 0x4
功能:表示其他用户对文件具有读权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IRUSR (deprecated)
public const S_IRUSR: UInt32 = 0x100
功能:表示文件所有者具有读权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IRWXG (deprecated)
public const S_IRWXG: UInt32 = 0x38
功能:表示文件用户组具有读、写、执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IRWXO (deprecated)
public const S_IRWXO: UInt32 = 0x7
功能:表示其他用户对文件具有读、写和执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IRWXU (deprecated)
public const S_IRWXU: UInt32 = 0x1C0
功能:表示文件所有者具有读、写和执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IWGRP (deprecated)
public const S_IWGRP: UInt32 = 0x10
功能:表示文件用户组具有写权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IWOTH (deprecated)
public const S_IWOTH: UInt32 = 0x2
功能:表示其他用户对文件具有写权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IWUSR (deprecated)
public const S_IWUSR: UInt32 = 0x80
功能:表示文件所有者具有写权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IXGRP (deprecated)
public const S_IXGRP: UInt32 = 0x8
功能:表示文件用户组具有执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IXOTH (deprecated)
public const S_IXOTH: UInt32 = 0x1
功能:表示其他用户对文件具有执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
类型:UInt32
const S_IXUSR (deprecated)
public const S_IXUSR: UInt32 = 0x40
功能:表示文件所有者具有执行权限,适用函数 open,open64,openat,openat64,chmod(mode),fchmod(mode),fchmodat(mode),creat, 所属函数参数 flag。
注意:
未来版本即将废弃。
const W_OK (deprecated)
public const W_OK: Int32 = 0x2
功能:测试文件写权限,适用函数 access,faccessat,所属函数参数 mode。
注意:
未来版本即将废弃。
类型:UInt32
const X_OK (deprecated)
public const X_OK: Int32 = 0x1
功能:测试文件执行权限,适用函数 access,faccessat,所属函数参数 mode。
注意:
未来版本即将废弃。
类型:Int32
函数
func open(String, Int32) (deprecated)
public func `open`(path: String, oflag: Int32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。
当文件打开方式参数 oflag 设置为 O_CREAT 时,可以通过参数设置文件权限。
O_RDONLY、O_RDWR、O_WRONLY 作为 oflag 取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func open(String, Int32, UInt32) (deprecated)
public func `open`(path: String, oflag: Int32, flag: UInt32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。path 代表文件路径,oflag 代表文件打开的方式,其中 O_RDONLY、O_RDWR、O_WRONLY 作为 oflag 取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 操作。
当文件打开方式参数 oflag 设置为 O_CREAT 时,可以通过参数设置文件权限。
O_RDONLY、O_RDWR、O_WRONLY 作为 oflag 取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
- oflag: Int32 - 文件打开的方式。
- flag: UInt32 - 如果
oflag设置了 O_CREAT 并且需要创建新文件,则flag参数标识对新文件的权限,否则flag不改变文件权限。
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func access(String, Int32) (deprecated)
public func access(path: String, mode: Int32): Int32
功能:判断某个文件是否具有某种权限,具有返回 0,否则返回 -1。
mode 为指定权限,传入类型 R_OK、W_OK、X_OK、F_OK。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 文件具有待检查的权限返回
0,否则返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func chdir(String) (deprecated)
public func chdir(path: String): Int32
功能:通过指定路径的方式,更改调用进程的当前工作目录。
注意:
未来版本即将废弃。
参数:
- path: String - 改变后的路径。
返回值:
- Int32 - 设置成功,返回
0,设置失败, 返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func chmod(String, UInt32) (deprecated)
public func chmod(path: String, mode: UInt32): Int32
功能:修改文件访问权限。
在 Windows 环境下:
- 所有文件和目录都是可读的,chmod() 不能更改文件的可读权限;
- 在
Windows环境下,文件的可执行权限通过文件扩展名设置,所有目录都是可执行的,chmod() 不能更改文件和目录的可执行权限。
注意:
未来版本即将废弃。
参数:
返回值:
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func chown(String, UInt32, UInt32) (deprecated)
public func chown(path: String, owner: UInt32, group: UInt32): Int32
功能:修改文件所有者和文件所有者所属组。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 操作成功时返回
0,失败时返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func close(Int32) (deprecated)
public func close(fd: Int32): Int32
功能:关闭文件,close 将会触发数据写回磁盘,并释放文件占用的资源。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
返回值:
- Int32 - 成功时返回
0,失败时返回-1。
func creat(String, UInt32) (deprecated)
public func creat(path: String, flag: UInt32): Int32
功能:创建文件并为其返回文件描述符,或在失败时返回 -1。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 返回文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func dup(Int32) (deprecated)
public func dup(fd: Int32): Int32
功能:用于复制旧 fd 参数指定的文件描述符并返回。此新文件描述符和旧的参数 fd 引用同一文件,共享文件各种状态。共享所有的锁定、读写位置和各项权限或标志等。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
返回值:
- Int32 - 返回最小且未使用的文件描述符,执行失败时返回
-1。
func dup2(Int32, Int32) (deprecated)
public func dup2(fd: Int32, fd2: Int32): Int32
功能:用于复制 oldfd 参数指定的文件描述符,并将其返回到 newfd 参数。如果参数 newfd 是打开的文件描述符,则 newfd 指定的文件将首先关闭。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 -
fd2文件描述符。
func faccessat(Int32, String, Int32, Int32) (deprecated)
public func faccessat(fd: Int32, path: String, mode: Int32, flag: Int32): Int32
功能:判断 fd 对应的文件是否具有某种权限,具有返回 0,否则返回 -1。
mode 为指定权限,传入类型 R_OK、W_OK、X_OK、F_OK。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
- path: String - 文件路径。
- mode: Int32 - 待检查的权限。
- flag: Int32 - 将以下一个或多个值按位或运算获取。
(512)使用有效的用户和组ID执行访问检查,默认情况下使用有效ID;(256)如果路径名是符号链接,不会取消引用而是返回有关链接本身信息。
返回值:
- Int32 - 文件具有待检查的权限返回
0,否则返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func fchdir(Int32) (deprecated)
public func fchdir(fd: Int32): Int32
功能:通过指定文件路径的描述符,更改调用进程的当前工作目录。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 改变后的文件路径的描述符。
返回值:
- Int32 - 设置成功,返回
0,设置失败, 返回-1。
func fchmod(Int32, UInt32) (deprecated)
public func fchmod(fd: Int32, mode: UInt32): Int32
功能:修改文件描述符对应的文件访问权限。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 操作成功时返回
0,失败时返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func fchmodat(Int32, String, UInt32, Int32) (deprecated)
public func fchmodat(fd: Int32, path: String, mode: UInt32, flag: Int32): Int32
功能:修改文件描述符对应的文件访问权限。
path为相对路径且fd为特殊值AT_FDCWD时,则路径将相对于调用进程的当前工作目录。path为相对路径且fd非AT_FDCWD时,则路径将相对于fd引用的文件所属目录。path为绝对路径时fd参数将被忽略。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
- path: String - 文件路径。
- mode: UInt32 - 要修改的权限。
- flag: Int32 - 取值可为
0,或(256)如果路径名是符号链接,不会取消引用它,而是返回有关链接本身的信息。
返回值:
- Int32 - 操作成功时返回
0,失败时返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func fchown(Int32, UInt32, UInt32) (deprecated)
public func fchown(fd: Int32, owner: UInt32, group: UInt32): Int32
功能:修改 fd 对应的文件所有者和文件所有者所属组。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 操作成功时返回
0,失败时返回-1。
func fchownat(Int32, String, UInt32, UInt32, Int32) (deprecated)
public func fchownat(fd: Int32, path: String, owner: UInt32, group: UInt32, flag: Int32): Int32
功能:修改文件描述符对应的文件所有者和文件所有者所属组。
path为相对路径且fd为特殊值AT_FDCWD时,则路径将相对于调用进程的当前工作目录。path为相对路径且fd非AT_FDCWD时,则路径将相对于fd引用的文件所属目录。path为绝对路径时fd参数将被忽略。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
- path: String - 文件路径。
- owner: UInt32 - 所有者
uid。 - group: UInt32 - 指定
gid参数。 - flag: Int32 - 取值可为
0,或(256)如果路径名是符号链接,不会取消引用它,而是返回有关链接本身的信息。
返回值:
- Int32 - 操作成功时返回
0,失败时返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func getcwd() (deprecated)
public func getcwd(): String
功能:获取当前执行进程工作目录的绝对路径。
注意:
未来版本即将废弃。
返回值:
- String - 操作成功,返回包含路径信息的字符串,操作失败则返回空字符串。
func getgid() (deprecated)
public func getgid(): UInt32
功能:获取用户组 ID。
注意:
未来版本即将废弃。
返回值:
- UInt32 - 当前用户组
ID。
func getgroups(Int32, CPointer<UInt32>) (deprecated)
public unsafe func getgroups(size: Int32, gidArray: CPointer<UInt32>): Int32
功能:获取当前用户所属组的代码。
如果 gidArray 参数大小的值为零,则函数仅返回表示用户所属的组数,不会向 gidArray 中放入 gid。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 执行成功,返回组代码,执行失败, 返回
-1。
func gethostname() (deprecated)
public func gethostname(): String
功能:获取主机名称,此名称通常是 TCP/IP 网络上主机的名称。
注意:
未来版本即将废弃。
返回值:
- String - 获取到的主机的名称字符串, 获取失败则返回空字符串。
func getlogin() (deprecated)
public func getlogin(): String
功能:获取当前登录名。
注意:
未来版本即将废弃。
返回值:
- String - 操作成功时返回登录名,失败时返回空字串。
func getos() (deprecated)
public func getos(): String
功能:从 /proc/version 文件中获取 Linux 系统的信息。例如: Linux version 4.15.0-142-generic (buildd@lgw01-amd64-036) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #146-Ubuntu SMP Tue Apr 13 01:11:19 UTC 2021。
注意:
未来版本即将废弃。
返回值:
- String - 获取到的 Linux 系统的信息字符串。
func getpgid(Int32) (deprecated)
public func getpgid(pid: Int32): Int32
功能:获取 pid 指定的进程的 PGID,如果 pid 为零,返回调用进程的进程 ID。
注意:
未来版本即将废弃。
参数:
- pid: Int32 - 目标进程
ID。
返回值:
- Int32 - 执行成功,返回进程组
ID,执行失败, 返回-1。
func getpgrp() (deprecated)
public func getpgrp(): Int32
功能:获取调用进程的父进程 ID。
注意:
未来版本即将废弃。
返回值:
- Int32 - 返回调用进程的父进程
ID。
func getpid() (deprecated)
public func getpid(): Int32
功能:获取调用进程的进程 ID(PID)。
注意:
未来版本即将废弃。
返回值:
- Int32 - 返回调用进程的进程
ID(PID)。
func getppid() (deprecated)
public func getppid(): Int32
功能:获取调用进程的父进程 ID。
注意:
未来版本即将废弃。
返回值:
- Int32 - 返回调用进程的父进程
ID。
func getuid() (deprecated)
public func getuid(): UInt32
功能:获取调用进程的真实用户 ID。
注意:
未来版本即将废弃。
返回值:
- UInt32 - 当前真实用户
ID。
func isBlk(String) (deprecated)
public func isBlk(path: String): Bool
功能:检查传入对象是否为块设备,并返回布尔类型。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Bool - 如果是,返回
true,否则返回false。
func isChr(String) (deprecated)
public func isChr(path: String): Bool
功能:检查传入对象是否为字符设备,返回布尔类型。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Bool - 如果是,返回
true,否则返回false。
func isDir(String) (deprecated)
public func isDir(path: String): Bool
功能:检查传入对象是否为文件夹,返回布尔类型。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Bool - 如果是,返回
true,否则返回false。
func isFIFO(String) (deprecated)
public func isFIFO(path: String): Bool
功能:检查传入对象是否为 FIFO 文件,返回布尔类型。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Bool - 如果是,返回
true,否则返回false。
func isLnk(String) (deprecated)
public func isLnk(path: String): Bool
功能:检查传入对象是否为软链路,返回布尔类型。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Bool - 如果是,返回
true,否则返回false。
func isReg(String) (deprecated)
public func isReg(path: String): Bool
功能:检查传入对象是否为普通文件,返回布尔类型。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Bool - 如果是,返回
true,否则返回false。
func isSock(String) (deprecated)
public func isSock(path: String): Bool
功能:检查传入对象是否为套接字文件,返回布尔类型。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Bool - 如果是,返回
true,否则返回false。
func isType(String, UInt32) (deprecated)
public func isType(path: String, mode: UInt32): Bool
功能:检查文件是否为指定模式的文件。如果是,返回 ture,否则返回 false。根据模式的不同值确定不同的类型。
注意:
未来版本即将废弃。
参数:
返回值:
- Bool - 如果是指定模式的文件,返回
true,否则返回false。
func isatty(Int32) (deprecated)
public func isatty(fd: Int32): Bool
功能:用于测试文件描述符是否引用终端,成功时返回 true,否则返回 false。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
返回值:
- Bool - 操作成功时返回
true,否则返回false。
func kill(Int32, Int32) (deprecated)
public func kill(pid: Int32, sig: Int32): Int32
功能:系统调用可用于向任何进程组或进程发送任何信号。
- 如果
pid大于0,则信号sig将发送到pid对应的进程。 - 如果
pid等于0,然后sig被发送到调用进程的进程组中的每个进程。 - 如果
pid等于-1,则sig被发送到调用进程有权发送信号的每个进程。 - 如果
pid小于-1,则将sig发送到ID为-pid的进程组中的每个进程。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 操作成功时返回
0,否则返回-1。
func killpg(Int32, Int32) (deprecated)
public func killpg(pgid: Int32, sig: Int32): Int32
功能:将信号 sig 发送到进程组 pgrp,如果 pgrp 为 0,则 killpg() 将信号发送到调用进程的进程组。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 操作成功时返回
0,否则返回-1。
func lchown(String, UInt32, UInt32) (deprecated)
public func lchown(path: String, owner: UInt32, group: UInt32): Int32
功能:修改文件链接本身所有者和所有者所属组。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 操作成功时返回
0,失败时返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func link(String, String) (deprecated)
public func link(path: String, newpath: String): Int32
功能:为存在的文件创建链接,一个文件可以有多个指向其 i-node 的目录条目。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
path或newPath包含空字符时,抛出异常。
func linkat(Int32, String, Int32, String, Int32) (deprecated)
public func linkat(fd: Int32, path: String, nfd: Int32, newPath: String, lflag: Int32): Int32
功能:创建相对于目录文件描述符的文件链接。
path为相对路径且fd为特殊值AT_FDCWD时,则路径将相对于调用进程的当前工作目录。path为相对路径且fd非AT_FDCWD时,则路径将相对于fd引用的文件所属目录。path为绝对路径时fd参数将被忽略。newPath的场景与path相同,只是当newPath为相对路径时是相对于nfd引用的文件所属目录。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
- path: String - 文件路径。
- nfd: Int32 - 其他文件描述符。
- newPath: String - 其他文件路径,如果
newpath存在,则不会覆盖。 - lflag: Int32 - AT_EMPTY_PATH 或
AT_SYMLINK_FOLLOW或0。
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
path或newPath包含空字符时,抛出异常。
func lseek(Int32, Int64, Int32) (deprecated)
public func lseek(fd: Int32, offset: Int64, whence: Int32): Int64
功能:当文件进行读或写时,读或写位置相应增加。本函数用于控制文件的读或写位置。调用成功时,返回当前读写位置,即从文件开头开始的字节数。如果发生错误,返回 -1。
注意:
未来版本即将废弃。
参数:
返回值:
- Int64 - 调用成功时,返回当前读写位置,即从文件开头开始的字节数。
func nice(Int32) (deprecated)
public func nice(inc: Int32): Int32
功能:更改当前线程的优先级。
成功时返回新值,失败时返回 -1。 inc 在值大于 19 时,返回最大值 19。
只有超级用户才能使用负的 inc 值,表示优先级高,进程执行得更快。 inc 代表当前进程的优先级,取值的范围是 +19(低优先级)到 -20。
注意:
未来版本即将废弃。
参数:
- inc: Int32 - 当前进程的优先级, 值的范围是
+19(低优先级)到-20。
返回值:
- Int32 - 返回新优先级值。
func open64(String, Int32) (deprecated)
public func open64(path: String, oflag: Int32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。
- 当文件打开方式参数
oflag设置为 O_CREAT 时,可以通过参数设置文件权限。 - O_RDONLY、O_RDWR、O_WRONLY 作为
oflag取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func open64(String, Int32, UInt32) (deprecated)
public func open64(path: String, oflag: Int32, flag: UInt32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。
- 当文件打开方式参数
oflag设置为 O_CREAT 时,可以通过参数设置文件权限。 - O_RDONLY、O_RDWR、O_WRONLY 作为
oflag取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
- oflag: Int32 - 文件打开的方式。
- flag: UInt32 - 如果
oflag设置了 O_CREAT 并且需要创建新文件,则flag参数标识对新文件的权限,否则flag不改变文件权限。
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func openat(Int32, String, Int32) (deprecated)
public func openat(fd: Int32, path: String, oflag: Int32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。
- 当文件打开方式参数
oflag设置为 O_CREAT 时,可以通过参数设置文件权限。 - O_RDONLY、O_RDWR、O_WRONLY 作为
oflag取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func openat(Int32, String, Int32, UInt32) (deprecated)
public func openat(fd: Int32, path: String, oflag: Int32, flag: UInt32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。
- 当文件打开方式参数
oflag设置为 O_CREAT 时,可以通过参数设置文件权限。 - O_RDONLY、O_RDWR、O_WRONLY 作为
oflag取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 路径的文件描述符。
- path: String - 文件路径。
- oflag: Int32 - 文件打开的方式。
- flag: UInt32 - 如果
oflag设置了 O_CREAT 并且需要创建新文件,则flag参数标识对新文件的权限,否则flag不改变文件权限。
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func openat64(Int32, String, Int32) (deprecated)
public func openat64(fd: Int32, path: String, oflag: Int32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。
- 当文件打开方式参数
oflag设置为 O_CREAT 时,可以通过参数设置文件权限。 - O_RDONLY、O_RDWR、O_WRONLY 作为
oflag取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func openat64(Int32, String, Int32, UInt32) (deprecated)
public func openat64(fd: Int32, path: String, oflag: Int32, flag: UInt32): Int32
功能:打开文件并为其返回新的文件描述符,或在失败时返回 -1。
- 当文件打开方式参数
oflag设置为 O_CREAT 时,可以通过参数设置文件权限。 - O_RDONLY、O_RDWR、O_WRONLY 作为
oflag取值为互斥关系,但可以与其他操作标识一起使用,如 O_APPEND 。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 路径的文件描述符。
- path: String - 文件路径。
- oflag: Int32 - 文件打开的方式。
- flag: UInt32 - 如果
oflag设置了 O_CREAT 并且需要创建新文件,则flag参数标识对新文件的权限,否则flag不改变文件权限。
返回值:
- Int32 - 返回新的文件描述符,执行失败时返回
-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func pread(Int32, CPointer<UInt8>, UIntNative, Int32) (deprecated)
public unsafe func pread(fd: Int32, buffer: CPointer<UInt8>, nbyte: UIntNative, offset: Int32): IntNative
功能:将 fd 指向的文件的 nbyte 字节传输到 buffer 指向的内存中。如果 nbyte 为 0,则函数无效果,并返回 0。返回值是实际读取的字节数。返回值为 0 表示到达文件末尾或无法读取数据。此外,文件的读写位置随着读取字节的变化而变化。
建议 nbyte 的大小与 buffer 的大小相同,且 buffer 的大小小于或等于 150000 字节。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 待读取文件的文件描述符。
- buffer: CPointer<UInt8> - 缓冲区容器。
- nbyte: UIntNative - 读取字节数,建议采用
buffer.size。 - offset: Int32 - 读取位置的偏移量。
返回值:
- IntNative - 返回实际读取字节数,读取无效时返回
-1。
func pwrite(Int32, CPointer<UInt8>, UIntNative, Int32) (deprecated)
public unsafe func pwrite(fd: Int32, buffer: CPointer<UInt8>, nbyte: UIntNative, offset: Int32): IntNative
功能:将 buffer 指向的内存中 nbyte 字节从指定偏移位置开始写入到 fd 指向的文件。指定文件的读写位置会随之移动。
建议 nbyte 的大小与 buffer 的大小相同,且 buffer 的大小小于或等于 150000 字节。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 待读取文件的文件描述符。
- buffer: CPointer<UInt8> - 缓冲区容器。
- nbyte: UIntNative - 读取字节数,建议采用
buffer.size。 - offset: Int32 - 读取位置的偏移量。
返回值:
- IntNative - 返回实际写入数,执行失败时返回
-1。
func read(Int32, CPointer<UInt8>, UIntNative) (deprecated)
public unsafe func read(fd: Int32, buffer: CPointer<UInt8>, nbyte: UIntNative): IntNative
功能:将 fd 指向的文件的 nbyte 字节传输到 buffer 指向的内存中。如果 nbyte 为 0,则函数无效果,并返回 0。返回值是实际读取的字节数。返回值为 0 表示到达文件末尾或无法读取数据。此外,文件的读写位置随着读取字节的变化而变化。
建议 nbyte 的大小与 buffer 的大小相同,且 buffer 的大小小于或等于 150000 字节。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 待读取文件的文件描述符。
- buffer: CPointer<UInt8> - 缓冲区容器。
- nbyte: UIntNative - 读取字节数,建议采用
buffer.size。
返回值:
- IntNative - 返回实际读取字节数,读取无效时返回
-1。
func remove(String) (deprecated)
public func remove(path: String): Int32
功能:删除文件或目录。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func rename(String, String) (deprecated)
public func rename(oldName: String, newName: String): Int32
功能:重命名文件,如果需要将会移动文件所在目录。文件的任何其他硬链接不受影响。旧路径打开的文件描述符也不受影响。
各种限制将决定重命名操作是否成功,具体场景如下:
- 如果
newName已经存在,它将被原子替换,这样另一个尝试访问newName的进程就不会发现它丢失,但是可能会有一个窗口,其中旧路径和新路径都引用要重命名的文件。 - 如果旧路径和新路径是引用同一文件的现有硬链接,则重命名不做任何操作,并返回成功状态。
- 如果
newName存在,但操作因某种原因失败,则重命名保证保留newName的实例。 oldName可以指定目录。在这种情况下,newName必须不存在,或者它必须指定空目录。- 如果旧路径引用符号链接,则链接将重命名;如果新路径引用符号链接,则链接将被覆盖。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
oldName或newName包含空字符时,抛出异常。
func renameat(Int32, String, Int32, String) (deprecated)
public func renameat(oldfd: Int32, oldName: String, newfd: Int32, newName: String): Int32
功能:重命名文件,如果需要将会移动文件所在目录。
renameat() 与 rename() 处理相同,此处仅描述两者差异点:
oldName为相对路径且oldfd为特殊值AT_FDCWD时,则路径将相对于调用进程的当前工作目录。oldName为相对路径且oldfd非AT_FDCWD时,则路径将相对于oldfd引用的文件所属目录。oldName为绝对路径时oldfd参数将被忽略。newName的场景与oldName相同,只是当newName为相对路径时是相对于newfd引用的文件所属目录。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
oldName或newName包含空字符时,抛出异常。
func setgid(UInt32) (deprecated)
public func setgid(id: UInt32): Int32
功能:设置调用进程的有效组 ID,需要适当的权限。
注意:
未来版本即将废弃。
参数:
- id: UInt32 - 调用进程的有效组
ID号。
返回值:
- Int32 - 设置成功,返回
0,设置失败, 返回-1。
func sethostname(String) (deprecated)
public func sethostname(buf: String): Int32
功能:设置主机名,仅超级用户可以调用。
注意:
未来版本即将废弃。
参数:
- buf: String - 需要设置的主机名。
返回值:
- Int32 - 设置成功,返回
0,设置失败, 返回-1。
异常:
- IllegalArgumentException - 如果参数
buf包含空字符则抛出异常。
func setpgid(Int32, Int32) (deprecated)
public func setpgid(pid: Int32, pgrp: Int32): Int32
功能:此函数将参数 pid 指定的组 ID 设置为参数 pgrp 指定的组 ID。 如果 pid 为 0,则使用当前进程的组 ID。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 执行成功,返回组
ID,执行失败, 返回-1。
func setpgrp() (deprecated)
public func setpgrp(): Int32
功能:将当前进程所属的组 ID 设置为当前进程的进程 ID,此函数等同于调用 setpgid(0, 0)。
注意:
未来版本即将废弃。
返回值:
- Int32 - 执行成功,返回当前进程的组
ID,执行失败, 返回-1。
func setuid(UInt32) (deprecated)
public func setuid(id: UInt32): Int32
功能:设置调用进程的有效用户 ID,需要适当的权限。
注意:
未来版本即将废弃。
参数:
- id: UInt32 - 调用进程的有效用户
ID号。
返回值:
- Int32 - 设置成功,返回
0,设置失败, 返回-1。
func symlink(String, String) (deprecated)
public func symlink(path: String, symPath: String): Int32
功能:创建一个名为 symPath 链接到 path 所指定的文件。
- 符号链接在运行时被解释为链接的内容已被替换到要查找文件或目录的路径中。
- 符号链接可能包含..路径组件,这些组件(如果在链接的开头使用)引用链接所在目录的父目录。
- 符号链接(也称为软链接)可以指向现有文件或不存在的文件,后者被称为悬空链接。
- 符号链接的权限是不相关的,在跟踪链接时,所有权将被忽略,但当请求删除或重命名链接并且链接位于设置了粘滞位的目录中时,所有权将被检查。
- 如果 symPath 已存在,则不会被覆盖。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
path或symPath包含空字符时,抛出异常。
func symlinkat(String, Int32, String) (deprecated)
public func symlinkat(path: String, fd: Int32, symPath: String): Int32
功能:创建一个名为 symPath 链接到 path 与 fd 所指定的文件。
symPath为相对路径且fd为特殊值AT_FDCWD时,则路径将相对于调用进程的当前工作目录。symPath为相对路径且fd非AT_FDCWD时,则路径将相对于fd引用的文件所属目录。symPath为绝对路径时fd参数将被忽略。
注意:
未来版本即将废弃。
参数:
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
path或symPath包含空字符时,抛出异常。
func ttyname(Int32) (deprecated)
public func ttyname(fd: Int32): String
功能:返回终端名称。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
返回值:
- String - 操作成功时返回路径名,失败时,返回
NULL。
func umask(UInt32) (deprecated)
public func umask(cmask: UInt32): UInt32
功能:设置权限掩码。
注意:
未来版本即将废弃。
参数:
- cmask: UInt32 - 文件权限参数。
返回值:
- UInt32 - 返回文件上一个掩码的值。
func unlink(String) (deprecated)
public func unlink(path: String): Int32
功能:从文件系统中删除文件。
- 如果
path是指向文件的最后一个链接,并且没有进程打开该文件,则该文件将被删除,它使用的空间可供重复使用。 - 如果
path是指向文件的最后一个链接,但仍然有进程打开该文件,该文件将一直存在,直到引用它的最后一个文件描述符关闭。 - 如果
path引用了符号链接,则该链接将被删除。 - 如果
path引用了套接字、FIFO 或设备,则该文件将被删除,但打开对象的进程可能会继续使用它。
注意:
未来版本即将废弃。
参数:
- path: String - 文件路径。
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func unlinkat(Int32, String, Int32) (deprecated)
public func unlinkat(fd: Int32, path: String, ulflag: Int32): Int32
功能:从文件系统中删除文件。
该函数系统调用的操作方式与 unlink 函数完全相同,但此处描述的差异除外:
path为相对路径且fd为特殊值AT_FDCWD时,则路径将相对于调用进程的当前工作目录。path为相对路径且fd非AT_FDCWD时,则路径将相对于fd引用的文件所属目录。path为绝对路径时fd参数将被忽略。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 文件描述符。
- path: String - 文件路径。
- ulflag: Int32 - 可以指定为
0,或者可以设置为控制 unlinkat() 操作的标志值按位或运算。标志值当前取值仅支持 AT_REMOVEDIR。
返回值:
- Int32 - 成功返回
0,错误返回-1。
异常:
- IllegalArgumentException - 当函数参数
path包含空字符时,抛出异常。
func write(Int32, CPointer<UInt8>, UIntNative) (deprecated)
public unsafe func write(fd: Int32, buffer: CPointer<UInt8>, nbyte: UIntNative): IntNative
功能:将 buffer 指向的内存中 nbyte 字节写入到 fd 指向的文件。指定文件的读写位置会随之移动。
建议 nbyte 的大小与 buffer 的大小相同,且 buffer 的大小小于或等于 150000 字节。
注意:
未来版本即将废弃。
参数:
- fd: Int32 - 待写入文件的文件描述符。
- buffer: CPointer<UInt8> - 缓冲区容器。
- nbyte: UIntNative - 读取字节数,建议采用
buffer.size。
返回值:
- IntNative - 返回实际读取字节数,读取无效时返回
-1。
文件内容相关操作
下面是文件内容相关操作示例。
代码如下:
import std.posix.*
main(): Int64 {
var fd = `open`("textcase.txt", O_RDWR | O_APPEND | O_CREAT, S_IRWXU)
println("fd ==> ${fd}")
close(fd)
var fd2 = `open`("textcase.txt", O_RDWR)
var len = lseek(fd2, 0, SEEK_END)
println("len ==> ${len}")
close(fd2)
var str1 = unsafe{LibC.mallocCString(" ")}
var buf = str1.getChars()
var fd3 = `open`("textcase.txt", O_RDWR)
var readNum = unsafe { read(fd3, buf, 2) }
unsafe{ LibC.free(str1)}
println("readNum ==> ${readNum}")
close(fd3)
var str2 = unsafe{LibC.mallocCString("123456")}
var buf2 = str2.getChars()
var fd4 = `open`("textcase.txt", O_RDWR)
var fd5 = dup(fd4)
var writeNum = unsafe { write(fd5, buf2, UIntNative(str2.size())) }
unsafe { LibC.free(str2)}
println("writeNum ==> ${writeNum}")
close(fd4)
return 0
}
可能出现的运行结果:
fd ==> 3
len ==> 6
readNum ==> 2
writeNum ==> 6
文件信息相关操作
下面是文件信息相关操作示例,以下示例支持 Linux 平台,其他平台支持情况见本包概述。
代码如下:
import std.posix.*
main(): Int64 {
var result1: Bool = isType("/notdirs", S_IFDIR)
println("result ==> ${result1}")
var result2: Bool = isDir("/dev")
println("result ==> ${result2}")
var result3 = access("./oscfg.cfg", F_OK)
println("result ==> ${result3}")
var result4 = chmod("oscfg.cfg", UInt32(S_IXUSR))
println("result ==> ${result4}")
return 0
}
运行结果:
result ==> false
result ==> true
result ==> -1
result ==> -1
获取各类系统信息
下面是获取各类系统信息示例,以下示例支持 Linux 平台,其他平台支持情况见本包概述。
代码如下:
import std.posix.*
main(): Int64 {
/* 系统名称相关 */
var os_info = getos()
println("os info ==> ${os_info}")
var hostname = gethostname()
println("hostname ==> ${hostname}")
var logname: String = getlogin()
println("logname ==> ${logname}")
/* 程序运行路径相关函数 */
var changePath = "/"
var chdir_result = chdir(changePath)
println("chdir_result ==> ${chdir_result}")
var cwd_path: String = getcwd()
println("cwd_path ==> ${cwd_path}")
/* 系统 id 相关函数 getpgid */
var arr: CString = unsafe { LibC.mallocCString(" ") }
var a: CPointer<UInt8> = arr.getChars()
var cp: CPointer<UInt32> = CPointer<UInt32>(a)
var getg = unsafe{ getgroups(0, cp)}
var s: String = " "
for (_ in 0..getg) {
s = s + "\0"
}
println(getg)
var local: UInt32 = 0
for (temp in 0..getg) {
unsafe { local = cp.read(Int64(temp)) }
println("getgroups ==> ${local.toString()}")
}
unsafe { LibC.free(arr)}
return 0
}
运行结果如下(根据系统不同返回结果可能不同):
Linux version 4.15.0-159-generic (buildd@lgw01-amd64-055) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #167-Ubuntu SMP Tue Sep 21 08:55:05 UTC 2021
hostname ==> e124e6e0fe0f
logname ==> root
chdir_result ==> 0
cwd_path ==> /
1
getgroups ==> 1309868064
进程相关信息操作
下面是进程相关信息操作示例,以下示例支持 Linux 平台,其他平台支持情况见本包概述。
代码如下:
import std.posix.*
main(): Int64 {
var result = nice(200)
print("${result}")
var result1 = kill(0, SIGCHLD)
println(result1)
var result2 = killpg(0, SIGURG)
println("result ==> ${result2}")
if (isatty(0) && isatty(1) && isatty(2)) {
print("true01 ")
} else {
print("false01 ")
}
if (isatty(-23) || isatty(4) || isatty(455) || isatty(43332)) {
print("true02 ")
} else {
println("false02")
}
return 0
}
运行结果:
190
result ==> 0
true01 false02
std.process
功能介绍
process 包主要提供 Process 进程操作接口,主要包括进程创建,标准流获取,进程等待,进程信息查询等。
本包提供多平台统一操控能力,目前支持 Linux 平台,macOS 平台与 Windows 平台。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| execute | 根据输入参数创建并运行一个子进程,等待该子进程运行完毕并返回子进程退出状态。 |
| executeWithOutput | 根据输入参数创建并运行一个子进程,等待该子进程运行完毕并返回子进程退出状态、标准输出和标准错误。 |
| findProcess | 根据输入进程 id 绑定一个进程实例。 |
| launch | 根据输入参数创建并运行一个子进程,并返回一个子进程实例。 |
类
| 类名 | 功能 |
|---|---|
| CurrentProcess (deprecated) | 此类为当前进程类,继承 Process 类,提供对当前进程操作相关功能。 |
| Process | 此类为进程类,提供进程操作相关功能。 |
| SubProcess | 此类为子进程类,继承 Process 类,提供对子进程操作相关功能。 |
枚举
| 枚举名 | 功能 |
|---|---|
| ProcessRedirect | 用于在创建进程时设置子进程标准流的重定向模式。 |
异常类
| 异常类名 | 功能 |
|---|---|
| ProcessException | process 包的异常类。 |
兼容性说明
class Process
| 成员 | 支持平台 |
|---|---|
| current (deprecated) | Linux Windows macOS |
| pid | Linux Windows macOS |
| name | Linux Windows macOS |
| command | Linux Windows macOS |
| arguments (deprecated) | Linux macOS |
| commandLine (deprecated) | Linux macOS |
| environment (deprecated) | Linux |
| workingDirectory (deprecated) | Linux macOS |
| of(Int64) (deprecated) | Linux Windows macOS |
| start(String, Array<String>, Path, Map<String, String>, ProcessRedirect, ProcessRedirect, ProcessRedirect) (deprecated) | Linux Windows macOS |
| run(String, Array<String>, Path, Map<String, String>, ProcessRedirect, ProcessRedirect, ProcessRedirect, Duration) (deprecated) | Linux Windows macOS |
| runOutput(String, Array<String>, Path, Map<String, String>, ProcessRedirect, ProcessRedirect, ProcessRedirect) (deprecated) | Linux Windows macOS |
| terminate(Bool) | Linux Windows macOS |
class CurrentProcss (deprecated)
注意:
未来版本即将废弃,可在 std.env 中找到代替功能。
| 成员 | 支持平台 |
|---|---|
| arguments | Linux Windows macOS |
| homeDirectory | Linux Windows macOS |
| tempDirectory | Linux Windows macOS |
| stdIn | Linux Windows macOS |
| stdOut | Linux Windows macOS |
| stdErr | Linux Windows macOS |
| atExit(() -> Unit) | Linux Windows macOS |
| exit(Int64) | Linux Windows macOS |
| getEnv(String) | Linux Windows macOS |
| removeEnv(String) | Linux Windows macOS |
| setEnv(String, String) | Linux Windows macOS |
class SubProcess
| 成员 | 支持平台 |
|---|---|
| stdIn (deprecated) | Linux Windows macOS |
| stdInPipe | Linux Windows macOS |
| stdOut (deprecated) | Linux Windows macOS |
| stdOutPipe | Linux Windows macOS |
| stdErr (deprecated) | Linux Windows macOS |
| stdErrPipe | Linux Windows macOS |
| wait(Duration) | Linux Windows macOS |
| waitOutput() | Linux Windows macOS |
函数
func execute(String, Array<String>, ?Path, ?Map<String, String>, ProcessRedirect, ProcessRedirect,ProcessRedirect, ?Duration)
public func execute(command: String,
arguments: Array<String>,
workingDirectory!: ?Path = None,
environment!: ?Map<String, String> = None,
stdIn!: ProcessRedirect = Inherit,
stdOut!: ProcessRedirect = Inherit,
stdErr!: ProcessRedirect = Inherit,
timeout!: ?Duration = None): Int64
功能:根据输入参数创建并运行一个子进程,等待该子进程运行完毕并返回子进程退出状态。
注意:
- 在
Windows平台上,在子进程执行完成后立即删除子进程的可执行文件可能删除失败并抛出异常,异常信息为Access is denied,如果遇到该问题,可以在一小段延迟后重新尝试删除该文件,详细实现可参考示例。
参数:
- command: String - 指定子进程命令,
command不允许包含空字符。 - arguments: Array<String> - 指定子进程参数,
arguments不允许数组中字符串中包含空字符。 - workingDirectory!: ?Path - 命名可选参数,指定子进程的工作路径,默认继承当前进程工作路径,路径必须为存在的目录且不允许为空路径或包含空字符。
- environment!: ?Map<String, String> - 命名可选参数,指定子进程环境变量,默认继承当前进程环境变量,
key不允许字符串中包含空字符或'=',value 不允许字符串中包含空字符。 - stdIn!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输入,默认继承当前进程标准输入。
- stdOut!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输出,默认继承当前进程标准输出。
- stdErr!: ProcessRedirect - 命名可选参数,指定子进程重定向标准错误,默认继承当前进程标准错误。
- timeout!: ?Duration - 命名可选参数,指定等待子进程超时时间,默认为不超时,
timeout指定为0或负值时表示不超时。
返回值:
- Int64 - 返回子进程退出状态,若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号。
异常:
-
- 当入参
command包含空字符 - 或者
arguments数组中字符串中包含空字符 - 或者
workingDirectory不是存在的目录或为空路径或包含空字符 - 或者
environment表中key字符串中包含空字符或'=' - 或者
value字符串中包含空字符 - 或者
stdIn、stdOut、stdErr输入为文件模式,输入的文件已被关闭或删除时,抛出异常。
- 当入参
-
ProcessException - 当内存分配失败或
command对应的命令不存在或等待超时,抛出异常。
func executeWithOutput(String, Array<String>, ?Path, ?Map<String, String>, ProcessRedirect, ProcessRedirect, ProcessRedirect)
public func executeWithOutput(command: String,
arguments: Array<String>,
workingDirectory!: ?Path = None,
environment!: ?Map<String, String> = None,
stdIn!: ProcessRedirect = Inherit,
stdOut!: ProcessRedirect = Pipe,
stdErr!: ProcessRedirect = Pipe): (Int64, Array<Byte>, Array<Byte>)
功能:根据输入参数创建并运行一个子进程,等待该子进程运行完毕并返回子进程退出状态、标准输出和标准错误。输出流、错误流中包含大量输出的场景不适用于本函数,建议通过 SubProcess 中提供的标准流属性结合 wait 函数自行处理。
参数:
- command: String - 指定子进程命令,
command不允许包含空字符。 - arguments: Array<String> - 指定子进程参数,
arguments不允许数组中字符串中包含空字符。 - workingDirectory!: ?Path - 命名可选参数,指定子进程的工作路径,默认继承当前进程工作路径,路径必须为存在的目录且不允许为空路径或包含空字符。
- environment!: ?Map<String, String> - 命名可选参数,指定子进程环境变量,默认继承当前进程环境变量,
key不允许字符串中包含空字符或'=',value 不允许字符串中包含空字符。 - stdIn!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输入,默认继承当前进程标准输入。
- stdOut!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输出,默认继承当前进程标准输出。
- stdErr!: ProcessRedirect - 命名可选参数,指定子进程重定向标准错误,默认继承当前进程标准错误。
返回值:
- (Int64, Array<Byte>, Array<Byte>) - 子进程执行返回结果,包含子进程退出状态(若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号),进程标准输出结果和进程错误结果。
异常:
- IllegalArgumentException
- 当入参
command包含空字符 - 或者
arguments数组中字符串中包含空字符 - 或者
workingDirectory不是存在的目录或为空路径或包含空字符 - 或者
environment表中key字符串中包含空字符或'=' - 或者
value字符串中包含空字符 - 或者
stdIn、stdOut、stdErr输入为文件模式,输入的文件已被关闭或删除时,抛出异常。
- 当入参
- ProcessException
- 当内存分配失败
- 或者
command对应的命令不存在 - 或者子进程不存在
- 或者标准流读取异常时,抛出异常。
func findProcess(Int64)
public func findProcess(pid: Int64): Process
功能:根据输入进程 id 绑定一个进程实例。
参数:
- pid: Int64 - 进程
id。
返回值:
- Process - 返回进程
id对应的进程实例。
异常:
- IllegalArgumentException - 当输入进程
id大于 Int32 最大值或小于0时,抛出异常。 - ProcessException - 当内存分配失败或
pid对应的进程不存在时,抛出异常。
func launch(String, Array<String>, ?Path, ?Map<String, String>, ProcessRedirect, ProcessRedirect, ProcessRedirect)
public func launch(command: String,
arguments: Array<String>,
workingDirectory!: ?Path = None,
environment!: ?Map<String, String> = None,
stdIn!: ProcessRedirect = Inherit,
stdOut!: ProcessRedirect = Inherit,
stdErr!: ProcessRedirect = Inherit): SubProcess
功能:根据输入参数创建并运行一个子进程,并返回一个子进程实例。调用该函数创建子进程后,需要调用 wait 或 waitOutput 函数,否则该子进程结束后成为的僵尸进程的资源不会被回收。
参数:
- command: String - 指定子进程命令,
command不允许包含空字符。 - arguments: Array<String> - 指定子进程参数,
arguments不允许数组中字符串中包含空字符。 - workingDirectory!: ?Path - 命名可选参数,指定子进程的工作路径,默认继承当前进程工作路径,路径必须为存在的目录且不允许为空路径或包含空字符。
- environment!: ?Map<String, String> - 命名可选参数,指定子进程环境变量,默认继承当前进程环境变量,
key不允许字符串中包含空字符或'=',value 不允许字符串中包含空字符。 - stdIn!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输入,默认继承当前进程标准输入。
- stdOut!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输出,默认继承当前进程标准输出。
- stdErr!: ProcessRedirect - 命名可选参数,指定子进程重定向标准错误,默认继承当前进程标准错误。
返回值:
- SubProcess - 返回一个子进程实例。
异常:
- IllegalArgumentException
- 当入参
command包含空字符 - 或者
arguments数组中字符串中包含空字符 - 或者
workingDirectory不是存在的目录或为空路径或包含空字符 - 或者
environment表中key字符串中包含空字符或'=' - 或者
value字符串中包含空字符 - 或者
stdIn、stdOut、stdErr输入为文件模式,输入的文件已被关闭或删除时,抛出异常。
- 当入参
- ProcessException - 当内存分配失败或
command对应的命令不存在时,抛出异常。
类
class CurrentProcess (deprecated)
public class CurrentProcess <: Process
功能:此类为当前进程类,继承 Process 类,提供对当前进程操作相关功能。
提供功能具体如下:
- 提供获取当前进程标准流(
stdIn、stdOut、stdErr)机制。 - 提供当前进程退出注册回调函数机制。
- 提供当前进程退出机制,允许设置退出状态码。
注意:
未来版本即将废弃。
父类型:
prop arguments
public prop arguments: Array<String>
功能:返回当前进程参数列表,例如当前进程命令行为 a.out ab cd ef,其中 a.out 是程序名,则返回的列表包含三个元素 ab cd ef。
说明:
- 使用 C 语言调用仓颉动态库方式时,通过 int SetCJCommandLineArgs(int argc, const char* argv[]) 设置的命令行参数,在使用当前进程的
arguments获取时,将会被舍弃掉第一个参数。
prop homeDirectory
public prop homeDirectory: Path
功能:获取 home 目录的路径。
类型:Path
prop stdErr
public prop stdErr: OutputStream
功能:获取当前进程标准错误流。
类型:OutputStream
prop stdIn
public prop stdIn: InputStream
功能:获取当前进程标准输入流。
类型:InputStream
prop stdOut
public prop stdOut: OutputStream
功能:获取当前进程标准输出流。
类型:OutputStream
prop tempDirectory
public prop tempDirectory: Path
功能:获取临时目录的路径。从环境变量中获取 TMPDIR、TMP、TEMP 和 TEMPDIR 环境变量。如果以上值在环境变量中均不存在,则默认返回 /tmp 目录。
类型:Path
func atExit(() -> Unit)
public func atExit(callback: () -> Unit): Unit
功能:注册回调函数,当前进程退出时执行注册函数。
注意:
请不要使用C语言 atexit 函数,避免出现不可期问题。
参数:
- callback: () ->Unit - 需要被注册回调的函数。
func exit(Int64)
public func exit(code: Int64): Nothing
功能:进程退出函数,执行到此函数直接结束当前进程,并且通过入参 code 设置返回状态码。
参数:
- code: Int64 - 当前进程退出状态码。
func getEnv(String)
public func getEnv(k: String): Option<String>
功能:获取指定名称的环境变量值。
参数:
- k: String - 环境变量名称。
返回值:
异常:
- IllegalArgumentException - 当函数参数
k包含空字符时,抛出异常。
func removeEnv(String)
public func removeEnv(k: String): Unit
功能:通过指定环境变量名称移除环境变量。
参数:
- k: String - 环境变量名称。
异常:
- IllegalArgumentException - 当函数参数
k包含空字符时,抛出异常。
func setEnv(String, String)
public func setEnv(k: String, v: String): Unit
功能:用于设置一对环境变量。如果设置了同名环境变量,原始环境变量值将被覆盖。
说明:
Windows 下如果传入的参数 v 是空字符串,那么会从环境中移除变量 k。
参数:
异常:
- IllegalArgumentException - 当函数参数
k或v中包含空字符时,抛出异常。
class Process
public open class Process
功能:此类为进程类,提供进程操作相关功能。
说明:
提供功能具体如下:
- 提供获取当前进程实例的功能。
- 提供根据进程
id绑定进程实例的功能。- 提供根据输入信息创建子进程的功能。
- 提供获取进程信息的功能。
- 提供关闭进程的功能,允许设置是否强制关闭进程。
static prop current (deprecated)
public static prop current: CurrentProcess
功能:获取当前进程实例。
注意:
未来版本即将废弃,使用 env 包的全局函数替代。
prop arguments (deprecated)
public open prop arguments: Array<String>
功能:获取进程参数。Windows 平台下无法在非特权 API 下获取到本属性,暂不支持获取。
注意:
未来版本即将废弃。
异常:
- ProcessException - 当进程不存在或对应进程为僵尸进程,或在
Windows平台下暂不支持场景,无法获取进程参数时,抛出异常。
prop command
public prop command: String
功能:获取进程命令。
类型:String
异常:
- ProcessException - 当进程不存在或对应进程为僵尸进程,无法获取进程命令时,抛出异常。
prop commandLine (deprecated)
public prop commandLine: Array<String>
功能:获取进程命令行。Windows 平台当前进程可获取,其他场景下无法在非特权 API 下获取到本属性,暂不支持获取。
注意:
未来版本即将废弃,使用 getcommandline() 替代。
异常:
- ProcessException - 当进程不存在或对应进程为僵尸进程,或在
Windows平台下暂不支持场景,无法获取进程命令行时,抛出异常。
prop environment (deprecated)
public prop environment: Map<String, String>
功能:获取进程环境变量。Windows 平台当前进程可获取,其他场景下无法在非特权 API 下获取到本属性,暂不支持获取。
注意:
未来版本即将废弃,使用 getVariables() 替代。
异常:
- ProcessException - 当进程不存在或对应进程为僵尸进程,或在
Windows平台下暂不支持场景,无法获取进程环境变量时,抛出异常。
prop name
public prop name: String
功能:获取进程名。
类型:String
异常:
- ProcessException - 当进程不存在或对应进程为僵尸进程,无法获取进程名时,抛出异常。
prop pid
public prop pid: Int64
功能:获取进程 id。
类型:Int64
prop startTime
public prop startTime: DateTime
功能:获取进程启动时间,获取失败时返回 DateTime.UnixEpoch。
类型:DateTime
prop systemTime
public prop systemTime: Duration
功能:获取进程启动时间,获取失败时返回 -1ms。
类型:Duration
prop userTime
public prop userTime: Duration
功能:获取进程启动时间,获取失败时返回 -1ms。
类型:Duration
prop workingDirectory (deprecated)
public prop workingDirectory: Path
功能:获取进程工作路径。Windows 平台当前进程可获取,其他场景下无法在非特权 API 下获取到本属性,暂不支持获取。
注意:
未来版本即将废弃,使用 getHomeDirectory() 替代。
类型:Path
异常:
- ProcessException - 当进程不存在或对应进程为僵尸进程,或在
Windows平台下暂不支持场景,无法获取进程工作路径时,抛出异常。
func isAlive()
public func isAlive(): Bool
功能:返回进程是否存活。
返回值:
- Bool - 进程存活则为
true,否则为false
static func of(Int64) (deprecated)
public static func of(pid: Int64): Process
功能:根据输入进程 id 绑定一个进程实例。
注意:
未来版本即将废弃,使用 findProcess 替代。
参数:
- pid: Int64 - 进程
id。
返回值:
- Process - 返回进程
id对应的进程实例。
异常:
- IllegalArgumentException - 当输入进程
id大于 Int32 最大值或小于0时,抛出异常。 - ProcessException - 当内存分配失败或
pid对应的进程不存在时,抛出异常。
static func run(String, Array<String>, ?Path, ?Map<String, String>, ProcessRedirect, ProcessRedirect,ProcessRedirect, ?Duration) (deprecated)
public static func run(command: String,
arguments: Array<String>,
workingDirectory!: ?Path = None,
environment!: ?Map<String, String> = None,
stdIn!: ProcessRedirect = Inherit,
stdOut!: ProcessRedirect = Inherit,
stdErr!: ProcessRedirect = Inherit,
timeout!: ?Duration = None): Int64
功能:根据输入参数创建并运行一个子进程,等待该子进程运行完毕并返回子进程退出状态。
注意:
- 未来版本即将废弃,使用 execute 替代。
- 在
Windows平台上,在子进程执行完成后立即删除子进程的可执行文件可能删除失败并抛出异常,异常信息为Access is denied,如果遇到该问题,可以在一小段延迟后重新尝试删除该文件,详细实现可参考示例。
参数:
- command: String - 指定子进程命令,
command不允许包含空字符。 - arguments: Array<String> - 指定子进程参数,
arguments不允许数组中字符串中包含空字符。 - workingDirectory!: ?Path - 命名可选参数,指定子进程的工作路径,默认继承当前进程工作路径,路径必须为存在的目录且不允许为空路径或包含空字符。
- environment!: ?Map<String, String> - 命名可选参数,指定子进程环境变量,默认继承当前进程环境变量,
key不允许字符串中包含空字符或'=',value 不允许字符串中包含空字符。 - stdIn!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输入,默认继承当前进程标准输入。
- stdOut!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输出,默认继承当前进程标准输出。
- stdErr!: ProcessRedirect - 命名可选参数,指定子进程重定向标准错误,默认继承当前进程标准错误。
- timeout!: ?Duration - 命名可选参数,指定等待子进程超时时间,默认为不超时,
timeout指定为0或负值时表示不超时。
返回值:
- Int64 - 返回子进程退出状态,若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号。
异常:
- IllegalArgumentException - 当入参
command包含空字符,或者arguments数组中字符串中包含空字符,或者workingDirectory不是存在的目录或为空路径或包含空字符,或者environment表中key字符串中包含空字符或'=',或value字符串中包含空字符,或者stdIn、stdOut、stdErr输入为文件模式,输入的文件已被关闭或删除时,抛出异常。 - ProcessException - 当内存分配失败或
command对应的命令不存在或等待超时,抛出异常。
static func runOutput(String, Array<String>, ?Path, ?Map<String, String>, ProcessRedirect, ProcessRedirect, ProcessRedirect) (deprecated)
public static func runOutput(command: String,
arguments: Array<String>,
workingDirectory!: ?Path = None,
environment!: ?Map<String, String> = None,
stdIn!: ProcessRedirect = Inherit,
stdOut!: ProcessRedirect = Pipe,
stdErr!: ProcessRedirect = Pipe): (Int64, Array<Byte>, Array<Byte>)
功能:根据输入参数创建并运行一个子进程,等待该子进程运行完毕并返回子进程退出状态、标准输出和标准错误。输出流、错误流中包含大量输出的场景不适用于本函数,建议通过 SubProcess 中提供的标准流属性结合 wait 函数自行处理。
注意:
未来版本即将废弃,使用 executeWithOutput 替代。
参数:
- command: String - 指定子进程命令,
command不允许包含空字符。 - arguments: Array<String> - 指定子进程参数,
arguments不允许数组中字符串中包含空字符。 - workingDirectory!: ?Path - 命名可选参数,指定子进程的工作路径,默认继承当前进程工作路径,路径必须为存在的目录且不允许为空路径或包含空字符。
- environment!: ?Map<String, String> - 命名可选参数,指定子进程环境变量,默认继承当前进程环境变量,
key不允许字符串中包含空字符或'=',value 不允许字符串中包含空字符。 - stdIn!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输入,默认继承当前进程标准输入。
- stdOut!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输出,默认继承当前进程标准输出。
- stdErr!: ProcessRedirect - 命名可选参数,指定子进程重定向标准错误,默认继承当前进程标准错误。
返回值:
- (Int64, Array<Byte>, Array<Byte>) - 子进程执行返回结果,包含子进程退出状态(若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号),进程标准输出结果和进程错误结果。
异常:
- IllegalArgumentException - 当入参
command包含空字符,或者arguments数组中字符串中包含空字符,或者workingDirectory不是存在的目录或为空路径或包含空字符,或者environment表中key字符串中包含空字符或'=',或value字符串中包含空字符,或者stdIn、stdOut、stdErr输入为文件模式,输入的文件已被关闭或删除时,抛出异常。 - ProcessException - 当内存分配失败,或者
command对应的命令不存在,或者子进程不存在,或者标准流读取异常时,抛出异常。
static func start(String, Array<String>, ?Path, ?Map<String, String>, ProcessRedirect, ProcessRedirect, ProcessRedirect) (deprecated)
public static func start(command: String,
arguments: Array<String>,
workingDirectory!: ?Path = None,
environment!: ?Map<String, String> = None,
stdIn!: ProcessRedirect = Inherit,
stdOut!: ProcessRedirect = Inherit,
stdErr!: ProcessRedirect = Inherit): SubProcess
功能:根据输入参数创建并运行一个子进程,并返回一个子进程实例。调用该函数创建子进程后,需要调用 wait 或 waitOutput 函数,否则该子进程结束后成为的僵尸进程的资源不会被回收。
注意:
未来版本即将废弃,使用 launch 替代。
参数:
- command: String - 指定子进程命令,
command不允许包含空字符。 - arguments: Array<String> - 指定子进程参数,
arguments不允许数组中字符串中包含空字符。 - workingDirectory!: ?Path - 命名可选参数,指定子进程的工作路径,默认继承当前进程工作路径,路径必须为存在的目录且不允许为空路径或包含空字符。
- environment!: ?Map<String, String> - 命名可选参数,指定子进程环境变量,默认继承当前进程环境变量,
key不允许字符串中包含空字符或'=',value 不允许字符串中包含空字符。 - stdIn!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输入,默认继承当前进程标准输入。
- stdOut!: ProcessRedirect - 命名可选参数,指定子进程重定向标准输出,默认继承当前进程标准输出。
- stdErr!: ProcessRedirect - 命名可选参数,指定子进程重定向标准错误,默认继承当前进程标准错误。
返回值:
- SubProcess - 返回一个子进程实例。
异常:
- IllegalArgumentException - 当入参
command包含空字符,或者arguments数组中字符串中包含空字符,或者workingDirectory不是存在的目录或为空路径或包含空字符,或者environment表中key字符串中包含空字符或'=',或value字符串中包含空字符,或者stdIn、stdOut、stdErr输入为文件模式,输入的文件已被关闭或删除时,抛出异常。 - ProcessException - 当内存分配失败或
command对应的命令不存在时,抛出异常。
func terminate(Bool)
public func terminate(force!: Bool = false): Unit
功能:终止进程,子进程执行返回结果,包含子进程退出状态(若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号),进程标准输出结果和进程错误结果。
参数:
- force!: Bool - 命名可选参数,指定是否强制关闭进程,默认为
false,若设置为false,对应进程可以在释放资源后结束;若设置为true,对应进程将被直接杀死。Windows平台实现为强制关闭进程。
异常:
- ProcessException - 如果进程不存在,不允许终止,则抛出异常。
func terminateAliveProcess(Int32, Bool)
protected open func terminateAliveProcess(pid: Int32, force: Bool): Unit
功能:终止指定进程,子进程执行返回结果,包含子进程退出状态(若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号),进程标准输出结果和进程错误结果。
参数:
-
pid: Int32 - 需要终止的进程
ID。 -
force!: Bool - 命名可选参数,指定是否强制关闭进程,默认为
false,若设置为false,对应进程可以在释放资源后结束;若设置为true,对应进程将被直接杀死。Windows平台实现为强制关闭进程。
异常:
- ProcessException - 如果进程不存在,不允许终止,则抛出异常。
class SubProcess
public class SubProcess <: Process
功能:此类为子进程类,继承 Process 类,提供对子进程操作相关功能。
说明:
提供功能具体如下:
- 提供获取子进程标准流(
stdIn、stdOut、stdErr)机制。- 提供等待子进程执行返回退出状态码机制,允许设置等待超时时长。
- 提供等待子进程执行返回输出结果(包含运行正常、异常结果)机制,允许设置等待超时时长。
父类型:
prop stdErr (deprecated)
public prop stdErr: InputStream
功能:获取输入流,连接到子进程标准错误流。
注意:
未来版本即将废弃,使用 stdErrPipe 替代。
类型:InputStream
prop stdErrPipe
public prop stdErrPipe: InputStream
功能:获取输入流,连接到子进程标准错误流。
类型:InputStream
prop stdIn (deprecated)
public prop stdIn: OutputStream
功能:获取输出流,连接到子进程标准输入流。
注意:
未来版本即将废弃,使用 stdInPipe 替代。
类型:OutputStream
prop stdInPipe
public prop stdInPipe: OutputStream
功能:获取输出流,连接到子进程标准输入流。
类型:OutputStream
prop stdOut (deprecated)
public prop stdOut: InputStream
功能:获取输入流,连接到子进程标准输出流。
注意:
未来版本即将废弃,使用 stdOutPipe 替代。
类型:InputStream
prop stdOutPipe
public prop stdOutPipe: InputStream
功能:获取输入流,连接到子进程标准输出流。
类型:InputStream
func wait(?Duration)
public func wait(timeout!: ?Duration = None): Int64
功能:阻塞当前进程等待子进程任务执行完成并返回子进程退出状态码,允许指定等待超时时间。对于需要操作标准流的场景(Pipe 模式),使用者需要优先处理标准流,避免子进程标准流缓冲区满后调用本函数产生死锁。
说明:
超时时间处理机制:
参数:
- timeout!: ?Duration - 命名可选参数,设置等待子进程超时时间,默认为
None。
返回值:
- Int64 - 返回子进程退出状态。若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号。
异常:
- TimeoutException - 当等待超时,子进程未退出时,抛出异常。
func waitOutput()
public func waitOutput(): (Int64, Array<Byte>, Array<Byte>)
功能:阻塞当前进程等待子进程任务执行完成,并返回子进程退出状态码、返回结果(包含输出流和错误流返回结果)。输出流、错误流中包含大量输出的场景不适用于本函数,建议通过 SubProcess 中提供的标准流属性结合 wait 函数自行处理。
返回值:
- (Int64, Array<Byte>, Array<Byte>) - 子进程执行返回结果,包含子进程退出状态(若子进程正常退出,返回子进程退出码,若子进程被信号杀死,返回导致子进程终止的信号编号),进程标准输出结果和进程错误结果。
异常:
- ProcessException - 当子进程不存在,或者标准流读取异常时,抛出异常。
枚举
enum ProcessRedirect
public enum ProcessRedirect {
| Inherit
| Pipe
| FromFile(File)
| Discard
}
功能:该枚举类型用于在创建进程时设置子进程标准流的重定向模式。
Discard
Discard
功能:构造一个标准流重定向枚举实例,表示子进程标准流将被丢弃。此模式下标准流属性不可读取或写入。
FromFile(File)
FromFile(File)
功能:构造一个标准流重定向枚举实例,表示子进程标准流将被重定向至指定的文件。重定向标准输入流将从指定文件读取,重定向标准输出流或标准错误流将写入至指定文件。重定向文件需保证存在且未关闭,否则不允许重定向。此模式下标准流属性不可读取或写入。参数 File 为指定存在且未关闭文件实例,创建子进程时,重定向标准流至该指定文件。
Inherit
Inherit
功能:构造一个标准流重定向枚举实例,表示子进程标准流将继承当前进程的标准流。此模式下标准流属性不可读取或写入。
Pipe
Pipe
功能:构造一个标准流重定向枚举实例,表示子进程标准流将被重定向至管道,并通过管道与当前进程连接。重定向标准输入流可通过管道向子进程写入数据,重定向标准输出流或标准错误流可通过管道读取子进程输出结果。此模式下可通过标准流属性读取或写入数据。
异常
class ProcessException
public class ProcessException <: IOException {
public init(message: String)
}
功能:process 包的异常类。
父类型:
init(String)
public init(message: String)
功能:创建 ProcessException 实例。
参数:
- message: String - 异常提示信息。
任意进程相关操作
下面是任意进程相关操作示例,以下示例不支持 Windows 平台。
代码如下:
import std.process.*
main(): Int64 {
let echoProcess: SubProcess = launch("sleep", "10s")
let ofProcess: Process = findProcess(echoProcess.pid)
println(ofProcess.pid)
println(ofProcess.name)
println(ofProcess.command)
ofProcess.terminate(force: true)
return 0
}
运行结果可能如下:
70753
sleep
sleep
子进程相关操作
下面是子进程相关操作示例,以下示例不支持 Windows 平台。
代码如下:
import std.process.*
import std.io.*
import std.fs.*
// 以Linux平台相关命令举例说明, 以下用例需要提前创建 “/root/code/Process/test” 目录
main(): Int64 {
let sleepProcess: SubProcess = launch("sleep", "10s", workingDirectory: Path("/root/code/Process/test"))
println(sleepProcess.pid)
println(sleepProcess.name)
println(sleepProcess.command)
sleepProcess.terminate(force: true)
let rtnCode = sleepProcess.wait()
println("sleepProcess rtnCode: ${rtnCode}")
let echoProcess: SubProcess = launch("echo", "hello cangjie!", stdOut: ProcessRedirect.Pipe)
let strReader: StringReader<InputStream> = StringReader(echoProcess.stdOutPipe)
println(strReader.readToEnd())
return 0
}
运行结果可能如下:
65953
sleep
sleep
sleepProcess rtnCode: 9
hello cangjie!
std.random
功能介绍
random 包提供生成伪随机数的能力。
API列表
类
| 类名 | 功能 |
|---|---|
| Random | 提供生成伪随机数的相关功能。 |
类
class Random
public class Random {
public init()
public init(seed: UInt64)
}
功能:提供生成伪随机数的相关功能。
示例:
import std.random.*
main() {
/* 创建 Random 对象并设置种子来获取随机对象 */
let m: Random = Random(3)
let b: Bool = m.nextBool()
let c: Int8 = m.nextInt8()
print("b=${b is Bool},")/* 对象也可以是 Bool 类型 */
println("c=${c is Int8}")
return 0
}
运行结果:
b=true,c=true
prop seed
public prop seed: UInt64
功能:获取随机数种子。
类型:UInt64
init()
public init()
功能:默认无参构造函数创建新的 Random 对象。
init(UInt64)
public init(seed: UInt64)
功能:使用随机数种子创建新的 Random 对象。
参数:
- seed: UInt64 - 随机数种子,如果设置相同随机种子,生成的伪随机数列表相同。
func next(UInt64) (deprecated)
public func next(bits: UInt64): UInt64
功能:生成一个用户指定位长的随机整数。
注意:
未来版本即将废弃,使用 nextBits 替代。
参数:
- bits: UInt64 - 要生成的伪随机数的位数,取值范围 (0, 64]。
返回值:
- UInt64 - 用户指定位长的伪随机数。
异常:
- IllegalArgumentException - 如果
bits等于 0 ,或大于 64,超过所能截取的 UInt64 长度,则抛出异常。
func nextBits(UInt64)
public func nextBits(bits: UInt64): UInt64
功能:生成一个指定位长的随机整数。
参数:
- bits: UInt64 - 要生成的伪随机数的位数,取值范围 (0, 64]。
返回值:
- UInt64 - 生成的用户指定位长的伪随机数。
异常:
- IllegalArgumentException - 如果
bits等于 0,或大于 64,超过所能截取的 UInt64 长度,则抛出异常。
func nextBool()
public func nextBool(): Bool
功能:获取一个布尔类型的伪随机值。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Bool = m.nextBool()
println("n=${n is Bool}")
return 0
}
运行结果:
n=true
func nextFloat16()
public func nextFloat16(): Float16
功能:获取一个 Float16 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Float16 = m.nextFloat16()
if (n is Float16) {
println("n is Float16")
}
return 0
}
运行结果:
n is Float16
func nextFloat32()
public func nextFloat32(): Float32
功能:获取一个 Float32 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Float32 = m.nextFloat32()
if (n is Float32) {
println("n is Float32")
}
return 0
}
运行结果:
n is Float32
func nextFloat64()
public func nextFloat64(): Float64
功能:获取一个 Float64 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Float64 = m.nextFloat64()
if (n is Float64) {
println("n is Float64")
}
return 0
}
运行结果:
n is Float64
func nextGaussianFloat16(Float16, Float16)
public func nextGaussianFloat16(mean!: Float16 = 0.0, sigma!: Float16 = 1.0): Float16
功能:获取一个 Float16 类型的符合指定均值与标准差的高斯分布的随机数。
默认获取一个 Float16 类型且符合均值为 0.0 标准差为 1.0 的高斯分布的随机数。其中均值是期望值,可解释为位置参数,决定了分布的位置,标准差可解释为尺度参数,决定了分布的幅度。
参数:
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Float16 = m.nextGaussianFloat16(mean: 0.0, sigma: 1.0)
if (n is Float16) {
println("n is Float16")
}
return 0
}
运行结果:
n is Float16
func nextGaussianFloat32(Float32, Float32)
public func nextGaussianFloat32(mean!: Float32 = 0.0, sigma!: Float32 = 1.0): Float32
功能:获取一个 Float32 类型的符合指定均值与标准差的高斯分布的随机数。
默认获取一个 Float32 类型且符合均值为 0.0 标准差为 1.0 的高斯分布的随机数。其中均值是期望值,可解释为位置参数,决定了分布的位置,标准差可解释为尺度参数,决定了分布的幅度。
参数:
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Float32 = m.nextGaussianFloat32(mean: 0.0, sigma: 1.0)
if (n is Float32) {
println("n is Float32")
}
return 0
}
运行结果:
n is Float32
func nextGaussianFloat64(Float64, Float64)
public func nextGaussianFloat64(mean!: Float64 = 0.0, sigma!: Float64 = 1.0): Float64
功能:获取一个 Float64 类型的符合指定均值与标准差的高斯分布的随机数。
默认获取一个 Float64 类型且符合均值为 0.0 标准差为 1.0 的高斯分布的随机数。其中均值是期望值,可解释为位置参数,决定了分布的位置,标准差可解释为尺度参数,决定了分布的幅度。
参数:
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Float64 = m.nextGaussianFloat64(mean: 0.0, sigma: 1.0)
if (n is Float64) {
println("n is Float64")
}
return 0
}
运行结果:
n is Float64
func nextInt16()
public func nextInt16(): Int16
功能:获取一个 Int16 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int16 = m.nextInt16()
if (n is Int16) {
println("n is Int16")
}
return 0
}
运行结果:
n is Int16
func nextInt16(Int16)
public func nextInt16(upper: Int16): Int16
功能:获取一个范围在 [0, upper) 的 Int16 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int16 = m.nextInt16(5)
if (n is Int16) {
println("n is Int16")
}
try {
let p: Int16 = m.nextInt16(-1)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 小于等于 0")
}
return 0
}
运行结果:
n is Int16
参数异常:upper 小于等于 0
func nextInt32()
public func nextInt32(): Int32
功能:获取一个 Int32 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int32 = m.nextInt32()
if (n is Int32) {
println("n is Int32")
}
return 0
}
运行结果:
n is Int32
func nextInt32(Int32)
public func nextInt32(upper: Int32): Int32
功能:获取一个范围在 [0, upper) 的 Int32 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int32 = m.nextInt32(5)
if (n is Int32) {
println("n is Int32")
}
try {
let p: Int32 = m.nextInt32(-1)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 小于等于 0")
}
return 0
}
运行结果:
n is Int32
参数异常:upper 小于等于 0
func nextInt64()
public func nextInt64(): Int64
功能:获取一个 Int64 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int64 = m.nextInt64()
if (n is Int64) {
println("n is Int64")
}
return 0
}
运行结果:
n is Int64
func nextInt64(Int64)
public func nextInt64(upper: Int64): Int64
功能:获取一个范围在 [0, upper) 的 Int64 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int64 = m.nextInt64(5)
if (n is Int64) {
println("n is Int64")
}
try {
let p: Int64 = m.nextInt64(-1)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 小于等于 0")
}
return 0
}
运行结果:
n is Int64
参数异常:upper 小于等于 0
func nextInt8()
public func nextInt8(): Int8
功能:获取一个 Int8 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int8 = m.nextInt8()
if (n is Int8) {
println("n is Int8")
}
return 0
}
运行结果:
n is Int8
func nextInt8(Int8): Int8
public func nextInt8(upper: Int8): Int8
功能:获取一个范围在 [0, upper) 的 Int8 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: Int8 = m.nextInt8(5)
if (n is Int8) {
println("n is Int8")
}
try {
let p: Int8 = m.nextInt8(-1)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 小于等于 0")
}
return 0
}
运行结果:
n is Int8
参数异常:upper 小于等于 0
func nextUInt16()
public func nextUInt16(): UInt16
功能:获取一个 UInt16 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt16 = m.nextUInt16()
if (n is UInt16) {
println("n is UInt16")
}
return 0
}
运行结果:
n is UInt16
func nextUInt16(UInt16)
public func nextUInt16(upper: UInt16): UInt16
功能:获取一个范围在 [0, upper) 的 UInt16 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt16 = m.nextUInt16(5)
if (n is UInt16) {
println("n is UInt16")
}
try {
let p: UInt16 = m.nextUInt16(0)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 等于 0")
}
return 0
}
运行结果:
n is UInt16
参数异常:upper 等于 0
func nextUInt32()
public func nextUInt32(): UInt32
功能:获取一个 UInt32 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt32 = m.nextUInt32()
if (n is UInt32) {
println("n is UInt32")
}
return 0
}
运行结果:
n is UInt32
func nextUInt32(UInt32)
public func nextUInt32(upper: UInt32): UInt32
功能:获取一个范围在 [0, upper) 的 UInt32 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt32 = m.nextUInt32(5)
if (n is UInt32) {
println("n is UInt32")
}
try {
let p: UInt32 = m.nextUInt32(0)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 等于 0")
}
return 0
}
运行结果:
n is UInt32
参数异常:upper 等于 0
func nextUInt64()
public func nextUInt64(): UInt64
功能:获取一个 UInt64 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt64 = m.nextUInt64()
if (n is UInt64) {
println("n is UInt64")
}
return 0
}
运行结果:
n is UInt64
func nextUInt64(UInt64)
public func nextUInt64(upper: UInt64): UInt64
功能:获取一个范围在 [0, upper) 的 UInt64 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt64 = m.nextUInt64(5)
if (n is UInt64) {
println("n is UInt64")
}
try {
let p: UInt64 = m.nextUInt64(0)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 等于 0")
}
return 0
}
运行结果:
n is UInt64
参数异常:upper 等于 0
func nextUInt8()
public func nextUInt8(): UInt8
功能:获取一个 UInt8 类型的伪随机数。
返回值:
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt8 = m.nextUInt8()
if (n is UInt8) {
println("n is UInt8")
}
return 0
}
运行结果:
n is UInt8
func nextUInt8(UInt8)
public func nextUInt8(upper: UInt8): UInt8
功能:获取一个范围在 [0, upper) 的 UInt8 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
示例:
import std.random.*
main() {
let m: Random = Random()
let n: UInt8 = m.nextUInt8(5)
if (n is UInt8) {
println("n is UInt8")
}
try {
let p: UInt8 = m.nextUInt8(0)
println(p)
} catch (e: IllegalArgumentException) {
println("参数异常:upper 等于 0")
}
return 0
}
运行结果:
n is UInt8
参数异常:upper 等于 0
func nextUInt8s(Array<UInt8>) (deprecated)
public func nextUInt8s(array: Array<UInt8>): Array<UInt8>
功能:生成随机数替换入参数组中的每个元素。
注意:
未来版本即将废弃,使用 nextBytes 替代。
参数:
返回值:
func nextBytes(Array<Byte>)
public func nextBytes(bytes: Array<Byte>): Unit
功能:生成随机数替换入参数组中的每个元素。
参数:
func nextBytes(Int32)
public func nextBytes(length: Int32): Array<Byte>
功能:生成指定长度的随机数数组。
参数:
- length: Int32 - 生成的随机数数组长度,
length大于 0。
返回值:
异常:
- IllegalArgumentException - 当参数
length小于等于 0 时,抛出异常。
std.ref
功能介绍
ref 包提供了弱引用相关的能力。弱引用是一个相对“强引用”的概念,对于强引用,如果引用不为空并且运行时分析可达性成立,则 GC 不会回收它,但是对于弱引用,在一些情况下即使可达性成立,GC 依然可能会回收该引用。
弱引用常用于缓存、对象池、线程池、事件监听器等场景。例如,我们可以使用弱引用来缓存一些大型的对象以达到复用的目的,与强引用不同的是,当内存不足时,这些被弱引用指向的对象也可以被 GC 自动回收,从而减少内存压力,而被强引用指向的对象则无法被 GC 自动回收,可能会造成 OOM 。
本包提供 WeakRef 类,支持将任意 Object 实例封装成弱引用实例,如果原 Object 实例没有除弱引用外的其他引用,将可能在某一时刻被 GC 回收。
同时,本包支持两种回收策略,激进回收策略( GC 会尽快回收弱引用指向的对象)和延迟回收策略( GC 会尽量晚回收弱引用指向的对象,例如仅在内存不足时回收)。
API列表
类
| 类名 | 功能 |
|---|---|
| WeakRef | 此类提供弱引用相关的功能,如果一个对象的引用被标记为弱引用,那么即使引用不为空并且该对象的可达性成立, GC 也可以按照指定的回收策略回收它。 |
| WeakRefBase | 此类不包含任何公开成员和公开函数,也不允许被继承、扩展, 仅作为 WeakRef 的基类。 |
枚举
| 枚举名 | 功能 |
|---|---|
| CleanupPolicy | 该枚举表示不同的清理策略,分别为 EAGER 和 DEFERRED。 |
类
class WeakRef<T> where T <: Object
public class WeakRef<T> <: WeakRefBase where T <: Object {
public init(value: T, cleanupPolicy: CleanupPolicy)
}
功能:此类提供弱引用相关的功能,如果一个对象的引用被标记为弱引用,那么即使引用不为空并且该对象的可达性成立, GC 也可以按照指定的回收策略回收它。
prop cleanupPolicy
public prop cleanupPolicy: CleanupPolicy
功能:获取该弱引用的清理策略。
prop value
public prop value: Option<T>
功能:读取弱引用指向的对象。如果弱引用为空或弱引用中的对象已被清理则返回 None。
类型:Option<T>
init(T, CleanupPolicy)
public init(value: T, cleanupPolicy: CleanupPolicy)
功能:为 value 对象创建弱引用,并指定清理策略。
参数:
- value: T - 弱引用指向的对象。
- cleanupPolicy: CleanupPolicy -
value对象的清理策略。
func clear()
public func clear(): Unit
功能:强制清理弱引用指向的对象,后续对 value 的访问将返回 None。
class WeakRefBase
sealed abstract class WeakRefBase
此类不包含任何公开成员和公开函数,也不允许被继承、扩展, 仅作为 WeakRef 的基类。
枚举
enum CleanupPolicy
public enum CleanupPolicy <: Equatable<CleanupPolicy> {
| EAGER
| DEFERRED
}
功能:该枚举表示不同的弱引用清理策略,分别为 EAGER 和 DEFERRED。
在 WeakRef 类中可以指定对象的清理策略。
EAGER
EAGER
功能:指定 WeakRef 实例的清理策略为 EAGER,在该清理策略下,GC 会尽快回收 WeakRef 指向的对象,但不能保证其立即回收,也不能保证其一定会被回收。
DEFERRED
DEFERRED
功能:指定 WeakRef 实例的清理策略为 DEFERRED,在该清理策略下,GC 会尽可能保证 WeakRef 中的对象存活,只有当可用内存不足时才回收它。
operator func ==(CleanupPolicy)
public operator func ==(that: CleanupPolicy): Bool
功能:对 Enum CleanupPolicy 判断是否相等。
参数:
- that: CleanupPolicy - 被比较的枚举实例。
返回值:
- Bool - 当前回收策略与
that回收策略相同时返回true,否则返回false。
operator func !=(CleanupPolicy)
public operator func !=(that: CleanupPolicy): Bool
功能:对 Enum CleanupPolicy 判断是否不等。
参数:
- CleanupPolicy: CleanupPolicy - 被比较的枚举实例。
返回值:
- Bool - 当前回收策略与
that回收策略不同时返回true,否则返回false。
WeakRef 用于缓存
以下使用 WeakRef 实现了一个缓存,假设某个数据的计算非常耗时,我们希望将其计算结果缓存起来,但又不希望过量缓存导致 OOM ,那么我们可以使用弱引用。
import std.ref.{WeakRef, CleanupPolicy}
public interface Cacheable<T> {
static func reCalculate() : T
}
public class Data <: Cacheable<Data> {
public var number: Int64
init(n : Int64) {
number = n
}
public static func reCalculate(): Data {
// 模拟运算
println("re-calculations!")
let data = Data(321)
return data
}
}
public class Cache<T> where T <: Object & Cacheable<T> {
private var cache : WeakRef<T>
public init(data: T) {
cache = WeakRef<T>(data, CleanupPolicy.DEFERRED) // 这里我们选用 DEFERRED 策略,因为我们希望 Data 保存的尽量久。
}
public func getData(): T {
match(cache.value) {
case Some(x) => x
case None =>
// 如果 GC 释放了缓存中的数据则重新运算
let data = T.reCalculate()
cache = WeakRef<T>(data, CleanupPolicy.DEFERRED)
data
}
}
public func clear() : Unit {
cache.clear()
}
}
main () {
let data = Data(123)
var c = Cache<Data>(data)
println(c.getData().number) // 直接从缓存中读取数据,不需要重新运算
println(c.getData().number) // 直接从缓存中读取数据,不需要重新运算
c.clear() // 清空缓存
println(c.getData().number) // 重新运算
return 0
}
运行结果:
123
123
re-calculations!
321
std.reflect
功能介绍
reflect 包提供了反射功能,使得程序在运行时能够获取到各种实例的类型信息,并进行各种读写和调用操作。
本包暂不支持 macOS 平台。
注意:
- 对于全局信息仓颉的反射功能只能访问可见性为
public的全局变量和全局函数。- 对于当前所在包,仓颉的反射功能可以访问所有全局定义的类型,而对于外部导入的包或动态加载的模块,则只能访问其中可见性为
public的全局定义的类型。- 对于成员信息仓颉的反射功能只能访问类型内的可见性为
public的成员(实例/静态成员变量/属性/函数),使用非public修饰符修饰的或缺省修饰符的成员均是不可见的。- 目前,仓颉的反射功能尚不支持函数类型、元组类型、
enum类型。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| parseParameterTypes(String) | 将字符串转换为包含具体类型信息的函数签名,以便 getStaticFunction 等函数使用。 |
类型别名
| 类型别名 | 功能 |
|---|---|
| Annotation | Object 的别名。 |
类
| 类名 | 功能 |
|---|---|
| ClassTypeInfo | 描述class类型的类型信息。 |
| ConstructorInfo | 描述构造函数信息。 |
| GenericTypeInfo | 描述泛型信息。 |
| GlobalFunctionInfo | 描述全局函数信息。 |
| GlobalVariableInfo | 描述全局变量信息。 |
| InstanceFunctionInfo | 描述实例成员函数信息。 |
| InstancePropertyInfo | 描述实例成员属性信息。 |
| InstanceVariableInfo | 描述实例成员变量信息。 |
| InterfaceTypeInfo | 描述interface类型的类型信息。 |
| PackageInfo | 描述包信息。 |
| ParameterInfo | 描述函数形参信息。 |
| PrimitiveTypeInfo | 描述原始数据类型的类型信息。 |
| StaticFunctionInfo | 描述静态成员函数信息。 |
| StaticPropertyInfo | 描述静态成员属性信息。 |
| StaticVariableInfo | 描述静态成员变量信息。 |
| StructTypeInfo | 描述struct类型的类型信息。 |
| TypeInfo | TypeInfo提供了所有数据类型通用的操作接口,支持用户进行反射操作。 |
枚举
| 枚举名 | 功能 |
|---|---|
| ModifierInfo | 描述修饰符信息。 |
异常类
| 异常类名 | 功能 |
|---|---|
| IllegalSetException | 表示对不可变类型进行更改异常。 |
| IllegalTypeException | 表示类型不匹配异常。 |
| InfoNotFoundException | 表示无法找到对应信息异常。 |
| InvocationTargetException | 表示调用函数包装异常。 |
| MisMatchException | 表示调用对应函数抛出异常。 |
| ReflectException | ReflectException 为 Reflect 包的基异常类。 |
函数
func parseParameterTypes(String)
public func parseParameterTypes(parameters: String): Array<TypeInfo>
功能:从字符串中解析出参数类型,并将其转换为类型数组,以便getStaticFunction等函数使用。
函数参数类型限定名称为函数类型的参数类型部分,不包含参数名、默认值,也不包含最外层的 ()。
因此对于下面的一个仓颉函数:
import m1.p1.T1
func f(a: Int64, b: T1, c!: Int64 = 0, d!: Int64 = 0): Int64 { ... }
其限定名称应该为"Int64, p1.T1, Int64, Int64"。对于无参函数的限定名称应该为 ""。
参数:
- parameters: String - 函数参数类型限定名称。
返回值:
异常:
- IllegalArgumentException - 字符串格式错误,则会抛出异常。
- InfoNotFoundException - 如果无法获得参数中的类型信息,则会抛出异常。
示例:
import std.reflect.*
class A {
}
main(): Unit {
println(parseParameterTypes("Int64, String, default.A"))
}
运行结果:
[Int64, String, default.A]
类型别名
type Annotation = Object
public type Annotation = Object
功能:Object 的别名。
类
class ClassTypeInfo
public class ClassTypeInfo <: TypeInfo
功能:描述 class 类型的类型信息。
父类型:
prop constructors
public prop constructors: Collection<ConstructorInfo>
功能:获取该 ClassTypeInfo 对应的 class 的所有 public 构造函数信息,返回对应集合。
注意:
- 如果该
class类型无任何public构造函数,则返回空集合。- 该集合不保证遍历顺序恒定。
类型:Collection<ConstructorInfo>
示例:
package test
import std.reflect.*
public class Rectangular {
public var myName = ""
public init() {}
public init(name: String) {
myName = name
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取 constructors
for (i in ty.constructors) {
println(i)
}
return
}
运行结果:
init()
init(String)
prop instanceVariables
public prop instanceVariables: Collection<InstanceVariableInfo>
功能:获取该 ClassTypeInfo 对应的 class 的所有 public 实例成员变量信息,返回对应集合。
注意:
- 如果该
class类型无任何public实例成员变量,则返回空集合。- 该集合不保证遍历顺序恒定。
- 该集合不包含任何继承而来的
public实例成员变量。
类型:Collection<InstanceVariableInfo>
示例:
package test
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public var myName = ""
public init() {}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取 instanceVariables
for (i in ty.instanceVariables) {
println(i)
}
return
}
运行结果:
length: Int64
width: Int64
myName: String
prop sealedSubclasses
public prop sealedSubclasses: Collection<ClassTypeInfo>
功能:如果该 ClassTypeInfo 对应的 class 类型拥有 sealed 语义,则获取该 class 类型所在包内的所有子类的类型信息,返回对应集合。
注意:
- 如果该
class类型不拥有sealed语义,则返回空集合。- 如果该
class类型拥有sealed语义,那么获得的集合必不可能是空集合,因为该class类型本身就是自己的子类。
prop staticVariables
public prop staticVariables: Collection<StaticVariableInfo>
功能:获取该 ClassTypeInfo 对应的 class 的所有 public 静态成员变量信息,返回对应集合。
注意:
- 如果该
class类型无任何public静态成员变量,则返回空集合。- 该集合不保证遍历顺序恒定。
- 该集合不包含任何继承而来的
public静态成员变量。
类型:Collection<StaticVariableInfo>
prop superClass
public prop superClass: Option<ClassTypeInfo>
功能:获取该 class 类型信息所对应的 class 类型的直接父类。
注意:
理论上只有 class Object 没有直接父类。
类型:Option<ClassTypeInfo>
func construct(Array<Any>)
public func construct(args: Array<Any>): Any
功能:在该 ClassTypeInfo 对应的 class 类型中根据实参列表搜索匹配的构造函数并调用,传入实参列表,返回调用结果。
参数:
返回值:
- Any - 该
class类型的实例。
异常:
- IllegalTypeException - 如果该
class类型拥有abstract语义,调用construct则抛出异常,因为抽象类不可被实例化。 - MisMatchException - 如果
args未能成功匹配任何该class类型的可见性为public的构造函数,则抛出异常。 - InvocationTargetException - 在被调用的构造函数内部抛出的任何异常均将被封装为 InvocationTargetException 异常并抛出。
示例:
package test
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public var myName = ""
public init() {}
public init(name: String) {
myName = name
}
public init(name: String, length: Int64, width: Int64) {
myName = name
this.length = length
this.width = width
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 通过不同入参构造实例
ty.construct()
ty.construct("Small rectangular")
ty.construct("Big rectangular", 1, 1)
return
}
func getConstructor(Array<TypeInfo>)
public func getConstructor(parameterTypes: Array<TypeInfo>): ConstructorInfo
功能:尝试在该 ClassTypeInfo 对应的 class 类型中获取与给定形参类型信息列表匹配的 public 构造函数的信息。
参数:
返回值:
- ConstructorInfo - 如果成功匹配则返回该
public构造函数的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public构造函数,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public var myName = ""
public init() {}
public init(name: String) {
myName = name
}
public init(name: String, length: Int64, width: Int64) {
myName = name
this.length = length
this.width = width
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取指定构造函数信息
let ci01 = ty.getConstructor(StructTypeInfo.get("String"))
println(ci01)
// 获取指定构造函数信息
let ci02 = ty.getConstructor(StructTypeInfo.get("String"), PrimitiveTypeInfo.get("Int64"), PrimitiveTypeInfo.get("Int64"))
println(ci02)
return
}
运行结果:
init(String)
init(String, Int64, Int64)
func getInstanceVariable(String)
public func getInstanceVariable(name: String): InstanceVariableInfo
功能:给定变量名称,尝试获取该 ClassTypeInfo 所对应的 class 类型中匹配的实例成员变量的信息。
参数:
- name: String - 变量名称。
返回值:
- InstanceVariableInfo - 如果成功匹配则返回该实例成员变量的信息。
异常:
- InfoNotFoundException - 如果没找到对应实例成员变量,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public var myName = ""
public init() {}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取类实例成员信息
let ivi = ty.getInstanceVariable("myName")
println(ivi)
return
}
运行结果:
myName: String
func getStaticVariable(String)
public func getStaticVariable(name: String): StaticVariableInfo
功能:给定变量名称,尝试获取该 ClassTypeInfo 所对应的 class 类型中匹配的静态成员变量的信息。
参数:
- name: String - 变量名称。
返回值:
- StaticVariableInfo - 如果成功匹配则返回该静态成员变量的信息。
异常:
- InfoNotFoundException - 如果没找到对应静态成员变量,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
public static var area: Int64 = 10
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取静态变量
let sv = ty.getStaticVariable("area")
println(sv)
return
}
运行结果:
static area: Int64
func isAbstract()
public func isAbstract(): Bool
功能:判断该 ClassTypeInfo 对应的 class 类型是否是抽象类。
返回值:
- Bool - 如果该 ClassTypeInfo 对应的
class类型是抽象类则返回true,否则返回false。
func isOpen()
public func isOpen(): Bool
功能:判断该 ClassTypeInfo 对应的 class 类型是否拥有 open 语义。
注意:
并不是只有被
open修饰符所修饰的class类型定义才拥有open语义,如:abstract class无论是否被open修饰符修饰都会拥有open语义。
返回值:
- Bool - 如果该 ClassTypeInfo 对应的
class类型拥有open语义则返回true,否则返回false。
func isSealed()
public func isSealed(): Bool
功能:判断该 ClassTypeInfo 对应的 class 类型是否拥有 sealed 语义。
返回值:
- Bool - 如果该 ClassTypeInfo 对应的
class类型拥有sealed语义则返回true,否则返回false。
static func get(String)
public redef static func get(qualifiedName: String): ClassTypeInfo
功能:获取给定限定名称所对应类型的 ClassTypeInfo。
参数:
- qualifiedName: String - 类型的限定名称。
返回值:
- ClassTypeInfo - 类型的限定名称
qualifiedName所对应的类型的类型信息。
异常:
- InfoNotFoundException - 如果无法获取与给定类型的限定名称
qualifiedName匹配的类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 ClassTypeInfo, 则抛出异常。
示例:
import std.reflect.*
public class Rectangular {}
main(): Unit {
let ty = ClassTypeInfo.get("default.Rectangular")
println(ty)
return
}
运行结果:
default.Rectangular
static func of(Any)
public redef static func of(a: Any): ClassTypeInfo
功能:获取给定的任意类型的实例的运行时类型所对应的类型信息。
运行时类型是指在程序运行时,通过动态绑定确定的类型,运行时类型与实例对象相绑定。在继承等场景下运行时类型和静态类型可能不一致。
参数:
- a: Any - 任意类型的实例。
返回值:
- ClassTypeInfo - 实例
a的运行时类型所对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得实例
a的运行时类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 ClassTypeInfo, 则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {}
main(): Unit {
var r = Rectangular()
let ty = ClassTypeInfo.of(r)
println(ty)
return
}
运行结果:
test.Rectangular
static func of(Object)
public static func of(a: Object): ClassTypeInfo
功能:获取给定的 class 类型的实例的运行时类型所对应的 class 类型信息。
参数:
- a: Object -
class类型的实例。
返回值:
- ClassTypeInfo -
class类型的实例a的运行时类型所对应的class类型信息。
异常:
- InfoNotFoundException - 如果无法获得实例
a的运行时类型所对应的class类型信息,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {}
main(): Unit {
var r = Rectangular()
let ty = ClassTypeInfo.of(r)
println(ty)
return
}
运行结果:
test.Rectangular
static func of<T>()
public redef static func of<T>(): ClassTypeInfo
功能:获取给定类型 T 对应的类型信息。
返回值:
- ClassTypeInfo -
T类型对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得类型 T 所对应的类型信息,抛出异常。
- IllegalTypeException - 如果获取到的类型信息不是 ClassTypeInfo, 则抛出异常。
示例:
import std.reflect.*
public class Rectangular {}
main(): Unit {
let ty = ClassTypeInfo.of<Rectangular>()
println(ty)
return
}
运行结果:
default.Rectangular
class ConstructorInfo
public class ConstructorInfo <: Equatable<ConstructorInfo> & Hashable & ToString
功能:描述构造函数信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 ConstructorInfo 对应的构造函数的注解,返回对应集合。
注意:
- 如果无任何注解作用于该构造函数信息所对应的构造函数,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop parameters
public prop parameters: ReadOnlyList<ParameterInfo>
功能:获取该 ConstructorInfo 所对应的构造函数的参数类型列表。
注意:
不保证参数顺序,可根据
ParameterInfo的index属性确定参数实际位置。
类型:ReadOnlyList<ParameterInfo>
示例:
package test
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public var myName = ""
public init() {}
public init(name: String) {
myName = name
}
public init(name: String, length: Int64, width: Int64) {
myName = name
this.length = length
this.width = width
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取 constructors
for (i in ty.constructors) {
// 获取 parameters
for (j in i.parameters) {
println("${i} 的入参有 ${j}")
}
}
return
}
运行结果:
init(String) 的入参有 String
init(String, Int64, Int64) 的入参有 String
init(String, Int64, Int64) 的入参有 Int64
init(String, Int64, Int64) 的入参有 Int64
func apply(Array<Any>)
public func apply(args: Array<Any>): Any
功能:调用该 ConstructorInfo 对应的构造函数,传入实参列表,并返回调用结果。
注意:
目前,
struct类型中定义的构造函数不支持被调用。
参数:
返回值:
- Any - 由该构造函数构造得到的类型实例。
异常:
- InvocationTargetException - 如果该构造函数信息所对应的构造函数所属的类型是抽象类,则会抛出异常。
- IllegalArgumentException - 如果实参列表
args中的实参的数目与该构造函数信息所对应的构造函数的形参列表中的形参的数目不等,则抛出异常。 - IllegalTypeException - 如果实参列表
args中的任何一个实参的运行时类型不是该构造函数信息所对应的构造函数的对应形参的声明类型的子类型,则抛出异常。 - Exception - 如果被调用的构造函数信息所对应的构造函数内部抛出异常,则该异常将被封装为 Exception 异常并抛出。
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 ConstructorInfo 对应的构造函数且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func hashCode()
public func hashCode(): Int64
功能:获取该构造器信息的哈希值。
返回值:
- Int64 - 该构造器信息的哈希值。
func toString()
public func toString(): String
功能:获取字符串形式的该构造函数信息。
返回值:
- String - 字符串形式的该构造函数信息。
operator func !=(ConstructorInfo)
public operator func !=(that: ConstructorInfo): Bool
功能:判断该构造器信息与给定的另一个构造器信息是否不等。
参数:
- that: ConstructorInfo - 被比较相等性的另一个构造器信息。
返回值:
- Bool - 如果该构造器信息与
that不等则返回true,否则返回false。
operator func ==(ConstructorInfo)
public operator func ==(that: ConstructorInfo): Bool
功能:判断该构造器信息与给定的另一个构造器信息是否相等。
参数:
- that: ConstructorInfo - 被比较相等性的另一个构造器信息。
返回值:
- Bool - 如果该构造器信息与
that相等则返回true,否则返回false。
class GenericTypeInfo
public class GenericTypeInfo <: TypeInfo & Equatable<GenericTypeInfo>
功能:描述泛型类型信息。
父类型:
operator func ==(GenericTypeInfo)
public operator func ==(that: GenericTypeInfo): Bool
功能:判断该泛型类型信息与给定的另一个泛型类型信息是否相等。
参数:
- that: GenericTypeInfo - 被比较相等性的另一个泛型类型信息。
返回值:
- Bool - 如果该泛型类型信息与
that相等则返回true,否则返回false。
class GlobalFunctionInfo
public class GlobalFunctionInfo <: Equatable<GlobalFunctionInfo> & Hashable & ToString
功能:描述全局函数信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有GlobalFunctionInfo 对应的全局函数的注解,返回对应集合。
注意:
- 如果无任何注解作用于该全局函数信息所对应全局函数,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop genericParams
public prop genericParams: Collection<GenericTypeInfo>
功能:获取该 GlobalFunctionInfo 对应的实例成员函数的泛型参数信息列表。
类型:Collection<GenericTypeInfo>
异常:
- InfoNotFoundException - GlobalFunctionInfo 没有泛型参数时抛出异常。
prop name
public prop name: String
功能:获取该 GlobalFunctionInfo 对应的全局函数的名称。
注意:
构成重载的所有全局函数将拥有相同的名称。
类型:String
prop parameters
public prop parameters: ReadOnlyList<ParameterInfo>
功能:获取该 GlobalFunctionInfo 对应的全局函数的参数信息列表。
注意:
不保证参数顺序,可根据
ParameterInfo的index属性确定参数实际位置。
类型:ReadOnlyList<ParameterInfo>
prop returnType
public prop returnType: TypeInfo
功能:获取该 GlobalFunctionInfo 对应的全局函数的返回类型的类型信息。
类型:TypeInfo
func apply(Array<Any>)
public func apply(args: Array<Any>): Any
功能:调用该 GlobalFunctionInfo 对应的全局函数,传入实参列表,返回调用结果。
注意:
args的类型确保和函数入参类型完全一致,否则会导致参数检查失败。
参数:
返回值:
- Any - 该全局函数的调用结果。
异常:
- InvocationTargetException - 如果存在泛型参数的函数调用了该方法,则抛出异常。
- IllegalArgumentException - 如果实参列表
args中的实参的数目与该全局函数信息GlobalFunctionInfo所对应的全局函数的形参列表中的形参的数目不等,则抛出异常。 - IllegalTypeException - 如果实参列表
args中的任何一个实参的运行时类型不是该全局函数信息所对应的全局函数的对应形参的声明类型的子类型,则抛出异常。 - Exception - 如果被调用的全局函数信息所对应全局函数内部抛出异常,则该异常将被封装为 Exception 异常并抛出。
func apply(Array<TypeInfo>, Array<Any>)
public func apply(genericTypeArgs: Array<TypeInfo>, args: Array<Any>): Any
功能:调用该 GlobalFunctionInfo 对应的全局泛型函数,传入泛型参数类型列表和实参列表,返回调用结果。
注意:
args的类型确保和函数入参类型完全一致,否则会导致参数检查失败。
参数:
返回值:
- Any - 该全局函数的调用结果。
异常:
- InvocationTargetException - 如果非泛型函数调用了该方法,则抛出异常。
- IllegalArgumentException - 如果实参列表
args中的实参的数目与该全局函数信息GlobalFunctionInfo所对应的全局函数的形参列表中的形参的数目不等,则抛出异常。 - IllegalArgumentException - 如果函数泛型参数列表
genericTypeArgs中的参数数目与该全局函数信息所对应的全局函数的泛型参数列表genericParams中的参数数目不等,则抛出异常。 - IllegalTypeException - 如果实参列表
args中的任何一个实参的运行时类型不是该全局函数信息所对应的全局函数的对应形参的声明类型的子类型,则抛出异常。 - IllegalTypeException - 如果传入的参数列表
args和泛型参数类型列表genericTypeArgs不满足该全局函数信息所对应的全局函数的参数的类型约束,则抛出异常。 - Exception - 如果被调用的全局函数信息所对应全局函数内部抛出异常,则该异常将被封装为 Exception 异常并抛出。
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 GlobalFunctionInfo 对应的全局函数且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func hashCode()
public func hashCode(): Int64
功能:获取该全局函数信息的哈希值。
返回值:
- Int64 - 该全局函数信息的哈希值。
func toString()
public func toString(): String
功能:获取字符串形式的该全局函数信息。
返回值:
- String - 字符串形式的该全局函数信息。
operator func ==(GlobalFunctionInfo)
public operator func ==(that: GlobalFunctionInfo): Bool
功能:判断该全局函数信息与给定的另一个全局函数信息是否相等。
参数:
- that: GlobalFunctionInfo - 被比较相等性的另一个全局函数信息。
返回值:
- Bool - 如果该全局函数信息与
that相等则返回true,否则返回false。
operator func !=(GlobalFunctionInfo)
public operator func !=(that: GlobalFunctionInfo): Bool
功能:判断该全局函数信息与给定的另一个全局函数信息是否不等。
参数:
- that: GlobalFunctionInfo - 被比较相等性的另一个全局函数信息。
返回值:
- Bool - 如果该全局函数信息与
that不等则返回true,否则返回false。
class GlobalVariableInfo
public class GlobalVariableInfo <: Equatable<GlobalVariableInfo> & Hashable & ToString
功能:描述全局变量信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 GlobalVariableInfo 对应的全局变量的注解,返回对应集合。
注意:
- 如果无任何注解作用于该全局变量信息所对应的全局变量,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop name
public prop name: String
功能:获取该 GlobalVariableInfo 对应的全局变量的名称。
类型:String
prop typeInfo
public prop typeInfo: TypeInfo
功能:获取该 GlobalVariableInfo 对应的全局变量的声明类型的类型信息。
类型:TypeInfo
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 GlobalVariableInfo 对应的全局变量且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func getValue()
public func getValue(): Any
功能:获取该 GlobalVariableInfo 对应的全局变量的值。
返回值:
- Any - 该全局变量的值。
func hashCode()
public func hashCode(): Int64
功能:获取该全局变量信息的哈希值。
返回值:
- Int64 - 该全局变量信息的哈希值。
func isMutable()
public func isMutable(): Bool
功能:判断该 GlobalVariableInfo 对应的全局变量是否可修改。
注意:
- 如果实例成员变量被
var修饰符所修饰,则该全局变量可被修改。- 如果实例成员变量被
let修饰符所修饰,则该全局变量不可被修改。
返回值:
- Bool - 如果该全局变量可被修改则返回
true,否则返回false。
func setValue(Any)
public func setValue(newValue: Any): Unit
功能:设置该 GlobalVariableInfo 对应的全局变量的值。
参数:
- newValue: Any - 新的值。
异常:
- IllegalSetException - 如果该全局变量信息所对应的全局变量不可修改,则抛出异常。
- IllegalTypeException - 如果新值
newValue的运行时类型不是全局变量信息所对应的全局变量的声明类型的子类型,则抛出异常。
func toString()
public func toString(): String
功能:获取字符串形式的该全局变量信息。
返回值:
- String - 字符串形式的该全局变量信息。
operator func ==(GlobalVariableInfo)
public operator func ==(that: GlobalVariableInfo): Bool
功能:判断该全局变量信息与给定的另一个全局变量信息是否相等。
参数:
- that: GlobalVariableInfo - 被比较相等性的另一个全局变量信息。
返回值:
- Bool - 如果该全局变量信息与
that相等则返回true,否则返回false。
operator func !=(GlobalVariableInfo)
public operator func !=(that: GlobalVariableInfo): Bool
功能:判断该全局变量信息与给定的另一个全局变量信息是否不等。
参数:
- that: GlobalVariableInfo - 被比较相等性的另一个全局变量信息。
返回值:
- Bool - 如果该全局变量信息与
that不等则返回true,否则返回false。
class InstanceFunctionInfo
public class InstanceFunctionInfo <: Equatable<InstanceFunctionInfo> & Hashable & ToString
功能:描述实例成员函数信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 InstanceFunctionInfo 对应的实例成员函数的注解,返回对应集合。
注意:
- 如果无任何注解作用于该实例成员函数信息所对应的实例成员函数,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop genericParams
public prop genericParams: Collection<GenericTypeInfo>
功能:获取该 InstanceFunctionInfo 对应的实例成员函数的泛型参数信息列表。
类型:Collection<GenericTypeInfo>
异常:
- InfoNotFoundException - GlobalFunctionInfo 没有泛型参数时抛出异常。
prop modifiers
public prop modifiers: Collection<ModifierInfo>
功能:获取该 InstanceFunctionInfo 对应的实例成员函数所拥有的所有修饰符的信息,返回对应集合。
注意:
- 如果该实例成员函数无任何修饰符,则返回空集合。
- 该集合不保证遍历顺序恒定。
- 即便未被某修饰符修饰,如果拥有该修饰符的语义,该修饰符信息也将被包括在该集合中。
prop name
public prop name: String
功能:获取该 InstanceFunctionInfo 对应的实例成员函数的名称。
注意:
- 构成重载的所有实例成员函数将拥有相同的名称。
- 操作符重载函数的名称就是该操作符本身的符号内容,如"
+","*","[]"。
类型:String
prop parameters
public prop parameters: ReadOnlyList<ParameterInfo>
功能:获取该 InstanceFunctionInfo 对应的实例成员函数的参数信息列表。
说明:
不保证参数顺序,可根据
ParameterInfo的index属性确定参数实际位置。
类型:ReadOnlyList<ParameterInfo>
prop returnType
public prop returnType: TypeInfo
功能:获取该 InstanceFunctionInfo 对应的实例成员函数的返回值类型的类型信息。
类型:TypeInfo
func apply(Any, Array<Any>)
public func apply(instance: Any, args: Array<Any>): Any
功能:调用该 InstanceFunctionInfo 对应实例成员函数,指定实例并传入实参列表,返回调用结果。
注意:
args的类型确保和函数入参类型完全一致。
参数:
返回值:
- Any - 该实例成员函数的调用结果。
异常:
- InvocationTargetException - 如果存在泛型参数的函数调用了该方法,则抛出异常。
- InvocationTargetException - 如果该实例成员函数信息所对应的实例成员函数是抽象的,或不存在相应的函数实现,则抛出异常。
- IllegalArgumentException - 如果实参列表
args中的实参的数目与该实例成员函数信息所对应的实例成员函数的形参列表中的形参的数目不等,则抛出异常。 - IllegalTypeException - 如果实例
instance的运行时类型与该实例成员函数信息所对应的实例成员函数所属的类型不相同,则抛出异常。 - IllegalTypeException - 如果实参列表
args中的任何一个实参的运行时类型不是该实例成员函数信息所对应的实例成员函数的对应形参的声明类型的子类型,则抛出异常。 - Exception - 如果被调用的实例成员函数信息所对应的实例成员函数内部抛出异常,则该异常将被封装为 Exception 异常并抛出。
func apply(Any, Array<TypeInfo>, Array<Any>)
public func apply(instance: Any, genericTypeArgs: Array<TypeInfo>, args: Array<Any>): Any
功能:调用该 InstanceFunctionInfo 对应泛型成员函数,指定实例并传入泛型参数的类型列表和参数列表,返回调用结果。
注意:
args的类型确保和函数入参类型完全一致。
参数:
返回值:
- Any - 该实例泛型函数的调用结果。
异常:
- InvocationTargetException - 如果该函数信息对应的成员函数是
abstract或不存在函数体,则会抛出异常。 - InvacationTargetException - 如果非泛型函数调用了此方法,则抛出异常。
- IllegalTypeException - 如果实例
instance的运行时类型与该成员函数信息所对应的成员函数所属的类型不相同,则抛出异常。 - IllegalArgumentException - 如果实参列表
args中的实参的数目与该成员函数信息所对应的成员函数的形参列表中的形参的数目不等,则抛出异常。 - IllegalArgumentException - 如果函数泛型参数列表
genericTypeArgs中的参数数目与该成员函数信息所对应的成员函数的泛型参数列表genericParams中的参数数目不等,则抛出异常。 - IllegalTypeException - 如果参数列表
args中的任何一个参数的运行时类型不是该实例成员函数信息所对应的实例成员函数的对应形参的声明类型的子类型,则抛出异常。 - IllegalTypeException - 如果传入的参数列表
args和泛型参数类型列表genericTypeArgs不满足该成员函数信息所对应的成员函数的参数的类型约束,则抛出异常。 - Exception - 如果被调用的实例成员函数信息所对应的实例成员函数内部抛出异常,则该异常将被封装为 Exception 异常并抛出。
示例:
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public func area(): Int64 {
return length * width
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("default.Rectangular")
// 获取 InstanceFunctionInfo
var gif = ty.getInstanceFunction("area")
// 调用反射函数
var r = Rectangular()
var result = gif.apply(r) as Int64
println(result)
return
}
运行结果:
Some(20)
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 InstanceFunctionInfo 对应的实例成员函数且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func hashCode()
public func hashCode(): Int64
功能:获取该实例成员函数信息的哈希值。
返回值:
- Int64 - 该实例成员函数信息的哈希值。
func isAbstract()
public func isAbstract(): Bool
功能:判断 InstanceFunctionInfo 所对应的实例成员函数是否拥有 abstract 语义。
返回值:
- Bool - 如果该实例成员函数拥有
abstract语义则返回true,否则返回false。
func isOpen()
public func isOpen(): Bool
功能:判断该 InstanceFunctionInfo 对应的实例成员函数是否拥有 open 语义。
返回值:
- Bool - 如果该实例成员函数拥有
open语义则返回true,否则返回false。
注意:
interface类型中的实例成员函数默认均拥有open语义。
func toString()
public func toString(): String
功能:获取字符串形式的该实例成员函数信息。
返回值:
- String - 字符串形式的该实例成员函数信息。
operator func ==(InstanceFunctionInfo)
public operator func ==(that: InstanceFunctionInfo): Bool
功能:判断该实例成员函数信息与给定的另一个实例成员函数信息是否相等。
参数:
- that: InstanceFunctionInfo - 被比较相等性的另一个实例成员函数信息。
返回值:
- Bool - 如果该实例成员函数信息与
that相等则返回true,否则返回false。
operator func !=(InstanceFunctionInfo)
public operator func !=(that: InstanceFunctionInfo): Bool
功能:判断该实例成员函数信息与给定的另一个实例成员函数信息是否不等。
参数:
- that: InstanceFunctionInfo - 被比较相等性的另一个实例成员函数信息。
返回值:
- Bool - 如果该实例成员函数信息与
that不等则返回true,否则返回false。
class InstancePropertyInfo
public class InstancePropertyInfo <: Equatable<InstancePropertyInfo> & Hashable & ToString
功能:描述实例成员属性信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 InstancePropertyInfo 对应的实例成员属性的注解,返回对应集合。
注意:
- 如果无任何注解作用于该实例成员属性信息所对应的实例成员属性,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop modifiers
public prop modifiers: Collection<ModifierInfo>
功能:获取该 InstancePropertyInfo 对应的实例成员属性所拥有的所有修饰符的信息,返回对应集合。
注意:
- 如果该实例成员属性无任何修饰符,则返回空集合。
- 该集合不保证遍历顺序恒定。
- 即便未被某修饰符修饰,如果拥有该修饰符的语义,该修饰符信息也将被包括在该集合中。
prop name
public prop name: String
功能:获取该 InstancePropertyInfo 对应的实例成员属性的名称。
类型:String
prop typeInfo
public prop typeInfo: TypeInfo
功能:获取该 InstancePropertyInfo 对应的实例成员属性的声明类型的类型信息。
类型:TypeInfo
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 InstancePropertyInfo 对应的实例成员属性且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func getValue(Any)
public func getValue(instance: Any): Any
功能:获取该 InstancePropertyInfo 对应的实例成员属性在给定实例中的值。
参数:
- instance: Any - 实例。
返回值:
- Any - 该实例成员属性在实例
instance中的值。
异常:
- IllegalTypeException - 如果实例
instance的运行时类型与该实例成员属性信息所对应的实例成员属性所属的类型不严格相同,则抛出异常。
示例:
import std.reflect.*
public class Rectangular {
public var length = 4
public prop width: Int64 {
get() {
5
}
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("default.Rectangular")
// 获取 InstancePropertyInfo
var gip = ty.getInstanceProperty("width")
// 获取实例值
var r = Rectangular()
var result = gip.getValue(r) as Int64
println(result)
return
}
运行结果:
Some(5)
func hashCode()
public func hashCode(): Int64
功能:获取该实例成员属性信息的哈希值。
返回值:
- Int64 - 该实例成员属性信息的哈希值。
func isAbstract()
public func isAbstract(): Bool
功能:判断该 InstancePropertyInfo 对应的实例成员属性是否是抽象的。
返回值:
- Bool - 如果该 InstancePropertyInfo 对应的实例成员属性是抽象的,则返回
true,否则返回false。
func isOpen()
public func isOpen(): Bool
功能:判断该 InstancePropertyInfo 对应的实例成员属性是否拥有 open 语义。
返回值:
- Bool - 如果该 InstancePropertyInfo 对应的实例成员属性拥有
open语义则返回true,否则返回false。
func isMutable()
public func isMutable(): Bool
功能:判断该 InstancePropertyInfo 对应的实例成员属性是否可修改。
注意:
- 如果实例成员属性被
mut修饰符所修饰,则该实例成员属性可被修改,否则不可被修改。
返回值:
- Bool - 如果该实例成员属性信息所对应的实例成员属性可被修改则返回
true,否则返回false。
func setValue(Any, Any)
public func setValue(instance: Any, newValue: Any): Unit
功能:设置该 InstancePropertyInfo 对应的实例成员属性在给定实例中的值。
参数:
异常:
- IllegalSetException - 如果该实例成员属性信息所对应的实例成员属性不可修改,则抛出异常。
- IllegalTypeException - 如果实例
instance的运行时类型与该实例成员属性信息所对应的实例成员属性所属的类型不严格相同,则抛出异常。 - IllegalTypeException - 如果新值
newValue的运行时类型不是该实例成员属性信息所对应的实例成员属性的声明类型的子类型,则抛出异常。
func toString()
public func toString(): String
功能:获取字符串形式的该实例成员属性信息。
返回值:
- String - 字符串形式的该实例成员属性信息。
operator func !=(InstancePropertyInfo)
public operator func !=(that: InstancePropertyInfo): Bool
功能:判断该实例成员属性信息与给定的另一个实例成员属性信息是否不等。
参数:
- that: InstancePropertyInfo - 被比较相等性的另一个实例成员属性信息。
返回值:
- Bool - 如果该实例成员属性信息与
that不等则返回true,否则返回false。
operator func ==(InstancePropertyInfo)
public operator func ==(that: InstancePropertyInfo): Bool
功能:判断该实例成员属性信息与给定的另一个实例成员属性信息是否相等。
参数:
- that: InstancePropertyInfo - 被比较相等性的另一个实例成员属性信息。
返回值:
- Bool - 如果该实例成员属性信息与
that相等则返回true,否则返回false。
class InstanceVariableInfo
public class InstanceVariableInfo <: Equatable<InstanceVariableInfo> & Hashable & ToString
功能:描述实例成员变量信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 InstanceVariableInfo 对应的实例成员变量的注解,返回对应集合。
注意:
- 如果无任何注解作用于该实例成员变量信息所对应的实例成员变量,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop modifiers
public prop modifiers: Collection<ModifierInfo>
功能:获取该 InstanceVariableInfo 对应的实例成员变量所拥有的所有修饰符的信息,返回对应集合。
注意:
- 如果该实例成员变量无任何修饰符,则返回空集合。
- 该集合不保证遍历顺序恒定。
- 即便未被某修饰符修饰,如果拥有该修饰符的语义,该修饰符信息也将被包括在该集合中。
prop name
public prop name: String
功能:获取该 InstanceVariableInfo 对应的实例成员变量的名称。
类型:String
prop typeInfo
public prop typeInfo: TypeInfo
功能:获取该 InstanceVariableInfo 对应的实例成员变量的声明类型的类型信息。
类型:TypeInfo
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 InstanceVariableInfo 对应的实例成员变量且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func getValue(Any)
public func getValue(instance: Any): Any
功能:获取该 InstanceVariableInfo 对应的实例成员变量在给定实例中的值。
参数:
- instance: Any - 实例。
返回值:
- Any - 该实例成员变量在实例
instance中的值。
异常:
- IllegalTypeException - 如果实例
instance的运行时类型与该实例成员变量信息所对应的实例成员变量所属的类型不严格相同,则抛出异常。
示例:
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("default.Rectangular")
// 获取 InstanceVariableInfo
var gip = ty.getInstanceVariable("width")
// 获取实例值
var r = Rectangular()
let v = gip.getValue(r) as Int64
println(v)
return
}
运行结果:
Some(5)
func hashCode()
public func hashCode(): Int64
功能:获取该实例成员变量信息的哈希值。
返回值:
- Int64 - 该实例成员变量信息的哈希值。
func isMutable()
public func isMutable(): Bool
功能:判断该 InstanceVariableInfo 对应的实例成员变量是否可修改。
注意:
- 如果实例成员变量被
var修饰符所修饰,则该实例成员变量可被修改。- 如果实例成员变量被
let修饰符所修饰,则该实例成员变量不可被修改。
返回值:
- Bool - 如果该实例成员变量信息所对应的实例成员变量可被修改则返回
true,否则返回false。
func setValue(Any, Any)
public func setValue(instance: Any, newValue: Any): Unit
功能:设置该 InstanceVariableInfo 对应的实例成员变量在给定实例中的值。
参数:
异常:
- IllegalSetException - 如果该实例成员变量信息所对应的实例成员变量不可修改,则抛出异常。
- IllegalTypeException - 如果实例
instance的运行时类型与该实例成员变量信息所对应的实例成员变量所属的类型不严格相同,则抛出异常。 - IllegalTypeException - 如果新值
newValue的运行时类型不是该实例成员变量信息所对应的实例成员变量的声明类型的子类型,则抛出异常。
func toString()
public func toString(): String
功能:获取字符串形式的该实例成员变量信息。
返回值:
- String - 字符串形式的该实例成员变量信息。
operator func ==(InstanceVariableInfo)
public operator func ==(that: InstanceVariableInfo): Bool
功能:判断该实例成员变量信息与给定的另一个实例成员变量信息是否相等。
参数:
- that: InstanceVariableInfo - 被比较相等性的另一个实例成员变量信息。
返回值:
- Bool - 如果该实例成员变量信息与
that相等则返回true,否则返回false。
operator func !=(InstanceVariableInfo)
public operator func !=(that: InstanceVariableInfo): Bool
功能:判断该实例成员变量信息与给定的另一个实例成员变量信息是否不等。
参数:
- that: InstanceVariableInfo - 被比较相等性的另一个实例成员变量信息。
返回值:
- Bool - 如果该实例成员变量信息与
that不等则返回true,否则返回false。
class InterfaceTypeInfo
public class InterfaceTypeInfo <: TypeInfo
功能:interface 类型的类型信息。
父类型:
prop sealedSubtypes
public prop sealedSubtypes: Collection<TypeInfo>
功能:如果该 InterfaceTypeInfo 所对应的 interface 类型拥有 sealed 语义,则获取该 interface 类型所在包内的所有子类型的类型信息,返回对应集合。
注意:
- 如果该
interface类型不拥有sealed语义,则返回空集合。- 如果该
interface类型拥有sealed语义,那么获得的集合必不可能是空集合,因为该interface类型本身就是自己的子类型。
类型:Collection<TypeInfo>
func isSealed()
public func isSealed(): Bool
功能:判断该 InterfaceTypeInfo 所对应的 interface 类型是否拥有 sealed 语义。
返回值:
- Bool - 如果该
interface类型拥有sealed语义则返回true,否则返回false。
static func get(String)
public redef static func get(qualifiedName: String): InterfaceTypeInfo
功能:获取给定 qualifiedName 所对应的类型的 InterfaceTypeInfo。
参数:
- qualifiedName: String - 类型的限定名称。
返回值:
- InterfaceTypeInfo - 类型的限定名称
qualifiedName所对应的Interface类型的类型信息。
异常:
- InfoNotFoundException - 如果无法获取与给定类型的限定名称
qualifiedName匹配的类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 InterfaceTypeInfo, 则抛出异常。
示例:
import std.reflect.*
public interface Rectangular {}
main(): Unit {
let ty = InterfaceTypeInfo.get("default.Rectangular")
println(ty)
return
}
运行结果:
default.Rectangular
static func of(Any)
public redef static func of(a: Any): InterfaceTypeInfo
功能:获取给定的任意类型实例的运行时类型所对应的类型信息。
运行时类型是指在程序运行时,通过动态绑定确定的类型,运行时类型与实例对象相绑定。在继承等场景下运行时类型和静态类型可能不一致。
参数:
- a: Any - 任意类型的实例。
返回值:
- InterfaceTypeInfo - 实例
a的运行时类型所对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得实例
a的运行时类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 InterfaceTypeInfo, 则抛出异常。
static func of<T>()
public redef static func of<T>(): InterfaceTypeInfo
功能:获取给定 T 类型对应的类型信息。
返回值:
- InterfaceTypeInfo -
T类型对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得类型 T 所对应的类型信息,抛出异常。
- IllegalTypeException - 如果获取到的类型信息不是 InterfaceTypeInfo, 则抛出异常。
class PackageInfo
public class PackageInfo <: Equatable<PackageInfo> & Hashable & ToString
功能:描述包信息。
父类型:
prop functions
public prop functions: Collection<GlobalFunctionInfo>
功能:获取该 PackageInfo 对应的包中所有 public 全局函数的信息所组成的列表。
类型:Collection<GlobalFunctionInfo>
prop name
public prop name: String
功能:获取该包信息所对应的包的名称。
注意:
包的名称不包含其所在的模块名称和其父包的名称,例如限定名称为
a/b.c.d的包的名称是d。
类型:String
prop parentPackage
public prop parentPackage: PackageInfo
功能:获取该 PackageInfo 对应的父包的 PackageInfo。
类型:PackageInfo
异常:
- InfoNotFoundException - 如果父包未被加载,则会抛出异常。
prop qualifiedName
public prop qualifiedName: String
功能:获取该 PackageInfo 对应的包的限定名称。
注意:
包的限定名称的格式是
(module_name/)?(default|package_name)(.package_name)*,例如限定名称为a/b.c.d的包位于模块a下的b包里的c包里。
类型:String
prop rootPackage
public prop rootPackage: PackageInfo
功能:获取该 PackageInfo 对应的 root 包的 PackageInfo。
注意:
如果包本身就是
root包,那么其rootPackage属性返回的是其本身。例如,限定名称为a.b.c的包,rootPackage返回的是a; 限定名称为a的包,rootpackage返回的是a。
类型:PackageInfo
异常:
- InfoNotFoundException - 如果
root包未被加载,则会抛出异常。
prop subPackages
public prop subPackages: Collection<PackageInfo>
功能:获取该 PackageInfo 对应的所有子包的 PackageInfo 集合。
注意:
- 该属性只会返回已被加载的子包。
- 不保证返回结果的顺序。
prop typeInfos
public prop typeInfos: Collection<TypeInfo>
功能:获取该 PackageInfo 对应的包中所有全局定义的 public 类型的类型信息,返回对应集合。
注意:
目前该列表不包含所有反射尚未支持的类型。
类型:Collection<TypeInfo>
prop variables
public prop variables: Collection<GlobalVariableInfo>
功能:获取该 PackageInfo 对应的包中所有 public 全局变量的信息所组成的列表。
类型:Collection<GlobalVariableInfo>
prop version
public prop version: String
功能:获取该 PackageInfo 对应的包的版本号。
注意:
由于目前动态库中尚无版本信息,获取到的版本号总是空字符串。
类型:String
static func get(String)
public static func get(qualifiedName: String): PackageInfo
功能:获取给定 qualifiedName 所对应的 PackageInfo。
参数:
- qualifiedName: String - 类型的限定名称。
返回值:
- PackageInfo - 类型的限定名称
qualifiedName所对应的包信息。
异常:
- InfoNotFoundException - 如果无法获取与给定类型的限定名称
qualifiedName所对应的类型信息,则抛出异常。
static func load(String)
public static func load(path: String): PackageInfo
功能:运行时动态加载指定路径下的一个仓颉动态库模块并获得该模块的信息。
注意:
- 为了提升兼容性,路径
path中的共享库文件名不需要后缀名(如.so和.dll等)。- 如果某个
package通过静态加载方式(如:import)已经导入过,那么动态加载该package会抛出异常。
参数:
- path: String - 共享库文件的绝对路径或相对路径。
返回值:
- PackageInfo - 指定仓颉动态库的包信息。
异常:
- ReflectException - 如果共享库加载失败,则会抛出异常。
- ReflectException - 如果具有相同包名称或相同文件名的共享库被重复加载,则会抛出异常。
- ReflectException - 如果动态库内部存在多个Package,则抛出异常。
- IllegalArgumentException - 当路径不合法时,抛出异常。
func getFunction(String, Array<TypeInfo>)
public func getFunction(name: String, parameterTypes: Array<TypeInfo>): GlobalFunctionInfo
功能:尝试在该 PackageInfo 对应的包中获取拥有给定函数名称且与给定形参类型信息列表匹配的 public 全局函数的信息。
参数:
返回值:
- GlobalFunctionInfo - 如果成功匹配则返回该全局定义的
public类型的函数信息。
异常:
- InfoNotFoundException - 如果没找到对应全局定义的
public全局函数,则抛出异常。
func getFunctions(String)
public func getFunctions(name: String): Array<GlobalFunctionInfo>
功能:尝试在该 PackageInfo 对应的包中获取拥有给定函数名称的所有 public 全局函数的信息。
参数:
- name: String - 全局函数的名称。
返回值:
- Array<GlobalFunctionInfo> - 拥有给定函数名称的所有
public全局函数的信息数组。
func getSubPackage(String)
public func getSubPackage(qualifiedName: String): PackageInfo
功能:尝试获取该 PackageInfo 对应限定名称为 qualifiedName 的子包的信息。
参数:
- qualifiedName: String - 子包的限定名称。
返回值:
- PackageInfo - 该子包的包信息。
异常:
- InfoNotFoundException - 如果该子包不存在或者未加载,则会抛出异常。
- IllegalArgumentException - 如果
qualifiedName不符合规范,则抛出异常。
func getTypeInfo(String)
public func getTypeInfo(qualifiedTypeName: String): TypeInfo
功能:尝试在该 PackageInfo 对应的包中获取拥有给定类型名称的全局定义的 public 类型的类型信息。
参数:
- qualifiedTypeName: String - 类型的限定名称
返回值:
- TypeInfo - 如果成功匹配则返回该全局定义的
public类型的类型信息。
异常:
- InfoNotFoundException - 如果没找到对应全局定义的
public类型,则抛出异常。
func getVariable(String)
public func getVariable(name: String): GlobalVariableInfo
功能:尝试在该 PackageInfo 对应的包中获取拥有给定变量名称的 public 全局变量的信息。
参数:
- name: String - 全局变量的名称。
返回值:
- GlobalVariableInfo - 如果成功匹配则返回该全局定义的
public类型的变量信息。
异常:
- InfoNotFoundException - 如果没找到对应全局定义的
public全局变量,则抛出异常。
func hashCode()
public func hashCode(): Int64
功能:获取该包信息的哈希值。
返回值:
- Int64 - 该包信息的哈希值。
func toString()
public func toString(): String
功能:获取字符串形式的该包信息。
注意:
内部实现为该包信息的限定名称字符串。
返回值:
- String - 字符串形式的该包信息。
operator func !=(PackageInfo)
public operator func !=(that: PackageInfo): Bool
功能:判断该包信息与给定的另一个包信息是否不等。
注意:
内部实现为比较两个包信息的限定名称是否相等。
参数:
- that: PackageInfo - 被比较相等性的另一个包信息。
返回值:
- Bool - 如果该包信息与
that不等则返回true,否则返回false。
operator func ==(PackageInfo)
public operator func ==(that: PackageInfo): Bool
功能:判断该包信息与给定的另一个包信息是否相等。
注意:
内部实现为比较两个包信息的限定名称是否相等。
参数:
- that: PackageInfo - 被比较相等性的另一个包信息。
返回值:
- Bool - 如果该包信息与
that相等则返回true,否则返回false。
class ParameterInfo
public class ParameterInfo <: Equatable<ParameterInfo> & Hashable & ToString
功能:描述函数形参信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 ParameterInfo 对应的函数形参的注解,返回对应集合。
注意:
- 如果无任何注解作用于该函数形参信息所对应的函数形参,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop index
public prop index: Int64
功能:获知该 ParameterInfo 对应的形参是其所在函数的第几个形参。
注意:
index从0开始计数。
类型:Int64
prop name
public prop name: String
功能:获取该 ParameterInfo 对应的形参的名称。
类型:String
prop typeInfo
public prop typeInfo: TypeInfo
功能:获取该 ParameterInfo 对应的函数形参的声明类型所对应的类型信息。
类型:TypeInfo
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 ParameterInfo 对应的函数形参且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func hashCode()
public func hashCode(): Int64
功能:获取该函数形参信息的哈希值。
返回值:
- Int64 - 该函数形参信息的哈希值。
func toString()
public func toString(): String
功能:获取字符串形式的该函数形参信息。
返回值:
- String - 字符串形式的该函数形参信息。
operator func !=(ParameterInfo)
public operator func !=(that: ParameterInfo): Bool
功能:判断该函数形参信息与给定的另一个函数形参信息是否不等。
参数:
- that: ParameterInfo - 被比较相等性的另一个函数形参信息。
返回值:
- Bool - 如果该函数形参信息与
that不等则返回true,否则返回false。
operator func ==(ParameterInfo)
public operator func ==(that: ParameterInfo): Bool
功能:判断该函数形参信息与给定的另一个函数形参信息是否相等。
参数:
- that: ParameterInfo - 被比较相等性的另一个函数形参信息。
返回值:
- Bool - 如果该函数形参信息与
that相等则返回true,否则返回false。
class PrimitiveTypeInfo
public class PrimitiveTypeInfo <: TypeInfo
功能:描述原始数据类型的类型信息。
原始数据类型包括无类型(Nothing)、单元类型(Unit)、字符类型(Rune)、布尔类型(Bool),整形类型(Int8,Int16,Int32,Int64,IntNative,UInt8,UInt16,UInt32,UInt64,UIntNative)和浮点类型(Float16,Float32,Float64)。
注意:
目前尚不支持
Nothing原始数据类型。
父类型:
static func get(String)
public redef static func get(qualifiedName: String): PrimitiveTypeInfo
功能:获取给定的类型的限定名称所对应类型的 PrimitiveTypeInfo。
参数:
- qualifiedName: String - 类型的限定名称。
返回值:
- PrimitiveTypeInfo - 类型的限定名称
qualifiedName所对应的类型的类型信息。
异常:
- InfoNotFoundException - 如果无法获取与给定类型的限定名称
qualifiedName匹配的类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 PrimitiveTypeInfo, 则抛出异常。
示例:
import std.reflect.*
main(): Unit {
var pti = PrimitiveTypeInfo.get("Int64")
println(pti)
return
}
运行结果:
Int64
static func of(Any)
public redef static func of(a: Any): PrimitiveTypeInfo
功能:获取给定的任意类型实例的运行时类型所对应的类型信息。
运行时类型是指在程序运行时,通过动态绑定确定的类型,运行时类型与实例对象相绑定。在继承等场景下运行时类型和静态类型可能不一致。
参数:
- a: Any - 任意类型的实例。
返回值:
- PrimitiveTypeInfo - 实例
a的运行时类型所对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得实例
a的运行时类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 PrimitiveTypeInfo, 则抛出异常。
示例:
import std.reflect.*
main(): Unit {
var a = 10
var pti = PrimitiveTypeInfo.of(a)
println(pti)
return
}
运行结果:
Int64
static func of<T>()
public redef static func of<T>(): PrimitiveTypeInfo
功能:获取给定 T 类型对应的类型信息。
返回值:
- PrimitiveTypeInfo -
T类型对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得类型 T 所对应的类型信息,抛出异常。
- IllegalTypeException - 如果获取到的类型信息不是 PrimitiveTypeInfo, 则抛出异常。
示例:
import std.reflect.*
main(): Unit {
var pti = PrimitiveTypeInfo.of<Int64>()
println(pti)
return
}
运行结果:
Int64
class StaticFunctionInfo
public class StaticFunctionInfo <: Equatable<StaticFunctionInfo> & Hashable & ToString
功能:描述静态成员函数信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 StaticFunctionInfo 对应的静态成员函数的注解,返回对应集合。
注意:
- 如果无任何注解作用于该 StaticFunctionInfo 对应的静态成员函数,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop genericParams
public prop genericParams: Collection<GenericTypeInfo>
功能:获取该 StaticFunctionInfo 对应的实例成员函数的泛型参数信息列表。
类型:Collection<GenericTypeInfo>
异常:
- InfoNotFoundException - GlobalFunctionInfo 没有泛型参数时抛出异常。
prop modifiers
public prop modifiers: Collection<ModifierInfo>
功能:获取该 StaticFunctionInfo 对应的静态成员函数所拥有的所有修饰符的信息,返回对应集合。
注意:
- 如果该静态成员函数无任何修饰符,则返回空集合。
- 该集合不保证遍历顺序恒定。
- 即便未被某修饰符修饰,如果拥有该修饰符的语义,该修饰符信息也将被包括在该集合中。
prop name
public prop name: String
功能:获取该 StaticFunctionInfo 对应的静态成员函数的名称。
注意:
构成重载的所有静态成员函数将拥有相同的名称。
类型:String
prop parameters
public prop parameters: ReadOnlyList<ParameterInfo>
功能:获取该 StaticFunctionInfo 对应的静态成员函数的参数信息列表。
注意:
不保证参数顺序,可根据
ParameterInfo的index属性确定参数实际位置。
类型:ReadOnlyList<ParameterInfo>
prop returnType
public prop returnType: TypeInfo
功能:获取该 StaticFunctionInfo 对应的静态成员函数的返回值类型的类型信息。
类型:TypeInfo
func apply(TypeInfo, Array<Any>)
public func apply(thisType: TypeInfo, args: Array<Any>): Any
功能:调用该 StaticFunctionInfo 对应静态成员函数,传入方法所属的类型信息和实参列表并返回调用结果。
注意:
args的类型确保和函数入参类型完全一致,否则会导致参数检查失败。
参数:
返回值:
- Any - 该静态成员函数的调用结果。
异常:
- InvocationTargetException - 如果该函数信息对应的静态成员函数存在泛型参数,则会抛出异常。
- InfoNotFoundException - 如果该函数信息对应的静态成员函数的函数体未实现,则会抛出异常。
- IllegalArgumentException - 如果实参列表
args中的实参的数目与该静态成员函数信息所对应的静态成员函数的形参列表中的形参的数目不等,则抛出异常。 - IllegalArgumentException - 如果
thisType和该静态函数的函数签名不一致,则抛出异常。 - IllegalTypeException - 如果实参列表
args中的任何一个实参的运行时类型不是该静态成员函数信息所对应的静态成员函数的对应形参的声明类型的子类型,则抛出异常。 - Exception - 如果被调用的静态成员函数信息所对应的静态成员函数内部抛出异常,则该异常将被封装为 Exception 异常并抛出。
示例:
package test
import std.reflect.*
public class Rectangular {
public static func myName(): String { "my name is Rectangular" }
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取静态函数
let sf = ty.getStaticFunction("myName")
let result = sf.apply(ty) as String
println(result)
return
}
运行结果:
Some(my name is Rectangular)
func apply(TypeInfo, Array<TypeInfo>, Array<Any>)
public func apply(thisType: TypeInfo, genericTypeArgs: Array<TypeInfo>, args: Array<Any>): Any
功能:调用该 StaticFunctionInfo 对应静态成员函数,传入方法所属的类型信息和实参列表并返回调用结果。
注意:
args的类型确保和函数入参类型完全一致,否则会导致参数检查失败。
参数:
返回值:
- Any - 该静态成员函数的调用结果。
异常:
- InvocationTargetException - 如果该函数信息对应的静态成员函数是非泛型函数,则抛出异常。
- InfoNotFoundException - 如果该函数信息对应的静态成员函数的函数体未实现,则会抛出异常。
- IllegalArgumentException - 如果实参列表
args中的实参的数目与该静态成员函数信息所对应的静态成员函数的形参列表中的形参的数目不等,则抛出异常。 - IllegalArgumentException - 如果实参列表
args中的泛型参数的数目与该静态成员函数信息所对应的泛型参数的数目不等,则抛出异常。 - IllegalArgumentException - 如果
thisType和该静态函数的函数签名不一致,则抛出异常。 - IllegalTypeException - 如果实参列表
args中的任何一个实参的运行时类型不是该静态成员函数信息所对应的静态成员函数的对应形参的声明类型的子类型,则抛出异常。 - IllegalTypeException - 如果传入的参数列表
args和泛型参数类型列表genericTypeArgs不满足该静态成员函数信息所对应的静态成员函数的参数的类型约束,则抛出异常。 - Exception - 如果被调用的静态成员函数信息所对应的静态成员函数内部抛出异常,则该异常将被封装为 Exception 异常并抛出。
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于 StaticFunctionInfo 对应的静态成员函数且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func hashCode()
public func hashCode(): Int64
功能:获取该静态成员函数信息的哈希值。
返回值:
- Int64 - 该静态成员函数信息的哈希值。
func toString()
public func toString(): String
功能:获取字符串形式的该静态成员函数信息。
返回值:
- String - 字符串形式的该静态成员函数信息。
operator func !=(StaticFunctionInfo)
public operator func !=(that: StaticFunctionInfo): Bool
功能:判断该静态成员函数信息与给定的另一个静态成员函数信息是否不等。
参数:
- that: StaticFunctionInfo - 被比较相等性的另一个静态成员函数信息。
返回值:
- Bool - 如果该静态成员函数信息与
that不等则返回true,否则返回false。
operator func ==(StaticFunctionInfo)
public operator func ==(that: StaticFunctionInfo): Bool
功能:判断该静态成员函数信息与给定的另一个静态成员函数信息是否相等。
参数:
- that: StaticFunctionInfo - 被比较相等性的另一个静态成员函数信息。
返回值:
- Bool - 如果该静态成员函数信息与
that相等则返回true,否则返回false。
class StaticPropertyInfo
public class StaticPropertyInfo <: Equatable<StaticPropertyInfo> & Hashable & ToString
功能:描述静态成员属性信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 StaticPropertyInfo 所对应的静态成员属性的注解所组成的集合。
注意:
- 如果无任何注解作用于该静态成员属性信息所对应的静态成员属性,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop modifiers
public prop modifiers: Collection<ModifierInfo>
功能:获取该 StaticPropertyInfo 对应的静态成员属性所拥有的所有修饰符的信息,返回对应集合。
注意:
- 如果该静态成员属性无任何修饰符,则返回空集合。
- 该集合不保证遍历顺序恒定。
- 目前获取到的修饰符集合内容较为混乱,尚未统一。
prop name
public prop name: String
功能:获取该 StaticPropertyInfo 对应的静态成员属性的名称。
类型:String
prop typeInfo
public prop typeInfo: TypeInfo
功能:获取该 StaticPropertyInfo 对应的静态成员属性的声明类型的类型信息。
类型:TypeInfo
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 StaticPropertyInfo 对应的静态成员属性且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func getValue()
public func getValue(): Any
功能:获取该 StaticPropertyInfo 对应的静态成员属性的值。
注意:
如果该静态成员属性缺少合法实现,如
interface类型中的抽象静态成员属性,则应抛出 UnsupportedException 异常,但由于后端尚未支持,故尚未实现。
返回值:
- Any - 该静态成员属性的值。
示例:
package test
import std.reflect.*
public class Rectangular {
public static prop sides: Int64 {
get() { 4 }
}
public static prop angles: Int64 {
get() { 4 }
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取静态属性
let sp = ty.getStaticProperty("sides")
let result = sp.getValue() as Int64
println(result)
return
}
运行结果:
Some(4)
func hashCode()
public func hashCode(): Int64
功能:获取该静态成员属性信息的哈希值。
返回值:
- Int64 - 该静态成员属性信息的哈希值。
func isMutable()
public func isMutable(): Bool
功能:判断该静态成员属性信息所对应的静态成员属性是否可修改。
返回值:
- Bool - 如果该静态成员属性信息所对应的静态成员属性可被修改则返回
true,否则返回false。
注意:
- 如果静态成员属性被
mut修饰符所修饰,则该静态成员属性可被修改,否则不可被修改。
func setValue(Any)
public func setValue(newValue: Any): Unit
功能:设置该 StaticPropertyInfo 对应的静态成员属性的值。
注意:
如果该静态成员属性缺少合法实现,如
interface类型中的抽象静态成员属性,则应抛出 UnsupportedException 异常,但由于后端尚未支持,故尚未实现。
参数:
- newValue: Any - 新值。
异常:
- IllegalSetException - 如果该静态成员属性信息所对应的静态成员属性不可修改,则抛出异常。
- IllegalTypeException - 如果新值
newValue的运行时类型不是该静态成员属性信息所对应的静态成员属性的声明类型的子类型,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
private static var valueArea = 0
public static mut prop area: Int64 {
get() { valueArea }
set(v) { valueArea = v }
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取静态属性
let sp = ty.getStaticProperty("area")
// 设置静态成员属性的值
sp.setValue(10)
let result = sp.getValue() as Int64
println(result)
return
}
运行结果:
Some(10)
func toString()
public func toString(): String
功能:获取字符串形式的该静态成员属性信息。
返回值:
- String - 字符串形式的该静态成员属性信息。
operator func !=(StaticPropertyInfo)
public operator func !=(that: StaticPropertyInfo): Bool
功能:判断该静态成员属性信息与给定的另一个静态成员属性信息是否不等。
参数:
- that: StaticPropertyInfo - 被比较相等性的另一个静态成员属性信息。
返回值:
- Bool - 如果该静态成员属性信息与
that不等则返回true,否则返回false。
operator func ==(StaticPropertyInfo)
public operator func ==(that: StaticPropertyInfo): Bool
功能:判断该静态成员属性信息与给定的另一个静态成员属性信息是否相等。
参数:
- that: StaticPropertyInfo - 被比较相等性的另一个静态成员属性信息。
返回值:
- Bool - 如果该静态成员属性信息与
that相等则返回true,否则返回false。
class StaticVariableInfo
public class StaticVariableInfo <: Equatable<StaticVariableInfo> & Hashable & ToString
功能:描述静态成员变量信息。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 StaticVariableInfo 对应的静态成员变量的注解,返回对应集合。
注意:
- 如果无任何注解作用于该 StaticVariableInfo 对应的静态成员变量,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop modifiers
public prop modifiers: Collection<ModifierInfo>
功能:获取该 StaticVariableInfo 对应的静态成员变量所拥有的所有修饰符的信息,返回对应集合。
注意:
- 如果该静态成员变量无任何修饰符,则返回空集合。
- 该集合不保证遍历顺序恒定。
- 目前获取到的修饰符集合内容较为混乱,尚未统一。
prop name
public prop name: String
功能:获取该 StaticVariableInfo 对应的静态成员变量的名称。
类型:String
prop typeInfo
public prop typeInfo: TypeInfo
功能:获取该 StaticVariableInfo 对应的静态成员变量的声明类型的类型信息。
类型:TypeInfo
func findAnnotation<T>() where T <: Annotation
public func findAnnotation<T>(): Option<T> where T <: Annotation
功能:尝试获取作用于该 StaticVariableInfo 对应的静态成员变量且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func getValue()
public func getValue(): Any
功能:获取该 StaticVariableInfo 对应的静态成员变量的值。
返回值:
- Any - 该静态成员变量的值。
注意:
- 返回值不支持为
struct类型。
示例:
package test
import std.reflect.*
public class Rectangular {
public static var area: Int64 = 10
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取静态变量
let sv = ty.getStaticVariable("area")
// 获取值
println(sv.getValue() as Int64)
return
}
运行结果:
Some(10)
func hashCode()
public func hashCode(): Int64
功能:获取该静态成员变量信息的哈希值。
返回值:
- Int64 - 该静态成员变量信息的哈希值。
func isMutable()
public func isMutable(): Bool
功能:判断该 StaticVariableInfo 对应的静态成员变量是否可修改。
注意:
- 如果静态成员变量被
var修饰符所修饰,则该静态成员变量可被修改。- 如果静态成员变量被
let修饰符所修饰,则该静态成员变量不可被修改。
返回值:
- Bool - 如果该静态成员变量信息所对应的静态成员变量可被修改则返回
true,否则返回false。
func setValue(Any)
public func setValue(newValue: Any): Unit
功能:设置该 StaticVariableInfo 对应的静态成员变量的值。
参数:
- newValue: Any - 新值。
异常:
- IllegalSetException - 如果该 StaticVariableInfo 对应的静态成员变量不可修改,则抛出异常。
- IllegalTypeException - 如果新值
newValue的运行时类型不是该静态成员变量信息所对应的静态成员变量的声明类型的子类型,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
public static var area: Int64 = 10
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取静态变量
let sv = ty.getStaticVariable("area")
// 设置值
sv.setValue(20)
println(sv.getValue() as Int64)
return
}
运行结果:
Some(20)
func toString()
public func toString(): String
功能:获取字符串形式的该静态成员变量信息。
返回值:
- String - 字符串形式的该静态成员变量信息。
operator func !=(StaticVariableInfo)
public operator func !=(that: StaticVariableInfo): Bool
功能:判断该静态成员变量信息与给定的另一个静态成员变量信息是否不等。
参数:
- that: StaticVariableInfo - 被比较相等性的另一个静态成员变量信息。
返回值:
- Bool - 如果该静态成员变量信息与
that不等则返回true,否则返回false。
operator func ==(StaticVariableInfo)
public operator func ==(that: StaticVariableInfo): Bool
功能:判断该静态成员变量信息与给定的另一个静态成员变量信息是否相等。
参数:
- that: StaticVariableInfo - 被比较相等性的另一个静态成员变量信息。
返回值:
- Bool - 如果该静态成员变量信息与
that相等则返回true,否则返回false。
class StructTypeInfo
public class StructTypeInfo <: TypeInfo
功能:描述 struct 类型的类型信息。
父类型:
由于实现限制,目前 Struct 类型的变量/属性修改需要参考如下代码手动 box/unbox。
import std.reflect.*
public struct SA {
public var v1 = 11
}
main() {
var sa = SA()
let saObj: Any = sa
StructTypeInfo.of<SA>().getInstanceVariable("v1").setValue(saObj, 22)
sa = (saObj as SA).getOrThrow()
println(sa.v1) // should be 22
}
prop constructors
public prop constructors: Collection<ConstructorInfo>
功能:获取该 StructTypeInfo 对应的 struct 的所有 public 构造函数信息,返回对应集合。
注意:
- 如果该
struct类型无任何public构造函数,则返回空集合。- 该集合不保证遍历顺序恒定。
类型:Collection<ConstructorInfo>
prop instanceVariables
public prop instanceVariables: Collection<InstanceVariableInfo>
功能:获取该 StructTypeInfo 对应的 struct 的所有 public 实例成员变量信息,返回对应集合。
注意:
- 如果该
struct类型无任何public实例成员变量,则返回空集合。- 该集合不保证遍历顺序恒定。
类型:Collection<InstanceVariableInfo>
prop staticVariables
public prop staticVariables: Collection<StaticVariableInfo>
功能:获取该 StructTypeInfo 对应的 struct 的所有 public 静态成员变量信息,返回对应集合。
注意:
- 如果该
struct类型无任何public静态成员变量,则返回空集合。- 该集合不保证遍历顺序恒定。
类型:Collection<StaticVariableInfo>
func construct(Array<Any>)
public func construct(args: Array<Any>): Any
功能:在该 StructTypeInfo 对应的 struct 类型中根据实参列表搜索匹配的构造函数并调用,传入实参列表,返回调用结果。
参数:
返回值:
- Any - 该
struct类型的实例。
异常:
- MisMatchException - 如果
args未能成功匹配任何该struct类型的public构造函数,则抛出异常 - InvocationTargetException - 在被调用的构造函数内部抛出的任何异常均将被封装为 InvocationTargetException 异常并抛出。
示例:
import std.reflect.*
public struct Rectangular {
public var length = 4
public var width = 5
public init() {}
public init(length: Int64, width: Int64) {
this.length = length
this.width = width
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 StructTypeInfo,也可以通过实例获取 StructTypeInfo
let ty = StructTypeInfo.get("default.Rectangular")
// 匹配构造函数并调用
let v = ty.construct(2, 3) as Rectangular
println(v.getOrThrow().length)
return
}
运行结果:
2
func getConstructor(Array<TypeInfo>)
public func getConstructor(parameterTypes: Array<TypeInfo>): ConstructorInfo
功能:尝试在该 StructTypeInfo 对应的 struct 类型中获取与给定形参类型信息列表匹配的 public 构造函数的信息。
参数:
返回值:
- ConstructorInfo - 如果成功匹配则返回该
public构造函数的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public构造函数,则抛出异常。
func getInstanceVariable(String)
public func getInstanceVariable(name: String): InstanceVariableInfo
功能:给定变量名称,尝试获取该 StructTypeInfo 对应的 struct 类型中匹配的实例成员变量的信息。
参数:
- name: String - 变量名称。
返回值:
- InstanceVariableInfo - 如果成功匹配则返回该实例成员变量的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public实例成员变量,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public var myName = ""
public init() {}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 ClassTypeInfo,也可以通过实例获取 ClassTypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取结构实例成员变量信息
let ivi = ty.getInstanceVariable("myName")
println(ivi)
return
}
运行结果:
myName: String
func getStaticVariable(String)
public func getStaticVariable(name: String): StaticVariableInfo
功能:给定变量名称,尝试获取该 StructTypeInfo 对应的 struct 类型中匹配的静态成员变量的信息。
参数:
- name: String - 变量名称。
返回值:
- StaticVariableInfo - 如果成功匹配则返回该静态成员变量的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public静态成员变量,则抛出异常。
示例:
package test
import std.reflect.*
public struct Rectangular {
public static var area: Int64 = 10
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 StructTypeInfo,也可以通过实例获取 StructTypeInfo
let ty = StructTypeInfo.get("test.Rectangular")
// 获取静态变量
let sv = ty.getStaticVariable("area")
println(sv)
return
}
运行结果:
static area: Int64
static func get(String)
public redef static func get(qualifiedName: String): StructTypeInfo
功能:获取给定 qualifiedName 所对应的类型的 StructTypeInfo。
参数:
- qualifiedName: String - 类型的限定名称。
返回值:
- StructTypeInfo - 类型的限定名称
qualifiedName所对应的Struct类型的类型信息。
异常:
- InfoNotFoundException - 如果无法获取与给定类型的限定名称
qualifiedName匹配的类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 StructTypeInfo, 则抛出异常。
示例:
import std.reflect.*
import std.reflect.*
public struct Rectangular {}
main(): Unit {
let ty = StructTypeInfo.get("default.Rectangular")
println(ty)
return
}
运行结果:
default.Rectangular
static func of(Any)
public redef static func of(a: Any): StructTypeInfo
功能:获取给定的任意类型实例的运行时类型所对应的类型信息。
运行时类型是指在程序运行时,通过动态绑定确定的类型,运行时类型与实例对象相绑定。在继承等场景下运行时类型和静态类型可能不一致。
参数:
- a: Any - 任意类型的实例。
返回值:
- StructTypeInfo - 实例
a的运行时类型所对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得实例
a的运行时类型所对应的类型信息,则抛出异常。 - IllegalTypeException - 如果获取到的类型信息不是 StructTypeInfo, 则抛出异常。
示例:
package test
import std.reflect.*
public struct Rectangular {}
main(): Unit {
var r = Rectangular()
let ty = StructTypeInfo.of(r)
println(ty)
return
}
运行结果:
test.Rectangular
static func of<T>()
public redef static func of<T>(): StructTypeInfo
功能:获取给定 T 类型对应的类型信息。
返回值:
- StructTypeInfo -
T类型对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得类型 T 所对应的类型信息,抛出异常。
- IllegalTypeException - 如果获取到的类型信息不是 StructTypeInfo, 则抛出异常。
示例:
import std.reflect.*
public struct Rectangular {}
main(): Unit {
let ty = StructTypeInfo.of<Rectangular>()
println(ty)
return
}
运行结果:
default.Rectangular
class TypeInfo
sealed abstract class TypeInfo <: Equatable<TypeInfo> & Hashable & ToString
功能:TypeInfo 提供了所有数据类型通用的操作接口。开发者通常无需向下转型为更具体的数据类型,如 ClassTypeInfo 等,就能进行反射操作。
TypeInfo 的子类包括 PrimitiveTypeInfo、StructTypeInfo、ClassTypeInfo 和 InterfaceTypeInfo,分别对应基本数据类型,struct 数据类型,class 数据类型和 interface 数据类型的类型信息。
说明:
类型的限定名称为
(module_name/)?(default|package_name)(.package_name)*.(type_name)。
父类型:
prop annotations
public prop annotations: Collection<Annotation>
功能:获取所有作用于该 TypeInfo 对应的类型的注解,返回对应集合。
注意:
- 如果无任何注解作用于该类型信息所对应的类型,则返回空集合。
- 该集合不保证遍历顺序恒定。
类型:Collection<Annotation>
prop instanceFunctions
public prop instanceFunctions: Collection<InstanceFunctionInfo>
功能:获取该 TypeInfo 对应类型的所有 public 实例成员函数信息,返回对应集合。
注意:
- 如果该 TypeInfo 对应的类型无任何
public实例成员函数,则返回空集合。- 该集合不保证遍历顺序恒定。
- 如果该类型信息所对应的类型是
struct或class类型,则该集合不包含继承而来的实例成员函数的信息。
类型:Collection<InstanceFunctionInfo>
prop instanceProperties
public prop instanceProperties: Collection<InstancePropertyInfo>
功能:获取该 TypeInfo 对应类型的所有 public 实例成员属性信息,返回对应集合。
注意:
- 如果该 TypeInfo 对应的类型无任何
public实例成员属性,则返回空集合。- 该集合不保证遍历顺序恒定。
- 如果该类型信息所对应的类型是
struct或class类型,则该集合不包含继承而来的实例成员属性的信息。
类型:Collection<InstancePropertyInfo>
prop modifiers
public prop modifiers: Collection<ModifierInfo>
功能:获取该 TypeInfo 对应的类型拥有的所有修饰符的信息,返回对应集合。
注意:
- 如果该类型无任何修饰符,则返回空集合。
- 该集合不保证遍历顺序恒定。
interface类型默认拥有open语义,故返回的集合总是包含open修饰符。- 由于反射功能只能对所有被
public访问控制修饰符所修饰的类型进行操作,故将忽略所有访问控制修饰符。
prop name
public prop name: String
功能:获取该 TypeInfo 对应的类型的名称。
注意:
类型:String
prop qualifiedName
public prop qualifiedName: String
功能:获取该 TypeInfo 对应的类型的限定名称。
注意:
- 限定名称包含模块名和包名前缀。
- 特别的,仓颉内置数据类型,以及位于
std模块core包下的所有类型的限定名称都是不带有任何模块名和包名前缀的。- 在缺省模块名和包名的上下文中定义的所有类型,均无模块名前缀,但拥有包名前缀"
default",如:"default.MyType"。
类型:String
prop staticFunctions
public prop staticFunctions: Collection<StaticFunctionInfo>
功能:获取该 TypeInfo 对应类型的所有 public 静态成员函数信息,返回对应集合。
注意:
- 如果该 TypeInfo 对应的类型无任何
public静态成员函数,则返回空集合。- 该集合不保证遍历顺序恒定。
- 如果该类型信息所对应的类型是
struct、class或interface类型,则该集合不包含继承而来的静态成员函数的信息。
类型:Collection<StaticFunctionInfo>
prop staticProperties
public prop staticProperties: Collection<StaticPropertyInfo>
功能:获取该 TypeInfo 对应类型的所有 public 静态成员属性信息,返回对应集合。
注意:
- 如果该 TypeInfo 对应的类型无任何
public静态成员属性,则返回空集合。- 该集合不保证遍历顺序恒定。
- 如果该类型信息所对应的类型是
struct、class或interface类型,则该集合不包含继承而来的静态成员属性的信息。
类型:Collection<StaticPropertyInfo>
prop superInterfaces
public prop superInterfaces: Collection<InterfaceTypeInfo>
功能:获取该 TypeInfo 对应的类型直接实现的所有 interface 类型的信息,返回对应集合。
注意:
类型:Collection<InterfaceTypeInfo>
static func get(String)
public static func get(qualifiedName: String): TypeInfo
功能:获取给定 qualifiedName 所对应的类型的 TypeInfo。
注意:
目前, 类型的限定名称
qualifiedName不支持Nothing类型、函数类型、元组类型和enum类型的限定名称。
参数:
- qualifiedName: String - 类型的限定名称。
返回值:
- TypeInfo - 类型的限定名称
qualifiedName所对应的类型的类型信息。
异常:
- InfoNotFoundException - 如果无法获取与给定类型的限定名称
qualifiedName匹配的类型所对应的类型信息,则抛出异常。
示例:
import std.reflect.*
public class Rectangular {}
main(): Unit {
let ty = TypeInfo.get("default.Rectangular")
println(ty)
return
}
运行结果:
default.Rectangular
static func of(Any)
public static func of(a: Any): TypeInfo
功能:获取给定的任意类型实例的运行时类型所对应的类型信息。
运行时类型是指在程序运行时,通过动态绑定确定的类型,运行时类型与实例对象相绑定。在继承等场景下运行时类型和静态类型可能不一致。
注意:
目前,实例
a不支持运行时类型为函数类型、元组类型、enum类型。
参数:
- a: Any - 任意类型的实例。
返回值:
- TypeInfo - 实例
a的运行时类型所对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得实例
a的运行时类型所对应的类型信息,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {}
main(): Unit {
var r: Any = Rectangular()
let ty = TypeInfo.of(r)
println(ty)
return
}
运行结果:
test.Rectangular
static func of(Object) (deprecated)
public static func of(a: Object): ClassTypeInfo
功能:获取给定的 class 类型的实例的运行时类型所对应的 class 类型信息。
注意:
未来版本即将废弃,使用 ClassTypeInfo 的 static func of(Object) 函数替代。
参数:
- a: Object -
class类型的实例。
返回值:
- ClassTypeInfo -
class类型的实例a的运行时类型所对应的class类型信息。
异常:
- InfoNotFoundException - 如果无法获得实例
a的运行时类型所对应的class类型信息,则抛出异常。
static func of<T>()
public static func of<T>(): TypeInfo
功能:获取给定 T 类型对应的类型信息。
注意:
返回值:
- TypeInfo -
T类型对应的类型信息。
异常:
- InfoNotFoundException - 如果无法获得类型 T 所对应的类型信息,抛出异常。
示例:
import std.reflect.*
public class Rectangular {}
main(): Unit {
let ty = TypeInfo.of<Rectangular>()
println(ty)
return
}
运行结果:
default.Rectangular
func findAnnotation<T>()
public func findAnnotation<T>(): Option<T>
功能:尝试获取作用于该 TypeInfo 对应的类型且拥有给定限定名称的注解。
返回值:
- Option<T> - 如果成功匹配则返回该注解,否则返回
None。
func getInstanceFunction(String, Array<TypeInfo>)
public func getInstanceFunction(name: String, parameterTypes: Array<TypeInfo>): InstanceFunctionInfo
功能:给定函数名称与函数形参类型列表所对应的类型信息列表,尝试获取该类型中匹配的实例成员函数的信息。
参数:
返回值:
- InstanceFunctionInfo - 如果成功匹配则返回该实例成员函数的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public实例成员函数,则抛出异常。
示例:
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public func area(): Int64 {
return length * width
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 TypeInfo,也可以通过实例获取 TypeInfo
let ty = TypeInfo.get("default.Rectangular")
// 获取 InstanceFunctionInfo
var gif = ty.getInstanceFunction("area")
println(gif)
return
}
运行结果:
func area(): Int64
func getInstanceFunctions(String)
public func getInstanceFunctions(name: String): Array<InstanceFunctionInfo>
功能:给定函数名称,尝试获取该类型中所有匹配的实例成员函数的信息。
参数:
- name: String - 函数名称。
返回值:
- Array<InstanceFunctionInfo> - 如果成功匹配则返回所有匹配到的实例成员函数信息。
示例:
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public func area(): Int64 {
return length * width
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 TypeInfo,也可以通过实例获取 TypeInfo
let ty = TypeInfo.get("default.Rectangular")
// 获取 InstanceFunctionInfo
var gif = ty.getInstanceFunctions("area")
println(gif)
return
}
运行结果:
[func area(): Int64]
func getInstanceProperty(String)
public func getInstanceProperty(name: String): InstancePropertyInfo
功能:尝试获取该类型中与给定属性名称匹配的实例成员属性的信息。
参数:
- name: String - 属性名称。
返回值:
- InstancePropertyInfo - 如果成功匹配则返回该实例成员属性的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public实例成员属性,则抛出异常。
示例:
import std.reflect.*
public class Rectangular {
public var length = 4
public prop width: Int64 {
get() {
5
}
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 TypeInfo,也可以通过实例获取 TypeInfo
let ty = TypeInfo.get("default.Rectangular")
// 获取 InstancePropertyInfo
var gip = ty.getInstanceProperty("width")
println(gip)
return
}
运行结果:
prop width: Int64
func getStaticFunction(String, Array<TypeInfo>)
public func getStaticFunction(name: String, parameterTypes: Array<TypeInfo>): StaticFunctionInfo
功能:通过给定函数名称与函数形参类型列表所对应的类型信息列表,尝试获取该类型中匹配的静态成员函数的信息。
参数:
返回值:
- StaticFunctionInfo - 如果成功匹配则返回该静态成员函数的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public静态成员函数,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
public static func myName(): String { "" }
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 TypeInfo,也可以通过实例获取 TypeInfo
let ty = ClassTypeInfo.get("test.Rectangular")
// 获取静态函数
let sf = ty.getStaticFunction("myName")
println(sf)
return
}
运行结果:
static func myName(): String
func getStaticFunctions(String)
public func getStaticFunctions(name: String): Array<StaticFunctionInfo>
功能:给定函数名称,尝试获取该类型中所有匹配的静态成员函数的信息。
参数:
- name: String - 函数名称。
返回值:
- Array<StaticFunctionInfo> - 如果成功匹配则返回所有匹配到的静态成员函数信息。
示例:
package test
import std.reflect.*
public class Rectangular {
public static func myName(): String { "" }
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 TypeInfo,也可以通过实例获取 TypeInfo
let ty = TypeInfo.get("test.Rectangular")
// 获取静态函数
let sf = ty.getStaticFunctions("myName")
println(sf)
return
}
运行结果:
[static func myName(): String]
func getStaticProperty(String)
public func getStaticProperty(name: String): StaticPropertyInfo
功能:尝试获取该类型中与给定属性名称匹配的静态成员属性的信息。
参数:
- name: String - 属性名称。
返回值:
- StaticPropertyInfo - 如果成功匹配则返回该静态成员属性的信息。
异常:
- InfoNotFoundException - 如果没找到对应
public静态成员属性,则抛出异常。
示例:
package test
import std.reflect.*
public class Rectangular {
private static var valueArea = 0
public static mut prop area: Int64 {
get() { valueArea }
set(v) { valueArea = v }
}
}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 TypeInfo,也可以通过实例获取 TypeInfo
let ty = TypeInfo.get("test.Rectangular")
// 获取静态属性
let sp = ty.getStaticProperty("area")
println(sp)
return
}
运行结果:
static mut prop area: Int64
func hashCode()
public func hashCode(): Int64
功能:获取该类型信息的哈希值。
注意:
内部实现为该类型信息的限定名称字符串的哈希值。
返回值:
- Int64 - 该类型信息的哈希值。
func isSubtypeOf(TypeInfo)
public func isSubtypeOf(supertype: TypeInfo): Bool
功能:判断当前 TypeInfo 实例对应的类型是否是参数中指定的 TypeInfo 实例表示的类型的子类型。
注意:
由于目前所有
struct类型均无法获得其实现的interface类型,所以在做struct是否为某interface的子类型的判断时总是返回false。
参数:
- supertype: TypeInfo - 目标类型的类型信息。
返回值:
示例:
package test
import std.reflect.*
public abstract class Rectangular {}
public class Square <: Rectangular {}
main(): Unit {
// 此处是通过 Rectangular 的类型的限定名称获取 TypeInfo,也可以通过实例获取 TypeInfo
let tyr = ClassTypeInfo.get("test.Rectangular")
let tys = ClassTypeInfo.get("test.Square")
println(tys.isSubtypeOf(tyr))
return
}
运行结果:
true
func toString()
public func toString(): String
功能:获取字符串形式的该类型信息。
注意:
内部实现为该类型信息的限定名称字符串。
返回值:
- String - 字符串形式的该类型信息。
operator func !=(TypeInfo)
public operator func !=(that: TypeInfo): Bool
功能:判断该类型信息与给定的另一个类型信息是否不等。
参数:
- that: TypeInfo - 被比较相等性的另一个类型信息。
返回值:
- Bool - 如果该类型信息的限定名称与
that不等则返回true,否则返回false。
operator func ==(TypeInfo)
public operator func ==(that: TypeInfo): Bool
功能:判断该类型信息与给定的另一个类型信息是否相等。
参数:
- that: TypeInfo - 被比较相等性的另一个类型信息。
返回值:
- Bool - 如果该类型信息的限定名称与
that相等则返回true,否则返回false。
枚举
enum ModifierInfo
public enum ModifierInfo <: Equatable<ModifierInfo> & Hashable & ToString {
| Open
| Override
| Redef
| Abstract
| Sealed
| Mut
| Static
}
功能:描述修饰符信息。
注意:
由于开发者通过反射功能获取到的类型信息均来自于
public的类型,这些类型都必定拥有public的访问控制语义,因此修饰符信息并不包含任何访问控制相关的修饰符。
父类型:
Abstract
Abstract
功能:表示 abstract 修饰符。
Mut
Mut
功能:表示 mut 修饰符。
Open
Open
功能:表示 open 修饰符。
Override
Override
功能:表示 override 修饰符。
Redef
Redef
功能:表示 redef 修饰符。
Sealed
Sealed
功能:表示 sealed 修饰符。
Static
Static
功能:表示 static 修饰符。
func hashCode()
public func hashCode(): Int64
功能:获取该修饰符信息的哈希值。
返回值:
- Int64 - 该修饰符信息的哈希值。
注意:
内部实现为该修饰符关键字字符串的哈希值。
func toString()
public override func toString(): String
功能:获取字符串形式的该修饰符信息。
返回值:
- String - 字符串形式的该修饰符信息。
注意:
字符串形式的修饰符信息即为修饰符关键字的标识符。
operator func ==(ModifierInfo)
public override operator func ==(that: ModifierInfo): Bool
功能:判断该修饰符信息与给定的另一个修饰符信息是否相等。
参数:
- that: ModifierInfo - 被比较相等性的另一个修饰符信息。
返回值:
- Bool - 如果该修饰符信息与
that相等则返回true,否则返回false。
注意:
修饰符信息的相等性的语义等价于
enum类型实例的相等性的语义。
operator func !=(ModifierInfo)
public override operator func !=(that: ModifierInfo): Bool
功能:判断该修饰符信息与给定的另一个修饰符信息是否不等。
注意:
修饰符信息的相等性的语义等价于
enum类型实例的相等性的语义。
参数:
- that: ModifierInfo - 被比较相等性的另一个修饰符信息。
返回值:
- Bool - 如果该修饰符信息与
that不等则返回true,否则返回false。
异常类
class IllegalSetException
public class IllegalSetException <: ReflectException {
public init()
public init(message: String)
}
功能:IllegalSetException 为对不可变类型进行更改异常。
父类型:
init()
public init()
功能:创建 IllegalSetException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 IllegalSetException 实例。
参数:
- message: String - 异常信息。
class IllegalTypeException
public class IllegalTypeException <: ReflectException {
public init()
public init(message: String)
}
功能:IllegalTypeException 为类型不匹配异常。
父类型:
init()
public init()
功能:创建 IllegalTypeException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 IllegalTypeException 实例。
参数:
- message: String - 异常信息。
class InfoNotFoundException
public class InfoNotFoundException <: ReflectException {
public init()
public init(message: String)
}
功能:InfoNotFoundException 为无法找到对应信息异常。
父类型:
init()
public init()
功能:创建 InfoNotFoundException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 InfoNotFoundException 实例。
参数:
- message: String - 异常信息。
class InvocationTargetException
public class InvocationTargetException <: ReflectException {
public init()
public init(message: String)
}
功能:InvocationTargetException 为调用函数包装异常。
父类型:
init()
public init()
功能:创建 InvocationTargetException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 InvocationTargetException 实例。
参数:
- message: String - 异常信息。
class MisMatchException
public class MisMatchException <: ReflectException {
public init()
public init(message: String)
}
功能:MisMatchException 为调用对应函数抛出异常。
父类型:
init()
public init()
功能:创建 MisMatchException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 MisMatchException 实例。
参数:
- message: String - 异常信息。
class ReflectException
public open class ReflectException <: Exception {
public init()
public init(message: String)
}
功能:ReflectException 为 Reflect 包的基异常类。
父类型:
init()
public init()
功能:创建 ReflectException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 ReflectException 实例。
参数:
- message: String - 异常信息。
func getClassName()
protected override open func getClassName(): String
功能:获得类名。
返回值:
- String - 类名字符串。
注解的使用
通过反射获取实例上注解的值。
代码如下:
import std.reflect.*
main() {
let ti = TypeInfo.of(Test())
let annotation = ti.findAnnotation<A>()
if (let Some(a) <- annotation) {
println(a.name)
}
}
@A["Annotation"]
public class Test {}
@Annotation
public class A {
const A(let name: String) {}
}
运行结果:
Annotation
动态加载的使用
在项目根目录 myProject 下分别创建两个目录 myModuleDirectory 和 myExecutableDirectory,分别在其中使用 cjpm 构建仓颉动态库模块和可执行文件,该可执行文件将在动态加载该仓颉动态库模块后通过反射对动态库模块中的全局变量进行操作。
$ mkdir -p myProject && cd myProject
$ mkdir -p myPackage && cd myPackage
# 在 myPackage 目录下执行该命令初始化该仓颉动态库模块的目录结构,如此便可对 myPackage 下的仓颉功能进行动态编译。
$ cjpm init --type=dynamic --name myPackage
cjpm init success
$ cat << EOF > src/myPackage.cj
package myPackage
public var myPublicGlobalVariable0: Int64 = 2333
public let myPublicGlobalVariable1 = MyPublicType("Initializing myPublicGlobalVariable1 in myPackage")
public class MyPublicType {
public MyPublicType(message: String) {
println(message)
}
public static func myPublicStaticMemeberFunction() {
println("myPackage.MyPublicType.myPublicStaticMemeberFunction is called.")
}
static let myStaticVariable = MyPublicType("Initializing myStaticVariable in myPackage.MyPublicType")
}
EOF
# 使用 cjpm 构建该仓颉动态库模块。
$ cjpm build
cjpm build success
$ cd .. && mkdir -p myExecutableDirectory && cd myExecutableDirectory
$ cjpm init
$ cat << EOF > src/main.cj
package myExecutableDirectory
import std.reflect.*
main(): Unit {
// 加载仓颉动态库。
let myPackage = PackageInfo.load("../myPackage/target/release/myPackage/libmyPackage")
println(myPackage.name)
TypeInfo.get("myPackage.MyPublicType") |> println
let myPublicGlobalVariable0 = myPackage.getVariable("myPublicGlobalVariable0")
(myPublicGlobalVariable0.getValue() as Int64).getOrThrow() |> println
myPublicGlobalVariable0.setValue(666)
(myPublicGlobalVariable0.getValue() as Int64).getOrThrow() |> println
}
EOF
# 构建并运行可执行程序。
$ cjpm run
Initializing myPublicGlobalVariable1 in myPackage
Initializing myStaticVariable in myPackage.MyPublicType
myPackage
myPackage.MyPublicType
2333
666
cjpm run finished
$ tree ..
..
├── myExecutableDirectory
│ ├── cjpm.lock
│ ├── cjpm.toml
│ ├── src
│ │ └── main.cj
│ └── target
│ └── release
│ ├── bin
│ │ ├── main
│ │ ├── myExecutableDirectory.bchir2
│ │ └── myExecutableDirectory.cjo
│ ├── myExecutableDirectory
│ │ └── incremental-cache.json
│ └── myExecutableDirectory-cache.json
└── myPackage
├── cjpm.lock
├── cjpm.toml
├── src
│ └── myPackage.cj
└── target
└── release
├── bin
├── myPackage
│ ├── incremental-cache.json
│ ├── libmyPackage.so
│ ├── myPackage.bchir2
│ └── myPackage.cjo
└── myPackage-cache.json
12 directories, 16 files
注意:
由于当前 PackageInfo.load 函数根据文件名来判断包名,因此不允许修改该文件名,否则将抛出无法找到仓颉动态库模块文件的异常。
成员信息的使用
import std.reflect.*
public class Rectangular {
public var length = 4
public var width = 5
public func area(): Int64 {
return length * width
}
}
main(): Unit {
let a = Rectangular()
let ty = TypeInfo.of(a)
const zl = 3
let members = ty.instanceVariables.toArray()
println((members[0].getValue(a) as Int64).getOrThrow())
println((members[1].getValue(a) as Int64).getOrThrow())
members[0].setValue(a, zl)
members[1].setValue(a, zl)
println((members[0].getValue(a) as Int64).getOrThrow())
println((members[1].getValue(a) as Int64).getOrThrow())
println(a.area())
let funcs = ty.instanceFunctions.toArray()
if (funcs[0].returnType.name == "Int64"){
println("The area of the square is ${zl**2}")
}
return
}
运行结果:
4
5
3
3
9
The area of the square is 9
TypeInfo 的使用
package Demo
import std.reflect.*
public class Foo {
public let item = 0
public func f() {}
}
main() {
let a = Foo()
let ty: TypeInfo = TypeInfo.of(a)
println(ty.name)
println(ty.qualifiedName)
println(ty.instanceFunctions.size)
}
运行结果:
Foo
Demo.Foo
1
std.regex
功能介绍
regex 包使用正则表达式分析处理文本的能力,支持查找、分割、替换、验证等功能。
regex 规则集
当前仓颉的正则表达式仅支持以下规则,使用不支持的规则会导致输出结果与预期不符。
| 字符 | 描述 |
|---|---|
\ | 将下一个字符标记为一个特殊字符(File Format Escape,清单见本表)、或一个原义字符(Identity Escape,有^$()*+?.[{\|共计 12 个)、或一个向后引用(backreferences)。例如,“n”匹配字符“n”。\n匹配一个换行符。序列\匹配\,而(则匹配(。 |
^ | 匹配输入字符串的开始位置。如果设置了 RegexOption 中的多行模式 multiLine(),^也匹配\n或\r之后的位置。 |
$ | 匹配输入字符串的结束位置。 |
* | 匹配前面的子表达式零次或多次。例如,zo*能匹配z、zo以及zoo。*等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,zo+能匹配zo以及zoo,但不能匹配z。+等价于{1,}。 |
? | 匹配前面的子表达式零次或一次。例如,do(es)?可以匹配does中的do和does。?等价于{0,1}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。例如,o{2}不能匹配Bob中的o,但是能匹配food中的两个o。 |
{n,} | n 是一个非负整数。至少匹配 n 次。例如,o{2,}不能匹配Bob中的o,但能匹配foooood中的所有o。o{1,}等价于o+。o{0,}则等价于o*。 |
{n,m} | m 和 n 均为非负整数,其中 n<=m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3}将匹配fooooood中的前三个o。o{0,1}等价于o?。请注意在逗号和两个数之间不能有空格。 |
? | 非贪心量化(Non-greedy quantifiers):当该字符紧跟在任何一个其他重复修饰符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串oooo,o+?将匹配单个o,而o+将匹配所有o。 |
. | 匹配除\n之外的任何单个字符。要匹配包括\n在内的任何字符,请使用像(.\|\n)的模式。 |
(pattern) | 匹配 pattern 并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的 Matches 集合中得到。要匹配圆括号字符,请使用\(或\)。可带数量后缀。 |
x\|y | 没有包围在()里,其范围是整个正则表达式。例如,z|food 能匹配z或food。(?:z|f)ood 则匹配zood或food。 |
[xyz] | 字符集合(character class)。匹配所包含的任意一个字符。例如,[abc]可以匹配plain中的a。特殊字符仅有反斜线\保持特殊含义,用于转义字符。其他特殊字符如星号、加号、各种括号等均作为普通字符。脱字符^如果出现在首位则表示负值字符集合;如果出现在字符串中间就仅作为普通字符。连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位(或末尾)则仅作为普通字符。右方括号应转义出现,也可以作为首位字符出现。 |
[^xyz] | 排除型字符集合(negated character classes)。匹配未列出的任意字符。例如,[^abc]可以匹配plain中的plin。 |
[a-z] | 字符范围。匹配指定范围内的任意字符。例如,[a-z]可以匹配a到z范围内的任意小写字母字符。 |
[^a-z] | 排除型的字符范围。匹配任何不在指定范围内的任意字符。例如,[^a-z]可以匹配任何不在a到z范围内的任意字符。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如,er\b可以匹配never中的er,但不能匹配verb中的er。 |
\B | 匹配非单词边界。er\B能匹配verb中的er,但不能匹配never中的er。 |
\d | 匹配一个数字字符。等价于[0-9]。 |
\D | 匹配一个非数字字符。等价于[^0-9]。 |
\f | 匹配一个换页符。等价于\x0c。 |
\n | 匹配一个换行符。等价于\x0a。 |
\r | 匹配一个回车符。等价于\x0d。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于[^\f\n\r\t\v]。 |
\t | 匹配一个制表符。等价于\x09。 |
\v | 匹配\n\v\f\r\x85。 |
\w | 匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]。 |
\W | 匹配任何非单词字符。等价于[^A-Za-z0-9_]。 |
\xnm | 十六进制转义字符序列。匹配两个十六进制数字 nm 表示的字符。例如,\x41匹配A。正则表达式中可以使用 ASCII 码。 |
\num | 向后引用(back-reference)一个子字符串(substring),该子字符串与正则表达式的第 num 个用括号围起来的捕捉群(capture group)子表达式(subexpression)匹配。其中 num 是从 1 开始的十进制正整数,Regex 捕获组上限为 63。例如:(.)\1匹配两个连续的相同字符。 |
(?:pattern) | 匹配 pattern 但不获取匹配的子字符串(shy groups),也就是说这是一个非获取匹配,不存储匹配的子字符串用于向后引用。这在使用或字符(\|)来组合一个模式的各个部分是很有用。 |
(?=pattern) | 正向肯定预查(look ahead positive assert),在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,Windows(?=95\|98\|NT\|2000)能匹配Windows2000中的Windows,但不能匹配Windows3.1中的Windows。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?!pattern) | 正向否定预查(negative assert),在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如Windows(?!95\|98\|NT\|2000)能匹配Windows3.1中的Windows,但不能匹配Windows2000中的Windows。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?<=pattern) | 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,(?<=95\|98\|NT\|2000)Windows能匹配2000Windows中的Windows,但不能匹配3.1Windows中的Windows。 |
(?<!pattern) | 反向否定预查,与正向否定预查类似,只是方向相反。例如(?<!95\|98\|NT\|2000)Windows能匹配3.1Windows中的Windows,但不能匹配2000Windows中的Windows。 |
(?i) | 通过规则指定部分规则忽略大小写。当前 Regex 仅支持全局忽略大小写,当该选项被指定时,会被当做全局忽略大小写对待。 |
(?-i) | 通过规则指定部分规则大小写敏感。 当前 Regex 默认大小写敏感,该选项仅做编译兼容处理,不做敏感处理。 |
+ | 单独一个加号,不是转义的\+。 |
* | 单独一个星号,不是转义的\*。 |
- | 单独一个减号,不是转义的\-。 |
] | 单独一个右中括号,不是转义的\]。 |
} | 单独一个右大括号,不是转义的\}。 |
[[:alpha:]] | 表示任意大小写字母。 |
[[:^alpha:]] | 表示除大小写字母以外的任意字符。 |
[[:lower:]] | 表示任意小写字母。 |
[[:^lower:]] | 表示除小写字母以外的任意字符。 |
[[:upper:]] | 表示任意大写字母。 |
[[:^upper:]] | 表示除大写字母以外的任意字符。 |
[[:digit:]] | 表示0到9之间的任意单个数字。 |
[[:^digit:]] | 表示除0到9之间的单个数字以外的任意字符。 |
[[:xdigit:]] | 表示十六进制的字母和数字。 |
[[:^xdigit:]] | 表示除十六进制的字母和数字以外的任意字符。 |
[[:alnum:]] | 表示任意数字或字母。 |
[[:^alnum:]] | 表示除数字或字母以外的任意字符。 |
[[:space:]] | 表示任意空白字符,包括"空格"、"tab键"等。 |
[[:^space:]] | 表示除空白字符以外的任意字符。 |
[[:punct:]] | 表示任意标点符号。 |
[[:^punct:]] | 表示除任意标点符号以外的任意字符。 |
在仓颉中,还存在一些特殊的规则:
-
?、+、*前面的字符不可量化时,会被忽略;特例:(*、|*、*开头时*会被视为普通字符。 -
*?在匹配全部*?之前的字符组成的字符串时,会匹配不到该字符。 -
正则表达式的捕获组的最大个数为 63,编译后的最大规则长度为 65535。
-
暂不支持的场景:((pattern1){m1,n1}pattern2){m2,n2},即:
- 组定义 1 被{m1,n1}修饰;
- 组定义 1 被组定义 2 包裹;
- 组定义 2 被{m2,n2}修饰。
-
待匹配字符串需要用户自行保障不包含
\0,否则会得到预期以外的结果,甚至会陷入死循环无法退出。
警告:
当前实现中未对规则为
{n}、{n,}、{n,m}创建的最小或者最大重复次数进行限制,重复次数过大会造成创建正则匹配器时占用大量的CPU和内存资源,甚至会触发栈溢出异常退出,从而导致执行时间过长或者ReDos攻击。
API 列表
类
| 类名 | 功能 |
|---|---|
| Matcher (deprecated) | 正则匹配器,用于扫描输入序列并进行匹配。 |
| Regex | 用来指定编译类型和输入序列。 |
| RegexOption (deprecated) | 用于指定正则匹配的模式。 |
枚举
| 枚举名 | 功能 |
|---|---|
| RegexFlag | 用于指定正则匹配的模式。 |
结构体
异常类
| 异常类名 | 功能 |
|---|---|
| RegexException | 提供 regex 相关的异常处理。 |
类
class Matcher (deprecated)
public class Matcher {
public init(re: Regex, input: String)
}
功能:正则匹配器,用于扫描输入序列并进行匹配。
注意:
未来版本即将废弃,使用 Regex 替代。
init(Regex, String)
public init(re: Regex, input: String)
功能:使用传入的正则表达式和输入序列创建 Matcher 实例。
参数:
func allCount()
public func allCount(): Int64
功能:获取正则表示式的匹配结果总数。
默认是从头到尾匹配的结果,使用了 setRegion 后只会在设置的范围内查找。
返回值:
- Int64 - 匹配结果总数。
func find()
public func find(): Option<MatchData>
功能:自当前字符串偏移位置起,查找第一个匹配到的子序列。
find 调用一次,当前偏移位置为最新一次匹配到的子序列后第一个字符位置,下次调用时,find 从当前位置开始匹配。
返回值:
异常:
- RegexException - 当存在匹配但提取匹配信息失败时,抛出异常。
func find(Int64)
public func find(index: Int64): Option<MatchData>
功能:重置该匹配器索引位置,从 index 对应的位置处开始对输入序列进行匹配,返回匹配到的子序列。
返回值:
异常:
- IndexOutOfBoundsException - 当 index 小于 0,或 index 大于等于输入序列的 size 时,抛出异常。
- RegexException - 当存在匹配但提取匹配信息失败时,抛出异常。
func findAll()
public func findAll(): Option<Array<MatchData>>
功能:对整个输入序列进行匹配,查找所有匹配到的子序列。
返回值:
- Option<Array<MatchData>> - 如果匹配到结果,返回 Option<Array<MatchData>>;如果匹配不到,返回 Option<Array<MatchData>>.None。
异常:
- RegexException - 当存在匹配但提取匹配信息失败时,抛出异常。
func fullMatch()
public func fullMatch(): Option<MatchData>
功能:对整个输入序列进行匹配。
返回值:
异常:
- RegexException - 当存在匹配但提取匹配信息失败时,抛出异常。
func getString()
public func getString(): String
功能:获取匹配序列。
返回值:
- String - 匹配序列。
func matchStart()
public func matchStart(): Option<MatchData>
功能:对输入序列的头部进行匹配。
返回值:
异常:
- RegexException - 当存在匹配但提取匹配信息失败时,抛出异常。
func region()
public func region(): Position
功能:返回匹配器的区域设置。
返回值:
- Position - 匹配器的区域设置。
func replace(String)
public func replace(replacement: String): String
功能:自当前字符串偏移位置起,匹配到的第一个子序列替换为目标字符串,并将当前索引位置设置到匹配子序列的下一个位置。
参数:
- replacement: String - 指定替换字符串。
返回值:
- String - 替换后字符串。
func replace(String, Int64)
public func replace(replacement: String, index: Int64): String
功能:从输入序列的 index 位置起匹配正则,将匹配到的第一个子序列替换为目标字符串。
参数:
返回值:
- String - 替换后字符串。
异常:
- IndexOutOfBoundsException - 当 index 小于 0,或 index 大于等于输入序列的 size 时,抛出异常。
func replaceAll(String)
public func replaceAll(replacement: String): String
功能:将输入序列中所有与正则匹配的子序列替换为给定的目标字符串。
参数:
- replacement: String - 指定替换字符串。
返回值:
- String - 替换后的字符串。
func replaceAll(String, Int64)
public func replaceAll(replacement: String, limit: Int64): String
功能:将输入序列中与正则匹配的前 limit 个子序列替换为给定的替换字符串。
参数:
返回值:
- String - 替换后字符串。
func resetRegion()
public func resetRegion(): Matcher
功能:重置匹配器开始位置和结束位置。
返回值:
- Matcher - 匹配器自身。
func resetString(String)
public func resetString(input: String): Matcher
功能:重设匹配序列,并重置匹配器。
参数:
- input: String - 新的匹配序列。
返回值:
- Matcher - 匹配器自身。
func setRegion(Int64, Int64)
public func setRegion(beginIndex: Int64, endIndex: Int64): Matcher
功能:设置匹配器可搜索区域的位置信息,具体位置由指定的 begin 和 end 决定。
参数:
返回值:
- Matcher - 匹配器自身。
异常:
- IndexOutOfBoundsException - 当 beginIndex 小于0,或 beginIndex 大于输入序列的 size 时,抛出异常;当 endIndex 小于0,或 endIndex 大于输入序列的 size 时,抛出异常;当 beginIndex 大于 endIndex 时,抛出异常。
func split()
public func split(): Array<String>
功能:将给定的输入序列根据正则尽可能的分割成多个子序列。
返回值:
func split(Int64)
public func split(limit: Int64): Array<String>
功能:将给定的输入序列根据正则尽可能的分割成多个子序列 (最多分割成 limit 个子串)。
参数:
- limit: Int64 - 最多分割的子串个数。
返回值:
class Regex
public class Regex {
public init(pattern: String, flags: Array<RegexFlag>)
public init(pattern: String, option: RegexOption)
}
功能:用来指定编译类型并创建正则表达式实例。
正则匹配规则详见 regex 规则集。
init(String, Array<RegexFlag>)
public init(pattern: String, flags: Array<RegexFlag>)
功能:创建 Regex 实例。
参数:
异常:
- RegexException - 当初始化失败时,抛出异常。
init(String, RegexOption) (deprecated)
public init(pattern: String, option: RegexOption)
功能:使用指定的模式创建一个 Regex 实例。
注意:
未来版本即将废弃,使用 init(String, Array<RegexFlag>) 替代。
参数:
- pattern: String - 正则表达式。
- option: RegexOption - 正则匹配的模式。
异常:
- RegexException - 当初始化失败时,抛出异常。
func find(String, Bool)
public func find(input: String, group!: Bool = false): Option<MatchData>
功能:查找第一个匹配到的子序列。
参数:
返回值:
异常:
- RegexException - 当存在匹配但提取匹配信息失败时,抛出异常。
示例:
import std.regex.*
main(): Unit {
let r1 = Regex("ab")
let r2 = Regex("ab", IgnoreCase)
match (r1.find("aB")) {
case Some(r) => println(r.matchString())
case None => println("None")
}
match (r2.find("aB")) {
case Some(r) => println(r.matchString())
case None => println("None")
}
}
运行结果:
None
aB
func findAll(String, Bool)
public func findAll(input: String, group!: Bool = false): Array<MatchData>
功能:对整个输入序列进行匹配,查找所有匹配到的子序列。
参数:
返回值:
异常:
- RegexException - 当存在匹配但提取匹配信息失败时,抛出异常。
示例:
import std.regex.*
main(): Unit {
let r = Regex("ab")
let arr = r.findAll("ababaaab")
let iter = arr.iterator()
println(arr.size)
while (true) {
match (iter.next()) {
case Some(i) => println(i.matchString())
case None => break
}
}
}
运行结果:
3
ab
ab
ab
func getNamedGroups()
public func getNamedGroups(): Map<String, Int64>
功能:获取命名捕获组的名称与索引映射。
返回值:
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
let arr = r.findAll("2024-10-24&2025-01-01", group: true)
for (md in arr) {
println("# found: `${md.matchString()}` and groupCount: ${md.groupCount()}")
for ((name, index) in r.getNamedGroups()) {
println("${name} => ${index}")
}
}
}
运行结果:
# found: `2024-10-24` and groupCount: 3
day => 3
month => 2
year => 1
# found: `2025-01-01` and groupCount: 3
day => 3
month => 2
year => 1
func lazyFindAll(String, Bool)
public func lazyFindAll(input: String, group!: Bool = false): Iterator<MatchData>
功能:对整个输入序列进行匹配,获取匹配的迭代器。
参数:
返回值:
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
let iter = r.lazyFindAll("2024-10-24&2025-01-01", group: true)
while (true) {
match (iter.next()) {
case Some(md) =>
println("# found: `${md.matchString()}` and groupCount: ${md.groupCount()}")
for ((name, index) in r.getNamedGroups()) {
println("${name} => ${index}")
}
case None => break
}
}
}
运行结果:
# found: `2024-10-24` and groupCount: 3
day => 3
month => 2
year => 1
# found: `2025-01-01` and groupCount: 3
day => 3
month => 2
year => 1
func matcher(String) (deprecated)
public func matcher(input: String): Matcher
功能:创建匹配器。
注意:
未来版本即将废弃。
参数:
- input: String - 要匹配的字符串。
返回值:
- Matcher - 创建的匹配器。
func matches(String)
public func matches(input: String): Bool
功能:判断入参 input 与正则表达式是否存在匹配。
参数:
- input: String - 要匹配的字符串。
返回值:
- Bool - 如果存在匹配,返回 true,否则返回 false。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
println(r.matches("2024-10-24&2025-01-01"))
}
运行结果:
true
func replace(String, String)
public func replace(input: String, replacement: String): String
功能:自当前字符串起始位置开始,匹配到的第一个子序列替换为目标字符串。
参数:
返回值:
- String - 替换后字符串。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
println(r.replace("2024-10-24&2025-01-01", "time"))
}
运行结果:
time&2025-01-01
func replace(String, String, Int64)
public func replace(input: String, replacement: String, index: Int64): String
功能:从输入序列的 index 位置起匹配正则,将匹配到的第一个子序列替换为目标字符串。
参数:
返回值:
- String - 替换后字符串。
异常:
- IndexOutOfBoundsException - 当 index 小于 0,或 index 大于等于输入序列的 size 时,抛出异常。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
println(r.replace("2024-10-24&2025-01-01", "time", 10))
}
运行结果:
2024-10-24&time
func replaceAll(String, String)
public func replaceAll(input: String, replacement: String): String
功能:将输入序列中所有与正则匹配的子序列替换为给定的目标字符串。
参数:
返回值:
- String - 替换后的字符串。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
println(r.replaceAll("2024-10-24&2025-01-01", "time"))
}
运行结果:
time&time
func replaceAll(String, String, Int64)
public func replaceAll(input: String, replacement: String, limit: Int64): String
功能:将输入序列中与正则匹配的前 limit 个子序列替换为给定的替换字符串。
参数:
- input: String - 待匹配序列。
- replacement: String - 指定替换字符串。
- limit: Int64 - 替换次数。如果 limit 等于 0,返回原来的序列;如果 limit 为负数,将尽可能多次的替换。
返回值:
- String - 替换后字符串。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
println(r.replaceAll("2019-4-5&2024-10-24&2025-01-01", "time", 10))
}
运行结果:
2019-4-5&time&time
func split(String)
public func split(input: String): Array<String>
功能:将给定的输入序列根据正则尽可能的分割成多个子序列。
参数:
- input: String - 待匹配序列。
返回值:
示例:
import std.regex.*
main(): Unit {
let r = Regex("&")
for (subStr in r.split("2019-4-5&2024-10-24&2025-01-01")) {
println(subStr)
}
}
运行结果:
2019-4-5
2024-10-24
2025-01-01
func split(String, Int64)
public func split(input: String, limit: Int64): Array<String>
功能:将给定的输入序列根据正则尽可能的分割成多个子序列 (最多分割成 limit 个子串)。
参数:
返回值:
func string()
public func string(): String
功能:获取正则的输入序列。
返回值:
- String - 输入序列。
class RegexOption (deprecated)
public class RegexOption <: ToString {
public init()
}
功能:用于指定正则匹配的模式。
注意:
未来版本即将废弃,使用 RegexFlag 替代。
父类型:
init()
public init()
功能:创建一个 RegexOption 实例, 匹配模式为普通模式(NORMAL)。
func ignoreCase()
public func ignoreCase(): RegexOption
功能:修改 RegexOption,修改匹配模式为忽略大小写(IGNORECASE)。
返回值:
- RegexOption - 修改后的 RegexOption。
func multiLine()
public func multiLine(): RegexOption
功能:修改 RegexOption,修改匹配模式为多行文本模式(MULTILINE)。
返回值:
- RegexOption - 修改后的 RegexOption。
func toString()
public func toString(): String
功能:获取 RegexOption 当前表示的正则匹配模式。
返回值:
- String - 正则匹配模式。
枚举
enum RegexFlag
public enum RegexFlag {
| IgnoreCase
| MultiLine
| Unicode
}
功能:用于指定正则匹配的模式。
IgnoreCase
IgnoreCase
功能:指定匹配模式为忽略大小写。
MultiLine
MultiLine
功能:指定匹配模式为多行文本模式。
Unicode
Unicode
功能:指定匹配模式支持 Unicode。
结构体
struct MatchData
public struct MatchData {}
功能:存储正则表达式匹配结果,并提供对正则匹配结果进行查询的函数。
func groupCount()
public func groupCount(): Int64
功能:获取捕获组的个数。
返回值:
- Int64 - 捕获组的个数。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
let iter = r.lazyFindAll("2024-10-24&2025-01-01", group: true)
while (true) {
match (iter.next()) {
case Some(md) => println("# found: `${md.matchString()}` and groupCount: ${md.groupCount()}")
case None => break
}
}
}
运行结果:
# found: `2024-10-24` and groupCount: 3
# found: `2025-01-01` and groupCount: 3
func groupNumber() (deprecated)
public func groupNumber(): Int64
功能:获取捕获组的个数。
注意:
未来版本即将废弃,使用 groupCount() 替代。
返回值:
- Int64 - 捕获组的个数。
func matchPosition()
public func matchPosition(): Position
功能:获取上一次匹配到的子字符串在输入字符串中起始位置和末尾位置的索引。
返回值:
- Position - 匹配结果位置信息。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
let iter = r.lazyFindAll("2024-10-24&2025-01-01", group: true)
while (true) {
match (iter.next()) {
case Some(md) =>
println("# found: ${md.matchString()} and groupCount: ${md.groupCount()}")
let pos = md.matchPosition(0)
println("pos: [${pos.start}, ${pos.end}]")
case None => break
}
}
}
运行结果:
# found: 2024-10-24 and groupCount: 3
pos: [0, 10]
# found: 2025-01-01 and groupCount: 3
pos: [11, 21]
func matchPosition(Int64)
public func matchPosition(group: Int64): Position
功能:根据给定的索引获取上一次匹配中该捕获组匹配到的子字符串在输入字符串中的位置信息。
参数:
- group: Int64 - 指定组。
返回值:
- Position - 对应捕获组的位置信息。
异常:
- IllegalArgumentException - 当未开启捕获组提取,或 group 小于 0 或者大于 groupCount 时,抛出异常。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
let iter = r.lazyFindAll("2024-10-24&2025-01-01", group: true)
while (true) {
match (iter.next()) {
case Some(md) =>
println("# found: ${md.matchString()} and groupCount: ${md.groupCount()}")
/* 月份的捕获组索引为 2 */
let pos = md.matchPosition(2)
println("# month: [${pos.start}, ${pos.end}]")
case None => break
}
}
}
运行结果:
# found: 2024-10-24 and groupCount: 3
# month: [5, 7]
# found: 2025-01-01 and groupCount: 3
# month: [16, 18]
func matchPosition(String)
public func matchPosition(group: String): Position
功能:根据给定的命名捕获组名称取上一次匹配中该捕获组匹配到的子字符串在输入字符串中的位置信息。
参数:
- group: String - 指定命名捕获组的名称。
返回值:
- Position - 对应捕获组的位置信息。
异常:
- IllegalArgumentException - 当未开启捕获组提取,或 捕获组名称不存在,抛出异常。
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
let iter = r.lazyFindAll("2024-10-24&2025-01-01", group: true)
while (true) {
match (iter.next()) {
case Some(md) =>
println("# found: ${md.matchString()} and groupCount: ${md.groupCount()}")
let pos = md.matchPosition("year")
println("year: [${pos.start}, ${pos.end}]")
case None => break
}
}
}
运行结果:
# found: 2024-10-24 and groupCount: 3
year: [0, 4]
# found: 2025-01-01 and groupCount: 3
year: [11, 15]
func matchString()
public func matchString(): String
功能:获取上一次匹配到的子字符串,结果与调用 matchString(0) 相同。
返回值:
- String - 匹配到的子字符串。
示例:
import std.regex.*
main(): Unit {
let r1 = Regex("ab")
let r2 = Regex("ab", IgnoreCase)
match (r1.find("aB")) {
case Some(r) => println(r.matchString())
case None => println("None")
}
match (r2.find("aB")) {
case Some(r) => println(r.matchString())
case None => println("None")
}
}
运行结果:
None
aB
func matchString(Int64)
public func matchString(group: Int64): String
功能:根据给定的索引获取上一次匹配中该捕获组匹配到的子字符串。
捕获组的索引从 1 开始,索引为 0 表示获取整个正则表达式的匹配结果。
参数:
- group: Int64 - 指定组。
返回值:
- String - 匹配到的子字符串。
异常:
- IllegalArgumentException - 当未开启捕获组提取,或 group 小于 0 或者大于 groupCount 时,抛出异常。
func matchString(String)
public func matchString(group: String): String
功能:根据给定的命名捕获组名称获取上一次匹配中该捕获组匹配到的子字符串。
参数:
- group: String - 指定命名捕获组的名称。
返回值:
- String - 匹配到的子字符串。
异常:
- IllegalArgumentException - 当未开启捕获组提取,或捕获组名称不存在,抛出异常。
struct Position
public struct Position {
public let end: Int64
public let start: Int64
}
功能:用来存储位置信息,表示的是一个前闭后开区间。
let end
public let end: Int64
功能:区间结束位置。
类型:Int64
let start
public let start: Int64
功能:区间开始位置。
类型:Int64
异常
class RegexException
public class RegexException <: Exception {
public init()
public init(message: String)
}
功能:提供正则的异常处理。
父类型:
init()
public init()
功能:创建 RegexException 实例。
init(String)
public init(message: String)
功能:根据异常信息创建 RegexException 实例。
参数:
- message: String - 异常提示信息。
regex 示例
Regex 匹配大小写
示例:
import std.regex.*
main(): Unit {
let r1 = Regex("ab")
let r2 = Regex("ab", IgnoreCase)
match (r1.find("aB")) {
case Some(r) => println(r.matchString())
case None => println("None")
}
match (r2.find("aB")) {
case Some(r) => println(r.matchString())
case None => println("None")
}
}
运行结果:
None
aB
Regex 匹配多行
示例:
import std.regex.*
main(): Unit {
let rule = ##"^(\w+)\s(\d+)*$"##
let input: String = """
Joe 164
Sam 208
Allison 211
Gwen 171
"""
let r = Regex(rule, MultiLine)
var arr = r.findAll(input)
for (md in arr) {
println(md.matchString())
}
}
运行结果:
Joe 164
Sam 208
Allison 211
Gwen 171
Regex 匹配 Unicode
示例:
import std.regex.*
main(): Unit {
let printMatchData: (MatchData) -> Unit = {
md =>
println("found: `${md.matchString()}`")
let pos = md.matchPosition()
println("[${pos.start}, ${pos.end})")
}
let unicodePattern = "(?:[\u{2460}\u{2461}\u{2462}\u{2463}\u{2464}\u{2465}\u{2466}\u{2467}\u{2468}]{2,4})"
let unicodeInput = "\u{2460}\u{2461} \u{2464}\u{2465}"
println("#Unicode disabled: ")
try {
for (md in Regex(unicodePattern).lazyFindAll(unicodeInput)) {
printMatchData(md)
}
} catch (e: IllegalArgumentException) {
println(e)
}
println("\n#Unicode enabled: ")
for (md in Regex(unicodePattern, Unicode).lazyFindAll(unicodeInput)) {
printMatchData(md)
}
println("\n#Unicode enabled with literals: ")
let unicodeLiteralPattern = "(?:[①②③④⑤⑥⑦⑧⑨]{2,4})"
let unicodeLiteralInput = "①② ⑤⑥"
for (md in Regex(unicodeLiteralPattern, Unicode).lazyFindAll(unicodeLiteralInput)) {
printMatchData(md)
}
}
运行结果:
#Unicode disabled:
IllegalArgumentException: Invalid utf8 byte sequence.
#Unicode enabled:
found: `①②`
[0, 6)
found: `⑤⑥`
[8, 14)
#Unicode enabled with literals:
found: `①②`
[0, 6)
found: `⑤⑥`
[8, 14)
Regex 和 MatchData 的使用
示例:
import std.regex.*
main(): Unit {
let r = Regex(#"a\wa"#)
for (md in r.findAll("1aba12ada555")) {
println(md.matchString())
let pos = md.matchPosition()
println("[${pos.start}, ${pos.end})")
}
}
运行结果:
aba
[1, 4)
ada
[6, 9)
Regex 中 replace/replaceAll 函数
示例:
import std.regex.*
main(): Unit {
let r = Regex("\\d")
/* 用 X 替换第一个数字 */
println(r.replace("a1b1c2d3f4", "X"))
/* 用 X 替换 index 为 2 之后出现的第一个数字 */
println(r.replace("a1b1c2d3f4", "X", 2))
/* 用 X 替换所有数字 */
println(r.replaceAll("a1b1c2d3f4", "X"))
/* 用 X 替换 index 为 2 之后出现的所有数字 */
println(r.replaceAll("a1b1c2d3f4", "X", 2))
/* 用 X 替换所有数字 */
println(r.replaceAll("a1b1c2d3f4", "X", -1))
}
运行结果:
aXb1c2d3f4
a1bXc2d3f4
aXbXcXdXfX
aXbXc2d3f4
aXbXcXdXfX
MatchData 中捕获组的使用
示例:
import std.regex.*
main(): Unit {
var r = Regex(#"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"#)
for (md in r.lazyFindAll("2024-10-24&2025-01-01", group: true)) {
println("# found: `${md.matchString()}` and groupCount: ${md.groupCount()}")
if (md.groupCount() > 0) {
for (i in 0..=md.groupCount()) {
println("group[${i}] : ${md.matchString(i)}")
let pos = md.matchPosition(i)
println("position : [${pos.start}, ${pos.end})")
}
}
for ((name, index) in r.getNamedGroups()) {
let pos = md.matchPosition(name)
println("${name} 是第 ${index} 组, position: [${pos.start}, ${pos.end}), 捕获: ${md.matchString(name)}")
}
}
}
运行结果:
# found: `2024-10-24` and groupCount: 3
group[0] : 2024-10-24
position : [0, 10)
group[1] : 2024
position : [0, 4)
group[2] : 10
position : [5, 7)
group[3] : 24
position : [8, 10)
day 是第 3 组, position: [8, 10), 捕获: 24
month 是第 2 组, position: [5, 7), 捕获: 10
year 是第 1 组, position: [0, 4), 捕获: 2024
# found: `2025-01-01` and groupCount: 3
group[0] : 2025-01-01
position : [11, 21)
group[1] : 2025
position : [11, 15)
group[2] : 01
position : [16, 18)
group[3] : 01
position : [19, 21)
day 是第 3 组, position: [19, 21), 捕获: 01
month 是第 2 组, position: [16, 18), 捕获: 01
year 是第 1 组, position: [11, 15), 捕获: 2025
std.runtime
功能介绍
runtime 包的作用是与程序的运行时环境进行交互,提供了一系列函数和变量,用于控制、管理和监视程序的执行。
CangJie 语言使用自动垃圾回收机制来管理内存,runtime 包提供了手动触发垃圾回收、设置垃圾回收的阈值、获取内存统计信息等功能,用于对垃圾回收进行调控和监测。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| dumpHeapData(Path) | 生成堆内存快照信息,写入指定路径的文件。 |
| GC(Bool) (deprecated) | 执行 GC。 |
| gc(Bool) | 执行 GC。 |
| getAllocatedHeapSize | 获取仓颉堆已被使用的大小,单位为 byte。 |
| getBlockingThreadCount | 获取阻塞的仓颉线程数。 |
| getGCCount | 获取触发 GC 的次数。 |
| getGCFreedSize | 获取触发 GC 后,成功回收的内存,单位为 byte。 |
| getGCTime | 获取触发的 GC 总耗时,单位为 us。 |
| getMaxHeapSize | 获取仓颉堆可以使用的最大值,单位为 byte。 |
| getNativeThreadCount | 获取物理线程数。 |
| getProcessorCount | 获取处理器数量。 |
| getThreadCount | 获取仓颉当前的线程数量。 |
| getUsedHeapSize | 在 Linux 平台下获取仓颉堆实际占用的物理内存大小, 单位为 byte。在 Windows 及 macOs 平台下获取仓颉进程实际占用的物理内存大小, 单位为 byte。 |
| SetGCThreshold(UInt64) (deprecated) | 修改用户期望触发 GC 的内存阈值,当仓颉堆大小超过该值时,触发 GC,单位为 KB。 |
| setGCThreshold(UInt64) | 修改用户期望触发 GC 的内存阈值,当仓颉堆大小超过该值时,触发 GC,单位为 KB。 |
| startCPUProfiling | 启动 CPU profiler 跟踪。 |
| stopCPUProfiling(Path) | 停止CPU profiler 跟踪,并将记录写入指定路径的文件。 |
结构体
| 结构体名 | 功能 |
|---|---|
| MemoryInfo (deprecated) | 提供获取一些堆内存统计数据的接口。 |
| ProcessorInfo (deprecated) | 提供获取一些处理器信息的接口。 |
| ThreadInfo (deprecated) | 提供获取一些仓颉线程统计数据的接口。 |
函数
func dumpHeapData(Path)
public func dumpHeapData(path: Path): Unit
功能:生成堆内存快照信息,写入指定路径的文件。
参数:
- path: Path - 生成堆内存快照文件的文件路径。
异常:
- MemoryInfoException - 生成堆内存快照失败时,抛出此异常。
func GC(Bool) (deprecated)
public func GC(heavy!: Bool = false): Unit
功能:执行 GC。
注意:
未来版本即将废弃,使用gc 替代。
参数:
func gc(Bool)
public func gc(heavy!: Bool = false): Unit
功能:执行 gc。
参数:
func getAllocatedHeapSize()
public func getAllocatedHeapSize(): Int64
功能:获取仓颉堆已被使用的大小,单位为 byte。
返回值:
- Int64 - 仓颉堆已被使用的大小,单位为 byte。
func getBlockingThreadCount()
public func getBlockingThreadCount(): Int64
功能:获取阻塞的仓颉线程数。
返回值:
- Int64 - 阻塞的仓颉线程数。
func getGCCount()
public func getGCCount(): Int64
功能:获取触发 GC 的次数。
返回值:
- Int64 - 触发 GC 的次数。
func getGCFreedSize()
public func getGCFreedSize(): Int64
功能:获取触发 GC 后,成功回收的内存,单位为 byte。
返回值:
- Int64 - 触发 GC 后,成功回收的内存,单位为 byte。
func getGCTime()
public func getGCTime(): Int64
功能:获取触发的 GC 总耗时,单位为 us。
返回值:
- Int64 - 触发的 GC 总耗时,单位为 us。
func getMaxHeapSize()
public func getMaxHeapSize(): Int64
功能:获取仓颉堆可以使用的最大值,单位为 byte。
返回值:
- Int64 - 仓颉堆可以使用的最大值,单位为 byte。
func getNativeThreadCount()
public func getNativeThreadCount(): Int64
功能:获取物理线程数。
返回值:
- Int64 - 物理线程数。
func getProcessorCount()
public func getProcessorCount(): Int64
功能:获取处理器数量。
返回值:
- Int64 - 处理器数量。
func getThreadCount()
public func getThreadCount(): Int64
功能:获取仓颉当前的线程数量。
返回值:
- Int64 - 仓颉当前的线程数量。
func getUsedHeapSize()
public func getUsedHeapSize(): Int64
功能:在 Linux 平台下获取仓颉堆实际占用的物理内存大小, 单位为 byte。在 Windows 及 macOs 平台下获取仓颉进程实际占用的物理内存大小, 单位为 byte。
返回值:
- Int64 - 仓颉堆或仓颉进程实际占用的物理内存大小,单位为 byte。
func SetGCThreshold(UInt64) (deprecated)
public func SetGCThreshold(value: UInt64): Unit
功能:修改用户期望触发 GC 的内存阈值,当仓颉堆大小超过该值时,触发 GC,单位为 KB。
注意:
未来版本即将废弃,使用setGCThreshold(UInt64) 替代。
参数:
示例: 设置用户期望的 GC 的内存阈值为 2MB。
import std.runtime.*
main() {
SetGCThreshold(2048)
}
func setGCThreshold(UInt64)
public func setGCThreshold(value: UInt64): Unit
功能:修改用户期望触发 gc 的内存阈值,当仓颉堆大小超过该值时,触发 gc,单位为 KB。
参数:
示例: 设置用户期望的 gc 的内存阈值为 2MB。
import std.runtime.*
main() {
setGCThreshold(2048)
}
func startCPUProfiling()
public func startCPUProfiling(): Unit
功能:启动 CPU profiler 跟踪。
异常:
- ProfilingInfoException - startCPUProfiling与stopCPUProfiling(Path)两个函数必须一一对应。若调用了startCPUProfiling后,没有调用stopCPUProfiling(Path),而是又调用了startCPUProfiling则抛出异常。
func stopCPUProfiling(Path)
public func stopCPUProfiling(path: Path): Unit
功能:停止CPU profiler 跟踪,并将记录写入指定路径的文件。
参数:
- path: Path - 生成记录文件的文件路径。
异常:
- ProfilingInfoException - startCPUProfiling与stopCPUProfiling(Path)两个函数必须一一对应。若没有调用了startCPUProfiling,直接调用stopCPUProfiling(Path)则抛出异常。
结构体
struct MemoryInfo (deprecated)
public struct MemoryInfo
功能:提供获取一些堆内存统计数据的接口。
注意:
未来版本即将废弃,使用全局函数getAllocatedHeapSize,getUsedHeapSize,getMaxHeapSize替代相关静态属性成员。
static prop allocatedHeapSize
public static prop allocatedHeapSize: Int64
功能:获取仓颉堆已被使用的大小,单位为 byte。
类型:Int64
static prop heapPhysicalMemory
public static prop heapPhysicalMemory: Int64
功能:在 Linux 平台下获取仓颉堆实际占用的物理内存大小, 单位为 byte。在 Windows 及 macOs 平台下获取仓颉进程实际占用的物理内存大小, 单位为 byte。
类型:Int64
static prop maxHeapSize
public static prop maxHeapSize: Int64
功能:获取仓颉堆可以使用的最大值,单位为 byte。
实例:
import std.runtime.*
main() {
println(MemoryInfo.maxHeapSize)
}
运行结果(以实际环境为准):
268435456
类型:Int64
struct ProcessorInfo (deprecated)
public struct ProcessorInfo
功能:提供获取一些处理器信息的接口。
注意:
未来版本即将废弃,使用getProcessorCount替代相关静态属性成员。
static prop processorCount
public static prop processorCount: Int64
功能:获取处理器数量。
类型:Int64
struct ThreadInfo (deprecated)
public struct ThreadInfo
功能:提供获取一些仓颉线程统计数据的接口。
注意:
未来版本即将废弃,使用getBlockingThreadCount,getNativeThreadCount, getThreadCount 替代相关静态属性成员。
static prop blockingThreadCount
public static prop blockingThreadCount: Int64
功能:获取阻塞的仓颉线程数。
类型:Int64
static prop nativeThreadCount
public static prop nativeThreadCount: Int64
功能:获取物理线程数。
类型:Int64
static prop threadCount
public static prop threadCount: Int64
功能:获取仓颉当前的线程数量。
类型:Int64
std.sort
功能介绍
sort 包提供数组类型的排序函数。
根据排序方式,本包提供了稳定排序和不稳定排序两套实现。稳定排序是指,相等元素的前后顺序在排序前后保持不变。反之,不稳定排序是指,不保证相等元素的前后顺序在排序前后保持一致。
本包提供了一组带泛型的排序函数,可用来对元素为 T 类型的数组进行排序。排序必然要求元素是可以比较的,因此,这组函数进一步分为两类:1、要求 T 实现 Comparable<T> 接口,2、将 T 相关的比较函数作为参数传入函数。
此外,本包提供辅助接口 SortByExtension(未来版本即将废弃) 和 SortExtension(未来版本即将废弃),可用来为其他类型实现与排序相关的函数。
API列表
函数
接口
| 接口名 | 功能 |
|---|---|
| SortByExtension (deprecated) | 此接口作为排序相关的辅助接口,内部为空。 |
| SortExtension (deprecated) | 此接口作为排序相关的辅助接口,内部为空。 |
函数
func sort<T>(Array<T>, Bool, Bool) where T <: Comparable<T>
public func sort<T>(data: Array<T>, stable!: Bool = false, descending!: Bool = false): Unit where T <: Comparable<T>
功能:对数组进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
参数:
示例:
import std.sort.*
class Rectangle <: Comparable<Rectangle> & ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func compare(r: Rectangle) {
let tValue: Int64 = this.width * this.height
let rValue: Int64 = r.width * r.height
if (tValue > rValue) {
return Ordering.GT
} else if (tValue == rValue) {
return Ordering.EQ
} else {
return Ordering.LT
}
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照面积降序排序 */
var arr = [Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)]
sort<Rectangle>(arr, stable: true, descending: true)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T>(Array<T>, (T, T) -> Ordering, Bool, Bool)
public func sort<T>(data: Array<T>, by!: (T, T) -> Ordering, stable!: Bool = false, descending!: Bool = false): Unit
功能:对数组按照比较函数进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入自定义的比较函数 by。如果 by 的返回值为 Ordering.GT,排序后 t1 在 t2 后;如果 by 的返回值为 Ordering.LT,排序后 t1 在 t2 前;如果 by 的返回值为 Ordering.EQ,排序后 t1 与 t2 的位置与是否是稳定排序有关,稳定则较排序前保持不变,否则有可能发生改变。
参数:
- data: Array<T> - 需要排序的数组。
- by!: (T, T) ->Ordering - 传入的比较函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
示例:
import std.sort.*
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照面积降序排序 */
var arr = [Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)]
sort<Rectangle>(
arr,
by: {
r1: Rectangle, r2: Rectangle =>
let r1Value: Int64 = r1.width * r1.height
let r2Value: Int64 = r2.width * r2.height
if (r1Value > r2Value) {
return Ordering.GT
} else if (r1Value == r2Value) {
return Ordering.EQ
} else {
return Ordering.LT
}
},
stable: true,
descending: true
)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T>(Array<T>, (T, T) -> Bool, Bool, Bool)
public func sort<T>(data: Array<T>, lessThan!: (T, T) -> Bool, stable!: Bool = false, descending!: Bool = false): Unit
功能:对数组按照比较函数进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入自定义的比较函数 lessThan。如果 lessThan 的返回值为 true,排序后 t1 在 t2 前;如果 lessThan 的返回值为false,又会分为两种情况,如果 t1 和 t2 不相等,排序后 t1 在 t2 后,如果相等,t1 与 t2 的前后位置关系与是否是稳定排序有关,稳定则较排序前保持不变,否则有可能发生改变。
参数:
- data: Array<T> - 需要排序的数组。
- lessThan!: (T, T) ->Bool - 传入的比较函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
示例:
import std.sort.*
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照面积降序排序 */
var arr = [Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)]
sort<Rectangle>(
arr,
lessThan: {
r1: Rectangle, r2: Rectangle =>
let r1Value: Int64 = r1.width * r1.height
let r2Value: Int64 = r2.width * r2.height
if (r1Value < r2Value) {
return true
} else {
return false
}
},
stable: true,
descending: true
)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T, K>(Array<T>, (T) -> K, Bool, Bool) where K <: Comparable<K>
public func sort<T, K>(data: Array<T>, key!: (T) -> K, stable!: Bool = false, descending!: Bool = false): Unit where K <: Comparable<K>
功能:对数组按照指定的键(键与键之间可比较)进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入数组元素到键的映射函数。
参数:
- data: Array<T> - 需要排序的数组。
- key!: (T) -> K - 元素到键的映射函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
示例:
import std.sort.*
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照宽降序排序 */
var arr = [Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)]
sort<Rectangle, Int64>(
arr,
key: {
r: Rectangle => return r.width
},
stable: true,
descending: true
)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T>(ArrayList<T>, Bool, Bool) where T <: Comparable<T>
public func sort<T>(data: ArrayList<T>, stable!: Bool = false, descending!: Bool = false): Unit where T <: Comparable<T>
功能:对 ArrayList 进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
参数:
- data: ArrayList<T> - 需要排序的
ArrayList。 - stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
示例:
import std.sort.*
import std.collection.*
class Rectangle <: Comparable<Rectangle> & ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func compare(r: Rectangle) {
let tValue: Int64 = this.width * this.height
let rValue: Int64 = r.width * r.height
if (tValue > rValue) {
return Ordering.GT
} else if (tValue == rValue) {
return Ordering.EQ
} else {
return Ordering.LT
}
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照面积降序排序 */
var arr = ArrayList<Rectangle>([Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)])
sort<Rectangle>(arr, stable: true, descending: true)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T>(ArrayList<T>, (T, T) -> Ordering, Bool, Bool)
public func sort<T>(data: ArrayList<T>, by!: (T, T) -> Ordering, stable!: Bool = false, descending!: Bool = false): Unit
功能:对 ArrayList 按照比较函数进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入自定义的比较函数 by。如果 by 的返回值为 Ordering.GT,排序后 t1 在 t2 后;如果 by 的返回值为 Ordering.LT,排序后 t1 在 t2 前;如果 by 的返回值为 Ordering.EQ,排序后 t1 与 t2 的位置与是否是稳定排序有关,稳定则较排序前保持不变,否则有可能发生改变。
参数:
- data: ArrayList<T> - 需要排序的
ArrayList。 - by!: (T, T) ->Ordering - 传入的比较函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
示例:
import std.sort.*
import std.collection.*
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照面积降序排序 */
var arr = ArrayList<Rectangle>([Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)])
sort<Rectangle>(
arr,
by: {
r1: Rectangle, r2: Rectangle =>
let r1Value: Int64 = r1.width * r1.height
let r2Value: Int64 = r2.width * r2.height
if (r1Value > r2Value) {
return Ordering.GT
} else if (r1Value == r2Value) {
return Ordering.EQ
} else {
return Ordering.LT
}
},
stable: true,
descending: true
)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T>(ArrayList<T>, (T, T) -> Bool, Bool, Bool)
public func sort<T>(data: ArrayList<T>, lessThan!: (T, T) -> Bool, stable!: Bool = false, descending!: Bool = false): Unit
功能:对 ArrayList 按照比较函数进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入自定义的比较函数 lessThan。如果 lessThan 的返回值为 true,排序后 t1 在 t2 前;如果 lessThan 的返回值为false,又会分为两种情况,如果 t1 和 t2 不相等,排序后 t1 在 t2 后,如果相等,t1 与 t2 的前后位置关系与是否是稳定排序有关,稳定则较排序前保持不变,否则有可能发生改变。
参数:
- data: ArrayList<T> - 需要排序的
ArrayList。 - lessThan!: (T, T) ->Bool - 传入的比较函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
示例:
import std.sort.*
import std.collection.*
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照面积降序排序 */
var arr = ArrayList<Rectangle>([Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)])
sort<Rectangle>(
arr,
lessThan: {
r1: Rectangle, r2: Rectangle =>
let r1Value: Int64 = r1.width * r1.height
let r2Value: Int64 = r2.width * r2.height
if (r1Value < r2Value) {
return true
} else {
return false
}
},
stable: true,
descending: true
)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T, K>(ArrayList<T>, (T) -> K, Bool, Bool) where K <: Comparable<K>
public func sort<T, K>(data: ArrayList<T>, key!: (T) -> K, stable!: Bool = false, descending!: Bool = false): Unit where K <: Comparable<K>
功能:对 ArrayList 按照指定的键(键与键之间可比较)进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入 ArrayList 元素到键的映射函数。
参数:
- data: ArrayList<T> - 需要排序的
ArrayList。 - key!: (T) -> K - 元素到键的映射函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
示例:
import std.sort.*
import std.collection.*
class Rectangle <: ToString {
var width: Int64
var height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func toString(): String {
return "#width: ${this.width}, height: ${this.height}"
}
}
main() {
/* 按照宽降序排序 */
var arr = ArrayList<Rectangle>([Rectangle(4, 8), Rectangle(6, 7), Rectangle(2, 6)])
sort<Rectangle, Int64>(
arr,
key: {
r: Rectangle => return r.width
},
stable: true,
descending: true
)
println(arr)
return 0
}
运行结果:
[#width: 6, height: 7, #width: 4, height: 8, #width: 2, height: 6]
func sort<T>(List<T>, Bool, Bool) where T <: Comparable<T>
public func sort<T>(data: List<T>, stable!: Bool = false, descending!: Bool = false): Unit where T <: Comparable<T>
功能:对 List 进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
参数:
func sort<T>(List<T>, (T, T) -> Ordering, Bool, Bool)
public func sort<T>(data: List<T>, by!: (T, T) -> Ordering, stable!: Bool = false, descending!: Bool = false): Unit
功能:对 List 按照比较函数进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入自定义的比较函数 by。如果 by 的返回值为 Ordering.GT,排序后 t1 在 t2 后;如果 by 的返回值为 Ordering.LT,排序后 t1 在 t2 前;如果 by 的返回值为 Ordering.EQ,排序后 t1 与 t2 的位置与是否是稳定排序有关,稳定则较排序前保持不变,否则有可能发生改变。
参数:
- data: List<T> - 需要排序的
List。 - by!: (T, T) ->Ordering - 传入的比较函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
func sort<T>(List<T>, (T, T) -> Bool, Bool, Bool)
public func sort<T>(data: List<T>, lessThan!: (T, T) -> Bool, stable!: Bool = false, descending!: Bool = false): Unit
功能:对 List 按照比较函数进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入自定义的比较函数 lessThan。如果 lessThan 的返回值为 true,排序后 t1 在 t2 前;如果 lessThan 的返回值为false,又会分为两种情况,如果 t1 和 t2 不相等,排序后 t1 在 t2 后,如果相等,t1 与 t2 的前后位置关系与是否是稳定排序有关,稳定则较排序前保持不变,否则有可能发生改变。
参数:
- data: List<T> - 需要排序的
List。 - lessThan!: (T, T) ->Bool - 传入的比较函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
func sort<T, K>(List<T>, (T) -> K, Bool, Bool) where K <: Comparable<K>
public func sort<T, K>(data: List<T>, key!: (T) -> K, stable!: Bool = false, descending!: Bool = false): Unit where K <: Comparable<K>
功能:对 List 按照指定的键(键与键之间可比较)进行排序。可根据入参指定是否要进行稳定排序,是升序还是降序。
用户需传入 List 元素到键的映射函数。
参数:
- data: List<T> - 需要排序的
List。 - key!: (T) -> K - 元素到键的映射函数。
- stable!: Bool - 是否使用稳定排序,默认为否。
- descending!: Bool - 是否使用降序排序,默认为否。
func stableSort<T>(Array<T>) where T <: Comparable<T> (deprecated)
public func stableSort<T>(data: Array<T>): Unit where T <: Comparable<T>
功能:对数组进行稳定升序排序。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
- data: Array<T> - 需要排序的数组。
func stableSort<T>(Array<T>, (T, T) -> Ordering) (deprecated)
public func stableSort<T>(data: Array<T>, comparator: (T, T) -> Ordering): Unit
功能:对数组进行稳定排序。
用户可传入自定义的比较函数 comparator,如果 comparator 的返回值为 Ordering.GT,排序后 t1 在 t2 后;如果 comparator 的返回值为 Ordering.LT,排序后 t1 在 t2 前;如果 comparator 的返回值为 Ordering.EQ,排序后 t1 与 t2 的位置较排序前保持不变。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
func unstableSort<T>(Array<T>) where T <: Comparable<T> (deprecated)
public func unstableSort<T>(data: Array<T>): Unit where T <: Comparable<T>
功能:对数组进行不稳定升序排序。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
- data: Array<T> - 需要排序的数组。
func unstableSort<T>(Array<T>, (T, T) -> Ordering) (deprecated)
public func unstableSort<T>(data: Array<T>, comparator: (T, T) -> Ordering): Unit
功能:对数组进行不稳定排序。
用户可传入自定义的比较函数 comparator,如果 comparator 的返回值为 Ordering.GT,排序后 t1 在 t2 后;如果 comparator 的返回值为 Ordering.LT,排序后 t1 在 t2 前;如果 comparator 的返回值为 Ordering.EQ,排序后 t1 与 t2 的位置较排序前保持不变。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
接口
interface SortByExtension<T> (deprecated)
public interface SortByExtension<T> {
func sortBy(comparator!: (T, T) -> Ordering): Unit
func sortBy(stable!: Bool, comparator!: (T, T) -> Ordering): Unit
}
功能:此接口作为排序相关的辅助接口,通过传入的比较函数,根据其返回值 Ordering 类型的结果,可对 T 进行自定义排序。
注意:
未来版本即将废弃。
func sortBy((T, T) -> Ordering) (deprecated)
func sortBy(comparator!: (T, T) -> Ordering): Unit
功能:通过传入的比较函数,根据其返回值 Ordering 类型的结果,可对 T 进行自定义排序。
注意:
未来版本即将废弃。
参数:
- comparator!: (T, T) ->Ordering - 用户传入的比较函数。
func sortBy(Bool, (T, T) -> Ordering) (deprecated)
func sortBy(stable!: Bool, comparator!: (T, T) -> Ordering): Unit
功能:通过传入的比较函数,根据其返回值 Ordering 类型的结果和稳定排序标志位,可对 T 进行自定义排序。
注意:
未来版本即将废弃。
参数:
注意:
未来版本即将废弃。
extend<T> Array<T> <: SortByExtension<T> (deprecated)
extend<T> Array<T> <: SortByExtension<T>
功能:此扩展用于实现 Array 的 sortBy 函数。
注意:
未来版本即将废弃。
父类型:
func sortBy((T, T) -> Ordering) (deprecated)
public func sortBy(comparator!: (T, T) -> Ordering): Unit
功能:通过传入的比较函数,根据其返回值 Ordering 类型的结果,可对数组进行自定义排序。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
- comparator!: (T, T) ->Ordering - 用户传入的比较函数,如,comparator: (t1: T, t2: T) -> Ordering,如果
comparator的返回值为 Ordering.GT,排序后t1在t2后;如果comparator的返回值为 Ordering.LT,排序后t1在t2前;如果comparator的返回值为 Ordering.EQ,且为稳定排序那么t1与t2的位置较排序前保持不变; 如果comparator的返回值为 Ordering.EQ,且为不稳定排序,那么t1,t2顺序不确定。
func sortBy(Bool, (T, T) -> Ordering) (deprecated)
public func sortBy(stable!: Bool, comparator!: (T, T) -> Ordering): Unit
功能:通过传入的比较函数,根据其返回值 Ordering 类型的结果,可对数组进行自定义排序。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
- stable!: Bool - 是否使用稳定排序。
- comparator!: (T, T) ->Ordering - 用户传入的比较函数,如,comparator: (t1: T, t2: T) -> Ordering,如果
comparator的返回值为 Ordering.GT,排序后t1在t2后;如果comparator的返回值为 Ordering.LT,排序后t1在t2前;如果comparator的返回值为 Ordering.EQ,且为稳定排序那么t1与t2的位置较排序前保持不变; 如果comparator的返回值为 Ordering.EQ,且为不稳定排序,那么t1,t2顺序不确定。
interface SortExtension (deprecated)
public interface SortExtension {
func sort(): Unit
func sort(stable!: Bool): Unit
func sortDescending(): Unit
func sortDescending(stable!: Bool): Unit
}
功能:此接口作为排序相关的辅助接口。
func sort() (deprecated)
func sort(): Unit
功能:实现对应类型的排序。
注意:
未来版本即将废弃。
func sort(Bool) (deprecated)
func sort(stable!: Bool): Unit
功能:依据传入的参数,实现对应类型的稳定或非稳定排序。
注意:
未来版本即将废弃。
参数:
- stable!: Bool - 是否使用稳定排序。
func sortDescending() (deprecated)
func sortDescending(): Unit
功能:实现对应类型的降序方式排序。
注意:
未来版本即将废弃。
func sortDescending(Bool) (deprecated)
func sortDescending(stable!: Bool): Unit
功能:依据传入的参数,实现对应类型的稳定或非稳定降序排序。
参数:
- stable!: Bool - 是否使用稳定排序。
注意:
未来版本即将废弃。
extend<T> Array<T> <: SortExtension where T <: Comparable<T> (deprecated)
extend<T> Array<T> <: SortExtension where T <: Comparable<T>
功能:此扩展用于实现 Array 的 sort/sortDescending 函数。
注意:
未来版本即将废弃。
父类型:
func sort() (deprecated)
public func sort(): Unit
功能:以升序的方式非稳定排序 Array。
注意:
未来版本即将废弃,使用 sort 替代。
func sort(Bool) (deprecated)
public func sort(stable!: Bool): Unit
功能:以升序的方式排序 Array。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
- stable!: Bool - 是否使用稳定排序。
func sortDescending() (deprecated)
public func sortDescending(): Unit
功能:以降序的方式排序 Array。
注意:
未来版本即将废弃,使用 sort 替代。
func sortDescending(Bool) (deprecated)
public func sortDescending(stable!: Bool): Unit
功能:以降序的方式排序 Array。
注意:
未来版本即将废弃,使用 sort 替代。
参数:
- stable!: Bool - 是否使用稳定排序。
对 Array 和 List 进行排序
对 Array 进行排序
创建无序 Array,并对这个 Array 进行排序。
示例:
import std.sort.*
class Student <: ToString {
public var name: String
public var age: Int64
public init(name: String, age: Int64) {
this.name = name
this.age = age
}
public func toString(): String {
return "{name: ${name} age: ${age}}"
}
}
main() {
/* 对 Int64 数组升序排序 */
var a = [1, 3, 5, 2, 4]
sort(a)
println(a)
/* 按照年龄升序排序 */
var b = [Student("A", 8), Student("B", 7), Student("C", 3), Student("D", 4), Student("E", 6)]
let comparator = {l: Student, r: Student => l.age.compare(r.age)}
sort(b, by: comparator)
println(b)
/* 按照年龄降序排序 */
var c = [Student("A", 8), Student("B", 7), Student("C", 3), Student("D", 4), Student("E", 6)]
let lessThan = {l: Student, r: Student => l.age < r.age}
sort(c, lessThan: lessThan, descending: true)
println(c)
/* 按照年龄升序排序,并且是稳定排序 */
var d = [Student("A", 8), Student("B", 7), Student("C", 7), Student("D", 4), Student("E", 7)]
let key = {i: Student => i.age}
sort(d, key: key, stable: true)
println(d)
return 0
}
运行结果:
[1, 2, 3, 4, 5]
[{name: C age: 3}, {name: D age: 4}, {name: E age: 6}, {name: B age: 7}, {name: A age: 8}]
[{name: A age: 8}, {name: B age: 7}, {name: E age: 6}, {name: D age: 4}, {name: C age: 3}]
[{name: D age: 4}, {name: B age: 7}, {name: C age: 7}, {name: E age: 7}, {name: A age: 8}]
对 List 进行排序
创建无序 List,并对这个 List 进行排序。
示例:
import std.sort.*
import std.collection.*
class Student <: ToString {
public var name: String
public var age: Int64
public init(name: String, age: Int64) {
this.name = name
this.age = age
}
public func toString(): String {
return "{name: ${name} age: ${age}}"
}
}
main() {
/* 对 Int64 的 List 进行升序排序 */
var a = ArrayList<Int64>([1, 3, 5, 2, 4])
sort(a)
println(a)
/* 按照年龄升序排序 */
var b = ArrayList<Student>([Student("A", 8), Student("B", 7), Student("C", 3), Student("D", 4), Student("E", 6)])
let comparator = {l: Student, r: Student => l.age.compare(r.age)}
sort(b, by: comparator)
println(b)
/* 按照年龄降序排序 */
var c = ArrayList<Student>([Student("A", 8), Student("B", 7), Student("C", 3), Student("D", 4), Student("E", 6)])
let lessThan = {l: Student, r: Student => l.age < r.age}
sort(c, lessThan: lessThan, descending: true)
println(c)
/* 按照年龄升序排序,并且是稳定排序 */
var d = ArrayList<Student>([Student("A", 8), Student("B", 7), Student("C", 7), Student("D", 4), Student("E", 7)])
let key = {i: Student => i.age}
sort(d, key: key, stable: true)
println(d)
return 0
}
运行结果:
[1, 2, 3, 4, 5]
[{name: C age: 3}, {name: D age: 4}, {name: E age: 6}, {name: B age: 7}, {name: A age: 8}]
[{name: A age: 8}, {name: B age: 7}, {name: E age: 6}, {name: D age: 4}, {name: C age: 3}]
[{name: D age: 4}, {name: B age: 7}, {name: C age: 7}, {name: E age: 7}, {name: A age: 8}]
std.sync
功能介绍
sync 包提供并发编程相关的能力。
随着越来越多的计算机开始使用多核处理器,要充分发挥多核的优势,并发编程也变得越来越重要。
不同编程语言会以不同的方式实现线程。一些编程语言通过调用操作系统 API 来创建线程,意味着每个语言线程对应一个操作系统线程,一般称之为 1:1 的线程模型;也有一些编程语言提供特殊的线程实现,允许多个语言线程在不同数量的操作系统线程的上下文中切换执行,这种也被称为 M:N 的线程模型,即 M 个语言线程在 N 个操作系统线程上调度执行,其中 M 和 N 不一定相等。
仓颉编程语言希望给开发者提供一个友好、高效、统一的并发编程界面,让开发者无需关心操作系统线程、用户态线程等概念上的差异,同时屏蔽底层实现细节,因此我们只提供一个仓颉线程的概念。仓颉线程采用的是 M:N 线程模型的实现,因此本质上它是一种用户态的轻量级线程,支持抢占,且相比操作系统线程内存资源占用更小。
当开发者希望并发执行某一段代码时,只需创建一个仓颉线程即可。
要创建一个新的仓颉线程,可以使用关键字 spawn 并传递一个无形参的 lambda 表达式,该 lambda 表达式即为我们想在新线程中执行的代码。
示例:
通过 spawn 关键字创建一个仓颉线程:
main () {
spawn {
// 在新线程中执行
println("Thread: ${Thread.currentThread.id}")
}
// 在主线程中执行
println("Thread: ${Thread.currentThread.id}")
sleep(Duration.second)
0
}
sync 包主要提供了不同类型的原子操作,可重入互斥锁及其接口,利用共享变量的线程同步机制以及定时器的功能。
原子操作提供了包括整数类型、Bool 类型和引用类型的原子操作。
其中整数类型包括:Int8、Int16、Int32、Int64、UInt8、UInt16、UInt32、UInt64。
整数类型的原子操作支持基本的读(load)写(store)、交换(swap/compareAndSwap)以及算术运算(fetchAdd/fetchSub)等操作,需要注意的是:
-
交换操作和算术操作的返回值是修改前的值。
-
compareAndSwap是判断当前原子变量的值是否等于指定值,如果等于,则使用另一值替换;否则不替换。
Bool 类型和引用类型的原子操作只提供读写和交换操作,需要注意的是:
引用类型原子操作只对引用类型有效。
互斥锁 Lock 在使用的时候存在诸多不便,比如稍不注意会忘了解锁,或者在持有互斥锁的情况下抛出异常不能自动释放持有的锁等。因此,仓颉编程语言提供 synchronized 关键字,搭配 Lock 一起使用,来解决类似的问题。
通过在 synchronized 后面加上一个互斥锁实例,对其后面修饰的代码块进行保护,可以使得任意时刻最多只有一个线程可以执行被保护的代码:
- 一个线程在进入
synchronized修饰的代码块之前,会自动获取Lock实例对应的锁,如果无法获取锁,则当前线程被阻塞。 - 一个线程在退出
synchronized修饰的代码块之前(包括在代码块中使用break、continue、return、throw等控制转移表达式),会自动释放该Lock实例的锁。
示例:
在每个 for 循环的线程进入 synchronized 代码块前,会自动获取 mtx 实例对应的锁,在退出代码块前,会释放 mtx 实例对应的锁。
import std.sync.Mutex
main () {
let mtx = Mutex()
let cnt = Box<Int64>(0)
for (_ in 0..10) {
spawn {
synchronized(mtx) {
cnt.value ++
println("count: ${cnt.value}")
}
}
}
sleep(Duration.second)
0
}
API 列表
常量&变量
| 常量&变量名 | 功能 |
|---|---|
| DefaultMemoryOrder (deprecated) | 默认内存顺序,详见枚举 MemoryOrder (deprecated)。 |
接口
| 接口名 | 功能 |
|---|---|
| Condition | 提供使线程阻塞并等待来自另一个线程的信号以恢复执行的功能的接口。 |
| IReentrantMutex (deprecated) | 提供可重入互斥锁接口。 |
| Lock | 提供实现可重入互斥锁的接口。 |
| UniqueLock | 提供实现独占锁的接口。 |
类
| 类名 | 功能 |
|---|---|
| AtomicBool | 提供 Bool 类型的原子操作相关函数。 |
| AtomicInt16 | 提供 Int16 类型的原子操作相关函数。 |
| AtomicInt32 | 提供 Int32 类型的原子操作相关函数。 |
| AtomicInt64 | 提供 Int64 类型的原子操作相关函数。 |
| AtomicInt8 | 提供 Int8 类型的原子操作相关函数。 |
| AtomicOptionReference | 提供引用类型原子操作相关函数。 |
| AtomicReference | 引用类型原子操作相关函数。 |
| AtomicUInt16 | 提供 UInt16 类型的原子操作相关函数。 |
| AtomicUInt32 | 提供 UInt32 类型的原子操作相关函数。 |
| AtomicUInt64 | 提供 UInt64 类型的原子操作相关函数。 |
| AtomicUInt8 | 提供 UInt8 类型的原子操作相关函数。 |
| Barrier | 提供协调多个线程一起执行到某一个程序点的功能。 |
| Monitor (deprecated) | 提供使线程阻塞并等待来自另一个线程的信号以恢复执行的功能。 |
| MultiConditionMonitor (deprecated) | 提供对同一个互斥锁绑定多个条件变量的功能。 |
| Mutex | 提供可重入锁相关功能。 |
| ReadWriteLock | 提供可重入读写锁相关功能。 |
| ReentrantMutex (deprecated) | 提供可重入锁相关功能。 |
| ReentrantReadMutex (deprecated) | 提供可重入读写锁中的读锁类型。 |
| ReentrantReadWriteMutex (deprecated) | 提供可重入读写锁相关功能。 |
| ReentrantWriteMutex (deprecated) | 提供可重入读写锁中的写锁类型。 |
| Semaphore | 提供信号量相关功能。 |
| SyncCounter | 提供倒数计数器功能。 |
| Timer | 提供定时器功能。 |
枚举
| 枚举类型 | 功能 |
|---|---|
| MemoryOrder (deprecated) | 内存顺序类型枚举。 |
| ReadWriteMutexMode (deprecated) | 读写锁公平模式枚举。 |
| CatchupStyle | 重复性任务定时器需要使用的追平策略枚举。 |
结构体
| 结构体 | 功能 |
|---|---|
| ConditionID (deprecated) | 用于表示互斥锁的条件变量,详见 MultiConditionMonitor。 |
异常类
| 异常类名 | 功能 |
|---|---|
| IllegalSynchronizationStateException | 此类为非法同步状态异常。 |
常量&变量
let DefaultMemoryOrder (deprecated)
public let DefaultMemoryOrder: MemoryOrder = MemoryOrder.SeqCst
功能:默认内存顺序,详见枚举 MemoryOrder (deprecated)。
注意:
未来版本即将废弃。
接口
interface Condition
public interface Condition {
func notify(): Unit
func notifyAll(): Unit
func wait(): Unit
func wait(timeout!: Duration): Bool
func waitUntil(predicate: ()->Bool): Unit
func waitUntil(predicate: ()->Bool, timeout!: Duration): Bool
}
功能:提供使线程阻塞并等待来自另一个线程的信号以恢复执行的功能的接口。
这是一种利用共享变量进行线程同步的机制,当一些线程因等待共享变量的某个条件成立而挂起时,另一些线程改变共享的变量,使条件成立, 然后执行唤醒操作。这使得挂起的线程被唤醒后可以继续执行。
func notify()
func notify(): Unit
功能:唤醒一个等待在关联互斥体上的线程。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func notifyAll()
func notifyAll(): Unit
功能:唤醒所有等待在关联互斥体上的线程。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func wait()
func wait(): Unit
功能:当前线程挂起,直到对应的 notify 函数被调用。
说明:
线程在进入等待时会释放对应的互斥锁,被唤醒后再次持有互斥锁。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func wait(Duration)
func wait(timeout!: Duration): Bool
功能:当前线程挂起,直到对应的 notify 函数被调用,或者挂起时间超过 timeout。
说明:
线程在进入等待时会释放对应的互斥锁,被唤醒后再次持有互斥锁。
参数:
- timeout!: Duration - 挂起时间,其默认值为 Duration.Max。
返回值:
- Bool - 如果 Monitor (deprecated) 被其他线程唤醒,返回
true;如果超时,则返回false。
异常:
- IllegalArgumentException - 如果
timeout小于等于 Duration.Zero,抛出异常。 - IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func waitUntil(()->Bool)
func waitUntil(predicate: ()->Bool): Unit
功能:当前线程挂起,直到对应的 notify 函数被调用且 predicate 结果为 true。
说明:
- 线程在进入等待时会释放对应的互斥锁,被唤醒后再次持有互斥锁。
- 此方法会先判断
predicate结果是否为true,若是则直接返回,否则将当前线程挂起。
参数:
- predicate: ()->Bool - 等待为真的条件。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func waitUntil(()->Bool,Duration)
func waitUntil(predicate: ()->Bool, timeout!: Duration): Bool
功能:当前线程挂起,直到对应的 notify 函数被调用且 predicate 结果为 true,或者挂起时间超过 timeout。
说明:
- 线程在进入等待时会释放对应的互斥锁,被唤醒后再次持有互斥锁。
- 此方法会先判断
predicate结果是否为true,若是则直接返回true,否则将当前线程挂起。
参数:
- predicate: ()->Bool - 等待为真的条件。
- timeout!: Duration - 挂起时间,其默认值为 Duration.Max。
返回值:
- Bool - 如果 Monitor (deprecated) 被其他线程唤醒且
predicate结果为true,返回true;如果超时,则返回false。
异常:
- IllegalArgumentException - 如果
timeout小于等于 Duration.Zero,抛出异常。 - IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
interface IReentrantMutex (deprecated)
public interface IReentrantMutex {
func lock(): Unit
func tryLock(): Bool
func unlock(): Unit
}
功能:提供实现可重入互斥锁的接口。
注意:
- 未来版本即将废弃,使用 Lock 替代。
- 开发者在实现该接口时需要保证底层互斥锁确实支持嵌套锁,否则在嵌套使用时,将会产生死锁问题。
func lock()
func lock(): Unit
功能:锁定互斥体。
如果互斥体已被锁定,则阻塞当前线程。
func tryLock()
func tryLock(): Bool
功能:尝试锁定互斥体。
返回值:
- Bool - 如果互斥体已被锁定,则返回 false;反之,则锁定互斥体并返回 true。
func unlock()
func unlock(): Unit
功能:解锁互斥体。
如果互斥体被重复加锁了 N 次,那么需要调用 N 次该函数来完全解锁。一旦互斥体被完全解锁,如果有其他线程阻塞在此锁上,则唤醒其中一个线程。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
interface Lock
public interface Lock {
func lock(): Unit
func tryLock(): Bool
func unlock(): Unit
}
功能:提供实现可重入互斥锁的接口。
注意:
开发者在实现该接口时需要保证底层互斥锁确实支持嵌套锁,否则在嵌套使用时,将会产生死锁问题。
func lock()
func lock(): Unit
功能:锁定互斥体。
如果互斥体已被锁定,则阻塞当前线程。
func tryLock()
func tryLock(): Bool
功能:尝试锁定互斥体。
返回值:
- Bool - 如果互斥体已被锁定,则返回 false;反之,则锁定互斥体并返回 true。
func unlock()
func unlock(): Unit
功能:解锁互斥体。
如果互斥体被重复加锁了 N 次,那么需要调用 N 次该函数来完全解锁。一旦互斥体被完全解锁,如果有其他线程阻塞在此锁上,则唤醒其中一个线程。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
interface UniqueLock
public interface UniqueLock <: Lock {
func condition(): Condition
}
功能:提供实现独占锁的接口。
父类型:
func condition()
func condition(): Condition
可能被用来实现 “单 Lock 多等待队列” 的并发原语。
返回值:
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
类
class AtomicBool
public class AtomicBool {
public init(val: Bool)
}
功能:提供 Bool 类型的原子操作相关函数。
init(Bool)
public init(val: Bool)
功能:构造一个封装 Bool 数据类型的原子类型 AtomicBool 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: Bool - 原子类型的初始值。
func compareAndSwap(Bool, Bool)
public func compareAndSwap(old: Bool, new: Bool): Bool
功能:CAS(Compare and Swap)操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(Bool, Bool, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: Bool, new: Bool, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(Bool, Bool) 替代。
参数:
- old: Bool - 与当前原子类型进行比较的值。
- new: Bool - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func load()
public func load(): Bool
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- Bool - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): Bool
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Bool - 当前原子类型的值。
func store(Bool)
public func store(val: Bool): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: Bool - 写入原子类型的值。
func store(Bool, MemoryOrder) (deprecated)
public func store(val: Bool, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(Bool) 替代。
参数:
- val: Bool - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(Bool)
public func swap(val: Bool): Bool
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: Bool - 写入原子类型的值。
返回值:
- Bool - 写入前的值。
func swap(Bool, MemoryOrder) (deprecated)
public func swap(val: Bool, memoryOrder!: MemoryOrder): Bool
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(Bool) 替代。
参数:
- val: Bool - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Bool - 写入前的值。
class AtomicInt16
public class AtomicInt16 {
public init(val: Int16)
}
功能:提供 Int16 类型的原子操作相关函数。
init(Int16)
public init(val: Int16)
功能:构造一个封装 Int16 数据类型的原子类型 AtomicInt16 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: Int16 - 原子类型的初始值。
func compareAndSwap(Int16, Int16)
public func compareAndSwap(old: Int16, new: Int16): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false
func compareAndSwap(Int16, Int16, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: Int16, new: Int16, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(Int16, Int16) 替代。
参数:
- old: Int16 - 与当前原子类型进行比较的值。
- new: Int16 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(Int16)
public func fetchAdd(val: Int16): Int16
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: Int16 - 与原子类型进行加操作的值。
返回值:
- Int16 - 执行加操作前的值。
func fetchAdd(Int16, MemoryOrder) (deprecated)
public func fetchAdd(val: Int16, memoryOrder!: MemoryOrder): Int16
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(Int16) 替代。
参数:
- val: Int16 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int16 - 执行加操作前的值。
func fetchAnd(Int16)
public func fetchAnd(val: Int16): Int16
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: Int16 - 与原子类型进行与操作的值。
返回值:
- Int16 - 执行与操作前的值。
func fetchAnd(Int16, MemoryOrder) (deprecated)
public func fetchAnd(val: Int16, memoryOrder!: MemoryOrder): Int16
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(Int16) 替代。
参数:
- val: Int16 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int16 - 执行与操作前的值。
func fetchOr(Int16)
public func fetchOr(val: Int16): Int16
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: Int16 - 与原子类型进行或操作的值。
返回值:
- Int16 - 执行或操作前的值。
func fetchOr(Int16, MemoryOrder) (deprecated)
public func fetchOr(val: Int16, memoryOrder!: MemoryOrder): Int16
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(Int16) 替代。
参数:
- val: Int16 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int16 - 执行或操作前的值。
func fetchSub(Int16)
public func fetchSub(val: Int16): Int16
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: Int16 - 与原子类型进行减操作的值。
返回值:
- Int16 - 执行减操作前的值。
func fetchSub(Int16, MemoryOrder) (deprecated)
public func fetchSub(val: Int16, memoryOrder!: MemoryOrder): Int16
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(Int16) 替代。
参数:
- val: Int16 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int16 - 执行减操作前的值。
func fetchXor(Int16)
public func fetchXor(val: Int16): Int16
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: Int16 - 与原子类型进行异或操作的值。
返回值:
- Int16 - 执行异或操作前的值。
func fetchXor(Int16, MemoryOrder) (deprecated)
public func fetchXor(val: Int16, memoryOrder!: MemoryOrder): Int16
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(Int16) 替代。
参数:
- val: Int16 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int16 - 执行异或操作前的值。
func load()
public func load(): Int16
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- Int16 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): Int16
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int16 - 当前原子类型的值。
func store(Int16)
public func store(val: Int16): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: Int16 - 写入原子类型的值。
func store(Int16, MemoryOrder) (deprecated)
public func store(val: Int16, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(Int16) 替代。
参数:
- val: Int16 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(Int16)
public func swap(val: Int16): Int16
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: Int16 - 写入原子类型的值。
返回值:
- Int16 - 写入前的值。
func swap(Int16, MemoryOrder) (deprecated)
public func swap(val: Int16, memoryOrder!: MemoryOrder): Int16
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(Int16) 替代。
参数:
- val: Int16 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int16 - 写入前的值。
class AtomicInt32
public class AtomicInt32 {
public init(val: Int32)
}
功能:提供 Int32 类型的原子操作相关函数。
init(Int32)
public init(val: Int32)
功能:构造一个封装 Int32 数据类型的原子类型 AtomicInt32 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: Int32 - 原子类型的初始值。
func compareAndSwap(Int32, Int32)
public func compareAndSwap(old: Int32, new: Int32): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(Int32, Int32, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: Int32, new: Int32, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(Int32, Int32) 替代。
参数:
- old: Int32 - 与当前原子类型进行比较的值。
- new: Int32 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(Int32)
public func fetchAdd(val: Int32): Int32
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: Int32 - 与原子类型进行加操作的值。
返回值:
- Int32 - 执行加操作前的值。
func fetchAdd(Int32, MemoryOrder) (deprecated)
public func fetchAdd(val: Int32, memoryOrder!: MemoryOrder): Int32
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(Int32) 替代。
参数:
- val: Int32 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int32 - 执行加操作前的值。
func fetchAnd(Int32)
public func fetchAnd(val: Int32): Int32
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: Int32 - 与原子类型进行与操作的值。
返回值:
- Int32 - 执行与操作前的值。
func fetchAnd(Int32, MemoryOrder) (deprecated)
public func fetchAnd(val: Int32, memoryOrder!: MemoryOrder): Int32
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(Int32) 替代。
参数:
- val: Int32 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int32 - 执行与操作前的值。
func fetchOr(Int32)
public func fetchOr(val: Int32): Int32
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: Int32 - 与原子类型进行或操作的值。
返回值:
- Int32 - 执行或操作前的值。
func fetchOr(Int32, MemoryOrder) (deprecated)
public func fetchOr(val: Int32, memoryOrder!: MemoryOrder): Int32
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(Int32) 替代。
参数:
- val: Int32 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int32 - 执行或操作前的值。
func fetchSub(Int32)
public func fetchSub(val: Int32): Int32
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: Int32 - 与原子类型进行减操作的值。
返回值:
- Int32 - 执行减操作前的值。
func fetchSub(Int32, MemoryOrder) (deprecated)
public func fetchSub(val: Int32, memoryOrder!: MemoryOrder): Int32
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(Int32) 替代。
参数:
- val: Int32 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int32 - 执行减操作前的值。
func fetchXor(Int32)
public func fetchXor(val: Int32): Int32
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: Int32 - 与原子类型进行异或操作的值。
返回值:
- Int32 - 执行异或操作前的值。
func fetchXor(Int32, MemoryOrder) (deprecated)
public func fetchXor(val: Int32, memoryOrder!: MemoryOrder): Int32
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(Int32) 替代。
参数:
- val: Int32 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int32 - 执行异或操作前的值。
func load()
public func load(): Int32
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- Int32 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): Int32
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int32 - 当前原子类型的值。
func store(Int32)
public func store(val: Int32): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: Int32 - 写入原子类型的值。
func store(Int32, MemoryOrder) (deprecated)
public func store(val: Int32, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(Int32) 替代。
参数:
- val: Int32 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(Int32)
public func swap(val: Int32): Int32
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: Int32 - 写入原子类型的值。
返回值:
- Int32 - 写入前的值。
func swap(Int32, MemoryOrder) (deprecated)
public func swap(val: Int32, memoryOrder!: MemoryOrder): Int32
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(Int32) 替代。
参数:
- val: Int32 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int32 - 写入前的值。
class AtomicInt64
public class AtomicInt64 {
public init(val: Int64)
}
功能:提供 Int64 类型的原子操作相关函数。
init(Int64)
public init(val: Int64)
功能:构造一个封装 Int64 数据类型的原子类型 AtomicInt64 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: Int64 - 原子类型的初始值。
func compareAndSwap(Int64, Int64)
public func compareAndSwap(old: Int64, new: Int64): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(Int64, Int64, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: Int64, new: Int64, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(Int64, Int64) 替代。
参数:
- old: Int64 - 与当前原子类型进行比较的值。
- new: Int64 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(Int64)
public func fetchAdd(val: Int64): Int64
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: Int64 - 与原子类型进行加操作的值。
返回值:
- Int64 - 执行加操作前的值。
func fetchAdd(Int64, MemoryOrder) (deprecated)
public func fetchAdd(val: Int64, memoryOrder!: MemoryOrder): Int64
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(Int64) 替代。
参数:
- val: Int64 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int64 - 执行加操作前的值。
func fetchAnd(Int64)
public func fetchAnd(val: Int64): Int64
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: Int64 - 与原子类型进行与操作的值。
返回值:
- Int64 - 执行与操作前的值。
func fetchAnd(Int64, MemoryOrder) (deprecated)
public func fetchAnd(val: Int64, memoryOrder!: MemoryOrder): Int64
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(Int64) 替代。
参数:
- val: Int64 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int64 - 执行与操作前的值。
func fetchOr(Int64)
public func fetchOr(val: Int64): Int64
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: Int64 - 与原子类型进行或操作的值。
返回值:
- Int64 - 执行或操作前的值。
func fetchOr(Int64, MemoryOrder) (deprecated)
public func fetchOr(val: Int64, memoryOrder!: MemoryOrder): Int64
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(Int64) 替代。
参数:
- val: Int64 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int64 - 执行或操作前的值。
func fetchSub(Int64)
public func fetchSub(val: Int64): Int64
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: Int64 - 与原子类型进行减操作的值。
返回值:
- Int64 - 执行减操作前的值。
func fetchSub(Int64, MemoryOrder) (deprecated)
public func fetchSub(val: Int64, memoryOrder!: MemoryOrder): Int64
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(Int64) 替代。
参数:
- val: Int64 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int64 - 执行减操作前的值。
func fetchXor(Int64)
public func fetchXor(val: Int64): Int64
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: Int64 - 与原子类型进行异或操作的值。
返回值:
- Int64 - 执行异或操作前的值。
func fetchXor(Int64, MemoryOrder) (deprecated)
public func fetchXor(val: Int64, memoryOrder!: MemoryOrder): Int64
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(Int64) 替代。
参数:
- val: Int64 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int64 - 执行异或操作前的值。
func load()
public func load(): Int64
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- Int64 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): Int64
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int64 - 当前原子类型的值。
func store(Int64)
public func store(val: Int64): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: Int64 - 写入原子类型的值。
func store(Int64, MemoryOrder) (deprecated)
public func store(val: Int64, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(Int64) 替代。
参数:
- val: Int64 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(Int64)
public func swap(val: Int64): Int64
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: Int64 - 写入原子类型的值。
返回值:
- Int64 - 写入前的值。
func swap(Int64, MemoryOrder) (deprecated)
public func swap(val: Int64, memoryOrder!: MemoryOrder): Int64
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(Int64) 替代。
参数:
- val: Int64 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int64 - 写入前的值。
示例:
import std.sync.*
let count = AtomicInt64(1)
main(): Int64 {
var val1 = 0
if (count.compareAndSwap(1, 2)) {
val1 = count.load()
println("count1 = ${val1}")
}
if (count.fetchAdd(2) == val1) {
var val2 = count.load()
println("count2 = ${val2}")
}
count.store(6)
var val3 = count.load()
println("count3 = ${val3}")
if (count.swap(8) == val3) {
var val4 = count.load()
println("count4 = ${val4}")
}
return 0
}
运行结果:
count1 = 2
count2 = 4
count3 = 6
count4 = 8
class AtomicInt8
public class AtomicInt8 {
public init(val: Int8)
}
功能:提供 Int8 类型的原子操作相关函数。
init(Int8)
public init(val: Int8)
功能:构造一个封装 Int8 数据类型的原子类型 AtomicInt8 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: Int8 - 原子类型的初始值。
func compareAndSwap(Int8, Int8)
public func compareAndSwap(old: Int8, new: Int8): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(Int8, Int8, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: Int8, new: Int8, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(Int8, Int8) 替代。
参数:
- old: Int8 - 与当前原子类型进行比较的值。
- new: Int8 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(Int8)
public func fetchAdd(val: Int8): Int8
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: Int8 - 与原子类型进行加操作的值。
返回值:
- Int8 - 执行加操作前的值。
func fetchAdd(Int8, MemoryOrder) (deprecated)
public func fetchAdd(val: Int8, memoryOrder!: MemoryOrder): Int8
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(Int8) 替代。
参数:
- val: Int8 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int8 - 执行加操作前的值。
func fetchAnd(Int8)
public func fetchAnd(val: Int8): Int8
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: Int8 - 与原子类型进行与操作的值。
返回值:
- Int8 - 执行与操作前的值。
func fetchAnd(Int8, MemoryOrder) (deprecated)
public func fetchAnd(val: Int8, memoryOrder!: MemoryOrder): Int8
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(Int8) 替代。
参数:
- val: Int8 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int8 - 执行与操作前的值。
func fetchOr(Int8)
public func fetchOr(val: Int8): Int8
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: Int8 - 与原子类型进行或操作的值。
返回值:
- Int8 - 执行或操作前的值。
func fetchOr(Int8, MemoryOrder) (deprecated)
public func fetchOr(val: Int8, memoryOrder!: MemoryOrder): Int8
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(Int8) 替代。
参数:
- val: Int8 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int8 - 执行或操作前的值。
func fetchSub(Int8)
public func fetchSub(val: Int8): Int8
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: Int8 - 与原子类型进行减操作的值。
返回值:
- Int8 - 执行减操作前的值。
func fetchSub(Int8, MemoryOrder) (deprecated)
public func fetchSub(val: Int8, memoryOrder!: MemoryOrder): Int8
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(Int8) 替代。
参数:
- val: Int8 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int8 - 执行减操作前的值。
func fetchXor(Int8)
public func fetchXor(val: Int8): Int8
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: Int8 - 与原子类型进行异或操作的值。
返回值:
- Int8 - 执行异或操作前的值。
func fetchXor(Int8, MemoryOrder) (deprecated)
public func fetchXor(val: Int8, memoryOrder!: MemoryOrder): Int8
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(Int8) 替代。
参数:
- val: Int8 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int8 - 执行异或操作前的值。
func load()
public func load(): Int8
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- Int8 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): Int8
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int8 - 当前原子类型的值。
func store(Int8)
public func store(val: Int8): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: Int8 - 写入原子类型的值。
func store(Int8, MemoryOrder) (deprecated)
public func store(val: Int8, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(Int8) 替代。
参数:
- val: Int8 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(Int8)
public func swap(val: Int8): Int8
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: Int8 - 写入原子类型的值。
返回值:
- Int8 - 写入前的值。
func swap(Int8, MemoryOrder) (deprecated)
public func swap(val: Int8, memoryOrder!: MemoryOrder): Int8
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(Int8) 替代。
参数:
- val: Int8 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Int8 - 写入前的值。
class AtomicOptionReference<T> where T <: Object
public class AtomicOptionReference<T> where T <: Object {
public init()
public init(val: Option<T>)
}
功能:提供引用类型原子操作相关函数。
该引用类型必须是 Object 的子类。
init()
public init()
功能:构造一个空的 AtomicOptionReference 实例。
init(Option<T>)
public init(val: Option<T>)
功能:构造一个封装 Option<T> 数据类型的原子类型 AtomicOptionReference 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: Option<T> - 原子类型的初始值。
func compareAndSwap(Option<T>, Option<T>)
public func compareAndSwap(old: Option<T>, new: Option<T>): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(Option<T>, Option<T>, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: Option<T>, new: Option<T>, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(Option<T>, Option<T>) 替代。
参数:
- old: Option<T> - 与当前原子类型进行比较的值。
- new: Option<T> - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func load()
public func load(): Option<T>
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- Option<T> - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): Option<T>
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Option<T> - 当前原子类型的值。
func store(Option<T>)
public func store(val: Option<T>): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: Option<T> - 写入原子类型的值。
func store(Option<T>, MemoryOrder) (deprecated)
public func store(val: Option<T>, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(Option<T>) 替代。
参数:
- val: Option<T> - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(Option<T>)
public func swap(val: Option<T>): Option<T>
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: Option<T> - 写入原子类型的值。
返回值:
- Option<T> - 写入前的值。
func swap(Option<T>, MemoryOrder) (deprecated)
public func swap(val: Option<T>, memoryOrder!: MemoryOrder): Option<T>
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(Option<T>) 替代。
参数:
- val: Option<T> - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- Option<T> - 写入前的值。
class AtomicReference<T> where T <: Object
public class AtomicReference<T> where T <: Object {
public init(val: T)
}
功能:引用类型原子操作相关函数。
该引用类型必须是 Object 的子类。
init(T)
public init(val: T)
功能:构造一个封装 T 数据类型的原子类型 AtomicReference 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: T - 原子类型的初始值。
func compareAndSwap(T, T)
public func compareAndSwap(old: T, new: T): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
- old: T - 与当前原子类型进行比较的值。
- new: T - 比较结果相等时,写入原子类型的值。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(T, T, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: T, new: T, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(T, T) 替代。
参数:
- old: T - 与当前原子类型进行比较的值。
- new: T - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func load()
public func load(): T
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- T - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): T
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- T - 当前原子类型的值。
func store(T)
public func store(val: T): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: T - 写入原子类型的值。
func store(T, MemoryOrder) (deprecated)
public func store(val: T, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(T) 替代。
参数:
- val: T - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(T)
public func swap(val: T): T
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: T - 写入原子类型的值。
返回值:
- T - 写入前的值。
func swap(T, MemoryOrder) (deprecated)
public func swap(val: T, memoryOrder!: MemoryOrder): T
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(T) 替代。
参数:
- val: T - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- T - 写入前的值。
class AtomicUInt16
public class AtomicUInt16 {
public init(val: UInt16)
}
功能:提供 UInt16 类型的原子操作相关函数。
init(UInt16)
public init(val: UInt16)
功能:构造一个封装 UInt16 数据类型的原子类型 AtomicUInt16 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: UInt16 - 原子类型的初始值。
func compareAndSwap(UInt16, UInt16)
public func compareAndSwap(old: UInt16, new: UInt16): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(UInt16, UInt16, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: UInt16, new: UInt16, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(UInt16, UInt16) 替代。
参数:
- old: UInt16 - 与当前原子类型进行比较的值。
- new: UInt16 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(UInt16)
public func fetchAdd(val: UInt16): UInt16
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: UInt16 - 与原子类型进行加操作的值。
返回值:
- UInt16 - 执行加操作前的值。
func fetchAdd(UInt16, MemoryOrder) (deprecated)
public func fetchAdd(val: UInt16, memoryOrder!: MemoryOrder): UInt16
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(UInt16) 替代。
参数:
- val: UInt16 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt16 - 执行加操作前的值。
func fetchAnd(UInt16)
public func fetchAnd(val: UInt16): UInt16
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: UInt16 - 与原子类型进行与操作的值。
返回值:
- UInt16 - 执行与操作前的值。
func fetchAnd(UInt16, MemoryOrder) (deprecated)
public func fetchAnd(val: UInt16, memoryOrder!: MemoryOrder): UInt16
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(UInt16) 替代。
参数:
- val: UInt16 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt16 - 执行与操作前的值。
func fetchOr(UInt16)
public func fetchOr(val: UInt16): UInt16
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: UInt16 - 与原子类型进行或操作的值。
返回值:
- UInt16 - 执行或操作前的值。
func fetchOr(UInt16, MemoryOrder) (deprecated)
public func fetchOr(val: UInt16, memoryOrder!: MemoryOrder): UInt16
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(UInt16) 替代。
参数:
- val: UInt16 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt16 - 执行或操作前的值。
func fetchSub(UInt16)
public func fetchSub(val: UInt16): UInt16
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: UInt16 - 与原子类型进行减操作的值。
返回值:
- UInt16 - 执行减操作前的值。
func fetchSub(UInt16, MemoryOrder) (deprecated)
public func fetchSub(val: UInt16, memoryOrder!: MemoryOrder): UInt16
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(UInt16) 替代。
参数:
- val: UInt16 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt16 - 执行减操作前的值。
func fetchXor(UInt16)
public func fetchXor(val: UInt16): UInt16
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: UInt16 - 与原子类型进行异或操作的值。
返回值:
- UInt16 - 执行异或操作前的值。
func fetchXor(UInt16, MemoryOrder) (deprecated)
public func fetchXor(val: UInt16, memoryOrder!: MemoryOrder): UInt16
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(UInt16) 替代。
参数:
- val: UInt16 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt16 - 执行异或操作前的值。
func load()
public func load(): UInt16
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- UInt16 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): UInt16
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt16 - 当前原子类型的值。
func store(UInt16)
public func store(val: UInt16): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: UInt16 - 写入原子类型的值。
func store(UInt16, MemoryOrder) (deprecated)
public func store(val: UInt16, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(UInt16) 替代。
参数:
- val: UInt16 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(UInt16)
public func swap(val: UInt16): UInt16
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: UInt16 - 写入原子类型的值。
返回值:
- UInt16 - 写入前的值。
func swap(UInt16, MemoryOrder) (deprecated)
public func swap(val: UInt16, memoryOrder!: MemoryOrder): UInt16
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(UInt16) 替代。
参数:
- val: UInt16 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt16 - 写入前的值。
class AtomicUInt32
public class AtomicUInt32 {
public init(val: UInt32)
}
功能:提供 UInt32 类型的原子操作相关函数。
init(UInt32)
public init(val: UInt32)
功能:构造一个封装 UInt32 数据类型的原子类型 AtomicUInt32 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: UInt32 - 原子类型的初始值。
func compareAndSwap(UInt32, UInt32)
public func compareAndSwap(old: UInt32, new: UInt32): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(UInt32, UInt32, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: UInt32, new: UInt32, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(UInt32, UInt32) 替代。
参数:
- old: UInt32 - 与当前原子类型进行比较的值。
- new: UInt32 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(UInt32)
public func fetchAdd(val: UInt32): UInt32
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: UInt32 - 与原子类型进行加操作的值。
返回值:
- UInt32 - 执行加操作前的值。
func fetchAdd(UInt32, MemoryOrder) (deprecated)
public func fetchAdd(val: UInt32, memoryOrder!: MemoryOrder): UInt32
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(UInt32) 替代。
参数:
- val: UInt32 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt32 - 执行加操作前的值。
func fetchAnd(UInt32)
public func fetchAnd(val: UInt32): UInt32
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: UInt32 - 与原子类型进行与操作的值。
返回值:
- UInt32 - 执行与操作前的值。
func fetchAnd(UInt32, MemoryOrder) (deprecated)
public func fetchAnd(val: UInt32, memoryOrder!: MemoryOrder): UInt32
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(UInt32) 替代。
参数:
- val: UInt32 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt32 - 执行与操作前的值。
func fetchOr(UInt32)
public func fetchOr(val: UInt32): UInt32
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: UInt32 - 与原子类型进行或操作的值。
返回值:
- UInt32 - 执行或操作前的值。
func fetchOr(UInt32, MemoryOrder) (deprecated)
public func fetchOr(val: UInt32, memoryOrder!: MemoryOrder): UInt32
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(UInt32) 替代。
参数:
- val: UInt32 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt32 - 执行或操作前的值。
func fetchSub(UInt32)
public func fetchSub(val: UInt32): UInt32
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: UInt32 - 与原子类型进行减操作的值。
返回值:
- UInt32 - 执行减操作前的值。
func fetchSub(UInt32, MemoryOrder) (deprecated)
public func fetchSub(val: UInt32, memoryOrder!: MemoryOrder): UInt32
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(UInt32) 替代。
参数:
- val: UInt32 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt32 - 执行减操作前的值。
func fetchXor(UInt32)
public func fetchXor(val: UInt32): UInt32
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: UInt32 - 与原子类型进行异或操作的值。
返回值:
- UInt32 - 执行异或操作前的值。
func fetchXor(UInt32, MemoryOrder) (deprecated)
public func fetchXor(val: UInt32, memoryOrder!: MemoryOrder): UInt32
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(UInt32) 替代。
参数:
- val: UInt32 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt32 - 执行异或操作前的值。
func load()
public func load(): UInt32
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- UInt32 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): UInt32
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt32 - 当前原子类型的值。
func store(UInt32)
public func store(val: UInt32): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: UInt32 - 写入原子类型的值。
func store(UInt32, MemoryOrder) (deprecated)
public func store(val: UInt32, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(UInt32) 替代。
参数:
- val: UInt32 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(UInt32)
public func swap(val: UInt32): UInt32
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: UInt32 - 写入原子类型的值。
返回值:
- UInt32 - 写入前的值。
func swap(UInt32, MemoryOrder) (deprecated)
public func swap(val: UInt32, memoryOrder!: MemoryOrder): UInt32
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(UInt32) 替代。
参数:
- val: UInt32 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt32 - 写入前的值。
class AtomicUInt64
public class AtomicUInt64 {
public init(val: UInt64)
}
功能:提供 UInt64 类型的原子操作相关函数。
init(UInt64)
public init(val: UInt64)
功能:构造一个封装 UInt64 数据类型的原子类型 AtomicUInt64 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: UInt64 - 原子类型的初始值。
func compareAndSwap(UInt64, UInt64)
public func compareAndSwap(old: UInt64, new: UInt64): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(UInt64, UInt64, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: UInt64, new: UInt64, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(UInt64, UInt64) 替代。
参数:
- old: UInt64 - 与当前原子类型进行比较的值。
- new: UInt64 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(UInt64)
public func fetchAdd(val: UInt64): UInt64
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: UInt64 - 与原子类型进行加操作的值。
返回值:
- UInt64 - 执行加操作前的值。
func fetchAdd(UInt64, MemoryOrder) (deprecated)
public func fetchAdd(val: UInt64, memoryOrder!: MemoryOrder): UInt64
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(UInt64) 替代。
参数:
- val: UInt64 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt64 - 执行加操作前的值。
func fetchAnd(UInt64)
public func fetchAnd(val: UInt64): UInt64
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: UInt64 - 与原子类型进行与操作的值。
返回值:
- UInt64 - 执行与操作前的值。
func fetchAnd(UInt64, MemoryOrder) (deprecated)
public func fetchAnd(val: UInt64, memoryOrder!: MemoryOrder): UInt64
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(UInt64) 替代。
参数:
- val: UInt64 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt64 - 执行与操作前的值。
func fetchOr(UInt64)
public func fetchOr(val: UInt64): UInt64
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: UInt64 - 与原子类型进行或操作的值。
返回值:
- UInt64 - 执行或操作前的值。
func fetchOr(UInt64, MemoryOrder) (deprecated)
public func fetchOr(val: UInt64, memoryOrder!: MemoryOrder): UInt64
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(UInt64) 替代。
参数:
- val: UInt64 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt64 - 执行或操作前的值。
func fetchSub(UInt64)
public func fetchSub(val: UInt64): UInt64
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: UInt64 - 与原子类型进行减操作的值。
返回值:
- UInt64 - 执行减操作前的值。
func fetchSub(UInt64, MemoryOrder) (deprecated)
public func fetchSub(val: UInt64, memoryOrder!: MemoryOrder): UInt64
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(UInt64) 替代。
参数:
- val: UInt64 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt64 - 执行减操作前的值。
func fetchXor(UInt64)
public func fetchXor(val: UInt64): UInt64
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: UInt64 - 与原子类型进行异或操作的值。
返回值:
- UInt64 - 执行异或操作前的值。
func fetchXor(UInt64, MemoryOrder) (deprecated)
public func fetchXor(val: UInt64, memoryOrder!: MemoryOrder): UInt64
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(UInt64) 替代。
参数:
- val: UInt64 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt64 - 执行异或操作前的值。
func load()
public func load(): UInt64
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- UInt64 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): UInt64
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt64 - 当前原子类型的值。
func store(UInt64)
public func store(val: UInt64): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: UInt64 - 写入原子类型的值。
func store(UInt64, MemoryOrder) (deprecated)
public func store(val: UInt64, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(UInt64) 替代。
参数:
- val: UInt64 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(UInt64)
public func swap(val: UInt64): UInt64
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: UInt64 - 写入原子类型的值。
返回值:
- UInt64 - 写入前的值。
func swap(UInt64, MemoryOrder) (deprecated)
public func swap(val: UInt64, memoryOrder!: MemoryOrder): UInt64
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(UInt64) 替代。
参数:
- val: UInt64 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt64 - 写入前的值。
class AtomicUInt8
public class AtomicUInt8 {
public init(val: UInt8)
}
功能:提供 UInt8 类型的原子操作相关函数。
init(UInt8)
public init(val: UInt8)
功能:构造一个封装 UInt8 数据类型的原子类型 AtomicUInt8 的实例,其内部数据初始值为入参 val 的值。
参数:
- val: UInt8 - 原子类型的初始值。
func compareAndSwap(UInt8, UInt8)
public func compareAndSwap(old: UInt8, new: UInt8): Bool
功能:CAS 操作,采用默认内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,则写入参数 new 指定的值,并返回 true;否则,不写入值,并返回 false。
参数:
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func compareAndSwap(UInt8, UInt8, MemoryOrder, MemoryOrder) (deprecated)
public func compareAndSwap(old: UInt8, new: UInt8, successOrder!: MemoryOrder, failureOrder!: MemoryOrder): Bool
功能:CAS 操作,成功时使用 successOrder 指定的内存排序方式,失败时则使用 failureOrder 指定的内存排序方式。
比较当前原子类型的值与参数 old 指定的值是否相等。若相等,写入参数 new 指定的值,返回 true;否则,不写入值,并返回 false。
注意:
未来版本即将废弃,使用 compareAndSwap(UInt8, UInt8) 替代。
参数:
- old: UInt8 - 与当前原子类型进行比较的值。
- new: UInt8 - 比较结果相等时,写入原子类型的值。
- successOrder!: MemoryOrder (deprecated) - CAS 操作成功时,执行“读 > 修改 > 写”操作需要的内存排序方式。
- failureOrder!: MemoryOrder (deprecated) - CAS 操作失败时,执行“读”操作需要的内存排序方式。
返回值:
- Bool - 比较后交换成功返回
true,否则返回false。
func fetchAdd(UInt8)
public func fetchAdd(val: UInt8): UInt8
功能:采用默认内存排序方式,将原子类型的值与参数 val 进行加操作,将结果写入当前原子类型实例,并返回加操作前的值。
参数:
- val: UInt8 - 与原子类型进行加操作的值。
返回值:
- UInt8 - 执行加操作前的值。
func fetchAdd(UInt8, MemoryOrder) (deprecated)
public func fetchAdd(val: UInt8, memoryOrder!: MemoryOrder): UInt8
功能:采用参数 memoryOrder 指定的内存排序方式,将原子类型的值与参数 val 进行加操作。将结果写入当前原子类型实例,并返回加法运算前的值。
注意:
未来版本即将废弃,使用 fetchAdd(UInt8) 替代。
参数:
- val: UInt8 - 与原子类型进行加操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt8 - 执行加操作前的值。
func fetchAnd(UInt8)
public func fetchAnd(val: UInt8): UInt8
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
参数:
- val: UInt8 - 与原子类型进行与操作的值。
返回值:
- UInt8 - 执行与操作前的值。
func fetchAnd(UInt8, MemoryOrder) (deprecated)
public func fetchAnd(val: UInt8, memoryOrder!: MemoryOrder): UInt8
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行与操作。将结果写入当前原子类型实例,并返回与操作前的值。
注意:
未来版本即将废弃,使用 fetchAnd(UInt8) 替代。
参数:
- val: UInt8 - 与原子类型进行与操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt8 - 执行与操作前的值。
func fetchOr(UInt8)
public func fetchOr(val: UInt8): UInt8
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
参数:
- val: UInt8 - 与原子类型进行或操作的值。
返回值:
- UInt8 - 执行或操作前的值。
func fetchOr(UInt8, MemoryOrder) (deprecated)
public func fetchOr(val: UInt8, memoryOrder!: MemoryOrder): UInt8
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行或操作。将结果写入当前原子类型实例,并返回或操作前的值。
注意:
未来版本即将废弃,使用 fetchOr(UInt8) 替代。
参数:
- val: UInt8 - 与原子类型进行或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt8 - 执行或操作前的值。
func fetchSub(UInt8)
public func fetchSub(val: UInt8): UInt8
功能:采用默认内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
参数:
- val: UInt8 - 与原子类型进行减操作的值。
返回值:
- UInt8 - 执行减操作前的值。
func fetchSub(UInt8, MemoryOrder) (deprecated)
public func fetchSub(val: UInt8, memoryOrder!: MemoryOrder): UInt8
功能:采用参数 memoryOrder 指定的内存排序方式,以原子类型的值为被减数,参数 val 为减数,做减操作。将结果写入当前原子类型实例,并返回减操作前的值。
注意:
未来版本即将废弃,使用 fetchSub(UInt8) 替代。
参数:
- val: UInt8 - 与原子类型进行减操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt8 - 执行减操作前的值。
func fetchXor(UInt8)
public func fetchXor(val: UInt8): UInt8
功能:采用默认内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
参数:
- val: UInt8 - 与原子类型进行异或操作的值。
返回值:
- UInt8 - 执行异或操作前的值。
func fetchXor(UInt8, MemoryOrder) (deprecated)
public func fetchXor(val: UInt8, memoryOrder!: MemoryOrder): UInt8
功能:采用参数 memoryOrder 指定的内存排序方式,将当前原子类型实例的值与参数 val 进行异或操作。将结果写入当前原子类型实例,并返回异或操作前的值。
注意:
未来版本即将废弃,使用 fetchXor(UInt8) 替代。
参数:
- val: UInt8 - 与原子类型进行异或操作的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt8 - 执行异或操作前的值。
func load()
public func load(): UInt8
功能:读取操作,采用默认内存排序方式,读取原子类型的值。
返回值:
- UInt8 - 当前原子类型的值。
func load(MemoryOrder) (deprecated)
public func load(memoryOrder!: MemoryOrder): UInt8
功能:读取操作,采用参数 memoryOrder 指定的内存排序方式,读取原子类型的值。
注意:
未来版本即将废弃,使用 load() 替代。
参数:
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt8 - 当前原子类型的值。
func store(UInt8)
public func store(val: UInt8): Unit
功能:写入操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型。
参数:
- val: UInt8 - 写入原子类型的值。
func store(UInt8, MemoryOrder) (deprecated)
public func store(val: UInt8, memoryOrder!: MemoryOrder): Unit
功能:写入操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型。
注意:
未来版本即将废弃,使用 store(UInt8) 替代。
参数:
- val: UInt8 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
func swap(UInt8)
public func swap(val: UInt8): UInt8
功能:交换操作,采用默认内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
参数:
- val: UInt8 - 写入原子类型的值。
返回值:
- UInt8 - 写入前的值。
func swap(UInt8, MemoryOrder) (deprecated)
public func swap(val: UInt8, memoryOrder!: MemoryOrder): UInt8
功能:交换操作,采用参数 memoryOrder 指定的内存排序方式,将参数 val 指定的值写入原子类型,并返回写入前的值。
注意:
未来版本即将废弃,使用 swap(UInt8) 替代。
参数:
- val: UInt8 - 写入原子类型的值。
- memoryOrder!: MemoryOrder (deprecated) - 当前操作的内存排序方式。
返回值:
- UInt8 - 写入前的值。
class Barrier
public class Barrier {
public init(count: Int64)
}
功能:提供协调多个线程一起执行到某一个程序点的功能。
率先达到程序点的线程将进入阻塞状态,当所有线程都达到程序点后,才一起继续执行。
init(Int64)
public init(count: Int64)
功能:创建 Barrier 对象。
参数:
- count: Int64 - 表示需要协调的线程数。
异常:
- IllegalArgumentException - 参数 count 为负数。
func wait(Duration)
public func wait(timeout!: Duration = Duration.Max): Unit
功能:线程进入 Barrier 等待点。
如果 Barrier 对象所有调用 wait 的次数(即进入等待点的线程数)等于初始值,那么唤醒所有等待的线程;如果调用 wait 方法次数仍小于初始值,那么当前线程进入阻塞状态直到被唤醒或者等待时间超过 timeout;如果调用 wait 次数已大于初始值,那么线程继续执行。
参数:
- timeout!: Duration - 阻塞时等待的最大时长,其默认值为 Duration.Max。
class Monitor (deprecated)
public class Monitor <: ReentrantMutex {
public init()
}
功能:提供使线程阻塞并等待来自另一个线程的信号以恢复执行的功能。
这是一种利用共享变量进行线程同步的机制,当一些线程因等待共享变量的某个条件成立而挂起时,另一些线程改变共享的变量,使条件成立, 然后执行唤醒操作。这使得挂起的线程被唤醒后可以继续执行。
注意:
未来版本即将废弃,使用 Condition 替代。
父类型:
init()
public init()
功能:通过默认构造函数创建 Monitor (deprecated)。
func notify()
public func notify(): Unit
功能:唤醒一个等待在该 Montior 上的线程。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func notifyAll()
public func notifyAll(): Unit
功能:唤醒所有等待在该 Montior 上的线程。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func wait(Duration)
public func wait(timeout!: Duration = Duration.Max): Bool
功能:当前线程挂起,直到对应的 notify 函数被调用,或者挂起时间超过 timeout。
说明:
线程在进入等待时会释放对应的互斥锁,被唤醒后再次持有互斥锁。
参数:
- timeout!: Duration - 挂起时间,其默认值为 Duration.Max。
返回值:
- Bool - 如果 Monitor (deprecated) 被其他线程唤醒,返回
true;如果超时,则返回false。
异常:
- IllegalArgumentException - 如果
timeout小于等于 Duration.Zero,抛出异常。 - IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
class MultiConditionMonitor (deprecated)
public class MultiConditionMonitor <: ReentrantMutex {
public init()
}
功能:提供对同一个互斥锁绑定多个条件变量的功能。
注意:
- 未来版本即将废弃,使用 Mutex 替代。
- 该类应仅当在 Monitor (deprecated) 类不足以实现高级并发算法时被使用。
- 初始化时,MultiConditionMonitor (deprecated) 没有与之相关的条件变量。
- 每次调用
newCondition将创建一个新的等待队列并与当前对象关联,并返回ConditionID (deprecated)类型实例作为唯一标识符。
父类型:
init()
public init()
功能:通过默认构造函数创建 MultiConditionMonitor (deprecated)。
func newCondition()
public func newCondition(): ConditionID
功能:创建一个与该 Monitor (deprecated) 相关的 ConditionID (deprecated),可能被用来实现 “单互斥体多等待队列” 的并发原语。
返回值:
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func notify(ConditionID)
public func notify(condID: ConditionID): Unit
功能:唤醒等待在所指定的条件变量的线程(如果有)。
参数:
- condID: ConditionID - 条件变量。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,或
condID不是由该 MultiConditionMonitor (deprecated) 实例通过newCondition函数创建时,抛出异常。
func notifyAll(ConditionID)
public func notifyAll(condID: ConditionID): Unit
功能:唤醒所有等待在所指定的条件变量的线程(如果有)。
参数:
- condID: ConditionID - 条件变量。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,或
condID不是由该 MultiConditionMonitor (deprecated) 实例通过newCondition函数创建时,抛出异常。
func wait(ConditionID, Duration)
public func wait(condID: ConditionID, timeout!: Duration = Duration.Max): Bool
功能:当前线程挂起,直到对应的 notify 函数被调用。
说明:
线程在进入等待时会释放对应的互斥锁,被唤醒后再次持有互斥锁。
参数:
- condID: ConditionID - 条件变量。
- timeout!: Duration - 挂起时间,其默认值为 Duration.Max。
返回值:
- Bool - 如果该 Monitor (deprecated) 指定的条件变量被其他线程唤醒,返回
true;如果超时,则返回false。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,或者挂起时间超过
timeout或condID不是由该 MultiConditionMonitor (deprecated) 实例通过newCondition函数创建时,抛出异常。 - IllegalArgumentException - 如果
timeout小于等于 Duration.Zero,抛出异常。
class Mutex
public class Mutex <: UniqueLock {
public init()
}
功能:提供可重入互斥锁相关功能。
可重入互斥锁的作用是对临界区加以保护,使得任意时刻最多只有一个线程能够执行临界区的代码。 当一个线程试图获取一个已被其他线程持有的锁时,该线程会被阻塞,直到锁被释放,该线程才会被唤醒,可重入是指线程获取该锁后可再次获得该锁。
注意:
- 在访问共享数据之前,必须尝试获取锁。
- 处理完共享数据后,必须进行解锁,以便其他线程可以获得锁。
父类型:
init()
public init()
功能:创建可重入互斥锁。
异常:
- IllegalSynchronizationStateException - 当出现系统错误时,抛出异常。
func condition()
public func condition(): Condition
功能:创建一个与该 Mutex 相关的 Condition。
可能被用来实现 “单 Lock 多等待队列” 的并发原语。
返回值:
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
func lock()
public func lock(): Unit
功能:锁定互斥体,如果互斥体已被锁定,则阻塞。
func tryLock()
public func tryLock(): Bool
功能:尝试锁定互斥体。
返回值:
- Bool - 如果互斥体已被锁定,则返回
false;反之,则锁定互斥体并返回true。
func unlock
public func unlock(): Unit
功能:解锁互斥体。
如果互斥体被重复加锁了 N 次,那么需要调用 N 次该函数来完全解锁,一旦互斥体被完全解锁,如果有其他线程阻塞在此锁上,那么唤醒它们中的一个。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
class ReadWriteLock
public class ReadWriteLock {
public init(fair!: Bool = false)
}
功能:提供可重入读写锁相关功能。
它和普通互斥锁的差异在于:读写锁同时携带两个互斥锁,分别为“读锁”以及“写锁”,并且它允许多个线程同时持有读锁。
读写锁的特殊性质说明:
- 写互斥性:只有唯一的线程能够持有写锁。当一个线程持有写锁,而其他线程再次获取锁(读锁或是写锁)时将被阻塞。
- 读并发性:允许多个线程同时持有读锁。当一个线程持有读锁,其他线程仍然可以获取读锁。但其他线程获取写锁时将被阻塞。
- 可重入性:一个线程可以重复获取锁。
- 当线程已持有写锁时,它可以继续获取写锁或者读锁。只有当锁释放操作和获取操作一一对应时,锁才被完全释放。
- 当线程已持有读锁时,它可以继续获取读锁。当锁释放操作和获取操作一一对应时,锁才被完全释放。注意,不允许在持有读锁的情况下获取写锁,这将抛出异常。
- 锁降级:一个线程在经历“持有写锁--持有读锁--释放写锁”后,它持有的是读锁而不再是写锁。
- 读写公平性:读写锁支持两种不同的模式,分别为“公平”及“非公平”模式。
- 在非公平模式下,读写锁对线程获取锁的顺序不做任何保证。
- 在公平模式下,当线程获取读锁时(当前线程未持有读锁),如果写锁已被获取或是存在线程等待写锁,那么当前线程无法获取读锁并进入等待。
- 在公平模式下,写锁释放会优先唤醒所有读线程、读锁释放会优先唤醒一个等待写锁的线程。当存在多个线程等待写锁,它们之间被唤醒的先后顺序并不做保证。
prop readLock
public prop readLock: Lock
功能:获取读锁。
类型:Lock
prop writeLock
public prop writeLock: UniqueLock
功能:获取写锁。
类型:UniqueLock
init(Bool)
public init(fair!: Bool = false)
功能:构造读写锁。
参数:
- fair!: Bool - 读写锁是否为公平模式,默认值为
false,即构造 “非公平” 的读写锁。
func isFair()
public func isFair(): Bool
功能:获取读写锁是否为 “公平” 模式。
返回值:
- Bool -
true表示 “公平” 模式,否则表示 “非公平” 模式。
class ReentrantMutex (deprecated)
public open class ReentrantMutex <: IReentrantMutex {
public init()
}
功能:提供可重入锁相关功能。
可重入互斥锁的作用是对临界区加以保护,使得任意时刻最多只有一个线程能够执行临界区的代码。 当一个线程试图获取一个已被其他线程持有的锁时,该线程会被阻塞,直到锁被释放,该线程才会被唤醒,可重入是指线程获取该锁后可再次获得该锁。
注意:
- 未来版本即将废弃,使用 Mutex 替代。
- ReentrantMutex (deprecated) 是内置的互斥锁,开发者需要保证不继承它。
- 在访问共享数据之前,必须尝试获取锁。
- 处理完共享数据后,必须进行解锁,以便其他线程可以获得锁。
父类型:
init()
public init()
功能:创建可重入互斥锁。
异常:
- IllegalSynchronizationStateException - 当出现系统错误时,抛出异常。
func lock()
public open func lock(): Unit
功能:锁定互斥体,如果互斥体已被锁定,则阻塞。
func tryLock()
public open func tryLock(): Bool
功能:尝试锁定互斥体。
返回值:
- Bool - 如果互斥体已被锁定,则返回
false;反之,则锁定互斥体并返回true。
func unlock
public open func unlock(): Unit
功能:解锁互斥体。
如果互斥体被重复加锁了 N 次,那么需要调用 N 次该函数来完全解锁,一旦互斥体被完全解锁,如果有其他线程阻塞在此锁上,那么唤醒它们中的一个。
异常:
- IllegalSynchronizationStateException - 如果当前线程没有持有该互斥体,抛出异常。
class ReentrantReadMutex (deprecated)
public class ReentrantReadMutex <: ReentrantMutex
功能:提供可重入读写锁中的读锁类型。
注意:
未来版本即将废弃,使用 Lock 替代。
父类型:
func lock()
public func lock(): Unit
功能:获取读锁。
注意:
- 在公平模式下,如果没有其他线程持有或等待写锁,或是当前线程已持有读锁,则立即持有读锁;否则,当前线程进入等待状态。
- 在非公平模式下,如果没有其他线程持有或等待写锁,则立即持有读锁;如果有其他线程持有写锁,当前线程进入等待状态;否则,线程是否能立即持有读锁不做保证。
- 多个线程可以同时持有读锁并且一个线程可以重复多次持有读锁;如果一个线程持有写锁,那么它仍可以持有读锁。
func tryLock()
public func tryLock(): Bool
功能:尝试获取读锁。该方法获取读锁时并不遵循公平模式。
返回值:
- Bool - 若成功获取读锁,返回
true;若未能获取读锁,返回false。
func unlock()
public func unlock(): Unit
功能:释放读锁。如果一个线程多次持有读锁,那么仅当释放操作和获取操作数量相同时才释放读锁;如果读锁被释放并且存在线程等待写锁,那么唤醒其中一个线程。
异常:
- IllegalSynchronizationStateException - 当前线程未持有读锁,那么将抛出异常。
class ReentrantReadWriteMutex (deprecated)
public class ReentrantReadWriteMutex {
public init(mode!: ReadWriteMutexMode = ReadWriteMutexMode.Unfair)
}
功能:提供可重入读写锁相关功能。
它和普通互斥锁的差异在于:读写锁同时携带两个互斥锁,分别为“读锁”以及“写锁”,并且它允许多个线程同时持有读锁。
注意:
未来版本即将废弃,使用 ReadWriteLock 替代。
读写锁的特殊性质说明:
- 写互斥性:只有唯一的线程能够持有写锁。当一个线程持有写锁,而其他线程再次获取锁(读锁或是写锁)时将被阻塞。
- 读并发性:允许多个线程同时持有读锁。当一个线程持有读锁,其他线程仍然可以获取读锁。但其他线程获取写锁时将被阻塞。
- 可重入性:一个线程可以重复获取锁。
- 当线程已持有写锁时,它可以继续获取写锁或者读锁。只有当锁释放操作和获取操作一一对应时,锁才被完全释放。
- 当线程已持有读锁时,它可以继续获取读锁。当锁释放操作和获取操作一一对应时,锁才被完全释放。注意,不允许在持有读锁的情况下获取写锁,这将抛出异常。
- 锁降级:一个线程在经历“持有写锁--持有读锁--释放写锁”后,它持有的是读锁而不再是写锁。
- 读写公平性:读写锁支持两种不同的模式,分别为“公平”及“非公平”模式。
- 在非公平模式下,读写锁对线程获取锁的顺序不做任何保证。
- 在公平模式下,当线程获取读锁时(当前线程未持有读锁),如果写锁已被获取或是存在线程等待写锁,那么当前线程无法获取读锁并进入等待。
- 在公平模式下,写锁释放会优先唤醒所有读线程、读锁释放会优先唤醒一个等待写锁的线程。当存在多个线程等待写锁,它们之间被唤醒的先后顺序并不做保证。
prop readMutex
public prop readMutex: ReentrantReadMutex
功能:获取读锁。
类型:ReentrantReadMutex (deprecated)
prop writeMutex
public prop writeMutex: ReentrantWriteMutex
功能:获取写锁。
类型:ReentrantWriteMutex (deprecated)
init(ReadWriteMutexMode)
public init(mode!: ReadWriteMutexMode = ReadWriteMutexMode.Unfair)
功能:构造读写锁。
参数:
- mode!: ReadWriteMutexMode (deprecated) - 读写锁模式,默认值为
Unfair,即构造“非公平”的读写锁。
class ReentrantWriteMutex (deprecated)
public class ReentrantWriteMutex <: ReentrantMutex
功能:提供可重入读写锁中的写锁类型。
注意:
未来版本即将废弃,使用 UniqueLock 替代。
父类型:
func lock()
public func lock(): Unit
功能:获取写锁。只允许唯一线程能够持有写锁,且该线程能多次重复持有写锁。如果存在其他线程持有写锁或是读锁,那么当前线程进入等待状态。
异常:
- IllegalSynchronizationStateException - 当前线程已持有读锁。
func tryLock()
public func tryLock(): Bool
功能:尝试获取写锁。该方法获取读锁时并不遵循公平模式。
返回值:
- Bool - 若成功获取写锁,返回
true;若未能获取写锁,返回false。
func unlock()
public func unlock(): Unit
功能:释放写锁。
注意:
- 如果一个线程多次持有读锁,那么仅当释放操作和获取操作数量相同时才释放读锁;如果读锁被释放并且存在线程等待写锁,那么唤醒其中一个线程。
- 在公平模式下,如果写锁被释放并且存在线程等待读锁,那么优先唤醒这些等待线程;如果没有线程等待读锁,但存在线程等待写锁,那么唤醒其中一个线程。
- 在非公平模式下,如果写锁被释放,优先唤醒等待写锁的线程还是等待读锁的线程不做保证,交由具体实现决定。
异常:
- IllegalSynchronizationStateException - 当前线程未持有写锁。
class Semaphore
public class Semaphore {
public init(count: Int64)
}
功能:提供信号量相关功能。
Semaphore 可以被视为携带计数器的 Monitor (deprecated),常用于控制并发访问共享资源的线程数量。
prop count
public prop count: Int64
功能:返回当前内部计数器的值。
类型:Int64
init(Int64)
public init(count: Int64)
功能:创建一个 Semaphore 对象并初始化内部计数器的值。
参数:
异常:
- IllegalArgumentException - 参数 count 为负数时抛出异常。
func acquire(Int64)
public func acquire(amount!: Int64 = 1): Unit
功能:向 Semaphore 对象获取指定值。
如果当前计数器小于要求的数值,那么当前线程将被阻塞,直到获取满足数量的值后才被唤醒。
参数:
- amount!: Int64 - 向对象内部计数器中获取的数值,默认值为 1。
异常:
- IllegalArgumentException - 参数
amount为负数,或大于初始值。
func release(Int64)
public func release(amount!: Int64 = 1): Unit
功能:向 Semaphore 对象释放指定值。
如果内部计数器在累加释放值后能够满足当前阻塞在 Semaphore 对象的线程,那么将得到满足的线程唤醒;内部计数器的值不会大于初始值,即如果计数器的值在累加后大于初始值,那么仍被设置为初始值。所有在调用 release 之前的操作都先发生于调用 acquire/tryAcquire 之后的操作。
参数:
- amount!: Int64 - 向对象内部计数器中释放的数值,默认值为 1。
返回值:
- Unit - 如果当前计数器小于要求的数值,则获取失败并返回
false;成功获取值时返回true。
异常:
- IllegalArgumentException - 参数
amount为负数,或大于初始值。
func tryAcquire(Int64)
public func tryAcquire(amount!: Int64 = 1): Bool
功能:尝试向 Semaphore 对象获取指定值。
该方法不会阻塞线程。如果有多个线程并发执行获取操作,则无法保证线程间的获取顺序。
参数:
- amount!: Int64 - 向对象内部计数器中获取的数值,默认值为 1。
返回值:
- Bool - 如果当前计数器小于要求的数值,则获取失败并返回
false;成功获取值时返回true。
异常:
- IllegalArgumentException - 参数
amount为负数,或大于初始值。
class SyncCounter
public class SyncCounter {
public init(count: Int64)
}
功能:提供倒数计数器功能。
线程可以等待计数器变为零。
prop count
public prop count: Int64
功能:获取计数器的当前值。
类型:Int64
init(Int64)
public init(count: Int64)
功能:创建倒数计数器。
参数:
异常:
- IllegalArgumentException - 如果参数 count 为负数。
func dec()
public func dec(): Unit
功能:计数器减一。
如果计数器变为零,那么唤醒所有等待的线程;如果计数器已经为零,那么数值保持不变。
func waitUntilZero(Duration)
public func waitUntilZero(timeout!: Duration = Duration.Max): Unit
功能:当前线程等待直到计数器变为零,或等待时间超过 timeout。
参数:
- timeout!: Duration - 阻塞时等待的最大时长,其默认值为 Duration.Max。
class Timer
public class Timer <: Equatable<Timer> & Hashable
功能:提供定时器功能。
用于在指定时间点或指定时间间隔后,执行指定任务一次或多次。
注意:
- Timer 隐式包含了
spawn操作,即,每个 Timer 会创建一个线程用于执行该 Timer 关联的 Task。- 每个 Timer 只能在初始化时绑定一个 Task,初始化完成后,无法重置关联的 Task。
- 只有关联 Task 执行完毕,或 使用
cancel接口主动取消 Timer,Timer 的生命周期才会结束,之后才能被 GC 回收。换句话说,在 Timer 关联的 Task 执行完毕或 Timer 被主动取消前,Timer 实例均不会被 GC 回收,从而确保关联 Task 可以被正常执行。- 系统繁忙时,Task 的触发时间可能会被影响。Timer 不保证 Task 的触发时间一定准时。Timer 保证 Task 的触发时间小于等于当前时间。
- Timer 不会主动捕获关联 Task 抛出的异常。只要 Task 有未被捕获的异常,Timer 就会失效。
- Timer 通常按使用方式分为 一次性任务定时器 和 重复性任务定时器两种,一次性任务定时器 Task 只会执行一次,重复性任务定时器 Task 会按指定周期执行, 直到使用
cancel接口主动取消 或者 达到 Timer 创建时指定的结束条件。
父类型:
static func after(Duration, ()->Option<Duration>)
public static func after(delay: Duration, task: () -> Option<Duration>): Timer
功能:初始化一个 Timer,关联的 Task 被调度执行的次数取决于它的返回值。如果定时器第一次触发的时间点小于当前时间,关联的 Task 会立刻被调度执行。如果关联 Task 的返回值为 Option.None,该 Timer 将会失效,并停止调度关联 Task。如果关联 Task 的返回值为 Option.Some(v) 且 v 大于 Duration.Zero,下次运行前的最小时间间隔将被设置为 v。否则,关联 Task 会立刻再次被调度执行。
参数:
返回值:
static func once(Duration, ()->Unit)
public static func once(delay: Duration, task: ()->Unit): Timer
功能:设置并启动一次性定时任务,返回控制这个任务的 Timer 对象实例。
参数:
- delay: Duration - 从现在开始到 Task 被执行的时间间隔。取值范围 [Duration.Min, Duration.Max],小于或等于 Duration.Zero 时 Task 将立即被执行。
- task: ()->Unit - 待定时执行的任务。
返回值:
- Timer - 生成的对象实例。
示例:
import std.time.MonoTime
main() {
let start = MonoTime.now()
Timer.once(Duration.second, {=>
println("Tick at: ${MonoTime.now() - start}")
})
sleep(Duration.second * 2)
0
}
运行结果:
Tick at: 1s2ms74us551ns
static func repeat(Duration, Duration, ()->Unit, CatchupStyle)
public static func repeat(delay: Duration, interval: Duration, task: ()->Unit, style!: CatchupStyle = Burst): Timer
功能:设置并启动重复性定时任务,返回控制这个任务的 Timer 对象实例。
参数:
- delay: Duration - 从现在开始到 Task 被执行的时间间隔。取值范围 [Duration.Min, Duration.Max],小于或等于 Duration.Zero 时 Task 将立即被执行。
- interval: Duration - 两次 Task 之间的时间间隔。取值范围 (Duration.Zero, Duration.Max]。
- task: ()->Unit - 待定时执行的任务。
- style!: CatchupStyle - 追平策略,默认 Burst。当 Task 执行时间过长时,后续任务执行时间点可能发生延迟,不同的追平策略适用于不同的场景,详见 CatchupStyle 说明。
返回值:
- Timer - 生成的对象实例。
异常:
- IllegalArgumentException - 当
interval小于等于 Duration.Zero 时,抛出异常。
示例:
import std.sync.{Timer}
import std.time.{MonoTime}
main() {
let start = MonoTime.now()
let timer = Timer.repeat(Duration.second, Duration.second, {=>
println("Tick at: ${MonoTime.now() - start}")
})
sleep(Duration.second * 5)
timer.cancel()
0
}
运行结果:
Tick at: 1s2ms72us188ns
Tick at: 2s4ms185us160ns
Tick at: 3s6ms275us464ns
Tick at: 4s8ms18us399ns
Tick at: 5s9ms621us394ns
static func repeatDuring(Duration, Duration, Duration, ()->Unit, CatchupStyle)
public static func repeatDuring(period: Duration, delay: Duration, interval: Duration, task: () -> Unit, style!: CatchupStyle = Burst): Timer
功能:设置并启动重复性定时任务,指定重复周期的最大持续时间,返回控制这个任务的 Timer 对象实例。
参数:
- period: Duration - 重复周期的最大持续时间,从 delay 之后开始计时。取值范围 (Duration.Zero, Duration.Max]。
- delay: Duration - 从现在开始到 Task 被执行的时间间隔。取值范围 [Duration.Min, Duration.Max],小于或等于 Duration.Zero时 Task 将立即被执行。
- interval: Duration - 两次 Task 之间的时间间隔。取值范围 (Duration.Zero, Duration.Max]。
- task: ()->Unit - 待定时执行的任务。
- style!: CatchupStyle - 追平策略,默认 Burst。当 Task 执行时间过长时,后续任务执行时间点可能发生延迟,不同的追平策略适用于不同的场景,详见 CatchupStyle 说明。
返回值:
- Timer - 生成的对象实例。
异常:
- IllegalArgumentException: 当 period 小于等于 Duration.Zero 或 interval 小于等于 Duration.Zero 时,抛出异常。
示例:
import std.sync.{Timer}
import std.time.{MonoTime}
main() {
let start = MonoTime.now()
Timer.repeatDuring(Duration.second * 5, Duration.second, Duration.second, {=>
println("Tick at: ${MonoTime.now() - start}")
})
sleep(Duration.second * 7)
0
}
运行结果:
Tick at: 1s2ms372us626ns
Tick at: 2s4ms714us879ns
Tick at: 3s6ms769us623ns
Tick at: 4s8ms780us235ns
Tick at: 5s660us104ns
Tick at: 6s3ms257us508ns
static func repeatTimes(Int64, Duration, Duration, ()->Unit, CatchupStyle)
public static func repeatTimes(count: Int64, delay: Duration, interval: Duration, task: () -> Unit, style!: CatchupStyle = Burst): Timer
功能:设置并启动重复性定时任务,指定 Task 最大执行次数,返回控制这个任务的 Timer 对象实例。
参数:
- count: Int64 - Task 最大执行次数。取值范围 (0, Int64.Max]。
- delay: Duration - 从现在开始到 Task 被执行的时间间隔。取值范围 [Duration.Min, Duration.Max],小于或等于 Duration.Zero 时 Task 将立即被执行。
- interval: Duration - 两次 Task 之间的时间间隔。取值范围 (Duration.Zero, Duration.Max]。
- task: ()->Unit - 待定时执行的任务。
- style!: CatchupStyle - 追平策略,默认 Burst。当 Task 执行时间过长时,后续任务执行时间点可能发生延迟,不同的追平策略适用于不同的场景,详见 CatchupStyle 说明。
返回值:
- Timer - 生成的对象实例。
异常:
- IllegalArgumentException - 当 count <= 0 或 interval 小于等于 Duration.Zero 时,抛出异常。
示例:
import std.sync.{Timer}
import std.time.{MonoTime}
main() {
let start = MonoTime.now()
Timer.repeatTimes(3, Duration.second, Duration.second, {=>
println("Tick at: ${MonoTime.now() - start}")
})
sleep(Duration.second * 4)
0
}
运行结果:
Tick at: 1s2ms855us251ns
Tick at: 2s5ms390us18ns
Tick at: 3s7ms935us552ns
func cancel()
public func cancel(): Unit
功能:取消该 Timer,关联 Task 将不再被调度执行。
如果调用该函数时关联 Task 正在执行,不会打断当前运行。该函数不会阻塞当前线程。调用该函数多次等同于只调用一次。
func hashCode()
public func hashCode(): Int64
功能:获取 Timer 对象的哈希值。
返回值:
- Int64 - 对象的哈希值。
operator func !=(Timer)
public operator func !=(rhs: Timer): Bool
功能:判断当前 Timer 与入参 rhs 指定的 Timer 是否不是同一个实例。
参数:
返回值:
operator func ==(Timer)
public operator func ==(rhs: Timer): Bool
功能:判断当前 Timer 与入参 rhs 指定的 Timer 是否是同一个实例。
参数:
返回值:
未来版本即将废弃,使用 load() 替代。
枚举
enum CatchupStyle
public enum CatchupStyle {
| Delay
| Burst
| Skip
}
功能:表示不同的重复性任务定时器需要使用的追平策略。
当任务执行时间过长时,后续任务执行时间点可能发生延迟,不同的追平策略适用于不同的场景:
Delay适用于不关心任务开始的时间点,需要两次任务执行之间的时间间隔固定的场景。Burst适用于定时任务之间有先后关系,需要依次执行任务的场景。Skip适用于定时任务之间没有先后关系,可以忽略中间任务的场景。
示例:
该示例创建了一个 Timer,该 Timer 会执行 3 次任务,从创建开始 1 秒后开始执行,每间隔 1 秒执行下一次任务,追平策略采用 Delay。
import std.sync.{Timer, CatchupStyle}
import std.time.{MonoTime}
main() {
let start = MonoTime.now()
Timer.repeatTimes(3, Duration.second, Duration.second, {=>
println("Tick at: ${MonoTime.now() - start}")
}, style: Delay)
sleep(Duration.second * 4)
0
}
Burst
Burst
功能:该策略下,每个任务的开始时间间隔固定,当任务执行时间大于设定的任务触发间隔时间时,依次执行错过的时间点上的任务,直到追平。
Delay
Delay
功能:该策略下,上一次任务结束与下一次任务开始的时间间隔总是固定的,即下一次任务的开始时间 = 上一次任务的结束时间 + 设定的任务触发间隔时间。
Skip
Skip
功能:该策略下,每个任务的开始时间间隔固定,当任务执行时间大于设定的任务触发间隔时间时,将跳过后面错过的时间点,以尽快追平。
enum MemoryOrder (deprecated)
public enum MemoryOrder {
| SeqCst
}
功能:内存顺序类型枚举。
内存顺序主要是指内存的读(load)写(store)操作的顺序,出于性能优化考虑编译器或CPU可能对指令进行重新排序,内存顺序枚举用来表示排序策略。
注意:
未来版本即将废弃。
SeqCst
SeqCst
功能:用于表示顺序一致的顺序,即禁止了指令重排,确保该原子操作之前的所有原子操作都先于该操作之后的原子操作完成。
enum ReadWriteMutexMode (deprecated)
public enum ReadWriteMutexMode {
| Unfair
| Fair
}
功能:读写锁公平模式枚举。
锁的公平性是指,当同时有多个线程在等同一把锁时,是否按照等待顺序依次获得锁。
注意:
未来版本即将废弃。
Fair
Fair
功能:用于表示读写锁公平模式,当锁被释放时,最早等待锁的线程先获得锁。
Unfair
Unfair
功能:用于表示读写锁非公平模式,当锁被释放时,任一等待中的线程可能获得锁。
结构体
struct ConditionID (deprecated)
public struct ConditionID
功能:用于表示互斥锁的条件变量,详见 MultiConditionMonitor (deprecated)。
注意:
未来版本即将废弃,使用 Condition 替代。
异常类
class IllegalSynchronizationStateException
public class IllegalSynchronizationStateException <: Exception {
public init()
public init(message: String)
}
功能:此类为非法同步状态异常。
父类型:
init()
public init()
功能:创建一个 IllegalSynchronizationStateException 实例。
init(String)
public init(message: String)
功能:创建一个 IllegalSynchronizationStateException 实例,其信息由参数 message 指定。
参数:
- message: String - 预定义消息。
Atomic、Monitor 和 Timer 的使用
Atomic 的使用
示例:
在多线程程序中,使用原子操作实现计数:
import std.sync.*
import std.time.*
import std.collection.*
let count = AtomicInt64(0)
main(): Int64 {
let list = ArrayList<Future<Int64>>()
/* 创建 1000 个线程 */
for (_ in 0..1000) {
let fut = spawn {
sleep(Duration.millisecond) /* 睡眠 1 毫秒 */
count.fetchAdd(1)
}
list.add(fut)
}
/* 等待所有线程完成 */
for (f in list) {
f.get()
}
var val = count.load()
println("count = ${val}")
return 0
}
运行结果:
count = 1000
Monitor (deprecated) 的使用
注意:
未来版本即将废弃,使用 Condition 替代。
示例:
在不同线程中,使用 Monitor 实现挂起和唤醒线程:
import std.sync.*
var mon = Monitor()
var flag: Bool = true
main(): Int64 {
let fut = spawn {
mon.lock()
while (flag) {
println("New thread: before wait")
mon.wait()
println("New thread: after wait")
}
mon.unlock()
}
/* 睡眠 10 毫秒,以确保新线程可以执行 */
sleep(10 * Duration.millisecond)
mon.lock()
println("Main thread: set flag")
flag = false
mon.unlock()
println("Main thread: notify")
mon.lock()
mon.notifyAll()
mon.unlock()
/* 等待新线程完成 */
fut.get()
return 0
}
运行结果:
New thread: before wait
Main thread: set flag
Main thread: notify
New thread: after wait
Mutex 的使用
示例:
在不同线程中,使用 Mutex 锁和解锁:
import std.sync.*
var mt = Mutex()
var con = synchronized(mt) { mt.condition() }
var flag: Bool = true
main(): Int64 {
let fut = spawn {
mt.lock()
while (flag) {
println("New thread: before wait")
con.wait()
println("New thread: after wait")
}
mt.unlock()
}
/* 睡眠 10 毫秒,以确保新线程可以执行 */
sleep(10 * Duration.millisecond)
mt.lock()
println("Main thread: set flag")
flag = false
mt.unlock()
println("Main thread: notify")
mt.lock()
con.notifyAll()
mt.unlock()
/* 等待新线程完成 */
fut.get()
return 0
}
运行结果:
New thread: before wait
Main thread: set flag
Main thread: notify
New thread: after wait
Condition 的使用
示例:
使用 Condition 实现挂起和唤醒线程:
import std.sync.{Mutex, Condition, AtomicBool}
var mutex = Mutex()
var flag = AtomicBool(true)
main(): Int64 {
let condition: Condition
synchronized(mutex) {
condition = mutex.condition() // 在持有锁的情况下生成 Condition 实例
}
let fut = spawn {
synchronized(mutex) {
println("New thread: before wait")
condition.waitUntil {=> !flag.load() } // 挂起当前线程,等待直到 flag 值为 true
println("New thread: after wait")
}
}
/* 睡眠 10 毫秒,以确保新线程可以执行 */
sleep(10 * Duration.millisecond)
synchronized(mutex) { // 等待子线程挂起
println("Main thread: set flag")
flag.store(false) // 修改 flag 值
println("Main thread: notify")
condition.notifyAll() // 唤醒等待中的子线程
}
/* 等待新线程完成 */
fut.get()
return 0
}
运行结果:
New thread: before wait
Main thread: set flag
Main thread: notify
New thread: after wait
Timer 的使用
示例:
使用 Timer 创建一次性和重复性任务:
import std.sync.*
main(): Int64 {
let count = AtomicInt8(0)
Timer.once(50 * Duration.millisecond) { =>
println("run only once")
count.fetchAdd(1)
}
let timer = Timer.repeat(100 * Duration.millisecond, 200 * Duration.millisecond, { =>
println("run repetitively")
count.fetchAdd(10)
})
sleep(Duration.second)
timer.cancel()
sleep(500 * Duration.millisecond)
println("count = ${count.load()}")
0
}
运行结果:
run only once
run repetitively
run repetitively
run repetitively
run repetitively
run repetitively
count = 51
std.time
功能介绍
time 包提供了与时间相关的类型,包括日期时间,时间间隔,单调时间和时区等,并提供了计算和比较的功能。
时间字符串格式
字符串解析时间有以下要求:
-
字符串必须包含描述具体年月日的信息:如公元年(y)+ 月(M)和日(d),或公元年(y)和一年中的第几天(D)。
-
如果不包含时分秒的描述信息,则均默认为 0;如果不包含时区信息,则默认为当前时区 TimeZone.Local。
-
对同一字母表示的格式不允许两次取值,如不允许两次对公元年(y)格式的赋值;表示时区的 O 和 Z 两种格式同样不允许一起出现。
-
其余的部分字母的格式会作为辅助信息验证,如“2023-04-24-Mon”使用格式“yyyy-MM-dd-www”进行解析时,会验证“Mon”的正确性。
字母含义
| 字母 | 含义 |
|---|---|
| a | 上下午 |
| y | 公元年 |
| Y | 基于周的年 |
| M | 月份 |
| d | 日 |
| D | 以年算的天数 |
| w | 以周算的天 |
| W | 基于 ISO-8601 标准的周 |
| h | 12小时制的小时 |
| H | 24小时制的小时 |
| m | 分钟数 |
| s | 秒数 |
| S | 小于一秒的部分 |
| z | 时区名和时区 ID |
| Z | 距零时区偏移 |
| O | 时区偏移 |
| G | 纪年 |
各字母对应规则如下。
规则
上下午
合法个数为 1,表示上午或者下午,固定为“AM”或“PM”。
年
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1、3、4 | 解析 4 位数年份,如 2023、0001等。 | 输出最少 4 位数年份,如 2023、0001、99999 等,不足 4 位则补 0。 |
| 2 | 解析 2 位数年份,如 23、69 等,其中 xx >= 69 的会解析为 19xx,否则为 20xx,负数同理。 | 输出 2 位或 4 位以上个数年份,如 23、69 等,其中 [1969, 1999] 会输出为 [69, 99],[2000, 2068] 会输出为 [00, 68],负数同理。其余情况至少输出 4 位,不足 4 位则补 0。 |
| 5 ~ 9 | 解析对应数量位数年份。 | 输出对应数量位数年份,不足则补 0。 |
月
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析 1 ~ 2 位数字,如 1、 01、 11 等。 | 输出 1 ~ 2 位数字,如 1、 11 等。 |
| 2 | 解析 2 位数字,如 01、11 等。 | 输出 2 位数字,如 01、11 等。 |
| 3 | 解析简写的月,如 Jan、Dec 等。 | 输出简写的月,如 Jan、Dec 等。 |
| 4 | 解析完整书写的月,如 January、December 等。 | 输出完整书写的月,如 January、December 等。 |
数值
不同 number 类型数据的表示范围根据实际值大小变动。
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析 1 ~ 2 位数字,如 1、01、11 等。 | 输出 1 ~ 2 位数字,如 1、 11 等。 |
| 2 | 解析 2 位数字,如 01、11 等。 | 输出 2 位数字,如 01、11 等。 |
小数秒
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析 3 位数字,如 001、123 等作为毫秒。 | 输出 3 位数字,如 001、123 等作为毫秒。 |
| 2 | 解析 6 位数字,如 000001、123456 等作为微秒。 | 输出 6 位数字,如 000001、123456 等作为微秒。 |
| 3 | 解析 9 位数字,如 000000001、123456789 等作为纳秒。 | 输出 9 位数字,如 000000001、123456789 等作为纳秒。 |
时区偏移量
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析格式如:+08、-08 等。 | 输出格式如:+08、-08 等,若偏移量不为整小时,则会截断。 |
| 2 | 解析格式如:+08:00、-08:59 等。 | 输出格式如:+08:00、-08:59 等,偏移量不为整分钟,则会截断。 |
| 3 | 解析格式如:+08:00:00、-08:59:59 等。 | 输出格式如:+08:00:00、-08:59:59 等。 |
| 4 | 解析格式如:+08:00:00、-08:59:59 等。 | 输出格式如:case2 或 case3、偏移量为 0 时,输出 Z。 |
时区名和时区 ID
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1、2、3 | 解析格式如:CST、GMT 等。 | 输出格式如:CST、GMT 等。 |
| 4 | 解析时区 ID,格式如:“Asia/Shanghai”等。 | 输出时区 ID,格式如:“Asia/Shanghai”等。 |
距零时区偏移
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析格式如:GMT+0、GMT+10 等。 | 输出格式如:GMT+0、GMT+10 等。 |
| 2 | 解析格式如:GMT+00:00、GMT+10:00 等。 | 输出格式如:GMT+00:00、GMT+10:00 等。 |
| 3 | 解析格式如:GMT+00:00:00、GMT+10:00:00 等。 | 输出格式如:GMT+00:00:00、GMT+10:00:00 等。 |
| 4 | 数量为 2 或 3 的格式。 | 数量为 2 或 3 的格式。 |
以年算的天数
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析格式如:1、 01、001 等 1 ~ 3 位数字。 | 输出格式如:1、12、123 等 1 ~ 3 位数字。 |
| 2 | 解析格式如:01、001 等 2 ~ 3 位数字。 | 输出格式如:001、012、123 等 2 ~ 3 位数字。 |
以周算的天
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析 1 位数字,如 0、6 等、0 表示周日,其余表示周一至周六。 | 输出 1 位数字,如 0、 6 等、0 表示周日,其余表示周一至周六。 |
| 2 | 解析 2 位数字,如 00、06 等,00 表示周日,其余表示周一至周六。 | 解析 2 位数字,如 00、06 等,00 表示周日,其余表示周一至周六。 |
| 3 | 解析简写的周,如 Sun、Sat 等。 | 解析简写的周,如 Sun、Sat 等。 |
| 4 | 解析完整书写的周,如 Sunday、Saturday 等。 | 解析完整书写的周,如 Sunday、Saturday 等。 |
纪年
| 字母数量 | 解析 | 输出 |
|---|---|---|
| 1 | 解析 A。 | 输出 A。 |
| 2 | 解析 AD。 | 输出 AD。 |
| 3 | 解析 Anno Domini。 | 输出 Anno Domini。 |
API 列表
类
| 类名 | 功能 |
|---|---|
| DateTimeFormat | 提供时间格式的功能,用于解析和生成 DateTime 。 |
| TimeZone | TimeZone 表示时区,记录了某一地区在不同时间较零时区的时间偏移,提供了从系统加载时区、自定义时区等功能。 |
枚举
| 枚举名 | 功能 |
|---|---|
| DayOfWeek | DayOfWeek 表示一周中的某一天,提供了与 Int64 类型转换,相等性判别以及获取枚举值的字符串表示的功能。 |
| Month | Month 用以表示月份,表示一年中的某一月,提供了与 Int64 类型转换和计算,相等性判别以及获取枚举值的字符串表示的功能。 |
结构体
| 结构体名 | 功能 |
|---|---|
| DateTime | DateTime 表示日期时间,是一个描述某一时间点的时间类型,提供了基于时区的日期时间读取、计算、比较、转换,以及序列化和反序列化等功能。 |
| MonoTime | MonoTime 表示单调时间,是一个用来衡量经过时间的时间类型,类似于一直运行的秒表,提供了获取当前时间,计算和比较等功能。 |
异常类
| 异常类名 | 功能 |
|---|---|
| InvalidDataException | InvalidDataException 表示加载时区时的异常。 |
| TimeParseException | TimeParseException 表示解析时间字符串时的异常。 |
类
class DateTimeFormat
public class DateTimeFormat {
public static const RFC1123: String = "www, dd MMM yyyy HH:mm:ss z"
public static const RFC3339: String = "yyyy-MM-ddTHH:mm:ssOOOO"
public static const RFC822: String = "ww dd MMM yy HH:mm:ss z"
public static const RFC850: String = "wwww, dd-MMM-yy HH:mm:ss z"
}
功能:提供时间格式的功能,用于解析和生成 DateTime 。
static const RFC1123
public static const RFC1123: String = "www, dd MMM yyyy HH:mm:ss z"
功能:提供 RFC1123 时间格式,时间字符串格式为 www, dd MMM yyyy HH:mm:ss z。
类型:String
static const RFC3339
public static const RFC3339: String = "yyyy-MM-ddTHH:mm:ssOOOO"
功能:提供 RFC3339 时间格式,时间字符串格式为 yyyy-MM-ddTHH:mm:ssOOOO。
类型:String
static const RFC822
public static const RFC822: String = "ww dd MMM yy HH:mm:ss z"
功能:提供 RFC822 时间格式,时间字符串格式为 ww dd MMM yy HH:mm:ss z。
类型:String
static const RFC850
public static const RFC850: String = "wwww, dd-MMM-yy HH:mm:ss z"
功能:提供 RFC850 时间格式,时间字符串格式为 wwww, ww-MMM-yy HH:mm:ss z。
类型:String
prop format: String (deprecated)
public prop format: String
功能:DateTimeFormat实例的字符串格式。
注意:
未来版本即将废弃不再使用。
类型:String
static func of(String) (deprecated)
public static func of(format: String): DateTimeFormat
功能:根据字符串创建具体的 DateTimeFormat 类型实例。
字符串的具体格式见时间字符串格式
注意:
未来版本即将废弃不再使用。
参数:
- format: String - 字符串格式。
返回值:
- DateTimeFormat - 时间格式。
异常:
- IllegalArgumentException - 当入参格式不符合时间字符串格式中字母数量的规定时,抛出异常。
class TimeZone
public class TimeZone <: ToString & Equatable<TimeZone> {
public static let Local: TimeZone
public static let UTC: TimeZone
public init(id: String, offset: Duration)
}
功能:TimeZone 表示时区,记录了某一地区在不同时间较零时区的时间偏移,提供了从系统加载时区、自定义时区等功能。
父类型:
static let Local
public static let Local: TimeZone
功能:获取本地时区。
Local 从系统环境变量 TZ 中获取时区 ID,并根据该时区 ID 从系统时区文件中加载时区。其行为与函数load相同。
环境变量 TZ 的取值为标准时区 ID 格式(各操作系统遵循相同规范),例如“Asia/Shanghai”。
若环境变量 TZ 未设置或者为空,加载本地时区的规则如下:
- 在 Linux/Unix like 系统上:加载系统路径“/etc/localtime”链接,时区名与“/etc/localtime”指向的相对路径名相同,例如“Asia/Shanghai”。
- 如果上一条执行失败或者在 Windows 系统上,返回 ID 为 “UTC&偏移量” 的时区,例如“Asia/Shanghai”对应的时区为“UTC+08:00”。
类型:TimeZone
static let UTC
public static let UTC: TimeZone
功能:获取 UTC 时区。
类型:TimeZone
prop id
public prop id: String
功能:获取当前 TimeZone 实例所关联的时区 ID。
类型:String
init(String, Duration)
public init(id: String, offset: Duration)
功能:使用指定的时区 ID 和偏移量构造一个自定义 TimeZone 实例。
参数:
- id: String - 时区 ID。使用“/”作为分隔符,例如“Asia/Shanghai”,各操作系统使用相同规范。
- offset: Duration - 相对 UTC 时区的偏移量,精度为秒,向东为正、向西为负。取值范围为 (-25 * Duration.hour, 26 * Duration.hour)。
异常:
- IllegalArgumentException - 当输入
id为空字符串,或offset超出有效区间时,抛出异常。
static func load(String)
public static func load(id: String): TimeZone
功能:从系统中加载参数 id 指定的时区。
说明:
- 在 Linux 和 macOS 系统中,若存在环境变量 CJ_TZPATH,则使用环境变量指定的路径加载时区文件(若存在多个通过分隔符 “:” 分开的环境变量值,则按照分隔路径的先后顺序依次查找时区文件,并加载第一个找到的时区文件),否则从系统时区文件目录(Linux 和 macOS 为 "/usr/share/zoneinfo")加载时区。
- 在 Windows 系统中,用户需下载时区文件并编译,设置环境变量 CJ_TZPATH 指向 zoneinfo 目录(若存在多个通过分隔符 “;” 分开的环境变量值,则按照分隔路径的先后顺序依次查找时区文件,并加载第一个找到的时区文件),否则会导致异常。
参数:
- id: String - 时区 ID。
返回值:
- TimeZone - 时区。
异常:
- IllegalArgumentException - 当参数
id为空,或长度超过 4096 字节,或不符合标准时区 ID 格式时,抛出异常。 - InvalidDataException - 当时区文件加载失败(找不到文件,文件解析失败等)时,抛出异常。
static func loadFromPaths(String, Array<String>)
public static func loadFromPaths(id: String, tzpaths: Array<String>): TimeZone
功能:根据参数 tzpaths 指定的时区文件目录,加载参数 id 指定的时区。
加载时区时,将从第一个被读取成功的时区文件路径中加载时区。时区文件格式需要满足时区信息格式。
参数:
返回值:
- TimeZone - 加载的时区。
异常:
- IllegalArgumentException - 当
id为空,或长度超过 4096 字节,或不符合标准时区 ID 格式时,抛出异常。 - InvalidDataException - 当时区文件加载失败(找不到文件,文件解析失败等)时,抛出异常。
static func loadFromTZData(String, Array<UInt8>)
public static func loadFromTZData(id: String, data: Array<UInt8>): TimeZone
功能:使用指定的时区 ID 和时区数据构造一个自定义 TimeZone 实例。id 可以是任何合法字符串,data 需要满足 IANA 时区文件格式,加载成功时获得 TimeZone 实例,否则抛出异常。
参数:
返回值:
- TimeZone - 加载的时区。
异常:
- IllegalArgumentException - 当
id为空时,抛出异常。 - InvalidDataException - 如果
data解析失败,则抛出异常。
func toString()
public func toString(): String
功能:获取本 TimeZone 实例时区 ID 的字符串表示。
返回值:
- String - 时区 ID 的字符串表示。
operator func !=(TimeZone)
public operator func !=(r: TimeZone): Bool
功能:判断当前 TimeZone 实例的引用是否不等于 r 的引用。
参数:
返回值:
operator func ==(TimeZone)
public operator func ==(r: TimeZone): Bool
功能:判断当前 TimeZone 实例的引用是否等于 r 的引用。
参数:
返回值:
枚举
enum DayOfWeek
public enum DayOfWeek <: ToString & Equatable<DayOfWeek> {
| Sunday
| Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
}
功能:DayOfWeek 表示一周中的某一天,提供了与 Int64 类型转换,相等性判别以及获取枚举值的字符串表示的功能。
父类型:
Friday
Friday
功能:构造一个表示周五的 DayOfWeek 实例。
Monday
Monday
功能:构造一个表示周一的 DayOfWeek 实例。
Saturday
Saturday
功能:构造一个表示周六的 DayOfWeek 实例。
Sunday
Sunday
功能:构造一个表示周日的 DayOfWeek 实例。
Thursday
Thursday
功能:构造一个表示周四的 DayOfWeek 实例。
Tuesday
Tuesday
功能:构造一个表示周二的 DayOfWeek 实例。
Wednesday
Wednesday
功能:构造一个表示周三的 DayOfWeek 实例。
static func of(Int64)
public static func of(dayOfWeek: Int64): DayOfWeek
功能:获取参数 dayOfWeek 对应的 DayOfWeek 实例。
参数:
- dayOfWeek: Int64 - 周几的整数表示,合法范围为 [0, 6]。其中,0 表示周日,1 至 6 表示周一至周六。
返回值:
异常:
- IllegalArgumentException - 当参数
dayOfWeek不在 [0, 6] 范围内时,抛出异常。
func toString()
public func toString(): String
功能:返回当前 DayOfWeek 实例的字符串表示,如 "Monday" 表示周一。
返回值:
func toInteger()
public func toInteger(): Int64
功能:获取当前 DayOfWeek 实例的整数表示,周日表示为 0,周一至周六表示为 1 至 6。
返回值:
func value() (deprecated)
public func value(): Int64
功能:获取当前 DayOfWeek 实例的整数表示,周日表示为 0,周一至周六表示为 1 至 6。
注意:
未来版本即将废弃,可使用 toInteger() 替代。
返回值:
operator func !=(DayOfWeek)
public operator func !=(r: DayOfWeek): Bool
功能:判断当前 DayOfWeek 和 r 是否不为一周中的同一天。
参数:
返回值:
operator func ==(DayOfWeek)
public operator func ==(r: DayOfWeek): Bool
功能:判断当前 DayOfWeek 和 r 是否表示一周中的同一天。
参数:
返回值:
operator func +(Int64)
public operator func +(n: Int64): DayOfWeek
功能:计算基于当前实例 n 天之后(n 为正数时)的表示值。若 n 为负数,则表示当天之前。
参数:
- n: Int64 - 后多少天。
返回值:
- DayOfWeek -
n天后的周数值。
operator func -(Int64)
public operator func -(n: Int64): DayOfWeek
功能:计算基于当前实例 n 天之前(n 为正数时)的表示值。若 n 为负数,则表示当天之后。
参数:
- n: Int64 - 前多少天。
返回值:
- DayOfWeek -
n天前的周数值。
enum Month
public enum Month <: ToString & Equatable<Month> {
| January
| February
| March
| April
| May
| June
| July
| August
| September
| October
| November
| December
}
功能:Month 用以表示月份,表示一年中的某一月,提供了与 Int64 类型转换和计算,相等性判别以及获取枚举值的字符串表示的功能。
父类型:
April
April
功能:构造一个表示四月的 Month 实例。
August
August
功能:构造一个表示八月的 Month 实例。
December
December
功能:构造一个表示十二月的 Month 实例。
February
February
功能:构造一个表示二月的 Month 实例。
January
January
功能:构造一个表示一月的 Month 实例。
July
July
功能:构造一个表示七月的 Month 实例。
June
June
功能:构造一个表示六月的 Month 实例。
March
March
功能:构造一个表示三月的 Month 实例。
May
May
功能:构造一个表示五月的 Month 实例。
November
November
功能:构造一个表示十一月的 Month 实例。
October
October
功能:构造一个表示十月的 Month 实例。
September
September
功能:构造一个表示九月的 Month 实例。
static func of(Int64)
public static func of(mon: Int64): Month
功能:获取参数 mon 对应 Month 类型实例。
参数:
- mon: Int64 - 整数形式的月,合法范围为 [1, 12],分别表示一年中的十二个月。
返回值:
异常:
- IllegalArgumentException - 当参数
mon不在 [1, 12] 范围内时,抛出异常。
func toString()
public func toString(): String
功能:返回当前 Month 实例的字符串表示,如 "January" 表示一月。
返回值:
func toInteger()
public func toInteger(): Int64
功能:获取当前 Month 实例的整数表示,一月至十二月分别表示为 1 至 12。
返回值:
func value() (deprecated)
public func value(): Int64
功能:获取当前 Month 实例的整数表示,一月至十二月分别表示为 1 至 12。
注意:
未来版本即将废弃,可使用 toInteger() 替代。
返回值:
operator func !=(Month)
public operator func !=(r: Month): Bool
功能:判断当前 Month 实例和 r 是否不为同一个月。
参数:
返回值:
operator func +(Int64)
public operator func +(n: Int64): Month
功能:计算基于当前日历月份 n 个月之后(n 为正数时)的日历月份。若 n 为负数,则表示当月之前。
参数:
- n: Int64 - 后多少月的数量。
返回值:
- Month -
n月后的月份。
operator func -(Int64)
public operator func -(n: Int64): Month
功能:计算基于当前日历月份 n 个前之后(n 为正数时)的日历月份。若 n 为负数,则表示当月之后。
参数:
- n: Int64 - 前多少月的数量。
返回值:
- Month -
n月前的月份。
operator func ==(Month)
public operator func ==(r: Month): Bool
功能:判断当前 Month 实例和 r 是否表示同一个月。
参数:
返回值:
结构体
struct DateTime
public struct DateTime <: ToString & Hashable & Comparable<DateTime> & Formattable & Parsable<DateTime>
功能:DateTime 表示日期时间,是一个描述某一时间点的时间类型,提供了基于时区的日期时间读取、计算、比较、转换,以及序列化和反序列化等功能。
-
DateTime 是不可变的类型,包含了日期,时间和时区信息。可表示的时间区间为 [-999,999,999-01-01T00:00:00.000000000, 999,999,999-12-31T23:59:59.999999999],该区间适用于任何合法的时区。
-
以下为 DateTime 中 now 和 nowUTC 函数获取当前时间使用的系统调用函数:
系统 系统调用函数 时钟类型 Linux clock_gettime CLOCK_REALTIME Windows clock_gettime CLOCK_REALTIME macOS clock_gettime CLOCK_REALTIME
父类型:
static prop UnixEpoch
public static prop UnixEpoch: DateTime
功能:获取 Unix 时间纪元,即表示零时区 1970年1月1日0时0分0秒0纳秒 的 DateTime 实例。
类型:DateTime
prop dayOfMonth
public prop dayOfMonth: Int64
功能:获取 DateTime 实例基于当前月第几日。
类型:Int64
prop dayOfWeek
public prop dayOfWeek: DayOfWeek
功能:获取 DateTime 实例基于当前周的第几日。
类型:DayOfWeek
prop dayOfYear
public prop dayOfYear: Int64
功能:获取 DateTime 实例基于当前年份的第几日。
类型:Int64
prop date
public prop date: (Int64, Month, Int64)
功能:获取 DateTime 实例的年份、月份和当前月第几日。
prop hour
public prop hour: Int64
功能:获取 DateTime 实例的小时。
类型:Int64
prop isoWeek
public prop isoWeek: (Int64, Int64)
功能:获取 DateTime 实例基于 ISO8601 标准的年份和基于年的周数。
prop minute
public prop minute: Int64
功能:获取 DateTime 实例的分钟。
类型:Int64
prop month
public prop month: Month
功能:获取 DateTime 实例的月份。
类型:Month
prop monthValue (deprecated)
public prop monthValue: Int64
功能:获取 DateTime 实例以数字形式表示的月份。
注意:
未来版本即将废弃不再使用。
类型:Int64
prop nanosecond
public prop nanosecond: Int64
功能:获取 DateTime 实例的纳秒。
类型:Int64
prop second
public prop second: Int64
功能:获取 DateTime 实例的秒。
类型:Int64
prop year
public prop year: Int64
功能:获取 DateTime 实例的年份。
类型:Int64
prop time
public prop time: (Int64, Int64, Int64)
功能:获取 DateTime 实例的时、分、秒。
prop zone
public prop zone: TimeZone
功能:获取 DateTime 实例所关联的时区。
类型:TimeZone
prop zoneId
public prop zoneId: String
功能:获取 DateTime 实例所关联的 TimeZone 实例的时区 ID。
类型:String
prop zoneOffset
public prop zoneOffset: Duration
功能:获取 DateTime 实例所关联的 TimeZone 实例的时间偏移。
类型:Duration
static func fromUnixTimeStamp(Duration)
public static func fromUnixTimeStamp(d: Duration): DateTime
功能:获取自 UnixEpoch 开始,参数 d 指定时间间隔后的日期时间。
参数:
- d: Duration - 时间间隔。
返回值:
异常:
- ArithmeticException - 当结果超过日期时间的表示范围时,抛出异常。
static func now(TimeZone)
public static func now(timeZone!: TimeZone = TimeZone.Local): DateTime
功能:获取参数 timeZone 指定时区的当前时间。该方法获取的当前时间受系统时间影响,如存在使用不受系统时间影响的计时场景,可使用 MonoTime.now() 替代。
参数:
- timeZone!: TimeZone - 时区,默认为本地时区。
返回值:
- DateTime - 返回指定时区当前时间。
static func nowUTC()
public static func nowUTC(): DateTime
功能:获取 UTC 时区的当前时间。该方法获取的当前时间受系统时间影响,如存在使用不受系统时间影响的计时场景,可使用 MonoTime.now() 替代。
返回值:
- DateTime - UTC 时区当前时间。
static func of(Int64, Int64, Int64, Int64, Int64, Int64, Int64, TimeZone)
public static func of(
year!: Int64,
month!: Int64,
dayOfMonth!: Int64,
hour!: Int64 = 0,
minute!: Int64 = 0,
second!: Int64 = 0,
nanosecond!: Int64 = 0,
timeZone!: TimeZone = TimeZone.Local
): DateTime
功能:根据参数指定的年、月、日、时、分、秒、纳秒、时区构造 DateTime 实例。
参数:
- year!: Int64 - 年,范围[-999,999,999, 999,999,999]。
- month!: Int64 - 月,范围[1, 12]。
- dayOfMonth!: Int64 - 日,范围[1, 31],最大取值需要跟 month 匹配,可能是 28、29、30、31。
- hour!: Int64 - 时,范围[0, 23]。
- minute!: Int64 - 分,范围[0, 59]。
- second!: Int64 - 秒,范围[0, 59]。
- nanosecond!: Int64 - 纳秒,范围[0, 999,999,999]。
- timeZone!: TimeZone - 时区。
返回值:
异常:
- IllegalArgumentException - 当参数值超出指定范围,抛出异常。
static func of(Int64, Month, Int64, Int64, Int64, Int64, Int64, TimeZone)
public static func of(
year!: Int64,
month!: Month,
dayOfMonth!: Int64,
hour!: Int64 = 0,
minute!: Int64 = 0,
second!: Int64 = 0,
nanosecond!: Int64 = 0,
timeZone!: TimeZone = TimeZone.Local
): DateTime
功能:根据参数指定的年、月、日、时、分、秒、纳秒、时区构造 DateTime 实例。
参数:
- year!: Int64 - 年,范围[-999,999,999, 999,999,999]。
- month!: Month - 月,Month 类型。
- dayOfMonth!: Int64 - 日,范围[1, 31],最大取值需要跟 month 匹配,可能是 28、29、30、31。
- hour!: Int64 - 时,范围[0, 23]。
- minute!: Int64 - 分,范围[0, 59]。
- second!: Int64 - 秒,范围[0, 59]。
- nanosecond!: Int64 - 纳秒,范围[0, 999,999,999]。
- timeZone!: TimeZone - 时区。
返回值:
异常:
- IllegalArgumentException - 当参数值超出指定范围,抛出异常。
static func ofEpoch(Int64, Int64)
public static func ofEpoch(second!: Int64, nanosecond!: Int64): DateTime
功能:根据入参 second 和 nanosecond 构造 DateTime 实例。入参 second 表示 unix 时间的秒部分,nanosecond 表示 unix 时间的纳秒部分。unix 时间以 UnixEpoch 开始计算,nanosecond 的范围不可以超过[0, 999,999,999],否则抛出异常。
参数:
返回值:
异常:
- IllegalArgumentException - 当
nanosecond值超出指定范围时,抛出异常。 - ArithmeticException - 当结果超过日期时间的表示范围时,抛出异常。
static func ofUTC(Int64, Int64, Int64, Int64, Int64, Int64, Int64)
public static func ofUTC(
year!: Int64,
month!: Int64,
dayOfMonth!: Int64,
hour!: Int64 = 0,
minute!: Int64 = 0,
second!: Int64 = 0,
nanosecond!: Int64 = 0
): DateTime
功能:根据参数指定的年、月、日、时、分、秒、纳秒构造 UTC 时区 DateTime 实例。
参数:
- year!: Int64 - 年,范围[-999,999,999, 999,999,999]。
- month!: Int64 - 月,范围[1, 12]。
- dayOfMonth!: Int64 - 日,范围[1, 31],最大取值需要跟 month 匹配,可能是 28、29、30、31。
- hour!: Int64 - 时,范围[0, 23]。
- minute!: Int64 - 分,范围[0, 59]。
- second!: Int64 - 秒,范围[0, 59]。
- nanosecond!: Int64 - 纳秒,范围[0, 999,999,999]。
返回值:
异常:
- IllegalArgumentException - 当参数值超出指定范围时,抛出异常。
static func ofUTC(Int64, Month, Int64, Int64, Int64, Int64, Int64)
public static func ofUTC(
year!: Int64,
month!: Month,
dayOfMonth!: Int64,
hour!: Int64 = 0,
minute!: Int64 = 0,
second!: Int64 = 0,
nanosecond!: Int64 = 0
): DateTime
功能:根据参数指定的年、月、日、时、分、秒、纳秒构造 UTC 时区 DateTime 实例。
参数:
- year!: Int64 - 年,范围[-999,999,999, 999,999,999]。
- month!: Month - 月,Month 类型。
- dayOfMonth!: Int64 - 日, 范围[1, 31],最大取值需要跟 month 匹配,可能是 28、29、30、31。
- hour!: Int64 - 时,范围[0, 23]。
- minute!: Int64 - 分,范围[0, 59]。
- second!: Int64 - 秒,范围[0, 59]。
- nanosecond!: Int64 - 纳秒,范围[0, 999,999,999]。
返回值:
异常:
- IllegalArgumentException - 当参数值超出指定范围时,抛出异常。
static func parse(String)
public static func parse(str: String): DateTime
功能:从参数 str 中解析得到时间,解析成功时返回 DateTime 实例。
参数:
- str: String - 时间字符串,格式为
RFC3339中date-time格式,可包含小数秒,如 "2023-04-10T08:00:00[.123456]+08:00"([]中的内容表示可选项)。
返回值:
异常:
- TimeParseException - 无法正常解析时,抛出异常。
static func parse(String, String)
public static func parse(str: String, format: String): DateTime
功能:根据 format 指定的时间格式,从字符串 str 中解析得到时间,解析成功时返回 DateTime 实例。
参数:
- str: String - 时间字符串,例如:"2023/04/10 08:00:00 +08:00"。
- format: String - 时间字符串的格式,例如:"yyyy/MM/dd HH:mm:ss OOOO"。格式说明详见时间字符串格式。
返回值:
异常:
- TimeParseException - 当无法正常解析时,或存在同一
format的多次取值时,抛出异常。 - IllegalArgumentException - 当
format格式不正确时,抛出异常。
static func parse(String, DateTimeFormat) (deprecated)
public static func parse(str: String, format: DateTimeFormat): DateTime
功能:根据 format 指定的时间格式,从字符串 str 中解析得到时间,解析成功时返回 DateTime 实例。
注意:
未来版本即将废弃,使用 parse(String, String) 替代。
参数:
- str: String - 时间字符串,例如:"2023/04/10 08:00:00 +08:00"。
- format: DateTimeFormat - 时间格式,例如:"yyyy/MM/dd HH:mm:ss OOOO"对应的时间格式。格式说明详见时间字符串格式。
返回值:
异常:
- TimeParseException - 当无法正常解析时,或存在同一
format的多次取值时,抛出异常。 - IllegalArgumentException - 当
format格式不正确时,抛出异常。
static func tryParse(String)
public static func tryParse(str: String): Option<DateTime>
功能:从参数 str 中解析得到时间,解析成功时返回 Option<DateTime> 实例。
参数:
- str: String - 时间字符串,格式为
RFC3339中date-time格式,可包含小数秒,如 "2023-04-10T08:00:00[.123456]+08:00"([]中的内容表示可选项)。
返回值:
func addDays(Int64)
public func addDays(n: Int64): DateTime
功能:获取 DateTime 实例 n 天之后的时间,返回新的 DateTime 实例。
参数:
返回值:
异常:
- ArithmeticException - DateTime 实例
n天后的日期时间超过表示范围时,抛出异常。
func addHours(Int64)
public func addHours(n: Int64): DateTime
功能:获取 DateTime 实例 n 小时之后的时间,返回新的 DateTime 实例。
参数:
返回值:
异常:
- ArithmeticException - DateTime 实例
n小时后的日期时间超过表示范围时,抛出异常。
func addMinutes(Int64)
public func addMinutes(n: Int64): DateTime
功能:获取 DateTime 实例 n 分钟之后的时间,返回新的 DateTime 实例。
参数:
返回值:
异常:
- ArithmeticException - DateTime 实例
n分钟后的日期时间超过表示范围时,抛出异常。
func addMonths(Int64)
public func addMonths(n: Int64): DateTime
功能:获取 DateTime 实例 n 月之后的时间,返回新的 DateTime 实例。
注意:
由于月的间隔不固定,若设 dt 表示 “2020年3月31日”,
dt.addMonths(1)不会返回非法日期“2020年4月31日”。为了尽量返回有效的日期,会偏移到当月最后一天,返回“2020年4月30日”。
参数:
返回值:
异常:
- ArithmeticException - DateTime 实例
n月后的日期时间超过表示范围时,抛出异常。
func addNanoseconds(Int64)
public func addNanoseconds(n: Int64): DateTime
功能:获取 DateTime 实例 n 纳秒之后的时间,返回新的 DateTime 实例。
参数:
返回值:
异常:
- ArithmeticException - DateTime 实例
n纳秒后时间的日期时间超过表示范围时,抛出异常。
func addSeconds(Int64)
public func addSeconds(n: Int64): DateTime
功能:获取 DateTime 实例 n 秒之后的时间,返回新的 DateTime 实例。
参数:
返回值:
异常:
- ArithmeticException - DateTime 实例
n秒后的日期时间超过表示范围时,抛出异常。
func addWeeks(Int64)
public func addWeeks(n: Int64): DateTime
功能:获取 DateTime 实例 n 周之后的时间,返回新的 DateTime 实例。
参数:
返回值:
异常:
功能:获取入参 n 周之后的时间,返回新的 DateTime 实例。
func addYears(Int64)
public func addYears(n: Int64): DateTime
功能:获取 DateTime 实例 n 年之后的时间,返回新的 DateTime 实例。
注意:
由于年的间隔不固定,若设 dt 表示 “2020年2月29日”,
dt.addYears(1)不会返回非法日期“2021年2月29日”。为了尽量返回有效的日期,会偏移到当月最后一天,返回 “2021年2月28日”。
参数:
返回值:
异常:
- ArithmeticException - DateTime 实例
n年后的日期时间超过表示范围时,抛出异常。
func compare(DateTime)
public func compare(rhs: DateTime): Ordering
功能:判断一个 DateTime 实例与参数 rhs 的大小关系。如果大于,返回 Ordering.GT;如果等于,返回 Ordering.EQ;如果小于,返回 Ordering.LT。
参数:
返回值:
func hashCode()
public func hashCode(): Int64
功能:获取 DateTime 实例的哈希值。
返回值:
- Int64 - 哈希值。
func inLocal()
public func inLocal(): DateTime
功能:获取 DateTime 实例在本地时区的时间。
返回值:
异常:
- ArithmeticException - 当返回的 DateTime 实例表示的日期时间超过表示范围时,抛出异常。
func inTimeZone(TimeZone)
public func inTimeZone(timeZone: TimeZone): DateTime
功能:获取 DateTime 实例在参数 timeZone 指定时区的时间。
参数:
- timeZone: TimeZone - 目标时区。
返回值:
异常:
- ArithmeticException - 当返回的 DateTime 实例表示的日期时间超过表示范围时,抛出异常。
func inUTC()
public func inUTC(): DateTime
功能:获取 DateTime 实例在 UTC 时区的时间。
返回值:
异常:
- ArithmeticException - 当返回的 DateTime 实例表示的日期时间超过表示范围时,抛出异常。
func toString()
public func toString(): String
功能:返回一个表示 DateTime 实例的字符串,其格式为 RFC3339 中 date-time 格式,如果时间包含纳秒信息(不为零),会打印出小数秒。
返回值:
func format(String)
public func format(fmt: String): String
功能:返回一个表示 DateTime 实例的字符串,其格式由参数 fmt 指定。格式说明详见时间字符串格式。
参数:
- fmt: String - 返回字符串的格式,其格式可为 "yyyy/MM/dd HH:mm:ss OOOO"。
返回值:
异常:
- IllegalArgumentException - 当
fmt格式不符合时间字符串格式,则抛出异常。
func toString(DateTimeFormat) (deprecated)
public func toString(format: DateTimeFormat): String
功能:返回一个表示 DateTime 实例的字符串,其格式由参数 format 指定。格式说明详见时间字符串格式。
注意:
未来版本即将废弃不再使用。
参数:
- format: DateTimeFormat - 时间格式,其格式可为 "yyyy/MM/dd HH:mm:ss OOOO"。
返回值:
异常:
- IllegalArgumentException - 当
format格式不正确时,抛出异常。
func toUnixTimeStamp()
public func toUnixTimeStamp(): Duration
功能:获取当前实例自 UnixEpoch 的时间间隔。
返回值:
operator func !=(DateTime)
public operator func !=(r: DateTime): Bool
功能:判断当前 DateTime 实例是否不等于 r。
若两个 DateTime 不相等,那么它们指向的不是同一 UTC 时间。
参数:
返回值:
operator func +(Duration)
public operator func +(r: Duration): DateTime
功能:实现 DateTime 类型和 Duration 类型加法,即 DateTime + Duration 运算。
参数:
- r: Duration - 加法的右操作数。
返回值:
异常:
- ArithmeticException - 当结果超过日期时间的表示范围时,抛出异常。
operator func -(DateTime)
public operator func -(r: DateTime): Duration
功能:实现 DateTime 类型之间的减法,即 DateTime - DateTime 运算。
参数:
- r: DateTime - 减法的右操作数。
返回值:
operator func -(Duration)
public operator func -(r: Duration): DateTime
功能:实现 DateTime 类型和 Duration 类型减法,即 DateTime - Duration 运算。
参数:
- r: Duration - 减法的右操作数。
返回值:
异常:
- ArithmeticException - 当结果超过日期时间的表示范围时,抛出异常。
operator func <(DateTime)
public operator func <(r: DateTime): Bool
功能:判断当前 DateTime 实例是否早于 r(指向更早的 UTC 时间的 DateTime 更小)。
参数:
返回值:
operator func <=(DateTime)
public operator func <=(r: DateTime): Bool
功能:判断当前 DateTime 实例是否早于或等于 r(指向更早的 UTC 时间的 DateTime 更小)。
参数:
返回值:
operator func ==(DateTime)
public operator func ==(r: DateTime): Bool
功能:判断当前 DateTime 实例是否等于 r。
若两个 DateTime 相等,那么它们指向同一 UTC 时间。
参数:
返回值:
operator func >(DateTime)
public operator func >(r: DateTime): Bool
功能:判断当前 DateTime 实例是否晚于 r(指向更晚的 UTC 时间的 DateTime 更大)。
参数:
返回值:
operator func >=(DateTime)
public operator func >=(r: DateTime): Bool
功能:判断当前 DateTime 实例是否晚于或等于 r(指向更晚的 UTC 时间的 DateTime 更大)。
参数:
返回值:
struct MonoTime
public struct MonoTime <: Hashable & Comparable<MonoTime>
功能:MonoTime 表示单调时间,是一个用来衡量经过时间的时间类型,类似于一直运行的秒表,提供了获取当前时间,计算和比较等功能。
-
MonoTime 可表示的范围为 Duration.Zero 至 Duration.Max,数值表示为 [0, 263)(单位为秒),精度为纳秒。通过 now 方法创建的 MonoTime 总是晚于先使用该方式创建的 MonoTime,常用于性能测试和时间优先的任务队列。
-
以下为 MonoTime 中 now 函数获取当前时间使用的系统调用函数:
系统 系统调用函数 时钟类型 Linux clock_gettime CLOCK_MONOTONIC Windows clock_gettime CLOCK_MONOTONIC macOS clock_gettime CLOCK_MONOTONIC
父类型:
static func now()
public static func now(): MonoTime
功能:获取与当前时间对应的 MonoTime。
返回值:
func compare(MonoTime)
public func compare(rhs: MonoTime): Ordering
功能:判断一个 MonoTime 实例与参数 rhs 的大小关系。如果大于,返回 Ordering.GT;如果等于,返回 Ordering.EQ;如果小于,返回 Ordering.LT。
参数:
返回值:
func hashCode()
public func hashCode(): Int64
功能:获取当前 MonoTime 实例的哈希值。
返回值:
- Int64 - 哈希值。
operator func !=(MonoTime)
public operator func !=(r: MonoTime): Bool
功能:判断当前 MonoTime 实例是否不等于 r。
参数:
- r: MonoTime - 单调时间。
返回值:
operator func +(Duration)
public operator func +(r: Duration): MonoTime
功能:实现 MonoTime 类型和 Duration 类型加法,即 MonoTime + Duration 运算。
参数:
- r: Duration - 时间间隔。
返回值:
- MonoTime - 参数
r表示时间间隔后的单调时间。
异常:
- ArithmeticException - 当结果超过单调时间的表示范围时,抛出异常。
operator func -(Duration)
public operator func -(r: Duration): MonoTime
功能:实现 MonoTime 类型和 Duration 类型减法,即 MonoTime - Duration 运算。
参数:
- r: Duration - 时间间隔。
返回值:
- MonoTime - 参数
r表示时间间隔前的单调时间。
异常:
- ArithmeticException - 当结果超过单调时间的表示范围时,抛出异常。
operator func -(MonoTime)
public operator func -(r: MonoTime): Duration
功能:实现 MonoTime 类型之间的减法,即 MonoTime - MonoTime 运算。
参数:
- r: MonoTime - 单调时间。
返回值:
- Duration - 当前实例距
r经过的时间间隔。
operator func <(MonoTime)
public operator func <(r: MonoTime): Bool
功能:判断当前 MonoTime 实例是否早于 r。
参数:
- r: MonoTime - 单调时间。
返回值:
operator func <=(MonoTime)
public operator func <=(r: MonoTime): Bool
功能:判断当前 MonoTime 实例是否早于或等于 r。
参数:
- r: MonoTime - 单调时间。
返回值:
operator func ==(MonoTime)
public operator func ==(r: MonoTime): Bool
功能:判断当前 MonoTime 实例是否等于 r。
参数:
- r: MonoTime - 单调时间。
返回值:
operator func >(MonoTime)
public operator func >(r: MonoTime): Bool
功能:判断当前 MonoTime 实例是否晚于 r。
参数:
- r: MonoTime - 单调时间。
返回值:
operator func >=(MonoTime)
public operator func >=(r: MonoTime): Bool
功能:判断当前 MonoTime 实例是否晚于或等于 r。
参数:
- r: MonoTime - 单调时间。
返回值:
异常类
class InvalidDataException
public class InvalidDataException <: Exception {
public init()
public init(message: String)
}
功能:InvalidDataException 表示加载时区时的异常。
父类型:
init()
public init()
功能:构造一个 InvalidDataException 实例。
init(String)
public init(message: String)
功能:根据参数 message 指定的异常信息,构造一个 InvalidDataException 实例。
参数:
- message: String - 预定义消息。
class TimeParseException
public class TimeParseException <: Exception {
public init()
public init(message: String)
}
功能:TimeParseException 表示解析时间字符串时的异常。
父类型:
init()
public init()
功能:构造一个 TimeParseException 实例。
init(String)
public init(message: String)
功能:根据参数 message 指定的异常信息,构造一个 TimeParseException 实例。
参数:
- message: String - 预定义消息。
获取当前时间以及时间差
该示例演示了如何获取当前时间,以及计算两个时间的差值。
import std.time.*
main() {
let before = DateTime.now() /* 获取当前时间 */
sleep(100 * Duration.millisecond) /* 睡眠 100 毫秒 */
let after = DateTime.now() /* 获取当前时间 */
println(before)
println(after)
println(after - before)
return
}
运行结果:(以实际结果为准)
2025-08-01T11:15:46.386650335+08:00
2025-08-01T11:15:46.487986524+08:00
101ms336us189ns
DateTime 比较
该示例选取中国标准时间(CST,时区 ID 为“Asia/Shanghai”)和美国东部夏令时时间(EDT,时区 ID 为“America/New_York”)进行时间比较。
说明:
示例中使用 TimeZone.load 函数加载时区信息,在不同平台上加载时区信息有不同的依赖,用户需按其要求进行设置。
import std.time.*
main() {
let tzSH = TimeZone.load("Asia/Shanghai")
let tzNY = TimeZone.load("America/New_York")
// 2024-05-25T00:00:00Z
let shanghai1 = DateTime.of(year: 2024, month: May, dayOfMonth: 25, hour: 8, timeZone: tzSH)
let new_york1 = DateTime.of(year: 2024, month: May, dayOfMonth: 24, hour: 20, timeZone: tzNY)
// 2024-05-25T01:00:00Z
let shanghai2 = DateTime.of(year: 2024, month: May, dayOfMonth: 25, hour: 9, timeZone: tzSH)
let new_york2 = DateTime.of(year: 2024, month: May, dayOfMonth: 24, hour: 21, timeZone: tzNY)
println(shanghai1 == new_york1)
println(shanghai1 != new_york2)
println(shanghai1 <= new_york2)
println(shanghai1 < new_york2)
println(shanghai2 >= new_york1)
println(shanghai2 > new_york1)
}
运行结果:
true
true
true
true
true
true
DateTime 与 String 类型的转换
该示例演示了如何通过格式化字符串 pattern,对时间进行格式化打印,以及从格式化字符串中解析时间。
说明:
示例中使用 TimeZone.load 函数加载时区信息,在不同平台上加载时区信息有不同的依赖,用户需按其要求进行设置。
import std.time.*
main() {
let pattern = "yyyy/MM/dd HH:mm:ssSSS OO"
let datetime = DateTime.of(
year: 2024,
month: May,
dayOfMonth: 22,
hour: 12,
minute: 34,
second: 56,
nanosecond: 789000000,
timeZone: TimeZone.load("Asia/Shanghai")
)
let str = datetime.format(pattern)
println(str)
println(DateTime.parse(str, pattern))
}
运行结果:
2024/05/22 12:34:56789000000 +08:00
2024-05-22T12:34:56.789+08:00
获取日期时间信息
该示例演示了如何获取日期时间的年、月、日等信息。
说明:
示例中使用 TimeZone.load 函数加载时区信息,在不同平台上加载时区信息有不同的依赖,用户需按其要求进行设置。
import std.time.*
main() {
let datetime = DateTime.of(
year: 2024,
month: May,
dayOfMonth: 22,
hour: 12,
minute: 34,
second: 56,
nanosecond: 789000000,
timeZone: TimeZone.load("Asia/Shanghai")
)
let yr = datetime.year
let mon = datetime.month
let day = datetime.dayOfMonth
let hr = datetime.hour
let min = datetime.minute
let sec = datetime.second
let ns = datetime.nanosecond
let zoneId = datetime.zoneId
let offset = datetime.zoneOffset
let dayOfWeek = datetime.dayOfWeek
let dayOfYear = datetime.dayOfYear
let (isoYear, isoWeek) = datetime.isoWeek
println("datetime is ${yr}, ${mon}, ${day}, ${hr}, ${min}, ${sec}, ${ns}, ${zoneId}, ${offset}")
println("datetime.toString() = ${datetime}")
println("${dayOfWeek}, ${dayOfYear}th day, ${isoWeek}th week of ${isoYear}")
}
运行结果:
datetime is 2024, May, 22, 12, 34, 56, 789000000, Asia/Shanghai, 8h
datetime.toString() = 2024-05-22T12:34:56.789+08:00
Wednesday, 143th day, 21th week of 2024
同一时间在不同时区的本地时间
该示例演示了如何将一个中国标准时间,转换为同一时间下 UTC 和美国东部夏令时时间。
说明:
示例中使用 TimeZone.load 函数加载时区信息,在不同平台上加载时区信息有不同的依赖,用户需按其要求进行设置。
import std.time.*
main() {
let datetime = DateTime.of(year: 2024, month: May, dayOfMonth: 22, hour: 12, timeZone: TimeZone.load("Asia/Shanghai"))
println("CST: ${datetime}")
println("UTC: ${datetime.inUTC()}")
println("EDT: ${datetime.inTimeZone(TimeZone.load("America/New_York"))}")
}
运行结果:
CST: 2024-05-22T12:00:00+08:00
UTC: 2024-05-22T04:00:00Z
EDT: 2024-05-22T00:00:00-04:00
利用 MonoTime 作计时
该示例演示了如何通过 MonoTime 类型进行计时。
import std.time.*
const count = 10000
main() {
let start = MonoTime.now()
for (_ in 0..count) {
DateTime.now()
}
let end = MonoTime.now()
let result = end - start
println("total cost: ${result.toNanoseconds()}ns")
}
运行结果(以实际结果为准)
total cost: 951159ns
std.unicode
功能介绍
unicode 包提供了按 unicode 编码标准处理字符的能力。
Unicode 是一种字符编码标准,旨在为所有语言和符号提供一个统一的编码方案,以便在计算机系统中交换和处理文本。
Unicode 编码标准将每个字符用唯一的码点表示,同时为每个字符定义了若干属性,如类别(字母、数字、标点等)、脚本(拉丁字母、希腊字母、汉字等)、大小写映射(大写或小写映射关系)、变音符号(是否带有变音符号,如重音符号)。
本包提供了 UnicodeRuneExtension 和 UnicodeStringExtension 接口类型,用于为其他类型扩展 Unicode 相关的字符操作。并为 Rune、String 类型实现了若干扩展方法,包括字符类型判断、字符大小写转换等。
API 列表
接口
| 接口名 | 功能 |
|---|---|
| UnicodeRuneExtension | Unicode 字符集相关扩展的接口,用于为 Rune 类型扩展 Unicode 字符集相关的操作。 |
| UnicodeStringExtension | Unicode 字符集相关扩展的接口,用于为 String 类型扩展 Unicode 字符集相关的操作。 |
枚举
| 枚举 | 功能 |
|---|---|
| CasingOption | 大小写转换时根据不同语言所需要的枚举类。 |
接口
interface UnicodeRuneExtension
public interface UnicodeRuneExtension {
func isLetter(): Bool
func isLowerCase(): Bool
func isNumber(): Bool
func isTitleCase(): Bool
func isUpperCase(): Bool
func isWhiteSpace(): Bool
func toLowerCase(): Rune
func toLowerCase(opt: CasingOption): Rune
func toTitleCase(): Rune
func toTitleCase(opt: CasingOption): Rune
func toUpperCase(): Rune
func toUpperCase(opt: CasingOption): Rune
}
功能:Unicode 字符集相关扩展的接口,用于为其他类型扩展 Unicode 字符集相关的操作。
可用于为 Rune 类型增加一系列与 Unicode 字符集相关的扩展函数,包括字符类型判断,字符大小写转换,删除空白字符等。
func isLetter()
func isLetter(): Bool
功能:判断该类型否是 Unicode 字母字符。
返回值:
- Bool - 如果该类型是
Unicode字母字符,返回true,否则返回false。
func isLowerCase()
func isLowerCase(): Bool
功能:判断该类型是否是 Unicode 小写字符。
返回值:
- Bool - 如果该类型是
Unicode小写字符,返回true,否则返回false。
func isNumber()
func isNumber(): Bool
功能:判断类型是否是 Unicode 数字字符。
返回值:
- Bool - 如果该类型是
Unicode数字字符,返回true,否则返回false。
func isTitleCase()
func isTitleCase(): Bool
功能:判断该类型是否是 Unicode 标题化字符。
Unicode 中的标题化字符指的是一种特殊的字母形式,它们在某些语言中用于表示标题中每个单词的首字母大写的形式。这些字母由特殊的字符表示,例如U+01C5(Dž)和U+01F1(DZ)。这些字符通常用于一些东欧语言,如克罗地亚语和塞尔维亚语。
标题化字符包括:0x01C5、0x01C8、0x01CB、0x01F2、0x1F88 - 0x1F8F、0x1F98 - 0x1F9F、0x1F98 - 0x1F9F、0x1FA8 - 0x1FAF、0x1FBC、0x1FCC、0x1FFC
返回值:
- Bool - 如果该类型是
Unicode标题大写字符,返回true,否则返回false。
func isUpperCase()
func isUpperCase(): Bool
功能::判断该类型是否是 Unicode 大写字符。
返回值:
- Bool - 如果该类型是
Unicode大写字符,返回true,否则返回false。
func isWhiteSpace()
func isWhiteSpace(): Bool
功能:判断该类型是否是 Unicode 空白字符。
空白字符包括 0x0009、0x000A、0x000B、0x000C、0x000D、0x0020、0x0085、0x00A0、0x1680、0x2000、0x2001、0x2002、0x2003、0x2004、0x2005、0x2006、0x2007、0x2008、0x2009、0x200A、0x2028、0x2029、0x202F、0x205F、0x3000。
返回值:
- Bool - 如果该类型是
Unicode空白字符,返回true,否则返回false。
func toLowerCase()
func toLowerCase(): Rune
功能:获取该类型对应的 Unicode 小写字符。
返回值:
- Rune - 当前类型对应的小写字符。
func toTitleCase()
func toTitleCase(): Rune
功能:获取该类型对应的 Unicode 标题大写字符。
返回值:
- Rune - 当前类型对应的标题大写字符。
func toUpperCase()
func toUpperCase(): Rune
功能:获取该类型对应的 Unicode 大写字符。
返回值:
- Rune - 当前类型对应的小写字符。
func toLowerCase(CasingOption)
func toLowerCase(opt: CasingOption): Rune
功能:获取该类型对应的 Unicode 小写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- Rune - 当前类型对应的小写字符。
func toTitleCase(CasingOption)
func toTitleCase(opt: CasingOption): Rune
功能:获取该类型对应的 Unicode 标题大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- Rune - 当前类型对应的标题大写字符。
func toUpperCase(CasingOption)
func toUpperCase(opt: CasingOption): Rune
功能:获取该类型对应的 Unicode 大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- Rune - 当前类型对应的小写字符。
extend Rune <: UnicodeRuneExtension
extend Rune <: UnicodeRuneExtension
功能:为 Rune 类型扩展 UnicodeRuneExtension 接口,支持字符集相关的操作。
父类型:
func isLetter()
public func isLetter(): Bool
功能:判断字符是否是 Unicode 字母字符。
返回值:
- Bool - 如果该字符是
Unicode字母字符,返回true,否则返回false。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.isLetter())
println(r'1'.isLetter())
}
运行结果:
true
false
func isLowerCase()
public func isLowerCase(): Bool
功能:判断字符是否是 Unicode 小写字符。
返回值:
- Bool - 如果该字符是
Unicode小写字符,返回true,否则返回false。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.isLowerCase())
println(r'A'.isLowerCase())
}
运行结果:
true
false
func isNumber()
public func isNumber(): Bool
功能:判断字符是否是 Unicode 数字字符。
返回值:
- Bool - 如果该字符是
Unicode数字字符,返回true,否则返回false。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.isNumber())
println(r'1'.isNumber())
}
运行结果:
false
true
func isTitleCase()
public func isTitleCase(): Bool
功能:判断字符是否是 Unicode 标题化字符。
Unicode 中的标题化字符指的是一种特殊的字母形式,它们在某些语言中用于表示标题中每个单词的首字母大写的形式。这些字母由特殊的字符表示,例如U+01C5(Dž)和U+01F1(DZ)。这些字符通常用于一些东欧语言,如克罗地亚语和塞尔维亚语。
标题化字符包括:0x01C5、0x01C8、0x01CB、0x01F2、0x1F88 - 0x1F8F、0x1F98 - 0x1F9F、0x1F98 - 0x1F9F、0x1FA8 - 0x1FAF、0x1FBC、0x1FCC、0x1FFC
返回值:
- Bool - 如果该字符是
Unicode标题大写字符,返回true,否则返回false。
示例:
import std.unicode.*
main(): Unit {
println(r'Dž'.isTitleCase())
}
运行结果:
true
func isUpperCase()
public func isUpperCase(): Bool
功能::判断字符是否是 Unicode 大写字符。
返回值:
- Bool - 如果该字符是
Unicode大写字符,返回true,否则返回false。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.isUpperCase())
println(r'A'.isUpperCase())
}
运行结果:
false
true
func isWhiteSpace()
public func isWhiteSpace(): Bool
功能:判断字符是否是 Unicode 空白字符。
空白字符包括 0x0009、0x000A、0x000B、0x000C、0x000D、0x0020、0x0085、0x00A0、0x1680、0x2000、0x2001、0x2002、0x2003、0x2004、0x2005、0x2006、0x2007、0x2008、0x2009、0x200A、0x2028、0x2029、0x202F、0x205F、0x3000。
返回值:
- Bool - 如果该字符是
Unicode空白字符,返回true,否则返回false。
示例:
import std.unicode.*
main(): Unit {
println(r' '.isWhiteSpace())
}
运行结果:
true
func toLowerCase()
public func toLowerCase(): Rune
功能:获取该字符对应的 Unicode 小写字符。
返回值:
- Rune - 当前字符对应的小写字符。
示例:
import std.unicode.*
main(): Unit {
println(r'A'.toLowerCase())
}
运行结果:
a
func toLowerCase(CasingOption)
public func toLowerCase(opt: CasingOption): Rune
功能:获取该字符对应的 Unicode 小写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- Rune - 当前字符对应的小写字符。
示例:
import std.unicode.*
main(): Unit {
println(r'A'.toLowerCase(CasingOption.Other))
}
运行结果:
a
func toTitleCase()
public func toTitleCase(): Rune
功能:获取该字符对应的 Unicode 标题大写字符。
返回值:
- Rune - 当前字符对应的标题大写字符。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.toTitleCase())
}
运行结果:
A
func toTitleCase(CasingOption)
public func toTitleCase(opt: CasingOption): Rune
功能:获取该字符对应的 Unicode 标题大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- Rune - 当前字符对应的标题大写字符。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.toTitleCase(CasingOption.Other))
}
运行结果:
A
func toUpperCase()
public func toUpperCase(): Rune
功能:获取该字符对应的 Unicode 大写字符。
返回值:
- Rune - 当前字符对应的小写字符。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.toUpperCase())
}
运行结果:
A
func toUpperCase(CasingOption)
public func toUpperCase(opt: CasingOption): Rune
功能:获取该字符对应的 Unicode 大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- Rune - 当前字符对应的小写字符。
示例:
import std.unicode.*
main(): Unit {
println(r'a'.toUpperCase(CasingOption.Other))
}
运行结果:
A
interface UnicodeStringExtension
public interface UnicodeStringExtension {
func isBlank(): Bool
func toLower(): String
func toLower(opt: CasingOption): String
func toTitle(): String
func toTitle(opt: CasingOption): String
func toUpper(): String
func toUpper(opt: CasingOption): String
func trim(): String
func trimEnd(): String
func trimLeft(): String
func trimRight(): String
func trimStart(): String
}
功能:Unicode 字符集相关扩展的接口,用于为其他类型扩展 Unicode 字符集相关的操作。
可用于为 String 类型增加一系列与 Unicode 字符集相关的扩展函数,包括字符类型判断,字符大小写转换,删除空白字符等。
func isBlank()
func isBlank(): Bool
功能:判断当前字符串是否为空,或仅包含 Unicode 字符集中的空字符。
空白字符包括 0x0009、0x000A、0x000B、0x000C、0x000D、0x0020、0x0085、0x00A0、0x1680、0x2000、0x2001、0x2002、0x2003、0x2004、0x2005、0x2006、0x2007、0x2008、0x2009、0x200A、0x2028、0x2029、0x202F、0x205F、0x3000。
返回值:
- Bool - 如果字符串为空,或仅包含空字符,返回
true,否则返回false。
func toLower()
func toLower(): String
功能:将当前字符串中所有 Unicode 字符集范围内的大写字符转化为小写字符。
返回值:
- String - 转换后的全小写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
func toLower(CasingOption)
func toLower(opt: CasingOption): String
功能:将当前字符串中所有 Unicode 字符集范围内的大写字符转化为小写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- String - 转换后的全小写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
func toTitle()
func toTitle(): String
功能:将当前字符串中 Unicode 字符集范围内可以转换为标题大写字符的转换为标题大写字符。
返回值:
- String - 转换后的标题大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
func toTitle(CasingOption)
func toTitle(opt: CasingOption): String
功能:将当前字符串中 Unicode 字符集范围内可以转换为标题大写字符的转换为标题大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- String - 转换后的标题大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
func toUpper()
func toUpper(): String
功能:将当前字符串中所有 Unicode 字符集范围内的小写字符转化为大写字符。
返回值:
- String - 转换后的全大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
func toUpper(CasingOption)
func toUpper(opt: CasingOption): String
功能:将当前字符串中所有 Unicode 字符集范围内的小写字符转化为大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- String - 转换后的全大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
func trim()
func trim(): String
功能:去除字符串开头结尾的空字符串,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
返回值:
- String - 去除首尾空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
func trimEnd()
func trimEnd(): String
功能:去除字符串结尾的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
返回值:
- String - 去除结尾空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
func trimLeft() (deprecated)
func trimLeft(): String
功能:去除字符串开头的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
注意:
未来版本即将废弃,使用 trimStart 替代。
返回值:
- String - 去除开头空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
func trimRight() (deprecated)
func trimRight(): String
功能:去除字符串结尾的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
注意:
未来版本即将废弃,使用 trimEnd 替代。
返回值:
- String - 去除结尾空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
func trimStart()
func trimStart(): String
功能:去除字符串开头的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
返回值:
- String - 去除开头空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
extend String <: UnicodeStringExtension
extend String <: UnicodeStringExtension
功能:为 String 类型扩展 UnicodeRuneExtension 接口,支持字符集相关的操作。
父类型:
func isBlank()
public func isBlank(): Bool
功能:判断当前字符串是否为空,或仅包含 Unicode 字符集中的空字符。
空白字符包括 0x0009、0x000A、0x000B、0x000C、0x000D、0x0020、0x0085、0x00A0、0x1680、0x2000、0x2001、0x2002、0x2003、0x2004、0x2005、0x2006、0x2007、0x2008、0x2009、0x200A、0x2028、0x2029、0x202F、0x205F、0x3000。
返回值:
- Bool - 如果字符串为空,或仅包含空字符,返回
true,否则返回false。
示例:
import std.unicode.*
main(): Unit {
println(" \t\n\r".isBlank())
}
运行结果:
true
func toLower()
public func toLower(): String
功能:将当前字符串中所有 Unicode 字符集范围内的大写字符转化为小写字符。
返回值:
- String - 转换后的全小写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println("AbcDEF".toLower())
}
运行结果:
abcdef
func toLower(CasingOption)
public func toLower(opt: CasingOption): String
功能:将当前字符串中所有 Unicode 字符集范围内的大写字符转化为小写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- String - 转换后的全小写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println("AbcDEF".toLower(CasingOption.Other))
}
运行结果:
abcdef
func toTitle()
public func toTitle(): String
功能:将当前字符串中 Unicode 字符集范围内可以转换为标题大写字符的转换为标题大写字符。
返回值:
- String - 转换后的标题大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println("AbcDEF".toTitle())
}
运行结果:
ABCDEF
func toTitle(CasingOption)
public func toTitle(opt: CasingOption): String
功能:将当前字符串中 Unicode 字符集范围内可以转换为标题大写字符的转换为标题大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- String - 转换后的标题大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println("AbcDEF".toTitle(CasingOption.Other))
}
运行结果:
ABCDEF
func toUpper()
public func toUpper(): String
功能:将当前字符串中所有 Unicode 字符集范围内的小写字符转化为大写字符。
返回值:
- String - 转换后的全大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println("AbcDEF".toUpper())
}
运行结果:
ABCDEF
func toUpper(CasingOption)
public func toUpper(opt: CasingOption): String
功能:将当前字符串中所有 Unicode 字符集范围内的小写字符转化为大写字符。
参数:
- opt: CasingOption - 传入的语言枚举。
返回值:
- String - 转换后的全大写字符串。
异常:
- IllegalArgumentException - 如果字符串中存在无效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println("AbcDEF".toUpper(CasingOption.Other))
}
运行结果:
ABCDEF
func trim()
public func trim(): String
功能:去除字符串开头结尾的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
返回值:
- String - 去除首尾空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println("\nx \t ".trim())
}
运行结果:
x
func trimEnd()
public func trimEnd(): String
功能:去除字符串结尾的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
返回值:
- String - 去除结尾空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println(" x ".trimEnd())
}
运行结果:
x
func trimLeft() (deprecated)
public func trimLeft(): String
功能:去除字符串开头的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
注意:
未来版本即将废弃,使用 trimStart 替代。
返回值:
- String - 去除开头空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println(" x ".trimLeft())
}
运行结果:
x
func trimRight() (deprecated)
public func trimRight(): String
功能:去除字符串结尾的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
注意:
未来版本即将废弃,使用 trimEnd 替代。
返回值:
- String - 去除结尾空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println(" x ".trimRight())
}
运行结果:
x
func trimStart()
public func trimStart(): String
功能:去除字符串开头的空字符,空字符定义见 Rune 类型的扩展函数 isWhiteSpace。
返回值:
- String - 去除开头空字符后的字符串。
异常:
- IllegalArgumentException - 如果字符串中不存在有效的 UTF-8 编码,抛出异常。
示例:
import std.unicode.*
main(): Unit {
println(" x ".trimStart())
}
运行结果:
x
枚举
enum CasingOption
public enum CasingOption {
| TR
| AZ
| LT
| Other
}
功能:大小写转换时根据不同语言所需要的枚举类。
TR
TR
功能:土耳其语。
AZ
AZ
功能:阿塞拜疆语。
LT
LT
功能:立陶宛语。
Other
Other
功能:其他语。
std.unittest
功能介绍
unittest 包用于编写仓颉项目单元测试代码,提供包括代码编写、运行和调测在内的基本功能,并为有经验的用户提供的一些高级功能。
仓颉单元测试支持 cjc 编译器(单包编译模式)和 cjpm 包管理器( 多包模式)。
用户可通过快速入门写出第一个单元测试程序。同时文档对于一些基础概念及用法做了说明并附有示例代码,另外,对于一些高阶特性例如参数化测试等做了进一步说明。
如下 API 从其他包中重导出,因此用户亦可以只导入 unittest 即可使用。
从 unittest.common 包中重导出
接口
| 接口名 | 功能 |
|---|---|
| DataProvider | DataStrategy 的组件,用于提供测试数据, T 指定提供者提供的数据类型。 |
| DataShrinker | DataStrategy 的组件,用于在测试期间缩减数据,T 指定该收缩器处理的数据类型。 |
| DataStrategy | 为参数化测试提供数据的策略,T 指定该策略操作的数据类型。 |
类
| 类名 | 功能 |
|---|---|
| Configuration | 存储 @Configure 宏生成的 unittest 配置数据的对象。Configuration 是一个类似 HashMap 的类,但它的键不是键和值类型,而是 String 类型,和任何给定类型的值。 |
| ConfigurationKey | 配置项的键值对象。提供判等及 hashCode 方法。 |
从 unittest.prop_test 包中重导出
函数
| 函数名 | 功能 |
|---|---|
| random<T>() | 该函数生成 T 类型的随机数据,其中 T 必须实现接口 Arbitrary<T> 。该函数的返回值是参数化测试的一种参数源。 |
接口
API 列表
函数
| 函数名 | 功能 |
|---|---|
| assertCaughtUnexpectedE(String, String, String, Option<AssertionCtx>) | 捕获的异常不符合预期,记录信息,抛出异常。 |
| assertEqual<T>(String, String, T, T, Option<AssertionCtx>) | 比较 expected 和 actual 值是否相等。若不等,直接抛出异常。 |
| defaultConfiguration() | 生成默认的配置信息。 |
| entryMain(TestPackage) | 提供给 cjc --test 使用,框架执行测试用例的入口函数。 |
| expectCaughtUnexpectedE(String,String,String, Option<AssertionCtx>) | 捕获的异常不符合预期,记录信息,不抛出异常。 |
| expectEqual(String, String, T, T, Option<AssertionCtx>) | 比较 expected 和 actual 值是否相等。记录比较结果,不抛出异常。 |
| fail(String) | 使该用例失败,直接抛出异常。 |
| failExpect(String) | 使该用例失败,记录信息,不抛出异常。 |
| invokeCustomAssert<T>(Array<String>, String, (AssertionCtx) -> T, Option<AssertionCtx>) | 运行在 @Test, @TestCase, 或 @CustomAssertion 宏中使用的 @Assert[caller](passerArgs) 指定的用户定义断言函数。 |
| invokeCustomExpect<T>(Array<String>, String, (AssertionCtx) -> Any, Option<AssertionCtx>) | 运行在 @Test, @TestCase, 或 @CustomAssertion 宏中使用的 @Expect[caller](passerArgs) 指定的用户定义断言函数。 |
类型别名
| 类型别名 | 功能 |
|---|---|
| MeasurementUnitTable | 用于为性能测试指定 Measurement 实例。 |
接口
| 接口名 | 功能 |
|---|---|
| BenchInputProvider | 用于处理性能测试的接口,其中需要在每次性能测试调用之前执行一些代码或者性能测试的输入发生了变化,并且每次都必须从头开始生成。 |
| BenchmarkConfig | 空接口,区分部分 Configuration 函数为性能相关配置。 |
| BenchmarkInputMarker | 当我们不知道 T 时,该接口能够检测 BenchInputProvider<T> 。 |
| Generator | 生成器生成 T 类型的值。 |
| Measurement | 在性能测试过程中可以收集和分析各种数据的接口。性能测试期间使用的 Measurement 的具体实例在 @Measure 宏中指定(例如在类声明中)。 |
| TestClass | 提供创建 TestSuite 的方法。 |
类
| 类名 | 功能 |
|---|---|
| AssertionCtx | 存储用户定义的断言的状态。提供用于编写用户定义断言的方法。 |
| Benchmark | 该类提供创建和运行单个性能测试用例的方法。 |
| BenchReport | 提供性能用例执行结果报告处理能力。 |
| CartesianProductProcessor<T0,T1> | 笛卡尔积处理器。 |
| ConsoleReporter | 打印单元测试用例结果或者性能测试用例结果到控制台。 |
| CsvReporter | 打印性能测试用例结果数据到 Csv 文件上。 |
| CsvRawReporter | 打印性能测试用例结果数据,该数据只有批次的原始测量值,到 Csv 文件上。 |
| CsvStrategy<T> | DataStrategy 对 CSV 数据格式的序列化实现。 |
| DataStrategyProcessor<T> | 所有 DataStrategy 组件的基类。该类的实例由 @Strategy 宏或成员函数创建。 |
| FlatMapProcessor<T,R> | 对参数数据进行 FlatMap 的处理器。 |
| FlatMapStrategyProcessor<T,R> | 对参数数据进行 FlatMap 的处理器。 |
| InputParameter | 入参对象类型。 |
| JsonStrategy<T> | DataStrategy 对 JSON 数据格式的序列化实现。 |
| LazyCyclicNode | 用于在一个循环中一个接一个地推进类型擦除的内部惰性迭代器。 |
| MapProcessor<T,R> | 对参数数据进行 Map 的处理器。 |
| PowerAssertDiagramBuilder | PowerAssert 输出结果构造器。 |
| RandomDataProvider<T> | 使用随机数据生成的 DataProvider 接口的实现。 |
| RandomDataShrinker<T> | 使用随机数据生成的 DataShrinker 接口的实现。 |
| RandomDataStrategy<T> | 使用随机数据生成的 DataStrategy 接口的实现。 |
| RawStatsReporter | 未处理的性能测试数据报告器。仅给框架内部使用。 |
| Report | 打印测试用例结果报告的基类。 |
| SerializableProvider<T> | 获取序列化数据 DataProvider 接口的实现。 |
| SimpleProcessor<T> | 简单的数据策略处理器。对 DataStrategyProcessor 的一种实现。 |
| TestGroup | 提供构建和运行测试组合方法的类。 |
| TestGroupBuilder | 提供配置测试组合的方法的构造器。 |
| TestPackage | 用例包对象。 |
| TestReport | 单元测试执行结果报告。 |
| TestSuite | 提供构建和执行测试套方法的类。 |
| TestSuiteBuilder | 提供配置测试套方法的测试套构造器。 |
| UnitTestCase | 提供创建和执行单元测试用例的方法的类。 |
| XmlReporter | 打印单元测试用例结果数据到 Xml 文件上。 |
枚举
| 枚举名 | 功能 |
|---|---|
| ExplicitGcType | 用于指定 @Configure 宏的 explicitGC 配置参数。表示 GC 执行的三种不同方式。 |
| TimeUnit | 可以在 TimeNow 类构造函数中使用的时间单位。 |
| PerfCounter | 枚举 Perf 构造器支持的 CPU 计数器。 |
结构体
| 结构体名 | 功能 |
|---|---|
| BatchInputProvider<T> | 输入提供程序,在执行之前在缓冲区中生成整个基准批次的输入。 |
| BatchSizeOneInputProvider<T> | 基准输入提供程序,在每次执行基准之前生成输入。 |
| CpuCycles | 使用本机 rdtscp 指令测量 CPU 周期数。仅适用于 x86 平台。 |
| GenerateEachInputProvider<T> | 基准输入提供程序,在每次执行基准之前生成输入。 |
| ImmutableInputProvider<T> | 最简单的输入提供程序,只需为基准测试的每次调用复制数据。适用于基准测试不会改变输入的情况。它在框架内默认使用。 |
| Perf | 使用linux 系统调用 perf_event_open 测量各种硬件和软件 CPU 计数器。仅在 Linux 上可用。 |
| TimeNow | Measurement 的实现,用于测量执行一个函数所花费的时间。 |
异常类
| 异常名 | 功能 |
|---|---|
| AssertException | @Expect / @Assert 检查失败时所抛出的异常。 |
| AssertIntermediateException | @PowerAssert 检查失败时所抛出的异常。 |
| UnittestCliOptionsFormatException | 控制台选项格式错误抛出的异常。 |
| UnittestException | 框架通用异常。 |
函数
func assertCaughtUnexpectedE(String, String, String, Option<AssertionCtx>)
public func assertCaughtUnexpectedE(
message: String,
expectedExceptions: String,
caughtException: String,
optParentCtx!: ?AssertionCtx = None
): Nothing
功能:捕获的异常不符合预期,记录信息,抛出异常。
参数:
- message: String - 不符合预期时的提示信息。
- expectedExceptions: String - 期望的捕获的异常。
- caughtException: String - 实际捕获的异常。
- optParentCtx!: Option<AssertionCtx> - 存储嵌套断言失败消息的上下文。
func assertEqual<T>(String, String, T, T, Option<AssertionCtx>): Unit where T <: Equatable<T>
public func assertEqual<T>(
leftStr: String,
rightStr: String,
expected: T,
actual: T,
optParentCtx!: ?AssertionCtx = None): Unit where T <: Equatable<T>
功能:比较 expected 和 actual 值是否相等。若不等,直接抛出异常。
参数:
- leftStr: String - 期望的表达式的字符串。
- rightStr: String - 实际的表达式的字符串。
- expected: T - 期望的值。
- actual: T - 实际值。
- optParentCtx!: Option<AssertionCtx> - 存储嵌套断言失败消息的上下文。
func defaultConfiguration()
public func defaultConfiguration(): Configuration
功能:生成默认的配置信息。
返回值:
- Configuration - 配置信息。
func entryMain(TestPackage)
public func entryMain(testPackage: TestPackage): Int64
功能:提供给 cjc --test 使用,框架执行测试用例的入口函数。
参数:
- testPackage: TestPackage - 测试包对象。
返回值:
- Int64 - 执行结果。
func expectCaughtUnexpectedE(String, String, String, Option<AssertionCtx>)
public func expectCaughtUnexpectedE(
message: String,
expectedExceptions: String,
caughtException: String,
optParentCtx!: ?AssertionCtx = None
): Unit
功能:捕获的异常不符合预期,记录信息,不抛出异常。
参数:
- message: String - 不符合预期时的提示信息。
- expectedExceptions: String - 期望的捕获的异常。
- caughtException: String - 实际捕获的异常。
- optParentCtx!: Option<AssertionCtx> - 存储嵌套断言失败消息的上下文。
func expectEqual<T>(String, String, T, T, Option<AssertionCtx>): Unit where T <: Equatable<T>
public func expectEqual<T>(
leftStr: String,
rightStr: String,
expected: T,
actual: T,
optParentCtx!: ?AssertionCtx
): Unit where T <: Equatable<T>
功能:比较 expected 和 actual 值是否相等。记录比较结果,不抛出异常。
参数:
- leftStr: String - 期望的表达式的字符串。
- rightStr: String - 实际的表达式的字符串。
- expected: T - 期望的值。
- actual: T - 实际值。
- optParentCtx!: Option<AssertionCtx> - 存储嵌套断言失败消息的上下文。
func fail(String)
public func fail(message: String): Nothing
功能:使该用例失败,直接抛出异常。
参数:
- message: String - 失败信息。
func failExpect(String)
public func failExpect(message: String): Unit
功能:使该用例失败,记录信息,不抛出异常。
参数:
- message: String - 失败信息。
func invokeCustomAssert<T>(Array<String>, String, (AssertionCtx) -> T, Option<AssertionCtx>)
public func invokeCustomAssert<T>(
passerdArgs: Array<String>,
caller: String,
assert: (AssertionCtx) -> T,
optParentCtx!: ?AssertionCtx = None
): T
功能:运行在 @Test, @TestCase,或 @CustomAssertion 宏中使用的 @Assert\[caller\](passerArgs) 指定的用户定义断言函数。
参数:
- passedArgs: Array<String> - 未处理的已传递参数。
- caller: String - 调用的自定义断言的名称。
- assert: (AssertionCtx) -> T - 捕获带有正确参数的断言调用。
- optParentCtx!: Option<AssertionCtx> - 存储嵌套断言失败消息的上下文。
返回值:
T- 由用户定义的断言返回的值。
func invokeCustomExpect(Array<String>, String, (AssertionCtx) -> Any, Option<AssertionCtx>)
public func invokeCustomExpect(
passerdArgs: Array<String>,
caller: String,
expect: (AssertionCtx) -> Any,
optParentCtx!: ?AssertionCtx = None
): Unit
功能:运行在 @Test, @TestCase, 或 @CustomAssertion 宏中使用的 @Expect\[caller\](passerArgs) 指定的用户定义断言函数。
参数:
- passedArgs: Array<String> - 未处理的已传递参数。
- caller: String - 调用的自定义断言的名称。
- expect: (AssertionCtx) -> Any - 捕获带有正确参数的断言调用。
- optParentCtx!: Option<AssertionCtx> - 存储嵌套断言失败消息的上下文。
类型别名
type MeasurementUnitTable
type MeasurementUnitTable = Array<(Float64, String)>
功能:用作 Measurement 中性能测试结果单位转换表的“边界-单位”对数组的别名。
要显示的性能测试结果值是根据归一化期间的边界从该表计算得出的。
例如,对于时间单位,它可以遵循 [(1.0, "ns"), (1_000.0, "us"), (1_000_000.0, "ms"), (1_000_000_000.0, "s"), ...]。
接口
interface BenchInputProvider
public interface BenchInputProvider<T> <: BenchmarkInputMarker {
mut func get(idx: Int64): T
mut func reset(max: Int64)
}
功能:当某些代码需要在性能测试执行前执行,或当输入变化就需要重新执行一段代码时,可实现本接口。同时 DataStrategy 的实现类型应返回此接口的实现类型。
用户一般不需要自行实现该接口,可直接使用 @Strategy 宏。
父类型:
mut func get(Int64)
mut func get(idx: Int64): T
功能:获取元素。该函数的执行时间包含在基准测量中,然后作为框架开销计算的一部分从结果中排除。
参数:
- idx : Int64 - 元素索引值。
返回值:
- T - 元素值。
mut func reset(Int64)
mut func reset(max: Int64)
功能:在基准测量之前调用。调用此函数后,后续的 get(i) 调用必须成功获取 [0, max) 中的 i 。
参数:
- max : Int64 - 最大值。
interface BenchmarkConfig
public interface BenchmarkConfig {
func batchSize(b: Int64): Unit
func batchSize(x: Range<Int64>): Unit
func warmup(x: Int64): Unit
func warmup(x: Duration): Unit
func minDuration(x: Duration): Unit
func explicitGC(x: ExplicitGcType): Unit
func minBatches(x: Int64): Unit
}
功能:该接口提供为 Configuration 宏配置性能测试相关信息的函数签名。
func batchSize(Int64)
func batchSize(b: Int64): Unit
功能:可实现该函数,为 @Configuration 宏配置批次的大小。
参数:
- b: Int64 - 需配置的批次大小值。
func batchSize(Range<Int64>): Unit
func batchSize(x: Range<Int64>): Unit
功能:可实现该函数,为 @Configuration 宏配置批次的大小。
参数:
func explicitGC(ExplicitGcType)
func explicitGC(x: ExplicitGcType): Unit
功能:可实现该函数,为 @Configuration 宏配置 GC 的类型。
参数:
- x: ExplicitGcType - 需配置的 GC 类型值。
func minBatches(Int64)
func minBatches(x: Int64): Unit
功能:可实现该函数,为 @Configuration 宏配置最小批次个数。
参数:
- Int64 - 需配置的最小批次个数。
func minDuration(Duration)
func minDuration(x: Duration): Unit
功能:可实现该函数,为 @Configuration 宏配置性能测试最小执行时间。
参数:
- x: Int64 - 需配置的性能测试最小执行时间。
func warmup(Int64)
func warmup(x: Int64): Unit
功能:可实现该函数,为 @Configuration 宏配置预热期的执行次数。
参数:
- x: Int64 - 需配置的预热期的执行次数。
func warmup(Duration)
func warmup(x: Duration): Unit
功能:可实现该函数,为 @Configuration 宏配置预热期的执行时间。
参数:
- x: Int64 - 需配置的预热期的执行时间。
interface BenchmarkInputMarker
public interface BenchmarkInputMarker
功能:当我们不知道 T 时,该接口能够检测 BenchInputProvider<T> 。
interface Generator<T>
public interface Generator<T> {
func next(): T
}
功能:生成器生成 T 类型的值。
func next()
func next(): T
功能:获取生成出来的 T 类型的值。
返回值:
- T - 生成的 T 类型的值。
interface Measurement
public interface Measurement {
prop conversionTable: MeasurementUnitTable
prop name: String
prop textDescription: String
func setup(): Unit
func measure(): Float64
}
功能:该接口指定如何在性能测试期间测量数据以及如何在报告中显示数据。
实现接口的实例可以作为宏 @Measure 的属性传递。
prop conversionTable
prop conversionTable: MeasurementUnitTable
功能:用于在性能测试报告中构建测量值的表示。
包含测量单位的边界对。
根据值的边界,使用最合适的单位。
对于 CSV 格式报告,始终选择下限以简化结果处理。
默认值为 [(1.0, "")]。
prop name
prop name: String
功能:当前 Measurement 类型的唯一显示名称。
有助于区分报告表中的不同测量类型。
默认值为 Measurement。
类型:String。
prop textDescription
prop textDescription: String
功能:描述此测量的简单文本将显示在某些报告中。
类型:String。
func measure()
func measure(): Float64
功能:将用于统计分析的测量运行时间的方法。
返回值:
- Float64 - 测量得到的数据。
func setup()
func setup()
功能:此测量的初始化例程。在每个基准步骤之前调用。
interface Reporter
sealed interface Reporter <TReport, TReturn>
功能:报告器基础接口。
interface TestClass
public interface TestClass {
func asTestSuite(): TestSuite
}
功能:提供创建 TestSuite 的方法。
func asTestSuite()
func asTestSuite(): TestSuite
功能:创建 TestSuite 的方法。
返回值:
- TestSuite - 测试套对象。
类
class AssertionCtx
public class AssertionCtx
功能:存储用户定义的断言的状态。提供用于编写用户定义断言的方法。
prop args
public prop args: String
功能:返回以逗号分隔的未解析的用户定义断言参数的字符串。
类型:String。
prop caller
public prop caller: String
功能:获取用户定义的断言函数的标识符。
类型:String。
prop hasErrors
public prop hasErrors: Bool
功能:如果用户定义内的任何断言失败,则为 true 。否则为 false。
类型:Bool
func arg(String)
public func arg(key: String): String
功能:返回表示原始传递的标识符的参数值的字符串表达,与参数列表中的标识符匹配。
参数:
- key: String - 函数参数列表中的标识符。
返回值:
- String - 对应标识符的参数值字符串表达。
func fail(String)
public func fail(message: String): Nothing
功能:存储失败信息,在用户定义的断言函数中提供并抛出 AssertExpection。
参数:
- message: String - 失败信息。
func fail<PP>(PP)
public func fail<PP>(pt: PP): Nothing where PP <: PrettyPrintable
功能:存储失败信息,在用户定义的断言函数中提供并抛出 AssertExpection。
参数:
- pt: PP <: PrettyPrintable - 失败信息。
func failExpect(String)
public func failExpect(message: String): Unit
功能:存储失败信息,在用户定义的断言函数内提供并继续函数执行。
参数:
- message: String - 失败信息。
func failExpect<PP>(PP)
public func failExpect<PP>(pt: PP): Unit where PP <: PrettyPrintable
功能:存储失败信息,在用户定义的断言函数内提供并继续函数执行。
参数:
- pt: PP <: PrettyPrintable - 失败信息。
func setArgsAliases(Array<String>)
public func setArgsAliases(aliases: Array<String>): Unit
功能:设置别名以通过函数 arg 访问未解析的用户定义的断言函数参数。框架内部使用,用户无需使用该函数。
参数:
- aliases: Array<String> - 标识符数组。数组的大小应与参数列表匹配(除
AssertionCtx外)。
class Benchmark
public class Benchmark {}
功能:该类提供创建和运行单个性能测试用例的方法。
prop name
public prop name: String
功能:获取用例名称。
类型:String。
func run()
public func run(): BenchReport
功能:运行该性能用例。
返回值:
- BenchReport - 运行结果报告。
static func create(String, Configuration, () -> Unit)
public static func create(name: String, configuration!: Configuration = Configuration(), body!: () -> Unit): Benchmark
功能:创建一个性能测试用例对象。
参数:
- name : String - 用例名称。
- configuration!: Configuration - 用例配置信息。
- body!: () -> Unit - 用例执行体。
返回值:
- Benchmark - 性能测试用例对象。
static func createParameterized<T>(String, DataStrategy<T>, Configuration, (T) -> Unit)
public static func createParameterized<T>(name: String, strategy: DataStrategy<T>, configuration!: Configuration = Configuration(), body!: (T) -> Unit): Benchmark
功能:创建一个参数化的性能测试用例对象。
参数:
- name : String - 用例名称。
- strategy : DataStrategy - 参数数据策略。
- configuration!: Configuration - 用例配置信息。
- body!: () -> Unit - 用例执行体。
返回值:
- Benchmark - 性能测试用例对象。
static func createParameterized<T>(String, DataStrategyProcessor<T>, Configuration, (T) -> Unit)
public static func createParameterized<T>(name: String, strategy: DataStrategyProcessor<T>, configuration!: Configuration = Configuration(), body!: (T) -> Unit): Benchmark
功能:创建一个参数化的性能测试用例对象。
参数:
- name : String - 用例名称。
- strategy : DataStrategyProcessor - 参数数据处理器。
- configuration!: Configuration - 用例配置信息。
- body!: () -> Unit - 用例执行体。
返回值:
- Benchmark - 性能测试用例对象。
class BenchReport
public class BenchReport <: Report {}
功能:提供性能用例执行结果报告处理能力。
父类型:
func reportTo<T>(Reporter<BenchReport, T>)
public func reportTo<T>(reporter: Reporter<BenchReport, T>): T
功能:打印性能用例结果报告。
参数:
- reporter : Reporter<BenchReport, T> - 性能用例结果报告。
返回值:
- T : 打印结果返回值。一般为 Unit 类型。
class CartesianProductProcessor<T0,T1>
public class CartesianProductProcessor<T0,T1> <: DataStrategyProcessor<(T0,T1)> {
public CartesianProductProcessor(let left: DataStrategyProcessor<T0>, let right: DataStrategyProcessor<T1>)
}
功能:笛卡尔积处理器。
父类型:
- DataStrategyProcessor<(T0, T1)>
CartesianProductProcessor(DataStrategyProcessor<T0>, DataStrategyProcessor<T1>)
public CartesianProductProcessor(let left: DataStrategyProcessor<T0>, let right: DataStrategyProcessor<T1>)
功能:CartesianProductProcessor主构造函数。
参数:
- left : DataStrategyProcessor<T0> - 数据策略处理器。
- right : DataStrategyProcessor<T1> - 数据策略处理器。
class ConsoleReporter
public class ConsoleReporter <: Reporter<TestReport, Unit> & Reporter<BenchReport, Unit>{
public ConsoleReporter(let colored!: Bool = true)
}
功能:打印单元测试用例结果或者性能测试用例结果到控制台。
父类型:
ConsoleReporter(Bool)
public ConsoleReporter(let colored!: Bool = true)
功能:ConsoleReporter构造函数。
参数:
- colored!: Bool - 是否使用带颜色的打印,默认带颜色。
class TextReporter<PP>
public class TextReporter<PP> <: Reporter<TestReport, PP> & Reporter<BenchReport, PP>
where PP <: PrettyPrinter {
public TextReporter(let into!: PP)
}
功能:将单元测试用例结果或性能测试结果打印到 PrettyPrinter 的子类。格式与 ConsoleReporter 相同。
父类型:
- Reporter<TestReport, PP>
- Reporter<BenchReport, PP>
TextReporter(PP)
public TextReporter(let into!: PP)
功能:TextReporter构造函数。
参数:
- into!: PP - PrettyPrinter 的子类。打印报告。
class CsvReporter
public class CsvReporter <: Reporter<BenchReport, Unit> {
public CsvReporter(let directory: Path)
}
功能:打印性能测试用例结果数据到 Csv 文件上。
父类型:
CsvReporter(Path)
public CsvReporter(let directory: Path)
功能:CsvReporter构造函数。
参数:
- directory: Path - 打印文件生成地址。
class CsvRawReporter
public class CsvRawReporter <: Reporter<BenchReport, Unit> {
public CsvRawReporter(let directory: Path)
}
功能:打印性能测试用例结果数据,该数据只有批次的原始测量值,到 Csv 文件上。
父类型:
CsvRawReporter(Path)
public CsvRawReporter(let directory: Path)
功能:CsvRawReporter构造函数。
参数:
- directory: Path - 打印文件生成地址。
class CsvStrategy<T>
public class CsvStrategy<T> <: DataStrategy<T> where T <: Serializable<T> {}
功能:DataStrategy 对 CSV 数据格式的序列化实现。
父类型:
- DataStrategy<T>
func provider(Configuration)
public override func provider(configuration: Configuration): SerializableProvider<T>
功能:生成序列化数据迭代器。
参数:
- configuration: Configuration - 数据配置信息。
返回值:
- SerializableProvider<T> - 序列化迭代器对象。
class DataStrategyProcessor<T>
abstract sealed class DataStrategyProcessor<T> {}
功能:所有 DataStrategy 组件的基类。该类的实例由 @Strategy 宏或成员函数创建。
prop isInfinite
protected prop isInfinite: Bool
功能:获取该策略是否为无限。
类型:Bool。
func intoBenchmark(String, Configuration, (T, Int64, Int64) -> Float64)
public func intoBenchmark(
caseName!: String,
configuration!: Configuration,
doRun!: (T, Int64, Int64) -> Float64
): Benchmark
功能:宏生成的代码使用的辅助函数。用于创建使用该策略的性能测试用例。
参数:
- caseName!: String - 用例名称。
- configuration!: Configuration - 配置信息。
- doRun!: (T, Int64, Int64) -> Float64 - 性能测试用例执行体。
返回值:
- Benchmark - 性能测试用例对象。
func intoUnitTestCase(String, Configuration, (T) -> Unit)
public func intoUnitTestCase(
caseName!: String,
configuration!: Configuration,
doRun!: (T) -> Unit
): UnitTestCase
功能:宏生成的代码使用的辅助函数。用于创建使用该策略的测试用例。
参数:
- caseName!: String - 用例名称。
- configuration!: Configuration - 配置信息。
- doRun!: (T) -> Unit - 性能测试用例执行体。
返回值:
- UnitTestCase - 测试用例对象。
func lastItemInfo()
protected func lastItemInfo(): Array<InputParameter>
功能:获取上一个处理条目的信息。
返回值:
- Array<InputParameter> - 上一个处理条目的信息。
func lastItem(Configuration)
protected func lastItem(configuration: Configuration): T
功能:获取上一个处理条目。
参数:
- configuration : Configuration - 处理策略配置信息。
返回值:
- T - 上一个处理条目。
func provide(Configuration)
protected func provide(configuration: Configuration): Iterable<T>
功能:生成依据配置信息和数据策略生成的数据迭代器。
参数:
- configuration : Configuration - 处理策略配置信息。
返回值:
- Iterable<T> - 数据迭代器。
func shrinkLastItem(Configuration, LazyCyclicNode)
protected func shrinkLastItem(configuration: Configuration, engine: LazyCyclicNode): Iterable<T>
功能:收缩上一个条目。
参数:
- configuration:Configuration - 配置信息。
- engine : LazyCyclicNode - 惰性节点。
返回值:
- Iterable<T> - 收缩后的数据迭代器。
static func start(DataStrategy<T>, String)
public static func start(s: DataStrategy<T>, name: String): SimpleProcessor<T>
功能:DataStrategy 的组合和映射的起点。
参数:
- s: DataStrategy<T> - 数据策略。
- name: String - 用例名称。
返回值:
- SimpleProcessor<T> - 测试用例处理器。
static func start<U>(() -> DataStrategy<U>, String)
public static func start<U>(f: () -> DataStrategy<U>, name: String): DataStrategyProcessor<U> where U <: BenchInputProvider < T >
功能:DataStrategy 的组合和映射的起点。
参数:
- s: () -> DataStrategy<U> - 生成数据策略的闭包。
- name: String - 用例名称。
返回值:
- DataStrategyProcessor<T> - 数据策略处理器。
static func start(() -> DataStrategy<T>, String, Int64)
public static func start(f: () -> DataStrategy<T>, name: String, x!: Int64 = 0): SimpleProcessor<T>
功能:DataStrategy 的组合和映射的起点。
参数:
- s: () -> DataStrategy<T> - 生成数据策略的闭包。
- name: String - 用例名称。
- x!: Int64 - 为实现不同返回值的重构增加的参数。
返回值:
- SimpleProcessor<T> - 测试用例处理器。
static func start(() -> DataStrategyProcessor<T>, String)
public static func start(f: () -> DataStrategyProcessor<T>, name: String): DataStrategyProcessor<T>
功能:DataStrategy 的组合和映射的起点。
参数:
- s: () -> DataStrategyProcessor<T> - 生成数据策略处理器的闭包。
- name: String - 用例名称。
返回值:
- DataStrategyProcessor<T> - 数据策略处理器。
static func start<U>(() -> DataStrategyProcessor<U>, String, Int64)
public static func start<U>(f: () -> DataStrategyProcessor<U>, name: String, x!: Int64 = 0):
DataStrategyProcessor<U> where U <: BenchInputProvider<T>
功能:DataStrategy 的组合和映射的起点。
参数:
- s: () -> DataStrategyProcessor<U> - 生成数据策略处理器的闭包。
- name: String - 用例名称。
- x!: Int64 - 为实现不同返回值的重构增加的参数。
返回值:
- DataStrategyProcessor<U> where U <: BenchInputProvider<T> - 数据策略处理器。
extend <T> DataStrategyProcessor<T>
extend <T> DataStrategyProcessor<T> {}
func map<R>((T) -> R)
public func map<R>(f: (T) -> R): MapProcessor<T, R>
功能:简单地将 f 应用于原始数据策略的每个项目。 Shrink 也会发生在原始输入上,然后进行映射。
参数:
- f: (T) -> R - 需要增加的处理逻辑函数。
返回值:
- MapProcessor<T, R> - 应用
f后的处理器。
func mapWithConfig<R>((T, Configuration) -> R)
public func mapWithConfig<R>(f: (T, Configuration) -> R): MapProcessor<T, R>
功能:可以访问当前的 Configuration ,只需将 f 应用于原始数据策略的每个项目。 Shrink 也会发生在原始输入上,然后进行映射。
参数:
- f: (T, Configuration) -> R - 需要增加的处理逻辑函数。
返回值:
- MapProcessor<T, R> - 应用
f后的处理器。
func flatMap<R>((T) -> DataProvider<R>)
public func flatMap<R>(f: (T) -> DataProvider<R>): FlatMapProcessor<T, R>
功能:简单地将 f 应用于原始数据策略的每个项目,然后展平结果。 Shrink 也会发生在原始输入上,然后进行 flatMap 。
参数:
- f: (T) -> DataProvider<R> - 需要增加的处理逻辑函数。
返回值:
- FlatMapProcessor<T, R> - 应用
f后的处理器。
func flatMapStrategy((T) -> DataStrategy<R>)
public func flatMapStrategy<R>(f: (T) -> DataStrategy<R>): FlatMapStrategyProcessor<T, R>
功能:简单地将 f 应用于原始数据策略的每个项目,然后展平结果。 Shrink 是通过返回的策略而不是原始输入来完成的。
参数:
- f: (T) -> DataStrategy<R> - 需要增加的处理逻辑函数。
返回值:
- FlatMapStrategyProcessor<T, R> - 应用
f后的处理器。
func product(DataStrategyProcessor<R>)
public func product<R>(p: DataStrategyProcessor<R>): CartesianProductProcessor<T, R>
功能:笛卡尔积组合器创建包含原始策略中元素的所有可能排列的数据策略。 对于无限策略,它首先迭代所有有限的子策略,然后才推进无限的子策略。 Shrink 独立且统一地发生在原始策略的每个元素上。
参数:
- p: DataStrategyProcessor<R> - 数据策略处理器。
返回值:
- CartesianProductProcessor<T, R> - 笛卡尔积处理器。
class FlatMapProcessor<T,R>
public class FlatMapProcessor<T,R> <: DataStrategyProcessor<R> {}
功能:对参数数据进行 FlatMap 的处理器。
父类型:
class FlatMapStrategyProcessor<T,R>
public class FlatMapStrategyProcessor<T,R> <: DataStrategyProcessor<R> {}
功能:对参数数据进行 FlatMap 的处理器。
父类型:
class InputParameter
public class InputParameter {}
功能:入参对象类型。
class JsonStrategy<T>
public class JsonStrategy<T> <: DataStrategy<T> where T <: Serializable<T> {}
功能:DataStrategy 对 JSON 数据格式的序列化实现。
父类型:
- DataStrategy<T>
func provider(Configuration)
public override func provider(configuration: Configuration): SerializableProvider<T>
功能:生成序列化数据迭代器。
参数:
- configuration: Configuration - 数据配置信息。
返回值:
- SerializableProvider<T> - 序列化迭代器对象。
class LazyCyclicNode
public open class LazyCyclicNode {}
功能:用于在一个循环中一个接一个地推进类型擦除的内部惰性迭代器。
func advance()
protected open func advance(): ?Unit
功能:前进一个值。
返回值:
- ?Unit - 当无法前进时返回 None ,否则返回 Unit 。
func recover()
protected open func recover(): Unit
功能:恢复或后退一个值。
class MapProcessor<T,R>
public class MapProcessor<T,R> <: DataStrategyProcessor<R> {}
功能:对参数数据进行 Map 的处理器。
父类型:
class PowerAssertDiagramBuilder
public class PowerAssertDiagramBuilder {
public init(expression: String)
}
功能:PowerAssert 输出结果构造器。
init(String)
public init(expression: String)
功能:构造函数。
参数:
- expression: String - 表达式字符串。
func r<T>(T, String, Int64)
public func r<T>(value: T, exprAsText: String, position: Int64): T
功能:记录对比数据。
参数:
返回值:
- T - 被记录的数据。
func r(String, String, Int64)
public func r(value: String, exprAsText: String, position: Int64): String
功能:记录对比数据。
参数:
返回值:
- String - 被记录的数据。
func r(Rune, String, Int64)
public func r(value: Rune, exprAsText: String, position: Int64): Rune
功能:记录对比数据。
参数:
返回值:
- Rune - 被记录的数据。
func h(Exception, String, Int64)
public func h(exception: Exception, exprAsText: String, position: Int64): Nothing
功能:处理异常。
参数:
func w(Bool)
public func w(passed: Bool): Unit
功能:当用例通过时返回成功结果,失败时抛出异常并打印对比结果。
参数:
- passed: Bool - 用例是否通过。
class RandomDataProvider<T>
public class RandomDataProvider<T> <: DataProvider<T> where T <: Arbitrary<T> {
public RandomDataProvider(private let configuration: Configuration)
}
功能:使用随机数据生成的 DataProvider 接口的实现。
父类型:
- DataProvider<T>
RandomDataProvider(Configuration)
public RandomDataProvider(private let configuration: Configuration)
功能:构造一个随机数据提供者RandomDataProvider的对象。
参数:
- configuration: Configuration - 配置对象,必须包含一个随机生成器,名称为
random,类型为 random.Random。
异常:
- IllegalArgumentException - 当 configuration 不包含 random 实例时,抛出异常。
prop isInfinite
public override prop isInfinite: Bool
功能:是否生成无限的数据。
类型:Bool。
func provide()
public override func provide(): Iterable<T>
功能:提供随机化生成的数据。
返回值:
- Iterable<T> - 从 T 的任意实例创建的无限迭代器。
class RandomDataShrinker<T>
public class RandomDataShrinker<T> <: DataShrinker<T> {}
功能:使用随机数据生成的 DataShrinker 接口的实现。
父类型:
- DataShrinker<T>
func shrinker(T)
public override func shrink(value: T): Iterable<T>
功能:获取值的缩减器。
参数:
- value: T - 参数值。
返回值:
class RandomDataStrategy<T>
public class RandomDataStrategy<T> <: DataStrategy<T> where T <: Arbitrary<T>{}
功能:使用随机数据生成的 DataStrategy 接口的实现。
父类型:
- DataStrategy<T>
func provider(Configuration)
public override func provider(configuration: Configuration): RandomDataProvider<T>
功能:获取随机数据的提供者。
参数:
- configuration: Configuration - 参数配置信息。
返回值:
- RandomDataProvider - 随机数提供者。
func shrinker(Configuration)
public override func shrinker(_: Configuration): RandomDataShrinker<T>
功能:获取随机数据的缩减器。
参数:
- _: Configuration - 参数配置信息。
返回值:
- RandomDataShrinker - 随机数据的缩减器。
class Report
sealed abstract class Report {}
功能:打印测试用例结果报告的基类。
prop errorCount
public prop errorCount: Int64
功能:获取错误的用例个数。
类型:Int64。
prop caseCount
public prop caseCount: Int64
功能:获取用例个数。
类型:Int64。
prop passedCount
public prop passedCount: Int64
功能:获取通过的用例个数。
类型:Int64。
prop failedCount
public prop failedCount: Int64
功能:获取失败的用例个数。
类型:Int64。
prop skippedCount
public prop skippedCount: Int64
功能:获取跳过的用例个数。
类型:Int64。
class RawStatsReporter
public class RawStatsReporter <: Reporter<BenchReport, HashMap<String, (Float64, Float64)>> {
public RawStatsReporter()
}
功能:未处理的性能测试数据报告器。仅给框架内部使用。
父类型:
RawStatsReporter()
public RawStatsReporter()
功能:RawStatsReporter构造函数。
class SerializableProvider<T>
public class SerializableProvider<T> <: DataProvider<T> where T <: Serializable<T> {}
功能:获取序列化数据 DataProvider 接口的实现。
父类型:
- DataProvider<T>
prop isInfinite
public prop isInfinite: Bool
功能:是否生成无限的数据。
Bool。
func provide()
public override func provide(): Iterable<T>
功能:获取数据迭代器。
返回值:
- Iterable<T> - 数据迭代器。
class SimpleProcessor<T>
public class SimpleProcessor<T> <: DataStrategyProcessor<T> {
public SimpleProcessor(let buildDelegate:() -> DataStrategy<T>, let name: String)
}
功能:简单的数据策略处理器。对 DataStrategyProcessor 的一种实现。
父类型:
SimpleProcessor(() -> DataStrategy<T>, String)
public SimpleProcessor(let buildDelegate:() -> DataStrategy<T>, let name: String)
功能:SimpleProcessor构造函数。
参数:
- buildDelegate : () -> DataStrategy<T> - 生成数据策略的闭包。
- name : String - 处理器名称。
class TestGroup
public class TestGroup {}
功能:提供构建和运行测试组合方法的类。
prop name
public prop name: String
功能:获取测试组合名称。
类型:String。
func runBenchmarks()
public func runBenchmarks(): BenchReport
功能:运行所有性能测试用例。
返回值:
- BenchReport - 性能测试用例报告。
func runBenchmarks(Configuration)
public func runBenchmarks(Configuration): BenchReport
功能:带运行配置得执行所有性能测试用例。
参数:
- configuration: Configuration - 运行配置。
返回值:
- BenchReport - 性能测试用例报告。
func runTests()
public func runTests(): TestReport
功能:执行所有单元测试用例。
返回值:
- TestReport - 单元测试用例报告。
func runTests(Configuration)
public func runTests(configuration: Configuration): TestReport
功能:带运行配置得执行所有单元测试用例。
参数:
- configuration: Configuration - 运行配置。
返回值:
- TestReport - 单元测试用例报告。
static func builder(String)
public static func builder(name: String): TestGroupBuilder
功能:创建测试组合构造器。
参数:
- name : String - 测试组合名称。
返回值:
- TestGroupBuilder - 测试组合构造器。
static func builder(TestGroup)
public static func builder(group: TestGroup): TestGroupBuilder
功能:创建测试组合构造器。
参数:
- group : TestGroup - 测试组合。
返回值:
- TestGroupBuilder - 测试组合构造器。
class TestGroupBuilder
public class TestGroupBuilder {}
功能:提供配置测试组合的方法的构造器。
func add(Benchmark)
public func add(benchmark: Benchmark): TestGroupBuilder
功能:为测试组合增加性能测试用例。
参数:
- benchmark : Benchmark - 性能测试用例。
返回值:
- TestGroupBuilder - 测试组合构造器。
func add(TestSuite)
public func add(suite: TestSuite): TestGroupBuilder
功能:为测试组合增加单元测试套。
参数:
- suite : TestSuite - 单元测试套。
返回值:
- TestGroupBuilder - 测试组合构造器。
func add(UnitTestCase)
public func add(test: UnitTestCase): TestGroupBuilder
功能:为测试组合增加单元测试用例。
参数:
- test : UnitTestCase - 单元测试用例。
返回值:
- TestGroupBuilder - 测试组合构造器。
func build()
public func build(): TestGroup
功能:配置完成后,构建测试组合对象。
返回值:
- TestGroup - 测试组合。
func configure(Configuration)
public func configure(configuration: Configuration): TestGroupBuilder
功能:为测试组合配置配置信息。
参数:
- configuration : Configuration - 配置信息。
返回值:
- TestGroupBuilder - 测试组合构造器。
func setName(String)
public func setName(name: String): TestGroupBuilder
功能:为测试组合设置名称。
参数:
- name : String - 名称。
返回值:
- TestGroupBuilder - 测试组合构造器。
class TestPackage
public class TestPackage {
public TestPackage(let name: String)
}
功能:用例包对象。
TestPackage(String)
public TestPackage(let name: String)
功能:TestPackage构造函数。
参数:
- name: String - 用例包名称。
func registerCase(() -> UnitTestCase)
public func registerCase(testCase: () -> UnitTestCase): Unit
功能:注册单元测试用例。
参数:
- testCase: () -> UnitTestCase - 单元测试用例生成闭包。
func registerSuite(() -> TestSuite)
public func registerSuite(suite: () -> TestSuite): Unit
功能:注册测试套。
参数:
- suite: () -> TestSuite - 测试套生成闭包。
func registerBench(() -> Benchmark)
public func registerBench(bench: () -> Benchmark): Unit
功能:注册性能用例。
参数:
- bench: () -> Benchmark - 性能用例生成闭包。
class TestReport
public class TestReport <: Report {}
功能:单元测试执行结果报告。
父类型:
func reportTo<T>(Reporter<TestReport, T>)
public func reportTo<T>(reporter: Reporter<TestReport, T>): T
功能:打印单元测试执行报告。
参数:
- reporter : Reporter<TestReport, T> - 单元测试报告打印器。
返回值:
- T : 打印返回值,一般为 Unit 。
class TestSuite
public class TestSuite {}
功能:提供构建和执行测试套方法的类。
prop name
public prop name: String
功能:获取测试套名称。
类型:String。
func runBenchmarks()
public func runBenchmarks(): BenchReport
功能:运行所有性能测试用例。
返回值:
- BenchReport - 性能测试运行结果。
func runBenchmarks(Configuration)
public func runBenchmarks(configuration: Configuration): BenchReport
功能:带配置信息得运行所有性能测试用例。
参数:
- configuration : Configuration - 运行配置信息。
返回值:
- BenchReport - 性能测试用例运行结果。
func runTests()
public func runTests(): TestReport
功能:运行测试套。
返回值:
- TestReport - 测试套运行结果。
func runTests(Configuration)
public func runTests(configuration: Configuration): TestReport
功能:带配置信息得运行测试套。
参数:
- configuration : Configuration - 运行配置信息。
返回值:
- TestReport - 测试套运行结果。
static func builder(String)
public static func builder(name: String): TestSuiteBuilder
功能:创建测试套构建器。
参数:
- name : String - 测试套名称。
返回值:
- TestSuiteBuilder - 测试套构造器。
static func builder(TestSuite)
public static func builder(suite: TestSuite): TestSuiteBuilder
功能:创建测试套构建器。
参数:
- suite : TestSuite - 测试套。
返回值:
- TestSuiteBuilder - 测试套构造器。
class TestSuiteBuilder
public class TestSuiteBuilder {}
功能:提供配置测试套方法的测试套构造器。
func add(Benchmark)
public func add(benchmark: Benchmark): TestSuiteBuilder
功能:为测试套添加性能用例。
参数:
- benchmark : Benchmark - 性能测试用例。
返回值:
- TestGroupBuilder - 测试组合构造器。
func add(UnitTestCase)
public func add(test: UnitTestCase): TestSuiteBuilder
功能:为测试套添加单元测试用例。
参数:
- test : UnitTestCase - 单元测试用例。
返回值:
- TestGroupBuilder - 测试组合构造器。
func afterAll(() -> Unit)
public func afterAll(body: () -> Unit): TestSuiteBuilder
功能:为测试套添加在所有用例执行完成后执行的生命周期管理闭包。
参数:
- body : () -> Unit - 执行体。
返回值:
- TestGroupBuilder - 测试组合构造器。
func afterEach(() -> Unit)
public func afterEach(body: () -> Unit): TestSuiteBuilder
功能:为测试套添加在每个用例执行完成后执行的生命周期管理闭包。
参数:
- body : () -> Unit - 执行体。
返回值:
- TestGroupBuilder - 测试组合构造器。
func afterEach((String) -> Unit)
public func afterEach(body: (String) -> Unit): TestSuiteBuilder
功能:为测试套添加在每个用例执行完成后执行的生命周期管理闭包。
参数:
- body : (String) -> Unit - 执行体。
返回值:
- TestGroupBuilder - 测试组合构造器。
func beforeAll(() -> Unit)
public func beforeAll(body: () -> Unit): TestSuiteBuilder
功能:为测试套添加在所有用例执行前执行的生命周期管理闭包。
参数:
- body : () -> Unit - 执行体。
返回值:
- TestGroupBuilder - 测试组合构造器。
func beforeEach(() -> Unit)
public func beforeEach(body: () -> Unit): TestSuiteBuilder
功能:为测试套添加在每个用例执行前执行的生命周期管理闭包。
参数:
- body : () -> Unit - 执行体。
返回值:
- TestGroupBuilder - 测试组合构造器。
func beforeEach((String) -> Unit)
public func beforeEach(body: (String) -> Unit): TestSuiteBuilder
功能:为测试套添加在每个用例执行前执行的生命周期管理闭包。
参数:
- body : (String) -> Unit - 执行体。
返回值:
- TestGroupBuilder - 测试组合构造器。
func template(TestSuite)
public func template(template: TestSuite): TestSuiteBuilder
功能:执行此方法可为测试套件设置模板。
参数
- template : TestSuite - 将作为模板的测试套件。
返回值:
- TestGroupBuilder - 测试组合构造器。
func build()
public func build(): TestSuite
功能:配置完成后构造测试套。
返回值:
- TestSuite - 测试套。
func configure(Configuration)
public func configure(configuration: Configuration): TestSuiteBuilder
功能:为测试套添加配置信息。
参数:
- configuration : Configuration - 测试配置信息。
返回值:
- TestGroupBuilder - 测试组合构造器。
func setName(String)
public func setName(name: String): TestSuiteBuilder
功能:为测试套设置名称。
参数:
- name : String - 测试套名称。
返回值:
- TestGroupBuilder - 测试组合构造器。
class UnitTestCase
public class UnitTestCase {}
功能:提供创建和执行单元测试用例的方法的类。
prop name
public prop name: String
功能:获取单元测试名称。
类型:String。
func run()
public func run(): TestReport
功能:运行单元测试用例。
返回值:
- TestReport - 单元测试执行结果报告。
static func create(String, Configuration, () -> Unit)
public static func create(name: String, configuration!: Configuration = Configuration(), body!: () -> Unit): UnitTestCase
功能:创建单元测试用例。
参数:
- name : String - 用例名称。
- configuration!: Configuration - 用例配置信息。
- body!: () -> Unit - 用例执行体。
返回值:
- UnitTestCase - 单元测试用例对象。
static func createParameterized<T>(String, DataStrategy<T>, Configuration, (T) -> Unit)
public static func createParameterized<T>(name: String, strategy: DataStrategy<T>, configuration!: Configuration = Configuration(), body!: (T) -> Unit): UnitTestCase
功能:创建参数化的单元测试用例。
参数:
- name : String - 用例名称。
- strategy : DataStrategy - 参数数据策略。
- configuration!: Configuration - 用例配置信息。
- body!: () -> Unit - 用例执行体。
返回值:
- UnitTestCase - 单元测试用例对象。
static func createParameterized<T>(String, DataStrategyProcessor<T>, Configuration, (T) -> Unit)
public static func createParameterized<T>(name: String, strategy: DataStrategyProcessor<T>, configuration!: Configuration = Configuration(), body!: (T) -> Unit): UnitTestCase
功能:创建参数化的单元测试用例。
参数:
- name : String - 用例名称。
- strategy : DataStrategyProcessor - 参数数据处理器。
- configuration!: Configuration - 用例配置信息。
- body!: () -> Unit - 用例执行体。
返回值:
- UnitTestCase - 单元测试用例对象。
class XmlReporter
public class XmlReporter <: Reporter<TestReport, Unit> {
public XmlReporter(let directory: Path)
}
功能:打印单元测试用例结果数据到 Xml 文件上。
父类型:
XmlReporter(Path)
public XmlReporter(let directory: Path)
功能:XmlReporter构造函数。
参数:
- directory: Path - 打印文件生成地址。
枚举
enum ExplicitGcType
public enum ExplicitGcType <: ToString {
Disabled |
Heavy |
Light
}
功能:用于指定 @Configure 宏的 explicitGC 配置参数。表示 GC 执行的三种不同方式。
父类型:
Disabled
Disabled
功能:GC 不会被框架显式调用。
Heavy
Heavy
功能:std.runtime.GC(heavy: true) 将在性能测试执行期间由框架显式调用。
Light
Light
功能:std.runtime.GC(heavy: false) 将在 Benchmark 函数执行期间由框架显式调用。这是默认设置。
func toString()
public override func toString(): String
功能:GC 执行的三种不同方式字符串。
返回值:
enum TimeUnit
public enum TimeUnit {
| Micros
| Millis
| Nanos
| Seconds
}
功能:可以在 TimeNow 构造函数中使用的时间单位。
Micros
Micros
功能:单位为微秒。
Millis
Millis
功能:单位为毫秒。
Nanos
Nanos
功能:单位为纳秒。
Seconds
Seconds
功能:单位为秒。
enum PerfCounter
public enum PerfCounter <: ToString {
| HW_CPU_CYCLES
| HW_INSTRUCTIONS
| HW_CACHE_REFERENCES
| HW_CACHE_MISSES
| HW_BRANCH_INSTRUCTIONS
| HW_BRANCH_MISSES
| HW_BUS_CYCLES
| HW_STALLED_CYCLES_FRONTEND
| HW_STALLED_CYCLES_BACKEND
| HW_REF_CPU_CYCLES
| SW_CPU_CLOCK
| SW_TASK_CLOCK
| SW_PAGE_FAULTS
| SW_CONTEXT_SWITCHES
| SW_CPU_MIGRATIONS
| SW_PAGE_FAULTS_MIN
| SW_PAGE_FAULTS_MAJ
| SW_EMULATION_FAULTS
}
功能:枚举 Perf 构造器支持的 CPU 计数器。
有关特定 CPU 计数器的详细信息,请参阅 Linux 内核中 perf_event_open 系统调用的文档。
父类型:
HW_CPU_CYCLES
HW_CPU_CYCLES
功能:原始 CPU 周期数。
HW_INSTRUCTIONS
HW_INSTRUCTIONS
功能:退役的 CPU 指令数量。
HW_CACHE_REFERENCES
HW_CACHE_REFERENCES
功能:缓存访问量。
HW_CACHE_MISSES
HW_CACHE_MISSES
功能:缓存未命中数量。
HW_BRANCH_INSTRUCTIONS
HW_BRANCH_INSTRUCTIONS
功能:退役的分支 CPU 指令数量。
HW_BRANCH_MISSES
HW_BRANCH_MISSES
功能:分支预测失败的数量。
HW_BUS_CYCLES
HW_BUS_CYCLES
功能:总线周期数。
HW_STALLED_CYCLES_FRONTEND
HW_STALLED_CYCLES_FRONTEND
功能:CPU 周期被浪费在 CPU 管道前端阶段的等待上的数量。
HW_STALLED_CYCLES_BACKEND
HW_STALLED_CYCLES_BACKEND
功能:CPU 周期被浪费在 CPU 管道后端阶段的等待上的数量。
HW_REF_CPU_CYCLES
HW_REF_CPU_CYCLES
功能:与频率无关的 CPU 周期数。
SW_CPU_CLOCK
SW_CPU_CLOCK
功能:每个 CPU 时钟时间量。
SW_TASK_CLOCK
SW_TASK_CLOCK
功能:每个任务的 CPU 时钟时间量。
SW_PAGE_FAULTS
SW_PAGE_FAULTS
功能:页错误数量。
SW_CONTEXT_SWITCHES
SW_CONTEXT_SWITCHES
功能:操作系统上下文切换的数量。
SW_CPU_MIGRATIONS
SW_CPU_MIGRATIONS
功能:CPU 之间的任务迁移量。
SW_PAGE_FAULTS_MIN
SW_PAGE_FAULTS_MIN
功能:次要页错误数量。
SW_PAGE_FAULTS_MAJ
SW_PAGE_FAULTS_MAJ
功能:主要页错误数量。
SW_EMULATION_FAULTS
SW_EMULATION_FAULTS
功能:需要内核模拟的不受支持的指令数量。
func toString()
public func toString(): String
功能: 将计数器转换为字符串。
返回值:
- String - 处理器计数器的字符串表示。
结构体
struct BatchInputProvider<T>
public struct BatchInputProvider<T> <: BenchInputProvider<T> {
public BatchInputProvider(let builder: () -> T)
}
功能:输入提供程序,在执行之前在缓冲区中生成整个基准批次的输入。
父类型:
BatchInputProvider(() -> T)
public BatchInputProvider(let builder: () -> T)
功能:BatchInputProvider构造函数。
参数:
- builder: () -> T - 用于生成基准测试输入的闭包。
mut func get(Int64)
public mut func get(idx: Int64): T
功能:获取元素,该函数的执行时间包含在基准测量中,然后作为框架开销计算的一部分从结果中排除。
参数:
- idx : Int64 - 元素索引值。
返回值:
- T - 元素值。
mut func reset(Int64)
public mut func reset(max: Int64)
功能:在基准测量之前调用。调用此函数后,后续的 get(i) 调用必须成功获取 [0, max) 中的 i 。
参数:
- max : Int64 - 最大值。
struct BatchSizeOneInputProvider<T>
public struct BatchSizeOneInputProvider<T> <: BenchInputProvider<T>{
public BatchSizeOneInputProvider(let builder: () -> T)
}
功能:基准输入提供程序,在每次执行基准之前生成输入。
与 GenerateEachInputProvider 的区别在于,当批量大小为 1 时,我们可以测量。
每个基准测试调用都是独立的,因此输入生成永远不会包含在测量中。
如果 GenerateEachInputProvider 给出的结果质量较差,则应使用。 这种情况可能会发生,因为生成输入所需的时间比实际基准要多得多,或者如果输入生成的执行时间非常不稳定。
父类型:
BatchSizeOneInputProvider(() -> T)
public BatchSizeOneInputProvider(let builder: () -> T)
功能:BatchSizeOneInputProvider构造函数。
参数:
- builder: () -> T - 用于生成基准测试输入的 lambda 。
mut func get(Int64)
public mut func get(idx: Int64): T
功能:获取元素,该函数的执行时间包含在基准测量中,然后作为框架开销计算的一部分从结果中排除。
参数:
- idx : Int64 - 元素索引值。
返回值:
- T - 元素值。
mut func reset(Int64)
public mut func reset(max: Int64)
功能:在基准测量之前调用。调用此函数后,后续的 get(i) 调用必须成功获取 [0, max) 中的 i 。
参数:
- max: Int64 - 最大值。
struct CpuCycles
public struct CpuCycles <: Measurement {}
功能:使用本机 rdtscp 指令测量 CPU 周期数。仅适用于 x86 平台。
父类型:
prop conversionTable
prop conversionTable: MeasurementUnitTable
功能:提供当前时间的单位换算表。
例如 [(1.0, "cycles")]。
prop name
prop name: String
功能:提供当前时间单位唯一的显示名称,例如:CpuCycles。
类型:String。
func measure()
public func measure(): Float64
功能:返回执行了多少个 CPU 周期。
返回值:
- Float64 - 计算得到的数据,用于统计分析。
func setup()
public func setup()
功能:在测量前执行的配置动作。
struct GenerateEachInputProvider<T>
public struct GenerateEachInputProvider<T> <: BenchInputProvider<T>{
public GenerateEachInputProvider(let builder: () -> T)
}
功能:基准输入提供程序,在每次执行基准之前生成输入。 生成时间包含在基准测量中,然后作为框架开销计算的一部分从最终结果中排除。
父类型:
GenerateEachInputProvider(() -> T)
public GenerateEachInputProvider(let builder: () -> T)
功能:GenerateEachInputProvider构造函数。
参数:
- builder: () -> T - 用于生成基准测试输入的闭包。
mut func get(Int64)
public mut func get(idx: Int64): T
功能:获取元素,该函数的执行时间包含在基准测量中,然后作为框架开销计算的一部分从结果中排除。
参数:
- idx : Int64 - 元素索引值。
返回值:
- T - 元素值。
mut func reset(Int64)
public mut func reset(max: Int64)
功能:在基准测量之前调用。调用此函数后,后续的 get(i) 调用必须成功获取 [0, max) 中的 i 。
参数:
- max : Int64 - 最大值。
struct ImmutableInputProvider<T>
public struct ImmutableInputProvider<T> <: BenchInputProvider<T> {
public ImmutableInputProvider(let data: T)
}
功能:最简单的输入提供程序,只需为基准测试的每次调用复制数据。适用于基准测试不会改变输入的情况。它在框架内默认使用。
父类型:
ImmutableInputProvider(T)
public ImmutableInputProvider(let data: T)
功能:ImmutableInputProvider构造函数。
参数:
- data: T - 基准测试的输入。
mut func get(Int64)
public mut func get(idx: Int64): T
功能:获取元素,该函数的执行时间包含在基准测量中,然后作为框架开销计算的一部分从结果中排除。
参数:
- idx : Int64 - 元素索引值。
返回值:
- T - 元素值。
static func createOrExisting(T, Int64)
public static func createOrExisting(arg: T, x!:Int64=0): ImmutableInputProvider<T>
功能:创建或获取一个 ImmutableInputProvider 对象。
参数:
- arg : T - 提供器需复制的参数。
- x!: Int64 - 为实现重载而增加的参数。
返回值:
- ImmutableInputProvider<T> - 输入提供器。
static func createOrExisting<U>(U): U where U <: BenchInputProvider<T>
public static func createOrExisting<U>(arg: U): U where U <: BenchInputProvider<T>
功能:创建或获取一个 BenchInputProvider 的子类型对象。
参数:
- arg : T - 提供器需复制的参数。
返回值:
- U where U <: BenchInputProvider<T> - 输入提供器。
struct Perf
public struct Perf <: Measurement {
public init()
public init(counter: PerfCounter)
}
功能:使用linux 系统调用 perf_event_open 测量各种硬件和软件 CPU 计数器。仅在 Linux 上可用。
父类型:
prop conversionTable
prop conversionTable: MeasurementUnitTable
功能:提供对应 CPU 计数器的换算表。
prop name
prop name: String
功能:为当前 CPU 计数器提供唯一的显示名称,例如:Perf(cycles)。
类型:String。
init()
public init()
功能:使用 CPU 周期计数器的默认构造函数。
init(PerfCounter)
public init(counter: PerfCounter)
功能:指定要测量的 CPU 计数器的构造函数。
参数:
- counter: PerfCounter
func measure()
public func measure(): Float64
功能:返回指定 CPU 计数器的值。
返回值:
- Float64 - 计算得到的数据,用于统计分析。
func setup()
func setup()
功能:此 CPU 计数器的初始化例程。在每个基准步骤之前调用。
struct TimeNow
public struct TimeNow <: Measurement {
public init()
public init(unit: ?TimeUnit)
}
功能:Measurement 的实现,用于测量执行一个函数所花费的时间。
父类型:
prop conversionTable
prop conversionTable: MeasurementUnitTable
功能:提供当前时间的单位换算表。
例如 [(1.0, "ns"), (1e3, "us"), (1e6, "ms"), (1e9, "s")]。
prop name
prop name: String
功能:提供当前时间单位唯一的显示名称,例如:Duration(ns) 或 Duration(s)。
类型:String。
prop textDescription
prop textDescription: String
功能:描述此测量的简单文本将显示在某些报告中。
类型:String。
init()
public init()
功能:自动选择输出格式的默认构造函数。
init(?TimeUnit)
public init(unit: ?TimeUnit)
功能:unit 参数用于指定打印结果时将使用的时间单位。
参数:
- unit: ?TimeUnit - 指定的时间单位。
func measure()
public func measure(): Float64
功能:获取当前时间用于统计分析。
返回值:
- Float64 - 计算得到的数据,用于统计分析。
异常类
class AssertException
public class AssertException <: Exception {
public init()
public init(message: String)
}
功能:@Expect / @Assert 检查失败时所抛出的异常。
父类型:
init()
public init(message: String)
功能:构造函数。
init(String)
public init(message: String)
功能:构造函数。
参数:
- message: String - 指定的异常信息。
class AssertIntermediateException
public class AssertIntermediateException <: Exception {
public let expression: String
public let originalException: Exception
}
功能:@PowerAssert 检查失败时所抛出的异常。
父类型:
let expression
public let expression: String
功能:检查的表达式。
类型:String。
let originalException
public let originalException: Exception
功能:原始的类型信息。
类型:Exception。
func getOriginalStackTrace
public func getOriginalStackTrace(): String
功能:获取原始的栈信息。
返回值:
- String - 栈信息。
class UnittestCliOptionsFormatException
public class UnittestCliOptionsFormatException <: UnittestException
功能:控制台选项格式错误抛出的异常。
父类型:
class UnittestException
public open class UnittestException <: Exception
功能:框架通用异常。
父类型:
Unittest 快速入门
先编写一个简单的仓颉函数:
package example
func add(left: Int64, right: Int64) {
return left + right
}
将这个函数保存在 add.cj 文件中,开始编写该函数的测试代码:
package example
@Test
func addTest() {
@Expect(add(2, 3), 5)
}
测试包含如下组件:
@Test宏,配置在addTest函数上,表示这是一个测试函数。@Expect宏,作为断言,检查输入的两个参数是否相等。在这个例子中,两个参数分别是add函数的结果add(2, 3)和预期值5。
将这个测试函数保存在 add_test.cj 文件中,和代码函数一起在 add.cj 中运行。
cjc add.cj add_test.cj --test -o add_test
./add_test
在测试执行过程中,将动态显示进度报告:
group example 0% [-------------------------] (00:00:01)
test TestCase_addTest.addTest (00:00:01)
passed: 0, failed: 0 0% [-------------------------] 0/1 (00:00:01)
正常情况下,将得到如下类似输出:
-------------------------------------------------------------------------------------------------
TP: default, time elapsed: 59363 ns, Result:
TCS: TestCase_addTest, time elapsed: 32231 ns, RESULT:
[ PASSED ] CASE: addTest (28473 ns)
Summary: TOTAL: 1
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
至此,我们就完成了测试的构建和运行。
下面我们来详细介绍一下用来构建测试的 cjc 命令。
# 待测试的代码文件
# ↓
cjc add.cj add_test.cj --test -o add_test
# ↑ ↑
# | --test 表明在测试模式下构建生成二进制文件
# 测试文件
注意,对于复杂项目来说,不建议直接运行 cjc 编译器。
对于结构庞大的大型项目,建议使用 cjpm 包管理器。
以 cjpm 项目测试为例。
首先创建一个简单的 cjpm 项目,其中包含一个名为 example 的包。
项目的文件结构如下所示(借用 cjc 示例中的文件):
- src
|
+- example
|
+- add.cj
+- add_test.cj
原文件已指明它们属于 example 包,因此只需运行以下命令即可初始化 cjpm 项目:
cjpm init example example
cjpm 包管理器内置支持运行单元测试,所以直接运行即可:
cjpm test
此命令会运行项目所有包中的测试,统一生成如下类似输出:
--------------------------------------------------------------------------------------------------
TP: example/example, time elapsed: 60989 ns, Result:
TCS: TestCase_addTest, time elapsed: 32804 ns, RESULT:
[ PASSED ] CASE: addTest (29195 ns)
Summary: TOTAL: 1
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
注意,无需指定 --test 或任何其他特殊选项。
默认情况下,cjpm 使用项目中的文件名来确认文件应该在测试模式还是正常模式下编译。
示例包中, add_test.cj 是测试文件,文件名以 _test.cj 结尾。
正常构建时,二进制文件或库的构建不包含这些文件。
单元测试框架 API 已经存在于 std 模块的 unittest 包中,宏也存在于 std 模块的 unittest.testmacro 包中,因此不需要在测试文件中显式导入。
如需了解更多关于 unittest 框架的基本概念,请参考单元测试基础。
Unittest 基础概念及用法
测试及测试用例
测试是用 @Test 宏标记的实体,会在测试过程中执行。
仓颉 unittest 框架中有两种测试:测试类和测试函数。
测试函数相对简单,每个函数包含全部测试运行的代码。
测试类适用于为测试引入更深层次的结构,或者覆盖测试生命周期行为的场景。
每个测试类由若干个测试用例组成,每个测试用例用 @TestCase 宏标记。
每个测试用例都是测试类内部的一个函数。
上一节中的示例,相同的测试可以改写为如下所示的测试类:
func add(a:Int64, b:Int64) {
a + b
}
@Test
class AddTests {
@TestCase
func addTest() {
@Expect(add(2, 3), 5)
}
@TestCase
func addZero() {
@Expect(add(2, 0), 2)
}
}
测试函数即函数中包含单个测试用例的测试。这种情况下不需要使用 @TestCase 宏。
cjpm test 中运行这个新的测试类会生成如下类似输出:
--------------------------------------------------------------------------------------------------
TP: example/example, time elapsed: 67369 ns, Result:
TCS: AddTests, time elapsed: 31828 ns, RESULT:
[ PASSED ] CASE: addTest (25650 ns)
[ PASSED ] CASE: addZero (4312 ns)
Summary: TOTAL: 2
PASSED: 2, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
cjpm test success
断言
断言是在测试用例函数体内执行的单个条件检查,用以判断代码是否正常运行。
断言有两种:@Expect 和 @Assert 。
创建一个错误的测试来说明两者的区别:
func add(a:Int64, b:Int64) {
a + b
}
@Test
func testAddIncorrect() {
@Expect(add(3, 3), 5)
}
运行测试失败,并生成以下结果(仅展示与此测试相关的部分):
TCS: TestCase_testAddIncorrect, time elapsed: 4236 ns, RESULT:
[ FAILED ] CASE: testAddIncorrect (3491 ns)
Expect Failed: `(add ( 3 , 3 ) == 5)`
left: 6
right: 5
在这个例子中,用 @Assert 替换 @Expect 不会有什么变化。添加一个检查项后,再次运行:
func add(a:Int64, b:Int64) {
a + b
}
@Test
func testAddIncorrect() {
@Expect(add(3, 3), 5)
@Expect(add(5, 3), 9)
}
运行测试失败,并生成以下结果(仅展示与此测试相关的部分):
TCS: TestCase_testAddIncorrect, time elapsed: 5058 ns, RESULT:
[ FAILED ] CASE: testAddIncorrect (4212 ns)
Expect Failed: `(add ( 3 , 3 ) == 5)`
left: 6
right: 5
Expect Failed: `(add ( 5 , 3 ) == 9)`
left: 8
right: 9
可以在输出中看到这两个检查的结果。
但是,如果用 @Assert 替换 @Expect :
func add(a:Int64, b:Int64) {
a + b
}
@Test
func testAddIncorrectAssert() {
@Assert(add(3, 3), 5)
@Assert(add(5, 3), 9)
}
可以得到以下输出:
TCS: TestCase_testAddIncorrectAssert, time elapsed: 31653 ns, RESULT:
[ FAILED ] CASE: testAddIncorrectAssert (30893 ns)
Assert Failed: `(add ( 3 , 3 ) == 5)`
left: 6
right: 5
可以看到,只有第一个 @Assert 检查失败了,其余的测试甚至都没有运行。
这是因为 @Assert 宏采用的是快速失败(fail-fast)机制:一旦首次断言失败,整个测试用例都失败,后续的断言不再检查。
在涉及大量断言的大型测试中,这一点非常重要,尤其是在循环中使用断言时。 并不需要等到全部失败,首次失败后用户即可感知。
在测试中选择 @Assert 还是 @Expect 取决于测试场景的复杂程度,以及是否需要采用快速失败机制。
使用 unittest 提供的两种断言宏时,可采用如下方式:
- 相等断言,其中
@Assert(a, b)或@Expect(a, b)的两个参数a和b,检查它们的参数值是否相等;假设a的类型为A,b的类型为B,A必须实现了 Equatable<B> 。 - 布尔断言
@Assert(c)或@Expect(c),其参数c为Bool类型,参数值true或false。
断言的第二种形式 @Assert(c) 可以视为 @Assert(c, true) 的简写形式。
失败断言
失败断言可以让测试用例运行失败。@Fail 采用快速失败机制,运行至此断言则整个测试用例失败,后续断言都不再检查。@FailExpect 运行至此断言会使得用例失败,但后续断言依然会被检查。
前述宏的参数为描述失败原因的字符串,@Fail 的返回值类型为 Nothing , @FailExpect 的类型为 Unit 。
举例来说:
@Test
func validate_even_number_generator() {
let even = generateRandomEven()
if (even % 2 == 1) {
@Fail("Not even number was generated: ${even}")
}
}
会输出如下错误信息:
[ FAILED ] CASE: validate_even_number_generator (54313 ns)
Assert Failed: `(Not even number was generated: 111)`
预期异常的断言
运行至此断言当预期抛出的异常类型未被抛出时,用例将失败,@AssertThrows 将不再进行后续检查,而 @ExpectThrows 将继续检查。
前述宏的属性入参为预期抛出的异常类型列表,通过 | 隔离不同异常类型,当没有属性入参时预期抛出异常基类 Exception 。入参为预期抛出异常的表达式或代码块。
举例来说:
// No.1
@AssertThrows(throw Exception())
// 语义上与 No.1 相同
@AssertThrows[Exception](throw Exception())
@AssertThrows[IllegalStateException | NoneValueException](random.seed = 42u64)
@ExpectThrows[OutOfMemoryError](foo())
@ExpectThrows({
foo()
boo()
})
@ExpectThrows[OutOfMemoryError]({
for (i in list) {
foo(i)
}
})
@AssertThrows 的返回类型
如果指定的异常不超过一个,则返回类型与预期抛出的异常类型相同:
let e: NoneValueException = @AssertThrows[NoneValueException](foo())
如果指定的异常超过一个,则返回类型为预期抛出的异常类型的最小公共超类型:
// A <: C
// B <: C
let e: C = @AssertThrows[A | B](foo())
@ExpectThrows 的返回类型
@ExpectThrows 检查失败后也会继续执行,在指定的异常不超过一个时,它返回的类型是 Option<T>,其中 T 是预期的异常类型:
let e: ?NoneValueException = @ExpectThrows[NoneValueException](foo())
在指定的异常超过一个时,返回的类型是 ?Exception :
let e: ?Exception = @ExpectThrows[NoneValueException | IllegalMemoryException](foo())
测试生命周期
测试用例之间有时可以共享创建或清理代码。测试框架支持4个生命周期步骤,分别通过相应的宏来设置。只能为 @Test 测试类指定生命周期步骤,不能为 @Test 顶层函数指定生命周期步骤。
| 宏 | 生命周期 |
|---|---|
| @BeforeAll | 在所有测试用例之前运行 |
| @BeforeEach | 在每个测试用例之前运行一次 |
| @AfterEach | 在每个测试用例之后运行一次 |
| @AfterAll | 在所有测试用例完成后运行 |
这些宏必须配置在 @Test 测试类的成员或静态函数上。@BeforeAll 和 @AfterAll 函数不能声明任何参数。 @BeforeEach 和 @AfterEach 函数可以声明一个 String 类型的参数(或者不声明参数)。
@Test
class FooTest {
@BeforeAll
func setup() {
// 在测试执行前运行这段代码。
}
}
每个宏可以应用于单个测试类内的多个函数。可以在单个函数上配置多个生命周期宏。生命周期宏不能配置在标有 @TestCase 或类似宏的函数上。
如果多个函数被标记为相同的生命周期步骤,则可以按照它们在代码中声明的顺序(从上到下)执行。
测试框架确保:
- 标记为 Before all 的步骤在所有测试用例运行之前,至少运行一次。
- 对于测试类中的每个测试用例
TC: 1) 标记为 Before each 的步骤在TC之前运行一次。 2) 运行TC。 3) 标记为 After each 的步骤在TC之后运行一次。 - 在测试类中的所有测试用例之后运行标记为 After all 的步骤。
注意:
如果没有运行测试用例,上述并不适用。
简单场景中,标识为 before all 和 after all 的步骤只运行一次。但也有例外:
- 对于类型参数化测试,标识为 before/after all 的步骤运行的数量为每个类型参数的组合数。
- 如果多个测试用例在不同的进程中并行执行,则每个进程中标识为 before/after all 的步骤都将运行一次。
@BeforeEach 和 @AfterEach 可以访问正在创建或删除的测试用例,只需要在相应的函数中指定一个 String 类型的参数即可。
@Test
class Foo {
@BeforeEach
func prepareData(testCaseName: String) {
// 测试用例函数的名称作为参数
// 本例中的"bar"
}
@AfterEach
func cleanup() {
// 不指定参数也可以
}
@TestCase
func bar() {}
}
为参数化测试或参数化性能测试配置生命周期时,注意标识为 before each 或 after each 的步骤仅在执行测试用例或基准之前或之后为其所有参数执行一次。也就是说,从生命周期的角度看,使用不同参数执行多次的测试主体会被视为单个测试用例。
如果参数化测试的每个参数都需要单独创建清理,需要将相应的代码配置在测试用例主体本身中。此外,还可以访问参数本身。
测试配置
单元测试框架中其他更高级的功能可能需要额外配置。 参考如下三种方式配置测试:
- 使用
@Configure宏 - 直接在运行测试时或在
cjpm test测试中使用命令行参数 - 使用
cjpm配置文件
运行配置
使用方法
运行 cjc 编译的可执行文件 test ,添加参数选项
./test --bench --filter=MyTest.*Test,-stringTest
--bench
默认情况下,只有被 @TestCase 修饰的函数会被执行。在使用 --bench 的情况下只执行 @Bench 宏修饰的用例。
--filter
如果您希望以测试类和测试用例过滤出测试的子集,可以使用 --filter=测试类名.测试用例名 的形式来筛选匹配的用例,例如:
--filter=*匹配所有测试类--filter=*.*匹配所有测试类所有测试用例(结果和*相同)--filter=*.*Test,*.*case*匹配所有测试类中以 Test 结尾的用例,或者所有测试类中名字中带有 case 的测试用例--filter=MyTest*.*Test,*.*case*,-*.*myTest匹配所有 MyTest 开头测试类中以 Test 结尾的用例,或者名字中带有 case的用例,或者名字中不带有 myTest 的测试用例
--dry-run
执行单元测试框架而不实际运行测试。可用于查看测试用例列表。
--include-tags
若需按 @Tag 宏中指定的类别选择测试的子集,则可使用 --include-tags 或 --exclude-tags 运行选项。例如:
--include-tags=Unittest运行所有的带有@Tag[Unittest]的测试用例。--include-tags=Unittest,Smoke运行所有的带有@Tag[Unittest]和/或@Tag[Smoke]的测试用例。--include-tags=Unittest+Smoke运行所有的带有@Tag[Unittest]和@Tag[Smoke]的测试用例。--include-tags=Unittest+Smoke+JiraTask3271,Backend运行所有的带有@Tag[Backend]和/或@Tag[Unittest, Smoke, JiraTask3271]的测试用例。
** 注意 ** 如果没有符合指定标签类别的测试用例。框架将不运行任何内容。 可以与
exclude-tags结合。详见--exclude-tags。
--exclude-tags
若需按 @Tag 宏中指定的类别选择测试的子集,则可使用 --include-tags 或 --exclude-tags 运行选项。例如:
--exclude-tags=Unittest运行所有的未带有@Tag[Unittest]的测试用例。--exclude-tags=Unittest,Smoke运行所有的未带有@Tag[Unittest]和/或@Tag[Smoke]的测试用例。--exclude-tags=Unittest+Smoke运行所有的未同时带有@Tag[Unittest]、@Tag[Smoke]的测试用例。--include-tags=Unittest --exclude-tags=Smoke运行所有带有@Tag[Unittest]但不带有@Tag[Smoke]的测试用例。
** 注意 **
exclude-tags的优先级高于include-tags,如果用例被排除,则必定不会被执行,例如--include-tags=Unittest+Smoke --exclude-tags=Smoke则带有@Tag[Smoke]的用例不会被执行。
--timeout-each=timeout
使用 --timeout-each=timeout 选项等同于对所有的测试类使用 @Timeout[timeout] 修饰。若代码中已有 @Timeout[timeout] ,则将被代码中的超时时间覆盖,即选项的超时时间配置优先级低于代码中超时时间配置。
timeout 的值应符合以下语法:
number ('millis' | 's' | 'm' | 'h')
例如: 10s, 9millis 等。
- millis : 毫秒
- s : 秒
- m : 分钟
- h : 小时
--parallel
打开 --parallel 选项将使测试框架在单独的多个进程中并行执行不同的测试类。
测试类之间应该是相互独立的,不依赖于共享的可变的状态值。
程序静态初始化可能会发生多次。
不允许与 --bench 同时使用。由于性能用例对底层资源敏感,用例是否并行执行,将影响性能用例的结果,因此禁止与 --bench 同时使用。
--parallel=<BOOL><BOOL>可为true或false,指定为true时,测试类可被并行运行,并行进程个数将受运行系统上的CPU核数控制。另外,--parallel可省略=true。--parallel=nCores指定了并行的测试进程个数应该等于可用的 CPU 核数。--parallel=NUMBER指定了并行的测试进程个数值。该数值应该为正整数。--parallel=NUMBERnCores指定了并行的测试进程个数值为可用的 CPU 核数的指定数值倍。该数值应该为正数(支持浮点数或整数)。
--option=value
以 --option=value 形式提供的任何非上述的选项均按以下规则处理并转换为配置参数(类似于 @Configure 宏处理的参数),并按顺序应用:
option 与 value 为任意自定义的运行配置选项键值对,option 可以为任意通过 - 连接的英文字符,转换到 @Configure 时将转换为小驼峰格式。value 的格式规则如下:
注:当前未检查 option 与 value 的合法性,并且选项的优先级低于代码中 @Configure 的优先级。
- 如果省略
=value部分,则该选项被视为Bool值true, 例如:--no-color生成配置条目noColor = true。 - 如果
value严格为true或false,则该选项被视为具有相应含义的Bool值:--no-color=false生成配置条目noColor = false。 - 如果
value是有效的十进制整数,则该选项被视为Int64值 , 例如:--random-seed=42生成配置条目randomSeed = 42。 - 如果
value是有效的十进制小数,则该选项被视为Float64值 , 例如:--angle=42.0生成配置条目angle = 42。 - 如果
value是带引号的字符串文字(被"符号包围),则该选项将被视为String类型,并且该值是通过解码"符号之间的字符串值来生成的,并处理转义符号,例如\n、\t、\"作为对应的字符值。例如,选项--mode="ABC \"2\""生成配置条目mode = "ABC \"2\""; - 除上述情况外
value值将被视为String类型,该值从所提供的选项中逐字获取。例如,--mode=ABC23[1,2,3]生成配置条目mode = "ABC23[1,2,3]"。
--report-path=path
该选项用于指定执行后生成测试报告的目录路径。默认情况下,如果不明确指定选项,将不会生成报告。
--report-format=value
该选项用于指定测试执行后生成的报告的格式。
目前,单元测试仅支持默认的 xml 格式。
基准测试支持:
csv: csv 报告中有统计数据。csv-raw: csv-raw 报告中只有批次的原始测量值。html: html 报告包含显示的所有结果和各种统计属性。可以在任何浏览器中查看。对于每个基准测试函数,html 报告包含:- 每个基准参数的摘要。
- 执行环境相关信息的汇总,例如硬件信息、操作系统信息、编译信息、环境变量。
- 每个基准参数的选项卡包含详细的统计信息。
- 核密度估计图。这是对基准函数的单次执行实际花费的时间的概率估计。
- 原始测量值及其线性回归图。
- 具有统计属性(例如平均值、中位数、R 平方、框架开销、标准差)及其置信区间的表。
基准测试的默认使用的格式为:
csv
--baseline-path=path
此选项指定用于比较的性能报告所在的路径。默认情况下,使用 '--report-path' 的值。
--capture-output
此选项使能测试用例的打印输出捕获。
默认情况下,在 cjpm test 执行时使能捕获,否则禁用捕获。
当测试用例打印输出捕获未使能时,打印输出将立即传播到单元测试输出。否则,单元测试将收集和处理测试用例的打印输出。
需要捕获打印输出的场景如下:
- 使用
--parallel执行时防止测试输出交错。 - 隐藏已通过测试的输出以使单元测试报告更加清晰。
- 将每个测试用例的输出分开,以查看哪个测试用例打印了什么。
--no-capture-output
此选项禁用测试用例打印输出捕获。
默认情况下,在 cjpm test 执行中启用捕获,否则禁用捕获。
使测试用例打印输出立即传播到单元测试输出。
--show-all-output
单元测试框架将打印报告中的所有输出,包括通过的测试用例的输出。 如果禁用测试输出捕获,则此选项失效。
--coverage-guided
单元测试框架将使能覆盖率引导的随机参数化测试。
--progress-brief
启用单元测试的简短(单行)动态进度报告。
--progress-entries-limit=limit
限制进度输出中显示的最大条目数。 limit 的合法值:非负整数值。
值 0 表示没有限制。默认值:无限制。
--no-progress
禁用动态进度报告。
如果指定选项 --dry-run,则隐含选项 --no-progress。
参数化测试
参数化测试入门
仓颉 unittest 框架支持参数化测试,格式为数据 DSL ,测试中框架自动插入输入参数。
如下为复杂代码示例,用函数对数组排序:
package example
func sort(array: Array<Int64>): Unit {
for (i in 0..array.size) {
var minIndex = i
for (j in i..array.size) {
if (array[j] < array[minIndex]) {
minIndex = j
}
}
(array[i], array[minIndex]) = (array[minIndex], array[i])
}
}
这个函数不是最优最高效的排序实现,但仍可以达成目的。 来测试一下。
package example
@Test
func testSort() {
let arr = [45, 5, -1, 0, 1, 2]
sort(arr)
@Expect(arr, [-1, 0, 1, 2, 5, 45])
}
测试结果显示,函数在单个输入的情况下可用。 接下来测试,如果数组只包含等值元素,排序函数还是否可用。
@Test
func testAllEqual() {
let arr = [0, 0, 0, 0]
let expected = [0, 0, 0, 0]
sort(arr)
@Expect(expected, arr)
}
测试结果显示函数可用,但还是不能确认是否适用于所有大小的数组。 接下来测试参数化数组的大小。
@Test[size in [0, 1, 50, 100, 1000]]
func testAllEqual(size: Int64) {
let arr = Array(size, repeat: 0)
let expected = Array(size, repeat: 0)
sort(arr)
@Expect(expected, arr)
}
至此,参数化测试已完成。 这种是最简单的参数化测试,即值驱动测试,直接在代码中列出测试运行的值。 参数化测试的参数可以不止一个。 不仅可以指定排序函数的大小,还可以指定待测试的元素。
@Test[
size in [0, 1, 50, 100, 1000],
item in (-1..20)
]
func testAllEqual(size: Int64, item: Int64) {
let arr = Array(size, repeat: item)
let expected = Array(size, repeat: item)
sort(arr)
@Expect(expected, arr)
}
注意,item 的取值范围为 -1..20 ,不是一个数组。
那么,运行这个测试,结果会如何?
参数 size 和 item 的取值会进行组合再测试和返回结果。
因此,测试函数时,不要配置过多参数;否则组合数量过大,导致测试变慢。
上述例子中,size 参数值有5个,item 参数值有21个,共有21×5=105种组合。
注意,值驱动测试不限于整型或内置类型。 也可以和任何仓颉类型一起使用。 参考如下测试:
@Test[
array in [
[],
[1, 2, 3],
[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1],
[-1, 0],
[-20]
]
]
func testDifferentArrays(array: Array<Int64>) {
// 测试数组是否已排序
for (i in 0..(array.size - 1)) {
@Expect(array[i] <= array[i + 1])
}
}
这里,直接以参数的形式提供测试的数据。
当然,用数组来测试代码可能过于笨重。
有时,对于这样的泛型函数,随机生成数据可能会更容易些。
接下来看一种更高级的参数化测试:随机测试。
通过调用函数 unittest.random<T>() 替换值驱动测试的数组或范围来创建随机测试:
@Test[
array in random()
]
func testRandomArrays(array: Array<Int64>) {
// 测试数组是否已排序
for (i in 0..(array.size - 1)) {
@Expect(array[i] <= array[i + 1])
}
}
这个测试本质上是生成大量完全随机的数值(默认为200个),用这些值来测试代码。 数值并不完全随机,偏向于边界值,如特定类型的零、最大值和最小值、空集合等。
特别注明:通常建议随机化测试与手工编写的测试混用,实践表明可以互为补充。
为了更好地描述随机测试,先把排序函数放一边,编写下面这样一个测试:
@Test[
array in random()
]
func testNonsense(array: Array<Int64>) {
if (array.size < 2) { return }
@Expect(array[0] <= array[1] + 500)
}
运行后,会生成如下类似输出:
[ FAILED ] CASE: testNonsense (1159229 ns)
REASON: After 4 generation steps and 200 reduction steps:
array = [0, -453923686263, 0]
with randomSeed = 1702373121372171563
Expect Failed: `(array [ 0 ] <= array [ 1 ] + 500 == true)`
left: false
right: true
结果可见,数组[0, -453923686263, 0]测试失败。
再运行一次:
[ FAILED ] CASE: testNonsense (1904718 ns)
REASON: After 5 generation steps and 200 reduction steps:
array = [0, -1196768422]
with randomSeed = 1702373320782980551
Expect Failed: `(array [ 0 ] <= array [ 1 ] + 500 == true)`
left: false
right: true
同样,测试失败,但值都不同。 为什么会这样呢? 因为随机测试本质上是随机的,所以每次都会生成新的随机值。 在各种不同的数据上测试函数,可能很好用;但是对于某些测试,这意味着多次运行中,有时成功,有时失败,不利于共享测试结果。 随机测试是一个强大的工具,但在使用时也需要了解这些弊端。
测试结果每次都不一样,如何向其他开发者展示结果呢? 答案很简单,就在运行测试时得到的输出中:
with randomSeed = 1702373320782980551
以上提供了一个随机种子,可以在测试中用作配置项。 改写测试如下:
@Test[
array in random()
]
@Configure[randomSeed: 1702373320782980551]
func testNonsense(array: Array<Int64>) {
if (array.size < 2) { return }
@Expect(array[0] <= array[1] + 500)
}
运行结果如下:
[ FAILED ] CASE: testNonsense (1910109 ns)
REASON: After 5 generation steps and 200 reduction steps:
array = [0, -1196768422]
with randomSeed = 1702373320782980551
Expect Failed: `(array [ 0 ] <= array [ 1 ] + 500 == true)`
left: false
right: true
注意,此次运行生成的值、生成值所用的步骤和随机种子与上次运行完全相同。
这种机制让随机测试可重复,可以保存在测试套件中与其他开发人员共享。
您也可以只从随机测试中获取数据(如本例中的数组值[0, -1196768422]),用这些值编写新测试。
快速看看失败的测试生成的输出。
REASON: After 5 generation steps and 200 reduction steps:
array = [0, -1196768422]
with randomSeed = 1702373320782980551
输出中包含几个重要信息:
- 测试失败前数据生成的步骤数:即测试失败前运行的迭代次数。
- 数据减量的步骤数:随机测试有缩减测试数据的机制,数据量减小后更方便操作,且提升了可读性。
- 导致测试失败的实际数据:按顺序列出所有参数(在本例中,只有一个参数
array)以及它们实际导致测试失败的值。其中参数应实现 ToString 接口,否则将只打印占位符。 - 以及前面提到的随机种子,用于重现随机测试。
有些测试比较棘手,需要调整随机生成的步骤数。
可以通过如下两个配置项控制:generationSteps 和 reductionSteps 。
随机测试一个最大的优点是,只要设置了足够多的步骤,它可以运行很长时间,这样就可以检查数百万个值。
为了不使测试太耗时,默认 generationSteps 和 reductionSteps 的最大值都是200。
通过这两个配置参数,就可以设置框架的最大步骤数。
例如,对于上面的这个小测试,参数设置为一个大的数值可能没有多大意义。之前的运行已经表明,通常不到10步,测试就会失败。
类型参数化测试
虽然当前排序实现仅针对整型数组排序,但本质上也可以对其他任何类型排序。
可以改写 sort 函数变成泛型函数,允许它对任意类型进行排序。
注意,元素必须是可比较的,这样才能排序。
package example
func sort<T>(array: Array<T>): Unit where T <: Comparable<T> {
for (i in 0..array.size) {
var minIndex = i
for (j in i..array.size) {
if (array[j] < array[minIndex]) {
minIndex = j
}
}
(array[i], array[minIndex]) = (array[minIndex], array[i])
}
}
所有测试均继续正常运行,可知排序函数已广泛适用。 但是,是否真的适用于整型以外的类型呢?
用示例中的 testDifferentArrays 编写一个新的测试,对其他类型(如字符串)进行测试:
@Test[
array in [
[],
["1","2","3"],
["1","2","3","4","5"],
["5","4","3","2","1"]
]
]
func testDifferentArraysString(array: Array<String>) {
// 测试数组是否已排序
let sorted = array.clone()
sort(sorted)
for (i in 0..(sorted.size - 1)) {
@Expect(sorted[i] <= sorted[i + 1])
}
}
运行测试可知,测试正常。 注意,两个测试的主体和断言完全相同。 试想,如果泛型函数的测试也可以泛型,不是更方便吗?
回到之前的随机测试示例:
@Test[array in random()]
func testRandomArrays(array: Array<Int64>) {
let sorted = array.clone()
sort(sorted)
for (i in 0..(sorted.size - 1)) {
@Expect(sorted[i] <= sorted[i + 1])
}
}
测试是广泛适用的,可以看到元素类型不限于 Int64 ,也可以是任何类型 T ,例如:
- 可以比较:需要实现 Comparable<T> ;
- 可以随机生成实例:需要实现 Arbitrary<T> ;
将这个测试改写为一个泛型函数:
@Test[array in random()]
func testRandomArrays<T>(array: Array<T>) where T <: Comparable<T> & Arbitrary<T> {
let sorted = array.clone()
sort(sorted)
for (i in 0..(sorted.size - 1)) {
@Expect(sorted[i] <= sorted[i + 1])
}
}
编译运行后,遇到了一个问题:
An exception has occurred:
MacroException: Generic function testRandomArrays requires a @Types macro to set up generic arguments
当然,要运行测试某些类型,需要先有这些类型。
用 @Types 宏设置测试,这样就可以运行测试 Int64、 Float64 和 String 这些类型了。
@Test[array in random()]
@Types[T in <Int64, Float64, String>]
func testRandomArrays<T>(array: Array<T>) where T <: Comparable<T> & Arbitrary<T> {
let sorted = array.clone()
sort(sorted)
for (i in 0..(sorted.size - 1)) {
@Expect(sorted[i] <= sorted[i + 1])
}
}
现在,运行测试,将编译并生成以下输出:
TCS: TestCase_testRandomArrays, time elapsed: 2491737752 ns, RESULT:
[ PASSED ] CASE: testRandomArrays<Int64> (208846446 ns)
[ PASSED ] CASE: testRandomArrays<Float64> (172845910 ns)
[ PASSED ] CASE: testRandomArrays<String> (2110037787 ns)
注意,每个类型,测试都是单独运行的,因为行为可能大不相同。
@Types 宏可以用于任何参数化的测试用例,包括测试函数和测试类。
重用、组合和映射参数策略
现在以 HashSet 为例。从测试 contains 开始。
@Test[data in random()]
func testHashSetContains(data: Array<Int64>) {
let hashSet = HashSet(len)
hashSet.add(all: data)
for (element in data){
@Assert(hashSet.contains(element))
}
}
效果很好。现在尝试测试 remove 。
@Test[data in random()]
func testHashSetRemove(data: Array<Int64>) {
let hashSet = HashSet(len)
hashSet.add(all: data)
for (element in data){
@Assert(hashSet.remove(element))
}
}
表面上看应该可以正常工作。然而很快就可以注意到它无法正常工作,因为随机生成的数组可能包含重复项,这会导致第二次删除调用失败。所以这里想要的是生成一些没有重复的数组。
var counter = 0
@OverflowWrapping
func generateUniqArray(len: Int64, start: Int64){
let rng = Random(start)
let step = Int64.Max / len
counter = 0
Array(len, { _ =>
counter += rng.nextInt64()%step
counter
} )
}
@Test[len in random(), start in random()]
func testHashSetRemove(len: Int64, start: Int64) {
let data = generateUniqArray(len,start)
let hashSet = HashSet(len)
hashSet.add(all: data)
for (element in data){
@Assert(hashSet.remove(element))
}
}
然而,即使将数据生成转移到一个单独的函数中,如果想在多个不同的测试之间重用它,它仍然会有相当多的重复。此外,在准备代码和测试代码之间的界限非常不明确。因此,为了解决上述问题,测试框架以 @Strategy 宏的形式提供了方便的 API,允许组合和映射现有策略。
var counter = 0
@Strategy[len in random(), start in random()]
@OverflowWrapping
func generateUniqArray(len: Int64, start: Int64): Array<Int64>{
let rng = Random(start)
let step = Int64.Max / len
counter = 0
Array(len, { _ =>
counter += rng.nextInt64()%step
counter
} )
}
现在,只需要这样的输入,就可以使用该策略:
@Test[data in generateUniqArray]
func testHashSetRemove(data: Array<Int64>) {
let hashSet = HashSet()
hashSet.add(all: data)
for (element in data){
@Assert(hashSet.remove(element))
}
}
@Test[data in generateUniqArray]
func testHashSetToArray(data: Array<Int64>) {
let hashSet = HashSet()
hashSet.add(all: data)
let result = hashSet.toArray()
result.sort()
data.sort()
@Assert(result == data)
}
对于测试来说,使用此类自定义策略的用例很少。但由于它们在相应章节中描述的基准测试中的使用,它们仍然是框架的重要组成部分。
覆盖率引导的随机参数化测试
如上所述,随机测试对于有能力的人来说是一个强大的工具,但它们也有一些局限性。 例如:
@Test[x in random()]
func testX(x: Int64) {
@Expect(x != 1234567)
}
虽然这样的测试看起来很简单,但如果运行它,可能不会得到预期的结果:
--------------------------------------------------------------------------------------------------
TP: default, time elapsed: 1393856 ns, RESULT:
TCS: TestCase_testX, time elapsed: 1393856 ns, RESULT:
[ PASSED ] CASE: testX (1378439 ns)
Summary: TOTAL: 1
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
而且即使你将生成步骤的数量增加到几百万,这个测试也可能不会失败,因为随机测试是随机的,生成精确的非常规数字的概率极低。 虽然此测试看起来是自动生成的,并且不能真正代表生产代码,但它显示了随机代码在更现实的场景中可能面临的相同问题,从而大大减少了其在更高级用途中的应用,例如查找代码中的安全缺陷。
为解决这个问题,仓颉单元测试框架引入了一项基于 security-fuzzing 测试技术的高级特性:覆盖率引导的随机参数化单元测试。该特性针对的是那些希望对其代码进行更细致的测试,同时仍然享受随机测试的可用性和易用性的用户。
使用覆盖率引导的单元测试,需要执行以下步骤:
- 该项目必须在编译器支持
SanitizerCoverage的情况下进行编译。具体需要以下两个选项:--sanitizer-coverage-trace-pc-guard和--sanitizer-coverage-trace-compares。 - 用例可执行文件必须配置 --coverage-guided 选项。
- 测试的生成步骤参数必须根据代码的复杂性增加,以允许覆盖引导算法继续进行。
如果我们使用编译器选项 --sanitizer-coverage-trace-pc-guard 和 --sanitizer-coverage-trace-compares 编译上面的示例,然后使用 --coverage-guided 选项运行它,我们得到类似于以下内容的结果:
--------------------------------------------------------------------------------------------------
TP: default, time elapsed: 2004749 ns, RESULT:
TCS: TestCase_testX, time elapsed: 2004749 ns, RESULT:
[ FAILED ] CASE: testX (17380 ns)
REASON: After 48 generation steps and 3 reduction steps:
x = 1234567
with randomSeed = 1721033700363557083
Expect Failed: `(x != 1234567 == true)`
left: false
right: true
Summary: TOTAL: 1
PASSED: 0, SKIPPED: 0, ERROR: 0
FAILED: 1, listed below:
TCS: TestCase_testX, CASE: testX
--------------------------------------------------------------------------------------------------
正如我们所看到的,测试在极少数生成步骤中失败(本例中为 48 个,但是,由于总是随机测试,结果可能会有所不同),但一般来说,建议至少将测试的生成步骤配置为数十万步。因此用例的执行时间可能会很长。
动态测试
动态测试入门
仓颉测试框架支持动态测试,其支持在存在编译期未知的测试数据时构造测试用例。关键场景如下:
- 创建基于外部数据的测试套。
- 创建基于参数或配置文件的测试套。
通过与普通测试用例对比,可以看到如何通过 @TestBuilder 来构造动态测试用例。
如下是一个通过 @Test/@TestCase 构造的简单测试套:
@Test
class A {
@TestCase
func f() { @Assert(false) }
@TestCase[x in [1, 2]]
func g(x: Int) {
@Assert( x >= 1 )
}
}
通过 @TestBuilder 可以创建跟上述测试套相同逻辑的动态测试套 :
@TestBuilder
public func buildCustomTestSuite(): TestSuite {
let suiteBuilder = TestSuite.builder("A")
let caseConfiguration = Configuration()
suiteBuilder.add(
UnitTestCase.create("f", configuration: caseConfiguration) { @Assert(false) })
suiteBuilder.add(
UnitTestCase.createParameterized("g", [1, 2]) { value => @Assert( value >= 1 ) })
suiteBuilder.build()
}
TestSuite 创建了一个 TestSuiteBuilder 对象,该对象支持添加用例。用例通过 UnitTestCase 类中的静态函数构造。该类支持构造简单用例或者参数化用例。
TestSuiteBuilder 被配置完毕后,最终创建生成一个 TestSuite 对象,作为被 @TestBuilder 修饰的函数的返回值。
当上述代码通过 --test 编译后再执行,输出结果与 @Test/@TestCase 构造的测试套一致。
--------------------------------------------------------------------------------------------------
TP: default, time elapsed: 121592 ns, RESULT:
TCS: A, time elapsed: 121592 ns, RESULT:
[ PASSED ] CASE: g (13969 ns)
[ FAILED ] CASE: f (91641 ns)
Assert Failed: `(false == true)`
left: false
right: true
Summary: TOTAL: 2
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 1, listed below:
TCS: A, CASE: f
--------------------------------------------------------------------------------------------------
@TestBuilder 有如下约束:
- 它只能修饰顶层函数,且该函数不能是
foreign函数。 - 它的返回值类型必须被显式指定,且必须为
TestSuite类型。 - 它可以与
@Configure/@Timeout/@Parallel宏组合使用,不允许与 unittest.testmacro 包中其他的宏组合。
运行动态测试并获取输出
如果需要不从单元测试框架运行测试用例,而是从程序内部运行测试,则可以借助 TestSuite runTests() 函数来实现。
例如:
import std.unittest.*
main() {
let suiteBuilder = TestSuite.builder("A")
let caseConfiguration = Configuration()
suiteBuilder.add(
UnitTestCase.create("f", configuration: caseConfiguration) { @Assert(false) })
suiteBuilder.add(
UnitTestCase.createParameterized("g", [1, 2]) { value => @Assert( value >= 1 ) })
let suite = suiteBuilder.build()
let report = suite.runTests()
}
runTests 函数返回 Report 类的实例。您可以使用 Report 对象执行以下操作:
- 使用
ConsoleReporter类将其打印到控制台:report.reportTo(ConsoleReporter(colored: true))。 - 使用
TextReporter类打印到任何PrettyPrinter实现:report.reportTo(TextReporter(into: PrettyText()))。 - 将结果输出为支持的格式之一,例如 XML(
XmlReporter,仅用于单元测试,不用于性能测试)或 CSV(CsvReporter或CsvRawReporter,仅用于性能测试)。
测试模版
入门
测试模板功能有助于将一些常见的测试和基础设施代码提取到可重用的组件中。特别是,它对于测试类层次结构很有用。
要创建测试模板,请将 @TestTemplate 宏放在抽象类上:
@TestTemplate
abstract class DbTest {
public prop dbConnection: DbConnection
@TestCase
func testCommonDbApi1() { /* ... */}
@TestCase
func testCommonDbApi2() { /* ... */}
}
可用这个模板创建多个实际的测试套件,例如测试与不同特定数据库的连接。要使用测试模板,只需继承相应的类:
@Test
class MySqlTest <: DbTest {
var dbConnection_: ?DbConnection = None
override prop dbConnection: DbConnection {
get() {
dbConnection_.getOrThrow()
}
}
@BeforeAll
func initializeConnection() {
dbConnection_ = Some(...)
}
@AfterAll
func closeConnection() {
dbConnection_.close()
}
@TestCase
func testSpecificlyMySqlFeatures() {
/* ... */
}
}
每个测试用例都将像在实际测试类本身中编写一样运行,结果如下:
------------------------------------------------------------
TP: default, time elapsed: 177679 ns, RESULT:
TCS: MySqlTest, time elapsed: 157163 ns, RESULT:
[ PASSED ] CASE: testCommonDbApi1 (34704 ns)
[ PASSED ] CASE: testCommonDbApi2 (8480 ns)
[ PASSED ] CASE: testSpecificlyMySqlFeatures (8329 ns)
Summary: TOTAL: 3
PASSED: 3, SKIPPED: 0, ERROR: 0
FAILED: 0
------------------------------------------------------------
测试模板本身可以由其他测试模板构建。
生命周期方法
测试模板还可以包含一些生命周期方法: @BeforeAll, @AfterAll, @BeforeEach, @AfterEach。生命周期方法按指定顺序执行:
@Before_生命周期方法按照从基类到继承类的顺序运行。@After_生命周期方法按照从继承类到基类的顺序运行。
@_Each 派生类的方法也适用于基类的测试用例。
@TestTemplate
abstract class BaseTemplate {
@BeforeEach
func baseBeforeEach() { println("base before each") }
@AfterEach
func baseAfterEach() { println("base after each") }
}
@TestTemplate
abstract class Template <: BaseTemplate {
@TestCase
func templateCase() { println("template case") }
}
@Test
class Test <: Template {
@BeforeEach
func beforeEach() { println("before each") }
@AfterEach
func afterEach() { println("after each") }
@TestCase
func testCase() { println("case") }
}
输出将为(启用输出捕获时):
------------------------------------------------------------
TP: default, time elapsed: 456925 ns, RESULT:
TCS: Test, time elapsed: 456925 ns, RESULT:
[ PASSED ] CASE: templateCase (38228 ns)
STDOUT:
base before each
before each
template case
after each
base after each
[ PASSED ] CASE: testCase (16098 ns)
STDOUT:
base before each
before each
case
after each
base after each
Summary: TOTAL: 2
PASSED: 2, SKIPPED: 0, ERROR: 0
FAILED: 0
------------------------------------------------------------
配置
@Configure 可以放置在测试模板类上,但是继承类的 @Configure 会覆盖为基类放置的值。所有测试用例都在合并后的配置下执行。
与其他特性交互的规则
@Parallel不能与@TestTemplate同时使用。@Types不能与@TestTemplate同时使用。@Bench可在模版中使用, 在指定--bench时下执行,就像基准被放置在继承类本身中一样。
基准测试
基准测试入门
仓颉单元测试框架为灵活创建基准测试提供了强大的支持。
为保证结果的可靠性,大部分工作都在仓颉单元测试框架内部完成,包括:
- 管理预热
- 重复执行
- 减少垃圾回收(garbage collection,GC)导致的噪音和离群值
- 测试框架开销
- 提供统计分析结果
通过在相应示例中使用@Bench宏即可构建一个简单的基准测试。
@Test
class Foo {
var x = 0
@Bench
func case() {
x += 1
}
}
要运行基准测试,您可以通过向测试可执行文件传入 --bench 选项来实现,或者在 cjpm 项目中,使用 cjpm bench 命令。
参数化基准测试
基准测试 API 的语法与单元测试相似,并且尽可能地与现有单元测试特性集成。
@Bench 宏支持参数化用例和数据策略,与 @TestCase 宏相同。
除此之外,其他大多数宏(如 @BeforeEach、@AfterEach、@BeforeAll、@AfterAll、@Types、@Configure)在基准测试中均以相同的方式工作。
例如,可以为默认的哈希方法编写一个简单的基准测试。注意,数据创建在基准测试外,确保在基准测试开始之前只创建一次。
@Test
class Foo {
var hash = 0
let data = String(Array(1000, item: r'a'))
@Bench
func hashCode() {
hash = data.hashCode()
}
}
接下来,若要在不同数据上运行此基准测试,最直接的方法如下:
@Test
class Foo {
var hash = 0
let data_1 = String(Array(1000, repeat: r'a'))
let data_2 = String(Array(10000, repeat: r'a'))
@Bench[data in [data_1, data_2]]
func hashCode(data: String) {
hash = data.hashCode()
}
}
尽管该方法有效,但你会发现最终报告将输入参数命名为 data[0] 和 data[1],因为对于任意的输入参数,框架并不知道在我们的基准测试中哪个属性最重要。此外,该方法还存在不必要的代码冗余问题。甚至,这种方法还存在一个更大的潜在问题:如果数据类型不是简单的字符串,而是更为复杂的形式,如字符串数组,那么就会分配大量活跃对象,其中大部分对象仅用于执行特定基准测试。
@Test
class ArrayBenchmarks {
var hash = 0
let data_1 = Array(1000) { i => i.toString() }
let data_2 = Array(10000) { i => i.toString() }
@Bench[data in [data_1, data_2]]
func hashCode(data: Array<String>) {
var hasher = DefaultHasher()
for (e in data) {
hasher.write(e)
}
hash = hasher.finish()
}
@Bench
func createArray() {
Array(10,repeat: 0)
}
}
当对 createArray 进行基准测试时,每次触发GC都会涉及到遍历 data_1 和 data_2 元素,即便它们与除 hashCode 基准测试外的其他测试都无关。特别是在处理大量对象时,可能会导致基准测试不稳定,从而影响最终结果的准确性。
如前所述的问题及更复杂的问题,都可通过定义特定策略并应用 @Strategy 宏来解决。该宏能够接收与 @Bench 和 @TestCase 宏相同的数据领域特定语言(domain specific language,DSL),进而生成一种新策略,以扁平化方式映射输入。因此,本示例可进行如下演变:
@Test
class ArrayBenchmarks {
var hash = 0
@Strategy[len in [1000, 10000]]
func arrays(len: Int64): Array<String> {
Array(10000) { i => i.toString() }
}
@Bench[data in arrays]
func hashCodeArray(data: Array<String>) {
var hasher = DefaultHasher()
for (e in data) {
hasher.write(e)
}
hash = hasher.finish()
}
@Strategy[len in [1000, 10000]]
func strings(len: Int64): String {
String(Array(len, repeat: r'a'))
}
@Bench[data in strings]
func hashCodeString(data: String) {
hash = data.hashCode()
}
}
得到的输出如下:
TP: package, time elapsed: 18438985580 ns, RESULT:
TCS: ArrayBenchmarks, time elapsed: 18438962951 ns, RESULT:
| Case | Args | Median | Err | Err% | Mean |
|:---------------|:-------|---------:|------------:|-------:|---------:|
| hashCodeArray | 1000 | 10.68 us | ±0.0832 us | ±0.8% | 10.57 us |
| hashCodeArray | 10000 | 104.3 us | ±0.504 us | ±0.5% | 103.8 us |
| | | | | | |
| hashCodeString | 1000 | 165.7 ns | ±0.513 ns | ±0.3% | 165.6 ns |
| hashCodeString | 10000 | 1.576 us | ±0.00644 us | ±0.4% | 1.563 us |
Summary: TOTAL: 2
PASSED: 2, SKIPPED: 0, ERROR: 0
FAILED: 0
此时,框架将长度作为初始输入参数。在基准测试开始前,只为特定基准生成相关数据,因此不会影响后续基准测试。此处减少了代码冗余,甚至可以将 [1000, 10000] 数组移动到独立变量中来进一步减少冗余。此外,由于数据在框架内部处理,编译器无法直接获取精确的参数值进行优化。
现在,我们假设输入数据不能被基准测试改变,以确保每次函数调用接收的数据版本都是相同的。本框架同样支持那些允许修改输入数据的基准测试,详见每次调用前的设置小节。
如何取得理想结果
本框架主要用于减少各种因素对执行时间方差的影响,旨在获得可靠且可复现的结果。
结果表中的 Err% 列是衡量测试结果可靠性的主要指标。通常,如果 Err% 小于3%,则认为结果可靠,如果大于10%,则需深入探究原因并降低方差。这并不是普适的衡量标准,但可以用于初步判断。某些基准测试中,执行时间差异可能较大,导致方差变大,但均值仍趋于稳定。
然而,仍然有一些我们无法控制的外部因素,这些因素需要由用户自行管理。具体包括:
- 编译器优化选项。通常,除非你想测试特定优化的效果,否则应该启用大多数优化。建议至少启用仓颉编译器的
-O2选项。 - 后台 CPU 工作。如果操作系统在基准测试期间突然切换任务,可能会显著影响测试结果。因此,所有消耗 CPU 的后台任务应在启动基准测试前完成或暂停。也可以为这些务设置明确的 CPU 亲和性,以确保基准测试和其他 CPU 密集型任务运行在不同的 CPU 核上。
- 使用外部 I/O。用户可能会不小心测试到 I/O 操作的性能和延迟,而非后续处理的性能。建议单独对 I/O 部分或处理部分进行基准测试。
- 不必要的优化。如需测试某个函数在特定参数值下的性能,编译器可能会将这些参数值当作常量进行优化。使用参数化基准测试可以避免这种情况。未来还将提供“黑盒”内方法,帮助更好地控制此类优化。
- 副作用。框架中的所有分析都假设经过基准测试的函数尽可能纯净,即执行过程中的代码路径仅依赖于输入参数。因此,在编写基准测试时,必须确保副作用(例如修改全变量或测试类字段)不会影响每次基准测试迭代时代码的执行方式。注意,默认情况下,每次调用待基准测试的函数时,参数值是相同的。如果参数修改了,则意味着下一次调会使用修改后的值。不建议如此操作,因为每次调用都需要再设置一次。
- 冗余静态分配。如果在基准测试之前分配了大量对象(无论是静态分配还是在
@Before*方法中分配),需要确保这些对象在相关基准测试结束后被及时释放。否则,可能会增加 GC 负担,因为 GC 仍然需要遍历这些不再使用但仍然可达的对象,影响后续基准测试的准确性。
本框架会尽力检测是否存在这些因素且影响了基准测试结果,并在相应情况下发出警告。但这仅作为一种提醒,而非可靠的解决方案。也就是说,即使没有产生警告,也并不能保证已正确排除了所有这些因素的影响。此外,在一些情况下,例如启用编译优化选项,也可能无法准确知道用户究竟想要基准测试的是什么。
框架的测试方式
框架的核心算法可以用以下伪代码表示:
// 由@Bench[arg in dataStrategy] 宏在 someFunc(arg: Arg) 函数上生成
let measurement = TimeNow() // 或者使用通过 @Measure 宏提供的其他 Measurement 实现
func measureBatchSomeFunc(
parameter: ImmutableInputProvider<Arg>, // 或任何由策略返回的其他 BenchInputProvider 实现
batchSize: Int64,
maxBatchSize: Int64,
): Float64 {
parameter.reset(maxBatchSize) // 如果需要批量预生成输入数据,则重置 BatchInputProvider
measurement.setup()
let start = measurement.measure()
for(i in 0..maxBatchSize) { // 循环始终执行到 maxBatchSize,这样我们可以将循环本身所需的时间从最终结果中排除
let arg = parameter.get(i)
if (i < batchSize) {
/*
body of someFunc
*/
}
}
measurement.measure() - start
}
Framework.addBenchmark(dataStrategy, Benchmark(measureBatchSomeFunc))
// 框架内部
for (data in dataStrategy) {
benchmark.runBench(data)
}
doStatisticalAnalisys(benchmark.results)
class Benchmark<T> {
let results = ArrayList<(BatchSize, BatchResult)>
Benchmark(let runBatch: (T, Int64, Int64) -> Float64) {}
func runBench(data: T) {
let estimation = warmup(data)
let batchSizes = calcBatchSizes(estimation)
for (i in batchSizes) {
let resultBatch = runBatch(data, i, batchSizes.end)
results.append(i, resultBatch)
// 根据explicitGC配置参数运行GC
explicitGC.invoke()
}
}
func warmup(data: T) {
// 根据 warmup 配置参数进行预热
}
func calcBatchSizes(estimation: Duration) {
// 根据预热估计选择最合适的批处理量和批处理大小
}
}
这里的主要逻辑是,measureBatchSomeFunc(data, i, maxBatchSize) 和 measureBatchSomeFunc(data, i+n, maxBatchSize) 的执行时间差正好是执行 n 次 someFunc 的时间。
这意味着,通过估算这两次执行时间的差异,我们可以精确地估算出单次执行 someFunc 所需的时间。而这样的估算不包括测试本身、批量循环或获取下一份输入数据所带来的开销。
高级特性
某些基准测试需要特殊配置,以便准确地判断预期结果或深入了解测试结果。本框架提供了多种API,旨在覆盖尽可能多的复杂用例。
详细报告
当基准测试结果存在显著的不稳定性时,单纯查看聚合的统计参数往往不足以帮助分析。而打印所有原始数据虽然能提供详细信息,但打印信息过多,不便于人工分析。为了解决这一问题,我们提供了一种基于HTML的报告,其中包含各种图表,展示原始测试数据及其统计分析结果。要生成此报告,需使用 --report-format=html 选项。该报告包含一个导航页面,列出所有执行过的测试用例,并且为每个用例提供详细报告,展示所有参数和执行的测试数据。每条测试数据还将附带一个概率分布的内核密度估计图以及一个展示所有原始测试数据的图表。目前,本框架使用 gnuplot 工具绘制图表,需要用户自行安装该工具。
如果用户具备统计学背景,可自行进行数据的统计分析。为方便分析,我们支持使用 --report-format=csv-raw 选项将原始测试数据导出为 CSV 格式。
自定义测试源
默认情况下,框架测试的是时间,通常这已经足够。然而,在某些情况下,为了更详细地调查性能问题,可能需要其他的性能特征。为了实现这样的测试,我们提供了 Measurement 接口。此外,我们还支持一些常见的高级测试源。要启用这些测试源,可以使用一个特殊的 @Measure 类来注释这样一个测试源列表。
@Test
@Measure[TimeNow(Nanos), CpuCycles(), Perf(), Perf(HW_CACHE_MISSES)]
class Bench {
var x = 0
@Bench
func case() {
x += 1
}
}
框架提供的开箱即用的测试工具包括:
TimeNow: 使用DateTime.now测试实时时间。可以配置特定的时间单位,以便所有结果都使用相同的时间单位打印。CpuCycles: 用于测试裸机 CPU 指令的 CPU 使用周期数。仅在有此类指令的平台上可用,并且可以在用户空间中执行。Perf: 使用Linux的perf_event_open系统调用,测试各种软硬件的CPU计数器。
每次调用前的设置
假设我们要对 Array.sort 函数进行基准测试。该函数会修改其输入数据,导致基准测试结果不同,因为除第一次外,后续每次调用 sort 函数都是在已排序的数组上进行测试。因此,为了解决这个问题,我们需要在每次调用函数之前都重新生成数据。我们提供了 BenchInputProvider 接口实现器,可以通过 @Strategy 注解的函数返回数据。
@Test
class Foo {
@Strategy[len in [1000, 10000]]
func strings(len: Int64): GenerateEachInputProvider<Array<Int64>> {
GenerateEachInputProvider { => Array<Int64> }
}
@Bench[data in strings]
func sort(data: Array<Int64>) {
data.sort()
}
}
本框架提供了如下四种实现,基本可以覆盖所有可能的使用场景:
ImmutableInputProvider: 每次仅复制原始数据。当返回常规策略类型(未实现BenchInputProvider接口)时,默认采用此实现。GenerateEachInputProvider: 每次在调用待基准测试函数之前生成数据。这样测试过程中生成数据,框架从总测试时间中减去生成开销。这种方法要求生成函数的执行应该尽可能纯净且稳定。此外,数据生成的时间应小于实际基准测试的时间,否则实际基准测试时间可能会因为生成函数的差异而不准确。每次调用前都建议如此设置,但如果前述条件不满足,或者方差仍然较大,可考虑其他方法。BatchSizeOneInputProvider: 每次在调用待基准测试函数之前生成数据。但这种方法特殊要求批处理大小为1,框架不会将数据生成时间计入总测试时间中。在这种模式下,框架会单独测试每次函数基准测试的执行时间。这种模式没有了批量执行的优势,因此主要缺点是精度较低。精度是否成为问题取决于硬件配置,但一般来说,如果基准测试时间小于1微秒,应注意;如果基准测试时间小于100纳秒,则强烈不建议采用此模式。BatchInputProvider: 每次批处理开始之前,在缓冲区中生成多个数据副本。理论上,这具有批量执行的优势。然而,它也有一系列问题。首先,它会导致冗余分配,如果批处理大小足够大,可能会带来大量的GC工作。其次,测试结果可能会略有不同,因为之前数据生成后立即交给待基准测试的函数,而现在数据很可能仍在缓存中。这种情况下,所有数据生成完成后,生成的第一个元素才可能会从缓存中移出。
高级配置参数
有许多与基准测试相关的配置参数可以通过 @Configue 宏进行设置。当前支持的配置参数包括:
batchSize: 用于指定当批处理大小与执行时间之间存在非线性关系时的精确批处理大小范围。默认情况下,框架会根据预热结果自动选择批处理大小。minBatches: 指定工作负载拆分后的最小批处理量。默认情况下,框架会根据预热结果在10到200之间选择最合适的值。注意,指定过大的值可能导致统计分析时间过长。warmup: 指定框架调用函数执行基准测试的预热时间。minDuration: 指定基准测试的目标持续时间。框架会选择批处理大小和批处理量,使整个基准测试阶段的执行时间略微超过minDuration的目标值。explicitGC: 指定批处理之间如何执行GC。默认情况下,框架会在批处理之间触发GC,尝试均匀分配GC工作负载。否则,对于内存分配密集型的基准测试,可能会出现不可知的GC波动,影响测试结果。但对于一些没有内存分配的基准测试,这种行为可能会导致结果不准确或不稳定。若要禁用此行为,可以将该参数设置为Disable。
此外,有时可能需要迭代多个不同值的参数,以验证其是否影响结果。为了支持这种需求,框架提供了数据DSL的特殊语法形式:config.<parameter> in <strategy>。
@Test
class Foo {
var x = 0
@Bench[config.warmup in [Duration.second*0.1, Duration.second]]
func case() {
x += 1
}
}
避免不必要的优化
在基准测试复杂代码时,通常代码会包含一些能够影响其行为的参数。因此,为了执行一个确定性的基准测试,你可能需要为这些参数指定具体的值。基准测试代码可能如下所示:
@Bench
func foo(): Unit {
complexCode(param: 1)
}
但是,可能存在这样的情况:这个函数在真实程序中并不是这么调用的。也就是说,param 的值在真实程序中是运行时计算出来的,而在这里我们使用了字面常量,允许编译器在优化时利用这些信息。问题在于,我们希望基准测试的 complexCode 能够准确模拟它在真实程序中的表现。因此,解决这个问题的方法是使用策略来隐藏编译器看到的确切值。
@Bench[arg in [1]]
func foo(arg: Int64): Unit {
complexCode(param: arg)
}
然而,这里依然存在另一个问题。complexCode 的返回值没有被使用。如果编译器检测到它可以部分或完全移除这个函数调用,将会发生优化。为了解决这个问题,应该通过黑盒处理返回值。这个功能仍在开发中,所以目前的临时解决方法是将返回值存储在全局变量中。
std.unittest.mock
功能介绍
unittest.mock 包提供仓颉单元测试的mock 框架,提供 API 用于创建和配置mock 对象(以及独立声明,例如顶层或静态函数和顶层或静态变量),这些 mock 对象与真实对象拥有签名一致的 API 。mock 测试技术支持隔离测试代码,测试用例使用 mock 对象编码,实现外部依赖消除。
mock 框架具有以下特性:
- 创建 mock 对象和 spy 对象:测试时无需修改生产代码。配置独立声明(例如顶层函数或变量、静态函数或变量)时不需要此步骤。
- 简单的配置 API :可配置 mock/spy 对象(或独立声明)的行为。
- 单元测试框架部分:无缝集成单元测试框架的其他特性,错误输出可读。
- 自动验证配置行为:大多数情况下不需要多余的验证代码。
- 提供验证 API:用于测试系统内部的复杂交互。
用户使用场景包括:
- 简化测试设置和代码。
- 测试异常场景。
- 用轻量级 mock 对象替换代价高的依赖,提高测试性能。
- 验证测试复杂场景,如调用的顺序/数量。
用户可通过快速入门写出第一个带 mock 的测试程序。同时文档对于一些基础概念及用法做了说明并附有示例代码,另外,针对配置 API (桩)的高阶用法做了进一步说明。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| mock<T>() | 创建类型 T 的 mock object, 这个对象默认情况下,所有的成员函数、属性或运算符重载函数没有任何具体实现。 |
| mock<T>(Array<StubMode>) | 创建类型 T 的 mock object , 参数指定了桩的模式。 |
| spy<T>(T) | 创建类型 T 的 spy object ( mock object 的扩展,对象的成员拥有默认实现的“骨架”对象)。 这个对象包装了所传入的对象,并且默认情况下成员函数、属性或运算符重载函数实现为对这个传入的实例对象的对应成员函数、属性或运算符重载函数的调用。 |
接口
| 接口名 | 功能 |
|---|---|
| ValueListener<T> | 此接口提供了多个成员函数以支持“监听”传入给桩签名的参数。 |
类
| 类名 | 功能 |
|---|---|
| ActionSelector | 此抽象类提供了为成员函数指定一个操作 API ,并允许链式调用的方法。 |
| AnyMatcher | 任意参数匹配器,即桩签名允许任意的参数。 |
| ArgumentMatcher | 参数匹配器抽象类,该类与其子类可作为桩签名的入参类型。 |
| CardinalitySelector<A> | 此接口提供了可定义桩签名的最近一次行为的执行次数的 API 。 |
| ConfigureMock | 配置 mock object 。 |
| Continuation<A> | 此类提供了可继续定义桩签名的行为的 API 。 |
| GetterActionSelector<TRet> | 此类提供了为属性 Getter 函数指定一个操作 API ,并允许链式调用的方法。 |
| Matchers | 该类提供生成匹配器的静态函数。匹配器对象仅可通过此处的静态函数生成。匹配器可在桩链中使用。 |
| MethodActionSelector<TRet> | 此类提供了为成员函数指定一个操作 API ,并允许链式调用。 |
| MockFramework | 提供用例执行所需的框架准备与结束回收阶段的函数。 |
| NoneMatcher | 参数值为 None 的匹配器。 |
| OrderedVerifier | 此类型用于收集 “验证语句”, 可在 ordered 函数中动态传入验证行为。 |
| SetterActionSelector<TRet> | 此类提供了为属性 Setter 函数指定一个操作 API ,并允许链式调用的方法。 |
| SyntheticField<T> | 合成字段。 |
| TypedMatcher<T> | 参数类型匹配器。 |
| UnorderedVerifier | 此类型用于收集 “验证语句”, 可在 unordered 函数中动态传入验证行为。 |
| Verify | Verify 提供了一系列静态方法来支持定义所需验证的动作,如 that 、 ordered 以及 unorder 。 |
| VerifyStatement | 此类型表示对“桩签名”在验证范围内的单个验证验证语句(即上文中的“验证语句”),提供了成员函数指定“桩签名”的执行次数。 |
枚举
| 枚举名 | 功能 |
|---|---|
| Exhaustiveness | 此枚举类型用于指定 unordered 函数的验证模式,包含两种模式。 |
| MockSessionKind | 控制允许在 MockSession 使用的桩的类型。 |
| StubMode | 控制桩的模式。 |
函数
func mock<T>()
public func mock<T>(): T
功能:创建类型 T 的 mock object, 这个对象默认情况下,所有的成员函数、属性或运算符重载函数没有任何具体实现。
可以通过 @On 指定这个对象的成员函数、属性或运算符重载函数的行为。
返回值:
- T - 类型 T 的
mock object。
func mock<T>(Array<StubMode>)
public func mock<T>(modes: Array<StubMode>): T
功能:创建类型 T 的 mock object , 参数指定了桩的模式。
参数:
- modes: Array<StubMode> - 指定桩的模式,可以为多个。
返回值:
- T - 类型 T 的
mock object。
func spy<T>(T)
public func spy<T>(objectToSpyOn: T): T
功能:创建类型 T 的 spy object ( mock object 的扩展,对象的成员拥有默认实现的“骨架”对象)。 这个对象包装了所传入的对象,并且默认情况下成员函数、属性或运算符重载函数实现为对这个传入的实例对象的对应成员函数、属性或运算符重载函数的调用。
可以通过 @On 重载这个对象的成员函数、属性或运算符重载函数的行为。
参数:
- objectToSpyOn: T - 传入实例对象,默认情况下,使用该对象的实现。
返回值:
- T - 类型 T 的
spy object。
接口
interface ValueListener<T>
public interface ValueListener<T> {
func lastValue(): Option<T>
func allValues(): Array<T>
func addCallback(callback: (T) -> Unit): Unit
static func new(): ValueListener<T>
static func onEach(callback: (T) -> Unit): ValueListener<T>
}
功能:此接口提供了多个成员函数以支持“监听”传入给桩签名的参数。即对每次调用中传入桩签名的参数进行指定的操作( addCallback() 或 onEach 中的闭包函数即为对参数进行的操作内容)。
一般与参数匹配器生成函数 argThat 或者 capture 配合使用。
值侦听器与参数捕获器一同作为参数匹配器的一种被传入到桩签名中,作为入参。在定义桩签名的参数值范围的同时检查参数值。
举例来说:
struct Animal {
Animal(
let name: String,
let info: String
) {}
}
abstract class AnimalUi {
func showAnimal(animal: Animal): Unit
}
let animals = [Animal("Smokey", "Cat, age: 5"), Animal("Daisy", "Dog, age: 9")]
@Test func testAnimal(): Unit {
let ui = mock<AnimalUi>()
// 定义了一个值监听器:检查每个值,当值不满足条件时抛出异常。
let listener = ValueListener<Animal>.onEach { animal =>
if (animal.name == "Smokey") {
@Assert(animal.info.contains("Cat"))
}
}
// 定义一个桩签名的“桩行为”,参数匹配器为可执行上述值监听器的参数捕获器。
@On(ui.showAnimal(capture(listener))).returns(())
for (animal in animals) {
// 此处将捕获传入的 animal 对象,并对其执行值监听器中的检查行为。
ui.showAnimal(animal)
}
}
func addCallback((T) -> Unit)
func addCallback(callback: (T) -> Unit): Unit
功能:为当前“值监听器”对象增加闭包函数,该函数将处理传入的参数值。
参数:
- callback: (T) ->Unit - 处理参数值的闭包函数。
func allValues()
func allValues(): Array<T>
功能:返回当前“值监听器”对象已所处理的所有值。
返回值:
- Array<T> - 返回“值监听器”对象所处理的所有值列表。
func lastValue()
func lastValue(): Option<T>
功能:返回当前“值监听器”对象所处理的最后一个值。
返回值:
- Option<T> - 返回“值监听器”对象所处理的最后一个值,不存在时,返回 None 。
func new()
static func new(): ValueListener<T>
功能:创建一个新的“值监听器”对象,不包含任何处理参数的闭包方法。
返回值:
- ValueListener<T> - “值监听器”对象。
func onEach((T) -> Unit)
static func onEach(callback: (T) -> Unit): ValueListener<T>
功能:创建一个新的“值监听器”对象,带有一个处理参数的闭包方法。
参数:
- callback: (T) ->Unit - 处理参数值的闭包函数。
返回值:
- ValueListener<T> - “值监听器”对象。
类
class ActionSelector
public sealed abstract class ActionSelector {}
功能:此抽象类提供了为成员函数指定一个操作 API ,并允许链式调用的方法。
入参为 mock object 或 spy object 的某个成员函数的调用表达式的 @On 宏调用表达式,将返回 ActionSelector 的实例。即,此类或其子类中的 API 可为成员函数插入桩代码。
func fails()
func fails(): Unit
功能:定义调用桩签名将导致测试失败,执行至桩签名即抛出 AssertionException 异常的行为。
class AnyMatcher
public class AnyMatcher <: ArgumentMatcher {}
功能:任意参数匹配器,即桩签名允许任意的参数。
父类型:
func matchesAny(Any)
public func matchesAny(_: Any)
功能:匹配任意类型的任意值。
参数:
- _: Any - 被检查的输入参数。任意类型的任意值。
返回值:
- Bool - 固定为
true。
extend AnyMatcher
extend AnyMatcher {}
功能:扩展 AnyMatcher 。
func value<T>()
public func value<T>(): T
功能:框架需要调用的参数匹配器的返回值。
返回值:
- T - 与实际入参类型匹配的值。
class ArgumentMatcher
public abstract class ArgumentMatcher {}
功能:参数匹配器抽象类,该类与其子类可作为桩签名的入参类型。
func withDescription(String)
public func withDescription(description: String): ArgumentMatcher
功能:配置参数匹配器抛出异常时的描述信息。
参数:
- description: String - 描述信息。
返回值:
- ArgumentMatcher - 被配置的参数匹配器。
func forParameter(String)
public func forParameter(name: String): ArgumentMatcher
功能:配置所匹配的参数名称。
参数:
- name: String - 所匹配的参数名称。
返回值:
- ArgumentMatcher - 被配置的参数匹配器。
func matchesAny(Any)
public func matchesAny(arg: Any)
功能:匹配任意类型的任意值。
参数:
- arg: Any - 被检查的输入参数。任意类型的任意值。
返回值:
- Bool - 匹配结果 。
class CardinalitySelector<A>
public class CardinalitySelector<A> where A <: ActionSelector {}
功能:此类提供了可定义桩签名的最近一次行为的执行次数的 API 。
例如:@On(foo.bar()).returns("Predefined value").atLeastOnce() 。
为方便表达,后文将桩签名的最近一次行为称为“桩行为”。
此接口提供的 API 提供的验证能力如下:
- 桩签名的调用次数超过指定次数将立即抛出 ExpectationFailedException 。
- 桩签名的调用次数不足时,框架将在测试用例执行完成后抛出 ExceptionFailedException 。
func anyTimes()
func anyTimes(): Unit
功能:定义“桩行为”可以执行任意次数。此函数对桩签名的调用次数不做任何校验。
func atLeastOnce()
func atLeastOnce(): Unit
功能:定义“桩行为”最少被执行一次。验证不到一次时,抛出异常。
异常:
- ExceptionFailedException - 验证“桩行为”执行次数不到一次时,抛出异常。
func atLeastTimes(Int64)
func atLeastTimes(minTimesExpected: Int64): Unit
功能:定义“桩行为”最少被执行指定次数的行为。验证实际执行次数低于最少指定次数时,抛出异常。
参数:
- minTimesExpected: Int64 - 预期“桩行为”最少被执行的次数。
异常:
- ExceptionFailedException - 验证“桩行为”执行少于指定次数时,抛出异常。
- IllegalArgumentException - 当作为
minTimesExpected参数传递的数字为负数时,抛出异常。
func once()
func once(): Continuation<R>
功能:定义“桩行为”仅被执行一次。此函数将在验证桩签名执行次数超出一次时,抛出异常。
返回值:
- Continuation<R> - 对象实例可调用方法继续生成 ActionSelector 对象。
异常:
- ExceptionFailedException - 验证“桩行为”执行次数超过一次时,立即抛出异常。
func times(Int64)
func times(expectedTimes: Int64): Continuation<R>
功能:定义“桩行为”被执行指定次数。验证不是指定次数时,抛出异常。
参数:
- expectedTimes: Int64 - 预期“桩行为”被执行的次数。
返回值:
- Continuation<R> - 对象实例可调用方法继续生成 ActionSelector 对象。
异常:
- ExceptionFailedException - 验证“桩行为”执行次数不是指定次数时,抛出异常。
- IllegalArgumentException - 当作为
expectedTimes参数传递的数字为负数时,抛出异常。
func times(Int64, Int64)
func times(min!: Int64, max!: Int64): Unit
功能:定义“桩行为”执行指定次数范围。验证超出指定次数范围时,抛出异常。
参数:
异常:
- ExceptionFailedException - 验证“桩行为”执行次数不是指定次数范围时,抛出异常。
- IllegalArgumentException - 当传入的
min或max参数为负数时,抛出异常。
class ConfigureMock
public class ConfigureMock {}
功能:配置 mock object 。
static func stubGetter<TObj, TRet>(() -> TRet,TObj,String,String,String,Int64)
public static func stubGetter<TObj, TRet>(
stubCall: () -> TRet,
objectReference: TObj,
objectName: String,
fieldOrPropertyName: String,
callDescription: String,
lineNumber: Int64
): GetterActionSelector<TRet>
功能:创建针对属性的 Getter 方法插入桩代码的操作器对象。
参数:
- stubCall: () -> TRet - 桩签名对应的调用表达式。
- objectReference: TObj - 被插桩的对象的引用。
- objectName: String - 被插桩的对象的名称。
- fieldOrPropertyName: String - 被插桩的字段或属性名称。
- callDescription: String - 桩签名对应的调用表达式的字符串表达。
- lineNumber: Int64 - 对应的调用表达式的行号。
返回值:
- GetterActionSelector<TRet> - 针对属性的 Getter 方法插入桩代码的操作器对象。
static func stubMethod<TObj, TRet>(() -> TRet,Array<ArgumentMatcher>,TObj,String,String,String,Int64)
public static func stubMethod<TObj, TRet>(
stubCall: () -> TRet,
matchers: Array<ArgumentMatcher>,
objectReference: TObj,
objectName: String,
methodName: String,
callDescription: String,
lineNumber: Int64
): MethodActionSelector<TRet>
功能:创建针对普通成员方法插入桩代码的操作器对象。
参数:
- stubCall: () -> TRet - 桩签名对应的调用表达式。
- matchers: Array<ArgumentMatcher> - 对应入参的参数匹配器。
- objectReference: TObj - 被插桩的对象的引用。
- objectName: String - 被插桩的对象的名称。
- methodName: String - 被插桩的方法名称。
- callDescription: String - 桩签名对应的调用表达式的字符串表达。
- lineNumber: Int64 - 对应的调用表达式的行号。
返回值:
- MethodActionSelector<TRet> - 针对普通成员方法插入桩代码的操作器对象。
static func stubSetter<TObj, TRet>(() -> Unit, () -> TArg,ArgumentMatcher,TObj,String,String,String,Int64)
public static func stubSetter<TObj, TArg>(
stubCall: () -> Unit,
_: () -> TArg,
matcher: ArgumentMatcher,
objectReference: TObj,
objectName: String,
fieldOrPropertyName: String,
callDescription: String,
lineNumber: Int64
): SetterActionSelector<TArg>
功能:创建针对属性 Setter 方法插入桩代码的操作器对象。
参数:
- stubCall: () -> Unit - 桩签名对应的调用表达式。
- _: () -> TArg - 用于捕获属性或者字段的类型。
- matcher: ArgumentMatcher - 入参的参数匹配器。
- objectReference: TObj - 被插桩的对象的引用。
- objectName: String - 被插桩的对象的名称。
- fieldOrPropertyName: String - 被插桩的属性或字段的名称。
- callDescription: String - 桩签名对应的调用表达式的字符串表达。
- lineNumber: Int64 - 对应的调用表达式的行号。
返回值:
- MethodActionSelector<TRet> - 针对普通成员方法插入桩代码的操作器对象。
class Continuation<A>
public class Continuation<A> where A <: ActionSelector {}
功能:此类提供了可继续定义桩签名的行为的 API 。 此类提供的方法能力如下:
- 允许当先前的操作得到满足时,桩签名将执行额外的操作。仅当后面跟着一个行为定义时,
Continuation实例才有意义。 - 当先前的操作未得到满足时,将抛出 MockFrameworkException 异常。并不保证抛出此异常的确切位置。
func then()
func then(): A
功能:当链中的先前操作完成时,返回 ActionSelector 的子类对象。
返回值:
- A - ActionSelector的子类对象实例。
异常:
- MockFrameworkException - 当先前的操作未得到满足时,将抛出异常。
class GetterActionSelector<TRet>
public class GetterActionSelector<TRet> <: ActionSelector {}
功能:此类提供了为属性 Getter 函数指定一个操作 API ,并允许链式调用的方法。
入参为 mock object 或 spy object 的某个成员函数的调用表达式的 @On 宏调用表达式,将返回 ActionSelector 的实例。即,此类或其子类中的 API 可为成员函数插入桩代码。
父类型:
func getsField(SyntheticField<TRet>)
public func getsField(field: SyntheticField<TRet>): CardinalitySelector<GetterActionSelector<TRet>>
功能:读取合成字段。
参数:
- field: SyntheticField<TRet> - 合成字段,处理可变属性。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func getsOriginal()
public func getsOriginal(): CardinalitySelector<GetterActionSelector<TRet>>
功能:读取原始属性或获取原始实例中的字段值。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func returns(TRet)
public func returns(value: TRet): CardinalitySelector<GetterActionSelector<TRet>>
功能:指定返回值。
参数:
- value: TRet - 指定的返回的值。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func returns(() -> TRet)
public func returns(valueFactory: () -> TRet): CardinalitySelector<GetterActionSelector<TRet>>
功能:指定返回值。
参数:
- valueFactory: () -> TRet - 指定的返回的值生成器。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func returnsConsecutively(Array<TRet>)
public func returnsConsecutively(values: Array<TRet>)
功能:指定返回多个值。
参数:
- values: Array<TRet> - 指定的返回的多个值。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func returnsConsecutively(ArrayList<TRet>)
public func returnsConsecutively(values: ArrayList<TRet>)
功能:指定返回多个值。
参数:
- values: ArrayList<TRet> - 指定的返回的多个值。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func throws(Exception)
public func throws(exception: Exception): CardinalitySelector<GetterActionSelector<TRet>>
功能:指定抛出异常。
参数:
- exception: Exception - 指定的抛出的异常。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func throws(() -> Exception)
public func throws(exceptionFactory: () -> Exception): CardinalitySelector<GetterActionSelector<TRet>>
功能:指定抛出异常。
参数:
- exceptionFactory: () -> Exception - 指定的抛出的异常的生成器。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
extend MethodActionSelector<Unit>
extend MethodActionSelector<Unit> {}
功能:扩展 MethodActionSelector 。
func returns()
public func returns(): CardinalitySelector<MethodActionSelector<TRet>>
功能:指定桩函数什么都不做。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
class Matchers
public class Matchers {}
功能:该类提供生成匹配器的静态函数。匹配器对象仅可通过此处的静态函数生成。匹配器可在桩链中使用。
例如:@On(foo.bar(ofType<Int64>())).returns(1)
参数匹配器可以在 @On 宏调用表达式入参处使用,来描述期望将哪些参数传递到桩签名中。参数匹配器有两个最常见的用途:
-
为不同的参数指定不同的行为。例如:
// 当 bar 的入参为 5 时,返回某个值 @On(foo.bar(eq(5))).returns(...) // 当 bar 的入参为 6 时,抛出异常 @On(foo.bar(eq(6))).throws(...) -
确保只有某些参数被传递到某些桩签名中。
let foo = mock<Foo>() // bar 的入参只能为正数,否则将抛出 UnhandledCallException 异常 @On(foo.bar(argThat<Int64> { arg => arg > 0 })).returns(...)注意:
上例仅适用于
mock object。spy object的行为不同。let foo = spy(Foo()) // 当 bar 的入参不为正数时,将调用 Foo() 对象的成员函数。 @On(foo.bar(argThat<Int64> { arg => arg <= 0 })).fails()
static func any()
public static func any(): AnyMatcher
功能:允许将任何值作为参数。
返回值:
- AnyMatcher - 允许任意值的参数匹配器。
static func argThat<T>(ValueListener<T>, (T) -> Bool)
public static func argThat<T>(listener: ValueListener<T>, predicate: (T) -> Bool): TypedMatcher<T>
功能:通过传入的 predicate 闭包函数过滤传入的参数值,允许 listener 值监听器对满足条件的传入参数值进行处理。
参数:
- listener: ValueListener<T> - 值监听器。
- predicate: (T) ->Bool - 过滤器,可通过此函数定义过滤参数值的匹配条件。
返回值:
- TypedMatcher<T> - 拥有值监听器和过滤器的类型匹配器。
static func argThat<T>((T) -> Bool)
public static func argThat<T>(predicate: (T) -> Bool): TypedMatcher<T>
功能:根据提供的过滤器闭包过滤输入值。
参数:
- predicate: (T) ->Bool - 过滤器。
返回值:
- TypedMatcher<T> - 参数过滤类型匹配器实例。
static func argThatNot<T>((T) -> Bool)
public static func argThatNot<T>(predicate: (T) -> Bool): TypedMatcher<T>
功能:根据提供的过滤器闭包过滤输入值。
参数:
- predicate: (T) ->Bool - 过滤器。
返回值:
- TypedMatcher<T> - 参数过滤类型匹配器实例。
static func capture<T>(ValueListener<T>)
public static func capture<T>(listener: ValueListener<T>): TypedMatcher<T>
允许 listener 值监听器对类型为 T 的传入参数值进行处理。当 capture 的类型参数未指定时,将使用值监听器的类型参数值。
参数:
- listener: ValueListener<T> - 值监听器。
返回值:
- TypedMatcher<T> - 拥有值监听器的类型匹配器。
注意:值监听器不允许在 @Called 的参数范围内使用。
static func default<T>(T)
public static func default<T>(target: T): TypedMatcher<T>
功能:根据结构(更高优先级)或引用相等性来匹配值。如果传入的参数既不是 Equatable<T> 也不是引用类型,则会在运行时抛出异常(编译期不做检查)。
参数:
- target: T - 必须通过结构或引用相等来匹配的匹配对象。
返回值:
- TypedMatcher<T> - 默认类型匹配器。
异常:
- MockFrameworkException - 如果参数 target 既不是 Equatable<T> 类型也不是引用类型,则抛出异常。
static func eq<T>(T)
public static func eq<T>(target: T): TypedMatcher<T> where T <: Equatable<T>
功能:根据与提供的值的结构相等性过滤输入值。
参数:
- target: T - 匹配对象。
返回值:
- TypedMatcher<T> - 仅允许结构上等于给定值的参数匹配器。
static func ofType<T>()
public static func ofType<T>(): TypedMatcher<T>
功能:根据类型过滤输入值。
返回值:
- TypedMatcher<T> - 仅允许特定类型的类型匹配器。
static func same<T>(T) where T <: Object
public static func same<T>(target: T): TypedMatcher<T> where T <: Object
功能:根据与所提供对象的引用相等性来过滤输入值。
参数:
- target: T - 匹配对象。
返回值:
- TypedMatcher<T> - 仅允许与给定对象引用相等的参数的参数匹配器。
extend Matchers
extend Matchers {}
功能:扩展 Matchers 。
static func none()
public static func none(): NoneMatcher
功能:过滤值为 None 的入参值。
返回值:
- NoneMatcher -
None值匹配器。
class MethodActionSelector<TRet>
public class MethodActionSelector<TRet> <: ActionSelector {}
功能:此类提供了为成员函数指定一个操作 API ,并允许链式调用。
入参为 mock object 或 spy object 的某个成员函数的调用表达式的 @On 宏调用表达式,将返回 ActionSelector<R> 的实例(其中 R 代表正在配置的函数成员的返回值类型)。
即,此类中的 API 可为成员函数插入桩代码。
父类型:
func callsOriginal()
func callsOriginal(): CardinalitySelector<R>
功能:定义桩签名执行原始代码逻辑的行为。
返回值:
- CardinalitySelector<R> - 定义了桩签名执行原始代码逻辑的 CardinalitySelector<R> 对象实例。
func returns(() -> R)
func returns(valueFactory: () -> R): CardinalitySelector<R>
功能:定义桩签名返回指定的值的行为,该值由传入的闭包生成。
参数:
- valueFactory: () ->R - 生成预期返回值的闭包函数(生成器)。
返回值:
- CardinalitySelector<R> - 定义了桩签名返回指定值的行为的 CardinalitySelector<R> 对象实例。
func returns(R)
func returns(value: R): CardinalitySelector<R>
功能:定义桩签名返回指定值的行为。
参数:
- value: R - 预期桩签名的返回值。
返回值:
- CardinalitySelector<R> - 定义了桩签名返回行为的 CardinalitySelector<R> 对象实例。
func returnsConsecutively(Array<R>)
func returnsConsecutively(values: Array<R>): Continuation<R>
功能:定义桩签名按列表顺序返回指定的值的行为。桩签名将被调用多次,次数与数组内值的个数相同。
参数:
- values: Array<R> - 桩签名的返回值列表。
返回值:
- Continuation<R> - 定义了桩签名按序返回指定值的行为的 Continuation<R> 对象实例。
异常:
- IllegalArgumentException - 当参数列表为空时,抛出异常。
func returnsConsecutively(ArrayList<R>)
func returnsConsecutively(values: ArrayList<R>): Continuation<R>
功能:定义桩签名按列表顺序返回指定的值的行为。桩签名将被连续调用多次,次数与数组列表内值的个数相同。
参数:
- values: ArrayList<R> - 桩签名的返回值列表。
返回值:
- Continuation<R> - 定义了桩签名按序返回指定值的 Continuation<R> 对象实例。
异常:
- IllegalArgumentException - 当参数列表为空时,抛出异常。
func throws(() -> Exception)
func throws(exceptionFactory: () -> Exception): CardinalitySelector<R>
功能:定义桩签名抛出异常的行为,异常由参数闭包函数生成。
说明:
throws vs fails
throws 意味着测试桩签名抛出异常后的行为是测试的目的。例如,当某些服务不可用时,系统是否可以正确恢复等。 fails 意味着调用桩签名将导致测试失败。即,如果系统行为正确,则永远不应调用该桩签名。
参数:
- exceptionFactory: () ->Exception - 构造预期桩签名抛出的异常对象的闭包函数(生成器)。
返回值:
- CardinalitySelector<R> - 定义了桩签名抛出异常行为的 CardinalitySelector<R> 对象实例。
func throws(Exception)
func throws(exception: Exception): CardinalitySelector<R>
功能:定义桩签名抛出异常的行为。
参数:
- exception: Exception - 预期桩签名抛出的异常对象。
返回值:
- CardinalitySelector<R> - 定义了桩签名抛出异常的行为的 CardinalitySelector<R> 对象实例。
class MockFramework
public class MockFramework {}
功能:提供用例执行所需的框架准备与结束回收阶段的函数。
static func openSession
public static func openSession(name: String, sessionKind: MockSessionKind): Unit
功能:打开一个新会话。会话形成一个类似堆栈的结构。
会话关闭的顺序与开始时的顺序相反。
在给定会话期间创建的 mock object 只能在该会话或其任何内部会话内部访问。
每个会话都保留自己的调用日志,因此对最新打开会话内进行的调用执行任何验证, 只有在会议结束时才能验证期望。
参数:
- name: String - 会话的名称。
- sessionKind: MockSessionKind - 指定允许的桩类型。
static func closeSession
public static func closeSession(): Unit
功能:打开一个新会话。会话形成一个类似堆栈的结构。
会话关闭的顺序与开始时的顺序相反。
在给定会话期间创建的 mock object 只能在该会话或其任何内部会话内部访问。
每个会话都保留自己的调用日志,因此对最新打开会话内进行的调用执行任何验证, 只有在会议结束时才能验证期望。
异常:
- MockFrameworkException - 检测到错误的配置信息的时候,抛出异常。
- ExpectationFailedException - 当预期未被满足时,抛出异常。
class NoneMatcher
public class NoneMatcher <: ArgumentMatcher {}
功能:参数值为 None 的匹配器。
父类型:
func matchesAny
public override func matchesAny(arg: Any): Bool
功能:匹配任意输入值,值为 None 时返回 true 。
参数:
- arg: Any - 待匹配的入参值。
返回值:
- Bool - 当输入为 None 时返回
true,否则返回false。
extend NoneMatcher
extend NoneMatcher {}
功能:扩展 NoneMatcher 。
func value<T>()
public func value<T>(): Option<T>
功能:框架需要调用的参数匹配器的返回值。
返回值:
- Option<T> - 与实际入参值类型匹配的值。
class OrderedVerifier
public class OrderedVerifier {}
功能:此类型用于收集 “验证语句”,可在 ordered 函数中动态传入验证行为。
func checkThat(VerifyStatement)
public func checkThat(statement: VerifyStatement): OrderedVerifier
功能:添加一条 “验证语句”。
参数:
- statement: VerifyStatement - 待被添加的“验证语句”。
返回值:
- OrderedVerifier - 返回对象自身。
class SetterActionSelector<TRet>
public class SetterActionSelector<TRet> <: ActionSelector {}
功能:此类提供了为属性 Setter 函数指定一个操作 API ,并允许链式调用的方法。
入参为 mock object 或 spy object 的某个成员函数的调用表达式的 @On 宏调用表达式,将返回 ActionSelector 的实例。即,此类或其子类中的 API 可为成员函数插入桩代码。
父类型:
func doesNothing()
public func doesNothing(): CardinalitySelector<SetterActionSelector<TArg>>
功能:指定该属性或字段不做任何动作。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func setsOriginal()
public func setsOriginal(): CardinalitySelector<SetterActionSelector<TArg>>
功能:设置原始属性或获取原始实例中的字段值。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func setsField(SyntheticField<TRet>)
public func setsField(field: SyntheticField<TArg>): CardinalitySelector<SetterActionSelector<TArg>>
功能:设置合成字段。
参数:
- field: SyntheticField<TRet> - 合成字段,处理可变属性。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func throws(Exception)
public func throws(exception: Exception): CardinalitySelector<GetterActionSelector<TRet>>
功能:指定抛出异常。
参数:
- exception: Exception - 指定的抛出的异常。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
func throws(() -> Exception)
public func throws(exceptionFactory: () -> Exception): CardinalitySelector<GetterActionSelector<TRet>>
功能:指定抛出异常。
参数:
- exceptionFactory: () -> Exception - 指定的抛出的异常的生成器。
返回值:
- CardinalitySelector<GetterActionSelector<TRet>> - 预期执行次数的操作器。
class SyntheticField<T>
public class SyntheticField<T> {}
功能:合成字段。用于处理可变属性和字段。
static func create(T)
public static func create(initialValue!: T): SyntheticField<T>
功能:创建合成字段。
参数:
- initialValue!: T - 初始值。
返回值:
- SyntheticField<T> - 合成字段。
class TypedMatcher<T>
public abstract class TypedMatcher<T> <: ArgumentMatcher {}
功能:参数类型匹配器。
父类型:
func matches(T)
public func matches(arg: T): Bool
功能:检查入参类型是否与预期相符。
参数:
- arg: T - 待检查的入参。
返回值:
- Bool - 若类型匹配则返回
true,否则返回false。
func matchesAny(Any)
public func matchesAny(arg: Any): Bool
功能:检查入参类型是否与预期相符。
参数:
- arg: Any - 待检查的入参。
返回值:
- Bool - 若类型匹配则返回
true,否则返回false。
extend<T> TypedMatcher<T>
extend<T> TypedMatcher<T> {}
功能:扩展 TypedMatcher 。
func value<T>()
public func value<T>(): T
功能:框架需要调用的参数匹配器的返回值。
返回值:
- T - 与实际入参值类型匹配的值。
class UnorderedVerifier
public class UnorderedVerifier{}
功能:此类型用于收集 “验证语句”, 可在 unordered 函数中动态传入验证行为。
func checkThat(VerifyStatement)
public func checkThat(statement: VerifyStatement):UnorderedVerifier
功能:添加一条 “验证语句”。
参数:
- statement: VerifyStatement - 待被添加的“验证语句”。
返回值:
- UnorderedVerifier - 返回对象自身。
class Verify
public class Verify {}
功能:Verify 提供了一系列静态方法来支持定义所需验证的动作,如 that 、 ordered 以及 unorder 。
一个验证动作可以包含多个由 @Called 生成的验证语句,来描述需要验证的动作。
通常验证的范围为所在测试用例的函数体,但 Verify 提供了 clearInvocationLog 函数来清除此前的执行记录,以缩小验证范围。
行为验证是指,验证“桩签名”的操作是否按所定义的方式执行,当验证实际执行与定义不一致时,将抛出异常。
具体支持验证的行为如下:
- 所指定的“桩签名”是否被执行。
- 所指定的“桩签名”是否执行指定的次数。
- 所指定的“桩签名”在执行时,被传入的参数是否满足要求。
- 所指定的多个“桩签名”的调用顺序是否满足要求。
行为验证主要通过以下两个步骤完成:
- 通过调用 Verify 的静态方法定义一个验证动作。
- 通过
@Called宏调用表达式定义所需验证的 “桩签名”的执行动作。为简化表达,后文将其称为“验证语句”。
举例来说:
let foo = mock<Foo>()
// 定义“桩签名”的“桩行为”
@On(foo.bar().returns(1))
// 实际“桩签名”在用例中的执行情况
foo.bar()
// 验证“桩签名”的执行情况:foo.bar() 至少执行了一次
Verify.that(@Called(foo.bar()))
值得注意的是, CardinalitySelector<R> 提供了一些 API ,其支持验证一些行为 。因此,用户可自由选择不同的方式进行行为验证。
static func clearInvocationLog()
public static func clearInvocationLog(): Unit
功能:清除前序的执行记录,以缩小验证范围。
static func noInteractions(Array<Object>)
public static func noInteractions(mocks: Array<Object>): Unit
功能:在验证范围内,对象没有任何执行动作时,验证通过。
参数:
异常:
- VerificationFailedException - 验证不通过时,抛出异常。
static func ordered((OrderedVerifier) -> Unit)
public static func ordered( collectStatements: (OrderedVerifier) -> Unit): Unit
功能:此函数支持验证“验证语句”是否被执行或执行的次数是否符合定义,并且校验执行顺序。默认情况下,“验证语句”的执行次数为一次。
传入列表中的“验证语句”必须是不相交的(即当单个调用行为,可以匹配多个“验证语句”时,将抛出异常)。
“验证语句”通过入参中的闭包动态增加。
验证模式为 exhaustive (全量匹配,验证范围内的所有执行情况都应在验证动作中被指定)。
参数:
- collectStatements: (OrderedVerifier) ->Unit - 支持可动态增加“验证语句”的闭包。
异常:
- VerificationFailedException - 验证不通过时,抛出异常。
static func ordered(Array<VerifyStatement>)
public static func ordered(statements: Array<VerifyStatement>): Unit
功能:此函数支持验证“验证语句”是否被执行或执行的次数是否符合定义,并且校验执行顺序。默认情况下,“验证语句”的执行次数为一次。
传入列表中的“验证语句”必须是不相交的(即当单个调用行为,可以匹配多个“验证语句”时,将抛出异常)。
验证模式为 exhaustive (全量匹配,验证范围内的所有执行情况都应在验证动作中被指定)。
举例来说:
for (i in 0..4) {
foo.bar(i % 2)
}
Verify.ordered(
@Called(foo.bar(0)),
@Called(foo.bar(1)),
@Called(foo.bar(0)),
@Called(foo.bar(1)),
)
// 将抛出异常,验证范围内有 4 次 foo.bar() 表达式的执行动作,此处只验证了2次执行。
Verify.ordered(
@Called(foo.bar(0)),
@Called(foo.bar(_)),
)
参数:
- statements: Array<VerifyStatement> - 所需验证的“验证语句”。
异常:
- VerificationFailedException - 验证不通过时,将抛出异常。
static func that(VerifyStatement)
public static func that(statement: VerifyStatement): Unit
功能:验证是否正确执行了传入的单个“验证语句”。
参数:
- statement: VerifyStatement - 所需验证的“验证语句”。
异常:
- VerificationFailedException - 验证不通过时,将抛出异常。
static func unordered((UnorderedVerifier) -> Unit)
public static func unordered(collectStatements: (UnorderedVerifier) -> Unit): Unit
功能:此函数支持验证“验证语句”是否被执行或执行的次数是否符合定义,并且不校验执行顺序。默认情况下,“验证语句”的执行次数为至少一次。
传入列表中的“验证语句”必须是不相交的(即当单个调用行为,可以匹配多个“验证语句”时,将抛出异常)。
验证模式为 exhaustive (全量匹配,验证范围内的所有执行情况都应在验证动作中被指定)。
“验证语句”通过入参中的闭包动态增加。举例来说:
let totalTimes = getTimes()
for (i in 0..totalTimes) {
foo.bar(i % 2)
}
// 通过闭包使得“验证语句”可以通过 totalTimes 的值确定内容
Verify.unordered { v =>
for (j in 0..totalTimes) {
v.checkThat(@Called(foo.bar(eq(j % 2))))
}
}
参数:
- collectStatements: (UnorderedVerifier) ->Unit - 支持可动态增加“验证语句”的闭包。
异常:
- VerificationFailedException - 验证不通过时,抛出异常。
static func unordered(Array<VerifyStatement>)
public static func unordered(statements: Array<VerifyStatement>): Unit
功能:此函数支持验证“验证语句”是否被执行或执行的次数是否符合定义,并且不校验执行顺序。默认情况下,“验证语句”的执行次数为至少一次。
传入列表中的“验证语句”必须是不相交的(即当单个调用行为,可以匹配多个“验证语句”时,将抛出异常)。
验证模式为 exhaustive (全量匹配,验证范围内的所有执行情况都应在验证动作中被指定)。
举例来说:
let foo = mock<Foo>()
for (i in 0..4) {
foo.bar(i % 2)
}
// 验证 bar() 在传入参数为 0 或 1 的情况下均至少执行一次
Verify.unordered(
@Called(foo.bar(0)),
@Called(foo.bar(1))
)
// 此处的验证动作将抛出异常,因为 `foo.bar(_)` 包含了 `foo.bar(1)`
Verify.unordered(
@Called(foo.bar(_)).times(2),
@Called(foo.bar(1)).times(2)
)
// 可以通过如下方式进行验证
// 验证入参为 1 的调用表达式执行了2次
Verify.that(@Called(foo.bar(1)).times(2))
// 验证任意入参的调用表达式执行了2次
Verify.that(@Called(foo.bar(_)).times(2)) // called four times in total
参数:
- statements: Array<VerifyStatement> - 待验证的多条“验证语句”,变长参数语法支持参数省略
[]。
异常:
- VerificationFailedException - 验证不通过时,抛出异常。
static func unordered(Exhaustiveness, (UnorderedVerifier) -> Unit)
public static func unordered(exhaustive: Exhaustiveness, collectStatements: (UnorderedVerifier) -> Unit): Unit
功能:此函数支持验证“验证语句”是否被执行或执行的次数是否符合定义,并且不校验执行顺序。默认情况下,“验证语句”的执行次数为至少一次。 传入列表中的“验证语句”必须是不相交的(即当单个调用行为,可以匹配多个“验证语句”时,将抛出异常)。 “验证语句”通过入参中的闭包动态增加。
参数:
- collectStatements: (UnorderedVerifier) ->Unit - 支持可动态增加“验证语句”的闭包。
- exhaustive: Exhaustiveness - 验证模式。
异常:
- VerificationFailedException - 验证不通过时,抛出异常。
static func unordered(Exhaustiveness, Array<VerifyStatement>)
public static func unordered(exhaustive: Exhaustiveness, statements: Array<VerifyStatement>): Unit
功能:此函数支持验证“验证语句”是否被执行或执行的次数是否符合定义,并且不校验执行顺序。默认情况下,“验证语句”的执行次数为至少一次。 传入列表中的“验证语句”必须是不相交的(即当单个调用行为,可以匹配多个“验证语句”时,将抛出异常)。
参数:
- statements: Array<VerifyStatement> - 待验证的多条“验证语句”,变长参数语法支持参数省略
[]。 - exhaustive: Exhaustiveness - 验证模式。
异常:
- VerificationFailedException - 验证不通过时,抛出异常。
class VerifyStatement
public class VerifyStatement {}
功能:此类型表示对“桩签名”在验证范围内的单个验证验证语句(即上文中的“验证语句”),提供了成员函数指定“桩签名”的执行次数。
该类型的对象仅可通过 @Called 宏调用表达式创建。
对一个对象连续调用多个成员函数没有意义,并且会抛出异常。即,执行次数仅可被指定一次。
当未调用成员函数指定执行次数时,将基于语句所在的验证动作类型定义默认的执行次数验证值。例如在 Verify.ordered() 中的“验证语句”默认为验证执行一次。
func atLeastOnce()
public func atLeastOnce(): VerifyStatement
功能:指定此“验证语句”验证在验证范围内“桩签名”最少被执行一次。
返回值:
- VerifyStatement - 返回对象自身。
异常:
- MockFrameworkException - 当对象已被指定过执行次数或已被传入过“验证动作”中时,将抛出异常。
func atLeastTimes(Int64)
public func atLeastTimes(minTimesExpected: Int64): VerifyStatement
功能:指定此“验证语句”验证在验证范围内“桩签名”最少执行指定的次数。
参数:
- minTimesExpected: Int64 - 预期验证的执行最少次数。
返回值:
- VerifyStatement - 返回对象自身。
异常:
- MockFrameworkException - 当对象已被指定过执行次数或已被传入过“验证动作”中时,将抛出异常。
- IllegalArgumentException - 当作为
minTimesExpected参数传递的数字为负数时,抛出异常。
func once()
public func once(): VerifyStatement
功能:指定此“验证语句”验证在验证范围内“桩签名”仅被执行一次。
返回值:
- VerifyStatement - 返回对象自身。
异常:
- MockFrameworkException - 当对象已被指定过执行次数或已被传入过“验证动作”中时,将抛出异常。
func times(Int64)
public func times(expectedTimes: Int64): VerifyStatement
功能:指定此“验证语句”验证在验证范围内“桩签名”被执行指定次数。
参数:
- expectedTimes: Int64 - 预期验证的执行次数。
返回值:
- VerifyStatement - 返回对象自身。
异常:
- MockFrameworkException - 当对象已被指定过执行次数或已被传入过“验证动作”中时,将抛出异常。
- IllegalArgumentException - 当作为
expectedTimes参数传递的数字为负数时,抛出异常。
func times(Int64, Int64)
public func times(min!: Int64, max!: Int64): VerifyStatement
功能:指定此“验证语句”验证在验证范围内“桩签名”的执行次数在指定范围内。
参数:
返回值:
- VerifyStatement - 返回对象自身。
异常:
- MockFrameworkException - 当对象已被指定过执行次数或已被传入过“验证动作”中时,将抛出异常。
- IllegalArgumentException - 当传入的
min或max参数为负数时,抛出异常。
枚举
enum Exhaustiveness
public enum Exhaustiveness {
Exhaustive | Partial
}
功能:此枚举类型用于指定 unordered 函数的验证模式,包含两种模式。
Exhaustive 模式要求对于验证范围内的所有桩签名,均需在验证动作中定义。
Partial 模式的要求较松,可以忽略“桩签名”在验证范围内未被验证动作定义的执行行为。
举例来说:
for (i in 0..6) {
foo.bar(i % 3)
}
// 此处验证动作将抛出异常,因为 foo.bar()在验证范围内一共执行了 6 次,而此处的验证动作仅指定了 4 次执行行为。
Verify.unordered(
@Called(foo.bar(1)).times(2),
@Called(foo.bar(2)).times(2)
)
// 此处验证动作可以成功,指定了 Partial 模式后,2 次未在验证动作中定义的执行行为将被忽略。
Verify.unordered(Partial,
@Called(foo.bar(1)).times(2),
@Called(foo.bar(2)).times(2)
)
Exhaustive
Exhaustive
功能:要求在验证范围内的每一次“桩签名”的调用均需在验证动作中被定义。
Partial
Partial
功能:允许验证范围内存在未在验证动作中被定义的“桩签名”的调用行为。
enum MockSessionKind
public enum MockSessionKind {
| Forbidden
| Stateless
| Verifiable
}
功能:控制允许在 MockSession 使用的桩的类型。
只能验证在 Verifiable 的 Session 中创建的桩的期望。
Forbidden
功能:不允许使用桩。
Stateless
功能:只允许无状态的桩。 不允许本质上有状态的操作,例如 returnsConsequively 和基数说明符( cardinality specifier, 指定预期执行次数的表达式)。
Verifiable
功能:允许任意桩。
enum StubMode
public enum StubMode {
| ReturnsDefaults
| SyntheticFields
}
功能:控制桩的模式。
ReturnsDefaults
功能:Mock object 将为基础类型返回默认的值。用于简化 mock object 的配置步骤。
这些默认值一般为空或 0 。
支持的基础类型为:Unit, 数值类型( 如 Int64 ), option 类型, Bool, String, Array, ArrayList, HashSet, HashMap 。
SyntheticFields
功能:Mock object 会将其可变属性和字段视为可变字段。
与直接使用 SyntheticField 类似,但更简洁。
读取未初始化的字段将导致错误。
异常类
class ExpectationFailedException
public open class ExpectationFailedException <: PrettyException {}
功能:在测试执行期间违反了 mock 配置期间设置的一个或多个期望。
父类型:
class MockFrameworkException
public class MockFrameworkException <: PrettyException {}
功能:框架异常信息,用户使用 API 不满足框架要求时,抛出该异常。
父类型:
class MockFrameworkInternalError
public class MockFrameworkInternalError <: PrettyException {}
功能:框架异常信息,用户不应期望该异常被抛出。
父类型:
class PrettyException
public abstract class PrettyException <: Exception & PrettyPrintable {}
功能:支持 PrettyPrintable 的异常类型,可以较好得打印异常信息。
父类型:
func pprint
public func pprint(to: PrettyPrinter): PrettyPrinter
功能:支持较好得颜色打印、缩进格式打印异常信息。
参数:
- to: PrettyPrinter - 增加颜色和缩进的打印器。
返回值:
- PrettyPrinter - 增加颜色和缩进的打印器。
class UnhandledCallException
public class UnhandledCallException <: PrettyException {}
功能:提供的桩均未处理该调用。
父类型:
class UnnecessaryStubbingException
public class UnnecessaryStubbingException <: PrettyException {}
功能:指示被测试的代码从未触发桩。
父类型:
class UnstubbedInvocationException
public class UnstubbedInvocationException <: PrettyException {}
功能:未提供与此调用匹配的桩。
父类型:
class VerificationFailedException
public class VerificationFailedException <: PrettyException {}
功能:验证失败时,框架所抛出的异常。
父类型:
mock 框架入门
使用 mock 框架
mock 框架本身是仓颉标准库中单元测试的一部分。使用 mock 框架前,需将 unittest.mock.* 和 unittest.mock.mockmacro.* 导入到测试文件中。
如果使用 cjpm 工具,仅需运行 cjpm test 命令即可自动启用 mock 框架。
如果直接使用 cjc ,参见使用 cjc。
示例
常见 mock 测试用例:
- 调用mock 构造函数创建 mock/spy 对象。
- 调用配置 API设置 mock 行为。
- 使用 mock 对象替代测试代码依赖。
- (可选)调用验证 API来验证测试代码与 mock/spy 对象之间的交互。
以如下简单API为例:
public interface Repository {
func requestData(id: UInt64, timeoutMs: Int): String
}
public class Controller {
public Controller(
private let repo: Repository
) {}
public func findData(id: UInt64): ?String {
try {
return repo.requestData(id, 100)
}
catch (e: TimeoutException) {
return None
}
}
}
public class TimeoutException <: Exception {}
如果 Repository 实现不理想,比如可能包含复杂的依赖关系,实现在其他包中,或者测试太慢,mock 框架可以在不创建依赖的情况下测试 Controller 。
测试 findData 方法:
//导入mock框架包
import std.unittest.mock.*
import std.unittest.mock.mockmacro.*
@Test
class ControllerTest {
let testId: UInt64 = 100
let testResponse = "foo"
@TestCase
func testFindSuccessfully() {
// 只需要创建mock,不用创建真正的Repository
let repository = mock<Repository>()
// 使用@On宏配置testData行为
@On(repository.requestData(testId, _)).returns(testResponse)
// 创建真正的Controller测试以便测试实际的实现
let controller = Controller(repository)
// 运行测试代码
let result = controller.findData(testId)
// 对结果运行断言
@Assert(result == Some(testResponse))
}
@TestCase
func testTimeout() {
let repository = mock<Repository>()
// 设置getData抛出异常
@On(repository.requestData(testId, _)).throws(TimeoutException())
let controller = Controller(repository)
// 底层实现抛出异常时,测试行为
let result = controller.findData(testId)
// 对结果运行断言
@Assert(result == None)
}
}
mock 基础概念及用法
创建 mock 对象
mock 构造函数可以通过调用 mock<T> 和 spy<T> 函数来创建两种对象:mock和spy,其中 T 表示被 mock 的类或接口。
public func mock<T>(): T
public func spy<T>(objectToSpyOn: T): T
mock 作为骨架对象,默认不对成员进行任何操作。
spy 作为一种特殊的 mock 对象用于封装某个类或接口的当前实例。默认情况下,spy 对象将其成员调用委托给底层对象。 其他方面,spy 和 mock 对象非常相似。
只有类(包括 final 类和 sealed 类)和接口支持通过这种方式 mock 。
参阅顶级和静态声明 了解如何 mock 顶级和静态声明。
配置 API
配置 API 是框架的核心,可以定义 mock/spy 对象成员(或顶层/静态声明)的行为(或重新定义 spy 对象(或顶层/静态声明))。
配置 API 的入口是 @On 宏调用。
@On(storage.getComments(testId)).returns(testComments)
示例中,如果 mock 对象 storage 接收到 getComments 方法的调用,并且指定了参数 testId ,则返回 testComment 。
如上行为即为打桩,桩(Stub, 模拟还未实现或无法在测试环境中执行的组件)需在测试用例主体内部先定义。
如下声明类型可以被打桩:
- 类和接口的实例成员(包括 final 成员)
- 静态函数、属性和字段
- 顶层函数和变量
以下声明不能打桩:
- 扩展成员
- Foreign 函数
- 局部函数和变量
- 构造器
- 常量
- 任意私有声明
一个完整的桩声明包含以下部分:
@On宏调用中描述的桩签名。- 用于描述桩行为的操作。
- (可选)用于设置预期的基数说明符( cardinality specifier, 指定预期执行次数的表达式)。
- (可选)续体( continuation, 支持链式调用的表达式)。
mock 框架拦截匹配桩签名的调用,并执行桩声明中指定的操作。
顶级和静态声明
与类或接口的成员不同,要打桩静态成员或顶层函数或变量时,不需要创建模拟对象。这些声明应该直接使用配置 API (例如 @On 宏)进行打桩。
如下是一个为顶层函数打桩的示例:
package catalog
public class Entry {
init(let id: Int64, let title: String, let description: String) {}
statuc func parse() { ... }
}
public func loadLastEntryInCatalog(): Entry {
let resp = client.get("http://mycatalog.com/api/entries/last")
let buf = Array<UInt8>(50, repeat: 0)
let len = resp.body.read(buf)
return Entry.parse(String.fromUtf8(buf[..len]))
}
public func drawLastEntryWidget() {
let lastEntry = loadLastEntryInCatalog()
// drawing...
}
package test
@Test
class RightsTest {
@TestCase
func removeLastEntry() {
@On(loadLastEntryInCatalog()).returns(Entry(1, "Test entry", "Test description"))
drawLastEntryWidget()
}
}
桩签名
桩签名定义了与特定调用子集匹配的一组条件,包括以下部分:
- mock/spy 对象的引用,必须是单个标识符。(独立声明(顶层或静态函数、变量)不需要此部分)
- 成员以及独立声明的调用。
- 特定格式的参数调用,参见参数匹配器。
签名可以匹配以下实体:
- 方法
- 属性 getter
- 属性 setter
- 字段读操作
- 字段写操作
- 静态函数
- 静态属性 getter
- 静态 属性 setter
- 静态字段读操作
- 静态字段写操作
- 顶层函数
- 顶层字段读操作
- 顶层字段写操作
只要对应声明被调用,并且所有参数(若有)都与相应的参数匹配器匹配时,桩签名就会匹配调用。
方法的桩的签名结构:<mock object name>.<method name>(<argument matcher>*)。
@On(foo.method(0, 1)) // 带参数 0 和 1 的方法调用
@On(foo.method(param1: 0, param2: 1)) // 带命名参数的方法调用
当桩属性 getter/setter 或字段读/写操作时,使用 <mock object name>.<property or field name> 或 <mock object name>.<property or field name> = <argument matcher> 。
@On(foo.prop) // 属性 getter
@On(foo.prop = 3) // 参数为 3 的属性 setter
对于顶层函数和静态函数,签名是类似的:
- 顶层函数:
<function name>(<argument matcher>*) - 静态函数:
<class name>.<static method name>(<argument matcher>*)
顶层变量和静态属性或字段的签名如下:
- 顶层变量:
<top-level variable name>或<top-level variable name> = <argument matcher> - 静态属性或字段:
<class name>.<static property/field name>或<class name>.<static property/field name> = <argument matcher>
对运算符函数打桩时,运算符的接收者必须是对 mock/spy 对象的单个引用,而运算符的参数必须是参数匹配器。
@On(foo + 3) // 'operator func +',参数为 3
@On(foo[0]) // 'operator func []',参数为 0
参数匹配器
每个桩签名必须包含所有参数的参数匹配器。单个参数匹配器定义了一个条件,用于接受所有可能参数值的某个子集。
每个匹配器都是通过调用 Matchers 类的静态方法来定义的。
例如 Matchers.any() 是一个允许任何参数的有效匹配器。为了方便起见,提供省略 Matcher. 前缀的语法糖。
预定义的匹配器包括:
| 匹配器 | 描述 | 语法糖 |
|---|---|---|
| any() | 任何参数 | _ 符号 |
eq(value: Equatable) | value 结构相等( structural equality ,对象的值相等,不一定内存相同)的参数 | 允许使用单个 identifier 和常量字面量 |
same(reference: Object) | reference 引用相等(referential equality, 对象的引用相等,内存相同)的参数 | 允许单个identifier |
ofType<T>() | 仅匹配 T 类型的值 | - |
argThat(predicate: (T) -> Bool) | 仅匹配由 predicate 筛选出的 T 类型的值 | - |
| none() | 匹配选项类型的 None 值 | - |
如果使用单个标识符作为参数匹配器,则优先选择结构相等的参数。
如果方法有默认参数,并且没有显式指定该参数,则使用 any() 匹配器。
示例:
let p = mock<Printer>() // 假设print采用ToString类型的单个参数。
@On(p.print(_)) // 可以使用“_”特殊字符代替 any() 。
@On(p.print(eq("foo"))) // 只匹配“foo”参数。
@On(p.print("foo")) // 常量字符串可以省略显式匹配器。
let predefined = "foo" // 可以传递单个标识符,而不是参数匹配器。
@On(p.print(predefined)) // 如果类型相等,则使用结构相等来匹配。
@On(p.print(ofType<Bar>())) // 仅匹配Bar类型的参数。
// 对于更复杂的匹配器,鼓励使用以下模式。
let hasQuestionMark = { arg: String => arg.contains("?") }
@On(p.print(argThat(hasQuestionMark))) // 只匹配包含问号的字符串。
正确选择函数重载依赖仓颉类型推断机制。可以使用 ofType 来解决与类型推断有关的编译时问题。
重要规则:函数调用作为参数匹配器时,会视为对匹配器的调用。
@On(foo.bar(calculateArgument())) // 不正确,calculateArgument()不是匹配器。
let expectedArgument = calculateArgument()
@On(foo.bar(expectedArgument)) // 正确,只要 'expectedArgument' 是可等价的和/或引用类型。
操作 API
mock 框架提供 API 来指定桩操作。触发桩后,打桩声明会执行指定的操作。如果调用与相应的 @On 宏调用指定的签名匹配,则会触发桩。
每个桩函数必须指定一个操作。
@On 宏调用返回的 ActionSelector 子类型会定义可用操作。操作列表取决于所打桩的实体。
通用(操作)
适用于所有桩的操作。
throws(exception: Exception):抛出exception。throws(exceptionFactory: () -> Exception):调用exceptionFactory去构造桩触发时抛出的异常。fails():如果触发了桩,则测试失败。
注意:
throws用于测试桩声明抛出异常时的系统行为。fails用于测试桩声明是否未被调用。
@On(service.request()).throws(TimeoutException())
函数和属性/字段 Getter 和顶层变量读操作
R 表示对应成员的返回类型。
returns():不做任何操作并返回(),仅当R为Unit时可用。returns(value: R):返回value。returns(valueFactory: () -> R):调用valueFactory去构造桩触发时抛出的异常。returnsConsecutively(values: Array<R>),returnsConsecutively(values: ArrayList<R>):触发桩时,返回values中的下一个元素。
@On(foo.bar()).returns(2) // 返回 0
@On(foo.bar()).returnsConsecutively(1, 2, 3) // 依次返回 1,2,3
属性/字段 Setter 和顶层变量写操作
doesNothing():忽略调用,不做任何操作。类似于返回 Unit 的函数的returns()。 更多信息详见这里。
spy 操作
对于 spy 对象,可以使用其他操作来委托监控实例。
callsOriginal():调用原始方法。getsOriginal():调用原始属性 getter 或获取原始实例中的字段值。setsOriginal():调用原始属性 setter 或设置原始实例中的字段值。
预期
定义桩时会隐式或显式地向桩附加预期。桩可以定义期望的基数。操作( fails 和 returnsConcesecutively 除外)返回CardinalitySelector 的实例,该实例可以使用基数说明符自定义预期。
CardinalitySelector 定义了如下函数:
once()atLeastOnce()anyTimes()times(expectedTimes: Int64)times(min!: Int64, max!: Int64)atLeastTimes(minTimesExpected: Int64)
anyTimes 说明符用于提升预期,即如果桩从未被触发,测试也不会失败。其他说明符都暗示了测试代码中特定桩的调用次数上下限。只要桩被触发的次数比预期的多,测试就会立即失败。下限在测试代码执行完毕后进行检查。
示例:
import std.unittest.mock.*
import std.unittest.mock.mockmacro.*
class Foo {
func bar() { }
}
@Test
func tooFewInvocations() {
let foo = mock<Foo>()
@On(foo.bar()).returns().times(2)
foo.bar()
}
输出:
Expectation failed
Too few invocations for stub foo.bar() declared at example_test.cj:9.
Required: exactly 2 times
Actual: 1
Invocations handled by this stub occured at:
example_test.cj:6
如果没有自定义预期,mock框架使用默认预期:
| 操作 | 默认期望基数 | 允许自定义基数 |
|---|---|---|
| fails | 不可调用 | 否 |
| returns | atLeastOnce | 是 |
| returnsConsecutively | times(values.size) | 否 |
| throws | atLeastOnce | 是 |
| doesNothing | atLeastOnce | 是 |
| (calls/gets/sets)Original | atLeastOnce | 是 |
桩链
returnsConsecutively 操作,once 和 times(n) 基数说明符返回一个续体实例。顾名思义,续体表示可以继续使用链,即指定某操作在前一个操作完全完成时立即执行。
续体本身只提供了一个返回新 ActionSelector 的 then() 函数。链上的所有操作都适用相同的规则。如果调用了 then() ,则必须指定新的操作。
总预期为各个链预期之和。如果在测试中指定了一个复杂的链,那么链的所有部分都会被触发。
@On(foo.bar()).returnsConsecutively(1, 2, 3, 4)
//同下
@On(foo.bar()).returnsConsecutively(1, 2).then().returnsConsecutively(3, 4)
// 指定了一个桩,总共必须调用 NUM_OF_RETRIES 次
@On(service.request()).throws(TimeoutException()).times(NUM_OF_RETRIES - 1). // 请求会先超时几次
then().returns(response).once() // 第一个成功响应之后,停止发送请求
使用 spy 和 mock 对象
spy 对象和 mock 对象在配置上是类似的,只不过 spy 对象监控的是当前实例。
主要区别如下:成员调用没有触发任何桩时,spy 对象调用底层实例的原始实现,mock 对象抛出运行时错误(并且测试失败)。
mock 对象无需创建真正的依赖来测试 API ,只需配置特定测试场景所需的行为。
spy 对象支持重写真实实例的可观察行为。只有通过 spy 对象引用的调用才会被拦截。创建 spy 对象对原始 spy 实例的引用无影响。spy 调用自己的方法不会被拦截。
let serviceSpy = spy(service)
// 模拟超时,继续使用真正的实现
@On(serviceSpy.request()).throws(TimeoutException()).once().then().callsOriginal()
// 测试代码必须使用'serviceSpy'引用
注意:
静态成员或顶级函数/变量的打桩行为类似于 spy,即对于未打桩的声明,将调用原始成员或原顶级函数/变量,而不是像 mock 中那样抛出异常。
mock 依赖
接口始终可以被 mock 。从另一个包 mock 一个类时,类本身和它的超类必须按特定方式编译, 即只能 mock 预编译库(如 stdlib )中的接口,不能 mock 类。
使用 cjc 编译
对于 cjc 来说,mock 是通过 --mock 标志来控制的。
如果想 mock 特定包中的类 p ,添加 --mock=on 标志到 cjc 进行调用。
说明:
在编译依赖
p的包时,也必须添加此标志。
在测试中使用mock对象( cjc--test )不需要额外的标志。
使用 cjpm 编译
cjpm 会自动检测 mock 使用,并生成正确的 cjc 调用,确保可以从任何从源代码编译的包中 mock 类。
还可以使用 cjpm 配置文件控制哪些包支持 mock 。
桩使用指南
mock/spy 对象和桩的使用方法多种多样。本文介绍了不同的模式和用例,便于用户编写 mock 框架的可维护且简洁的测试用例。
桩的工作原理
桩 通过在测试用例内部调用 @On 宏来声明,该声明在特定测试用例执行完成之前有效。多个测试用例之间可以共享桩。
mock 框架处理 mock/spy 对象成员(或静态成员或顶层函数或顶层变量)调用时的顺序如下:
- 查找特定声明的桩。后声明的桩优先于之前声明的桩。测试用例主体内部声明的桩优先于共享桩。
- 应用每个桩的参数匹配器。如果所有参数都成功匹配,则执行该桩定义的操作。
- 如果找不到桩,或者没有与实际参数匹配的桩,则应用默认行为:
- 对于 mock 对象,上报未打桩调用错误;
- 对于 spy 对象,调用被监视实例的原始成员;
- 对于静态成员或顶层函数或顶层变量,调用原始对应声明。
无论是否为单个成员定义了多个桩,每个桩都有自己的预期,需要满足这些预期才能通过测试。
@On(foo.bar(1)).returns(1)
@On(foo.bar(2)).returns(2)
foo.bar(2)
// 第一个桩已定义但从未使用,测试失败
重新定义桩
如果希望在测试中更改桩的行为,可以重新定义桩。
@On(service.request()).returns(testData)
// 使用服务
@On(service.request()).throws(Exception())
// 测试服务开始失败时会发生什么事情
同一声明定义多个桩
根据不同参数,可以使用多个桩来定义不同的行为。
示例:
@On(storage.get(_)).returns(None) // 1
@On(storage.get(TEST_ID)).returns(Some(TEST_DATA)) // 2
示例中,storage 为除 TEST_ID 之外的所有参数返回 None 。
如果从未使用 TEST_ID 参数调用 get ,则测试失败,因为桩 2 未使用。如果始终使用 TEST_ID 参数调用 get ,则测试失败,因为桩 1 未使用。这些限制确保测试代码是纯净的,让开发人员知道桩何时变为未使用。如果用例不需要此功能,则使用 anyTimes() 基数说明符来提升这些预期。
// 实现经常更改,但不希望测试中断
// 使用 anyTimes 提升与测试本身无关的预期
@On(storage.get(_)).returns(None).anyTimes()
@On(storage.get(TEST_ID)).returns(Some(TEST_DATA)) // 测试必须调用正在测试的内容
鉴于桩优先级是从下到上,以下用法都不正确。
@On(storage.get(TEST_ID)).returns(Some(TEST_DATA)) // 不正确,这个桩永远不会被触发
@On(storage.get(_)).returns(None) // 在上面的桩始终会被隐藏
您还可以使用预期来检查调用的参数。
let renderer = spy(Renderer())
@On(renderer.render(_)).fails()
let isVisible = { c: Component => c.isVisible }
@On(renderer.render(argThat(isVisible))).callsOriginal() // 只允许可见的组件
共享 mock 对象和桩
测试需要大量使用 mock 对象时可以多个测试用例共享 mock 对象和/或桩。 可以在任何位置创建 mock 或 spy 对象。然而,如果误将 mock 对象从一个测试用例泄漏到另一个测试用例,可能导致顺序依赖问题或测试不稳定。因此,不建议这样操作,mock 框架也会检测这类情况。 在同一测试类下的测试用例之间共享 mock 或 spy 对象时,可以将它们放在该类的实例变量中。
桩声明中隐含了预期,因此更难处理共享桩。测试用例之间不能共享预期。 只有2个位置可以声明桩:
- 测试用例主体(无论是
@Test函数还是@Test类中的@TestCase):检查预期。 - 在
@Test类中的beforeAll中:在测试用例之间共享桩。这样的桩不能声明预期,预期也不会被检查。不允许使用基数说明符。只允许returns(value)、throws(exception)、fails()、callsOriginal()等无状态操作。可以将这些桩视为具有隐式anyTimes()基数。
如果测试用例的预期相同,则可以在测试用例主体中提取和调用函数(测试类中非测试用例的成员函数)。
使用 beforeAll :
@Test
class TestFoo {
let foo = mock<Foo>()
// 单元测试框架会在执行测试用例之前调用以下内容
public func beforeAll(): Unit {
// 在所有测试用例之间共享默认行为
// 此桩无需在每个测试用例中使用
@On(foo.bar(_)).returns("default")
}
@TestCase
func testZero() {
@On(foo.bar(0)).returns("zero") // 本测试用例中需要使用此桩
foo.bar(0) // 返回 "zero"
foo.bar(1) // 返回 "default"
}
@TestCase
func testOne() {
@On(foo.bar(0)).returns("one")
foo.bar(0) // 返回 "one"
}
}
使用函数:
@Test
class TestFoo {
let foo = mock<Foo>()
func setupDefaultStubs() {
@On(foo.bar(_)).returns("default")
}
@TestCase
func testZero() {
setupDefaultStubs()
@On(foo.bar(0)).returns("zero")
foo.bar(0) // 返回"zero"
foo.bar(1) // 返回"default"
}
@TestCase
func testOne() {
setupDefaultStubs()
@On(foo.bar(0)).returns("zero")
foo.bar(0) // 返回"zero"
// 预期失败,桩已声明但从未使用
}
}
不要在测试类构造函数中声明桩。无法保证何时调用测试类构造函数。
捕获参数
mock 框架使用 captor(ValueListener) 参数匹配器捕获参数来检查传递到桩声明的实际参数。只要触发了桩,ValueListener 就会拦截相应的参数,并检查参数和/或添加验证参数。
每次调用时,还可以使用 ValueListener.onEach 静态函数来验证某个条件。接受 lambda 后,触发桩时都会调用这个 lambda 。lambda 用于接收参数的值。
let renderer = spy(TextRenderer())
let markUpRenderer = MarkupRenderer(renderer)
// 创建验证器
let validator = ValueListener.onEach { str: String =>
@Assert(str == "must be bold")
}
// 使用 'capture' 参数匹配器绑定参数到验证器
@On(renderer.renderBold(capture(validator))).callsOriginal() // 如果从来没有调用过,则测试失败
markUpRenderer.render("text inside tag <b>must be bold</b>")
另外 ValueListener 还提供了 allValues() 和 lastValue() 函数来检查参数。模式如下:
//创建捕获器
let captor = ValueListener<String>.new()
//使用'capture'参数匹配器绑定参数到捕获器
@On(renderer.renderBold(capture(captor))).callsOriginal()
markUpRenderer.render("text inside tag <b>must be bold</b>")
let argumentValues = captor.allValues()
@Assert(argumentValues.size == 1 && argumentValues[0] == "must be bold")
argThat 匹配器是一个结合了参数过滤和捕获的重载函数。argThat(listener, filter) 接受 ValueListener 实例和 filter 谓词。listener 只收集通过 filter 检查的参数。
let filter = { arg: String => arg.contains("bold") }
let captor = ValueListener<String>.new()
// 失败,除非参数被拦截,但下面已经声明了桩
@On(renderer.renderBold(_)).fails()
// 只收集包含 "bold" 的字符串
@On(renderer.renderBold(argThat(captor, filter))).callsOriginal()
markUpRenderer.render("text inside tag <b>must be bold</b>")
// 可以使用 'captor' 对象检查所有过滤参数
@Assert(captor.lastValue() == "must be bold")
参数捕获器可以与 mock 和 spy 对象一起使用。但是,在 @Called 宏中不允许使用此类参数匹配器。
自定义和使用参数匹配器
为了避免重复使用相同的参数匹配器,可以自定义参数匹配器。
如下示例为在测试用例之间共享匹配器:
@On(foo.bar(oddNumbers())).returns("Odd")
@On(foo.bar(evenNumbers())).returns("Even")
foo.bar(0) // "Even"
foo.bar(1) // "Odd"
由于每个匹配器都只是 Matchers 类的静态函数,因此可以使用扩展来自定义参数匹配器。新参数匹配器需要调用现有的(实例)。
extend Matchers {
static func evenNumbers(): TypedMatcher<Int> {
argThat { arg: Int => arg % 2 == 0}
}
static func oddNumbers(): TypedMatcher<Int> {
argThat { arg: Int => arg % 2 == 1}
}
}
函数参数匹配器可以包含参数。
extend Matchers {
// 只接受Int参数。
static func isDivisibleBy(n: Int): TypedMatcher<Int> {
argThat { arg: Int => arg % n == 0}
}
}
大多数匹配器函数都指定了返回类型 TypedMatcher<T> 。这样的匹配器只接受类型为 T 。在桩声明中使用参数匹配器调用时,类型为 T 的值应该是被打桩函数或属性 setter 的有效参数。换句话说,类型 T 应该是参数子类型或与参数实际类型相同。
设置属性和字段和顶层变量
字段和属性和顶层变量打桩的方式与函数相同,可以依相同操作来配置返回值。
setter 类似于返回 Unit 的函数。特殊操作 doesNothing() 可用于 setter。
可变属性打桩的常用模式如下:
@On(foo.prop).returns("value") // 配置getter
@On(foo.prop = _).doesNothing() // 忽略setter调用
极少场景下,我们期望可变属性的行为与字段的行为相同。要创建合成字段(框架生成的字段),请使用 SyntheticField.create 静态函数。合成字段存储由 mock 框架来管理。适用于 mock 含有可变属性和字段的接口或抽象类的场景。
执行 getsField 和 setsField 桩操作将字段或顶层变量绑定到特定的调用,这些操作可以将预期配置为任何其他操作。
interface Foo {
mut prop bar: String
}
@Test
func test() {
let foo = mock<Foo>()
let syntheticField = SyntheticField.create(initialValue: "initial")
@On(foo.bar).getsField(syntheticField) // 对属性的读取访问即为读取合成字段
@On(foo.bar = _).setsField(syntheticField) // 为属性写入新值
// 此时'bar'属性表现为字段
}
注意:
如果多个测试用例之间共享
SyntheticField对象,则该字段本身的值会在每个测试用例之前重置为initialValue,避免在测试之间共享可变状态。
桩的模式
通常,当一些调用匹配不到任何桩时将抛出异常。但是,对于某些常见情况,mock 对象可以配置增加默认行为,此时,当匹配不到任何桩时,将执行默认行为。这通过启用桩模式来实现。
有两种可用的模式 ReturnsDefaults 和 SyntheticFields 。这些模式通过枚举类型 StubMode 表示。可以通过在创建 mock 对象时将其传递给 mock 函数来为特定的 mock 对象启用桩模式。
public func mock<T>(modes: Array<StubMode>): T
桩模式可用于在配置 mock 对象时减少代码,并且它们可以与显式桩自由组合。显式的桩始终优先于其默认行为。
注意:
使用桩模式不会对 mock 对象的成员强加任何期望。 当用例是检查是否仅调用 mock 对象的某些特定成员,则应谨慎使用桩模式。被测对象的行为可能会以不期望的方式发生变化,但测试仍可能通过。 当前桩模式不支持打桩静态成员和顶级函数/变量。
ReturnsDefaults 模式
在此模式下,当成员的返回类型在如下表格中时,无需显式配置桩,即可调用。
let foo = mock<Foo>(ReturnsDefaults)
@Assert(foo.isPretty(), false)
此类成员返回的默认值也如如下表格所示。
| 类型 | 默认值 |
|---|---|
| Bool | false |
| numbers | 0 |
| String | empty string |
| Option | None |
| ArrayList, HashSet, Array | new empty collection |
| HashMap | new empty map |
ReturnsDefaults 模式仅对如下成员生效:
- 返回值为支持类型(如上表)的成员函数。
- 类型为支持类型(如上表)的属性读取器和字段。
SyntheticFields 模式
SyntheticFields 模式可简化对 SyntheticField 的配置动作,详见 设置属性和字段和顶层变量 章节。
SyntheticFields 将通过 mock 框架为所有属性和字段隐式创建对应类型的合成字段。但是,这些字段只能在被赋值后读取。仅对可变属性和字段生效。
let foo = mock<Foo>(SyntheticFields)
// can simply assign a value to a mutable property
foo.bar = "Hello"
@Assert(foo.bar, "Hello")
赋给属性和字段的值仅在相应的测试用例中可见。
当同时启用 SyntheticFields 和 ReturnsDefaults 时,赋的值优先于默认值。但是,只要字段或属性尚未被赋值,就可以使用默认值。
let foo = mock<Foo>(ReturnsDefaults, SyntheticFields)
@Assert(foo.bar, "")
foo.bar = "Hello"
@Assert(foo.bar, "Hello")
mock 框架验证 API
验证 API 是 mock 框架的一部分,其功能如下:
- 验证是否进行了某些调用。
- 验证特定调用的次数。
- 验证是否使用特定参数进行调用。
- 验证调用是否按特定顺序进行。
验证通过检查在执行测试期间构建的调用日志来运行断言。调用日志涵盖让 mock 和 spy 对象(以及静态成员和顶层函数和顶层变量)在测试中可访问的所有调用。只能验证在 mock/spy 对象(以及静态成员和顶层函数和顶层变量)上进行的调用。
Verify 类是验证 API 的入口。
@Called 宏用于构建关于代码的断言。
@Called 宏调用构造了一个 验证语句 ,即根据调用日志检查代码的单个断言。
Verify 类本身是静态方法的集合。诸如 that 、 ordered 、 unordered 等方法可构造验证块。
示例
let foo = mock<Foo>()
//配置foo
@On(foo.bar()).returns()
foo.bar()
Verify.that(@Called(foo.bar())) // 验证bar至少被调用一次
验证语句和 @Called 宏
验证语句由 VerifyStatement 类表示。 VerifyStatement 实例由 @Called 宏创建。
@Called 宏调用接受桩签名,类似于 @On 宏,并且适用参数匹配器的规则。
示例:
@Called(foo.bar(1, _)) // 匹配 bar 方法调用的验证语句,其中第一个参数为 '1'
@Called(Foo.baz) // 匹配 baz 静态属性 getter 调用的验证语句
VerifyStatement 类提供的 API 类似于桩配置时可用的基数说明符。
基数函数为:
once()atLeastOnce()times(expectedTimes: Int64)times(min!: Int64, max!: Int64)atLeastTimes(minTimesExpected: Int64)never()
调用这些函数会返回相同的 VerifyStatement 实例。同一语句不能重置基数,且必须在语句传递到验证块生成器函数之前设置基数。如果没有显式设置基数,则使用默认基数。
Verify.that(@Called(foo.bar()).atLeastOnce())
Verify.that(@Called(foo.bar()).once())
验证块
验证块通常包含一个或多个验证语句,且检查块中的语句会构成更复杂的断言。
在调用验证块时会立即验证,不验证之后发生的任何调用。
验证块不会改变调用日志的状态:日志中的每个调用都可以被任意数量的块检查。独立检查各个块,前后块之间没有依赖关系。除非在块之间发生了一些调用,或者手动清除了调用日志,否则调用验证块的顺序并不重要。
验证语句本身不执行任何类型的验证,必须传递到验证块中进行验证。
单个验证块仅检查在块内验证语句中提到的 mock/spy 对象上的调用,忽略对其他对象的调用。
Verify 类包含几个构建验证块的静态方法。有序验证块用于检查调用的确切顺序。无序验证块只验证调用的次数。
有序
如需检查一个或多个对象的调用顺序,使用 ordered 验证块生成器。
ordered 静态函数接收一个验证语句数组。
for (i in 0..4) {
foo.bar(i % 2)
}
Verify.ordered(
@Called(foo.bar(0)),
@Called(foo.bar(1)),
@Called(foo.bar(0)),
@Called(foo.bar(1))
)
允许检查多个对象的调用顺序。
for (i in 0..4) {
if (i % 2 == 0) {
fooEven.bar(i)
}
else {
forOdd.bar(i)
}
}
Verify.ordered(
@Called(fooEven.bar(0)),
@Called(fooOdd.bar(1)),
@Called(fooEven.bar(2)),
@Called(fooOdd.bar(3)),
)
有序验证的默认基数说明符是 once() 。如有需要,可使用其他基数说明符。
for (i in 0..4) {
foo1.bar(i)
}
for (i in 0..4) {
foo2.bar(i)
}
Verify.ordered(
@Called(foo1.bar(_).times(4)),
@Called(foo2.bar(_).times(4))
)
对于有序验证,须列出对(块中提到的) mock/spy 对象的所有调用。任何未列出的调用都会导致验证失败。
foo.bar(0)
foo.bar(10)
foo.bar(1000)
Verify.ordered(
@Called(foo.bar(0)),
@Called(foo.bar(10))
)
输出:
验证失败
以下调用未匹配到任何语句:
foo.bar(...) at example_test.cj:6
无序
无序验证只检查其验证语句的调用次数。
对于无序验证,除非显式指定,否则使用 atLeastOnce() 基数,即检查至少进行了一次的调用。
for (i in 0..4) {
foo.bar(i % 2)
}
//验证是否至少调用了一次使用参数0和参数1的bar
Verify.unordered(
@Called(foo.bar(0)),
@Called(foo.bar(1))
)
//验证是否调用了两次使用参数0和参数1的bar
Verify.unordered(
@Called(foo.bar(0)).times(2),
@Called(foo.bar(1)).times(2)
)
//验证是否总共调用了四次bar
Verify.unordered(
@Called(foo.bar(_)).times(4)
)
无序验证包括 Partial 和 Exhaustive 。
默认为 Exhaustive ,需要列出验证语句所提到的 mock/spy 对象的所有调用。 Partial 只列出部分调用。
for (i in 0..4) {
foo.bar(i)
}
//失败,foo.bar()的两次调用未在块中列出
Verify.unordered(
@Called(foo.bar(0)).once(),
@Called(foo.bar(1)).once()
)
//忽略无关调用
Verify.unordered(Partial,
@Called(foo.bar(0)).once(),
@Called(foo.bar(1)).once()
)
动态构建验证块
ordered 和 unordered 函数为接受 lambda 的重载函数。可使用 checkThat(statement: VerifyStatement) 函数动态添加语句。
示例:
let totalTimes = 40
for (i in 0..totalTimes) {
foo.bar(i % 2)
}
Verify.ordered { v =>
for (j in 0..totalTimes) {
v.checkThat(@Called(foo.bar(eq(j % 2))))
}
}
其他 API
另外,Verify 类还提供了以下工具。
- that(statement: VerifyStatement) 为 Verify.unordered(Paritial, statement) 的别名,用于检查单个语句,不需要列出对应 mock/spy 对象的所有调用。
- noInteractions(mocks: Array
clearInvocationLog()将日志重置为空状态。这会影响后面的所有验证块,但并不影响桩预期。
示例:
foo.bar()
Verify.that(@Called(foo.bar())) // OK
Verify.noInteractions(foo) // 失败,foo.bar() 调用在日志中
Verify.clearInvocationLog() // 清除日志
Verify.noInteractions(foo) // 从日志中清除所有与 foo 的交互
Verify.that(@Called(foo.bar())) // 失败
Verify 类 API
public static func that(statement: VerifyStatement): Unit
public static func unordered(
exhaustive: Exhaustiveness,
collectStatements: (UnorderedVerifier) -> Unit
): Unit
public static func unordered(
collectStatements: (UnorderedVerifier) -> Unit
): Unit
public static func unordered(statements: Array<VerifyStatement>): Unit
public static func unordered(
exhaustive: Exhaustiveness,
statements: Array<VerifyStatement>
): Unit
public static func ordered(
collectStatements: (OrderedVerifier) -> Unit
): Unit
public static func ordered(statements: Array<VerifyStatement>): Unit
public static func clearInvocationLog(): Unit
public static func noInteractions(mocks: Array<Object>): Unit
验证错误
验证失败时,会抛出 VerificationFailedException ,mock 框架会给出报告。不要捕获该异常。
失败类型如下:
- 调用次数太少或调用次数太多:调用次数与块中的语句不匹配。
- 语句不匹配:块中存在与日志中的调用不匹配的语句。
- 调用不匹配:日志中存在与块中的语句不匹配的调用。
- 意外调用:有序验证块需要的是其他的调用。
- 无用交互: noInteractions 检测到意外调用。
还有另一种失败类型不相交的语句,不一定是测试代码本身有问题。调用匹配到多个语句时,就会上报这种失败类型。在单个验证块中使用具有不相交参数匹配器的语句可能会导致此错误。不允许在语句和调用之间进行模糊匹配。
示例和模式
使用验证 API 的常见模式是验证测试代码(无论是函数、类还是整个包)与外部对象之间的交互。 如下所示:
- 创建 spy 对象。
- 将这些 spy 对象传递给测试代码。
- 验证代码和 spy 对象之间的交互。
验证调用数量
func testDataCaching() {
// 创建必要的spy或mock对象
let uncachedRepo = spy(Repository())
let invalidationTracker = mock<InvalidationTracker>()
@On(invalidationTracker.getTimestamp()).returns(0)
// 准备测试数据
let cachedRepo = CachedRepistory(uncachedRepo, invalidationTracker)
// 运行测试代码
for (i in 0..10) {
cachedRepo.get(TEST_ID)
}
// 验证得出只查询了一次基础repo,没有对未缓存repo的其他调用
Verify.unordered(Exhaustive,
@Called(uncachedRepo.get(TEST_ID)).once()
)
// 清除日志
Verify.clearInvocationLog()
// 设置其他行为
@On(invalidationTracker.getTimestamp()).returns(1)
for (i in 0..10) {
cachedRepo.get(TEST_ID)
}
// 自上次清除后只进行了一次调用
Verify.unordered(Exhaustive,
@Called(uncachedRepo.get(TEST_ID)).once()
)
}
验证带特定参数的调用
func testDrawingTriangle() {
// 创建必要的 spy 或 mock 对象
let canvas = spy(Canvas())
// 运行代码
canvas.draw(Triangle())
// 测试三角形由3条线和3个点组成
// 使用 'that' 块
Verify.that(
@Called(canvas.draw(ofType<Dot>())).times(3)
)
Verify.that(
@Called(canvas.draw(ofType<Line>())).times(3)
)
// 或者使用部分无序验证块
Verify.unordered(Partial, // 未知线条和点实际绘制的顺序
@Called(canvas.draw(ofType<Dot>())).times(3),
@Called(canvas.draw(ofType<Line>())).times(3)
)
// 使用枚举块时,必须枚举出所有调用
Verify.unordered(Exhaustive,
@Called(canvas.draw(ofType<Triangle>())).once(),
@Called(canvas.draw(ofType<Dot>())).times(3),
@Called(canvas.draw(ofType<Line>())).times(3)
)
// 验证用例从未调用入参为 Square 类型的 draw 函数
Verify.that(
@Called(canvas.draw(ofType<Square>)).never()
)
// 如果想通过更复杂的条件来区分参数
// 可以使用下面的模式
let isDot = { f: Figure =>
f is Dot // 此为更复杂的逻辑
}
Verify.that(
@Called(canvas.draw(argThat(isDot))).times(3)
)
// 注意,属于同一个块的语句必须明确只匹配了一个调用
// 以下为反例,有些调用匹配了两个语句
Verify.unordered(
@Called(canvas.draw(_)).times(7),
@Called(canvas.draw(ofType<Dot>())).times(3)
)
}
验证调用顺序
func testBuildFlight() {
let plane = spy(Plane())
FlightBuilder(plane).planFlight(Shenzhen, Shanghai, Beijing).execute()
Verify.ordered(
@Called(plane.takeOffAt(Shenzhen)),
@Called(plane.landAt(Shanghai)),
@Called(plane.takeOffAt(Shanghai)),
@Called(plane.landAt(Beijing))
)
}
预期与验证 API
配置桩时,可以设置预期和验证API覆盖测试代码的一些断言。这种情况别无他法,只能选择更能反映测试意图的方法。
一般情况下,建议避免重复验证块中的配置步骤。
let foo = mock<Foo>()
@On(foo.bar(_)).returns() // 如果从未使用此桩,测试失败
foo.bar(1)
foo.bar(2)
Verify.that(
// 不需要,自动验证
@Called(foo.bar(_)).atLeastOnce()
)
//但可以检查调用的数量和具体的参数
Verify.unordered(
@Called(foo.bar(1)).once(),
@Called(foo.bar(2)).once()
)
上面的示例可以使用预期重写:
let foo = mock<Foo>()
@On(foo.bar(1)).returns().once() // 预期只被调用一次,参数为`1`
@On(foo.bar(2)).returns().once() // 预期只被调用一次,参数为`2`
foo.bar(1)
foo.bar(2)
//如果没有桩被触发,则测试失败
std.unittest.mock.mockmacro
功能介绍
unittest.mock.mockmacro 为 mock 框架提供了用户所需的宏。
API 列表
宏
宏
@Called 宏
功能:创建一个验证语句。
@On 宏
功能:使用配置 API定义 mock/spy 对象成员的行为(或重新定义 spy 对象)。
std.unittest.testmacro
功能介绍
unittest.testmacro 为单元测试框架提供了用户所需的宏。
API 列表
宏
| 宏名 | 功能 |
|---|---|
| AfterAll | 声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在所有测试用例之后运行一次。 |
| AfterEach | 声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在每个测试用例之后运行一次。 |
| Assert | 声明 Assert 断言,测试函数内部使用,断言失败停止用例。 |
| AssertThrows | 声明预期异常的断言,测试函数内部使用,断言失败停止用例。 |
| BeforeAll | 声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在所有测试用例之前运行一次。 |
| BeforeEach | 声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在每个测试用例之前运行一次。 |
| Bench | 宏用于标记要执行多次的函数并计算该函数的预期执行时间。 |
| Configure | 为测试类或测试函数提供配置参数。它可以放置在测试类或测试函数上。 |
| CustomAssertion | @CustomAssertions 将函数指定为用户自定义断言。 |
| Expect | 声明 Expect 断言,测试函数内部使用,断言失败继续执行用例。 |
| ExpectThrows | 声明预期异常的断言,测试函数内部使用,断言失败继续执行用例。 |
| Fail | 声明预期失败的断言,测试函数内部使用,断言失败停止用例。 |
| FailExpect | 声明预期失败的断言,测试函数内部使用,断言失败继续执行用例。 |
| Measurement | 用于为性能测试指定 Measurement 实例。只能应用于标有 @Test 宏的类或顶级函数的范围内。 |
| Parallel | 可以修饰测试类。被 @Parallel 修饰的测试类中的测试用例可并行执行。 |
| PowerAssert | 检查传递的表达式是否为真,并显示包含传递表达式的中间值和异常的详细图表。 |
| Skip | 修饰已经被 @TestCase / @Bench 修饰的函数,使该测试用例被跳过。 |
| Strategy | 用于组合、映射和重用各种数据策略。 |
| Tag | @Tag 宏可以应用于 @Test 类和 @Test 或 @TestCase 函数,提供测试实体的元信息。 |
| Test | 宏应用于顶级函数或顶级类,使该函数或类转换为单元测试类。 |
| TestBuilder | 声明一个动态测试套。 |
| TestCase | 宏用于标记单元测试类内的函数,使这些函数成为单元测试的测试用例。 |
| Timeout | 指示测试应在指定时间后终止。它有助于测试可能运行很长时间或陷入无限循环的复杂算法。 |
| Types | 宏为测试类或测试函数提供类型参数。它可以放置在测试类或测试函数上。 |
宏
@AfterAll 宏
功能:声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在所有测试用例之后运行一次。
@AfterEach 宏
功能:声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在每个测试用例之后运行一次。
@Assert 宏
功能:@Assert 声明 Assert 断言,测试函数内部使用,断言失败停止用例。
@Assert(leftExpr, rightExpr),比较leftExpr和rightExpr值是否相同。@Assert(condition: Bool),比较condition是否为true,即@Assert(condition: Bool)等同于@Assert(condition: Bool, true)。@Assert[customAssertion](arguments...), 使用指定的参数arguments调用customAssertion函数,详见@CustomAssertion。
@AssertThrows 宏
功能:声明预期异常的断言,测试函数内部使用,断言失败停止用例。
@BeforeAll 宏
功能:声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在所有测试用例之前运行一次。
@BeforeEach 宏
功能:声明测试类中的函数为测试生命周期函数。被该宏修饰的函数在每个测试用例之前运行一次。
@Bench 宏
功能:@Bench 宏用于标记要执行多次的函数并计算该函数的预期执行时间。
此类函数将分批执行,并针对整个批次测量执行时间。这种测量将重复多次以获得结果的统计分布,并将计算该分布的各种统计参数。 当前支持的参数如下:
- 中位数
- 用作误差估计的中位数 99% 置信区间的绝对值
- 中位数 99% 置信区间的相对值
- 平均值
参数化的 DSL 与 @Bench 结合的示例如下,具体语法与规则详见@TestCase 宏章节:
func sortArray<T>(arr: Array<T>): Unit
where T <: Comparable<T> {
if (arr.size < 2) { return }
var minIndex = 0
for (i in 1..arr.size) {
if (arr[i] < arr[minIndex]) {
minIndex = i
}
}
(arr[0], arr[minIndex]) = (arr[minIndex], arr[0])
sortArray(arr[1..])
}
@Test
@Configure[baseline: "test1"]
class ArrayBenchmarks{
@Bench
func test1(): Unit
{
let arr = Array(10) { i: Int64 => i }
sortArray(arr)
}
@Bench[x in 10..20]
func test2(x:Int64): Unit
{
let arr = Array(x) { i: Int64 => i.toString() }
sortArray(arr)
}
}
输出如下, 增加 Args 列,列举不同参数下的测试数据,每个参数值将作为一个性能测试用例输出测试结果,多个参数时将列举全组合场景:
--------------------------------------------------------------------------------------------------
TP: default, time elapsed: 68610430659 ns, Result:
TCS: ArrayBenchmarks, time elapsed: 68610230100 ns, RESULT:
| Case | Args | Median | Err | Err% | Mean |
|:-------|:-------|---------:|----------:|-------:|---------:|
| test1 | - | 4.274 us | ±2.916 ns | ±0.1% | 4.507 us |
| | | | | | |
| test2 | 10 | 6.622 us | ±5.900 ns | ±0.1% | 6.670 us |
| test2 | 11 | 7.863 us | ±5.966 ns | ±0.1% | 8.184 us |
| test2 | 12 | 9.087 us | ±10.74 ns | ±0.1% | 9.918 us |
| test2 | 13 | 10.34 us | ±6.363 ns | ±0.1% | 10.28 us |
| test2 | 14 | 11.63 us | ±9.219 ns | ±0.1% | 11.67 us |
| test2 | 15 | 13.05 us | ±7.520 ns | ±0.1% | 13.24 us |
| test2 | 16 | 14.66 us | ±11.59 ns | ±0.1% | 15.53 us |
| test2 | 17 | 16.21 us | ±8.972 ns | ±0.1% | 16.35 us |
| test2 | 18 | 17.73 us | ±6.288 ns | ±0.0% | 17.88 us |
| test2 | 19 | 19.47 us | ±5.819 ns | ±0.0% | 19.49 us |
Summary: TOTAL: 11
PASSED: 11, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
@Configure 宏
功能:@Configure 宏为测试类或测试函数提供配置参数。它可以放置在测试类或测试函数上。
语法规则为 @Configure[parameter1: <value1>,parameter2: <value2>]
其中 parameter1 是仓颉标识符,value 是任何有效的仓颉表达式。均大小写敏感。
value 可以是常量或在标有 @Configure 的声明范围内有效的任何仓颉表达式。
如果多个参数具有不同的类型,则它们可以有相同的名称。如果指定了多个具有相同名称和类型的参数,则使用最新的一个。
目前支持的配置参数有:
randomSeed: 类型为 Int64, 为所有使用随机生成的函数设置起始随机种子。generationSteps: 类型为 Int64 :参数化测试算法中的生成值的最大步数。reductionSteps:类型为 Int64: 参数化测试算法中的缩减值的最大步数。
以下参数一般用于被 @Bench 修饰的 Benchmark 测试函数:
explicitGC:类型为 ExplicitGcType: Benchmark 函数测试期间如何调用 GC。默认值为 ExplicitGcType.Light 。baseline:类型为 String : 参数值为 Benchmark 函数的名称,作为比较 Benchmark 函数执行结果的基线。该结果值将作为附加列添加到输出中,其中将包含比较结果。batchSize:类型为 Int64 或者 Range<Int64> : 为 Benchmark 函数配置批次大小。默认值是由框架在预热期间计算得到。minBatches:类型为 Int64 : 配置 Benchmark 函数测试执行期间将执行多少个批次。默认值为10。minDuration:类型为 Duration : 配置重复执行 Benchmark 函数以获得更好结果的时间。默认值为 Duration.second * 5 。warmup:类型为 Duration 或者 Int64 : 配置在收集结果之前重复执行 Benchmark 函数的时间或次数。默认值为 Duration.second 。当值为 0 时,表示没有 warmup , 此时执行次数按用户输入的batchSize乘minBatches计算得到,当batchSize未指定时将抛出异常。
用户可以在 @Configure 宏中指定其他配置参数,这些参数将来可能会用到。
如果测试类使用 @Configure 宏指定配置,则该类中的所有测试函数都会继承此配置参数。
如果此类中的测试函数也标有 @Configure 宏,则配置参数将从类和函数合并,其中函数级宏优先。
@CustomAssertion 宏
功能:@CustomAssertions 将函数指定为用户自定义断言。
该宏修饰的函数应满足两个要求:
- 顶层函数
- 首个入参为
AssertionCtx类型。
示例如下:
@CustomAssertion
public func checkNotNone<T>(ctx: AssertionCtx, value: ?T): T {
if (let Some(res) <- value) {
return res
}
ctx.fail("Expected ${ctx.arg("value")} to be Some(_) but got None")
}
@CustomAssertion 的输出为树状结构,以提高 嵌套断言 的可读性。
例如:
@Test
func customTest() {
@Assert[checkNotNone](Option<Bool>.None)
}
[ FAILED ] CASE: customTest (120812 ns)
Assert Failed: @Assert[checkNotNone](Option < Bool >.None)
└── Assert Failed: `('Option < Bool >.None' was expected to be Some(_) but got None)`
返回值
@CustomAssertion 修饰的函数存在返回值时,它将被 @Assert 宏返回。
示例如下:
@Test
func testfunc() {
let maybeValue: Option<SomeObject> = maybeReturnsSomeObject()
let value = @Assert[checkNotNone](maybeValue)
@Assert[otherAssertion](value)
}
注意: 自定义
@Expect将总是返回Unit,不论@CustomAssertion修饰的函数返回值为什么类型。
嵌套断言
在 @CustomAssertion 定义中, @Assert/@Expect (包括自定义断言), @AssertThrows/@ExpectThrows, @Fail/@FailExpect宏均可被调用,形成嵌套。
例如:
@CustomAssertion
func iterableWithoutNone<T>(ctx: AssertionCtx, iter: Interable<?T>): Array<T> {
iter |> map { it: ?T => @Assert[checkNotNone](it)} |> collectArray
}
@Test
func customTest() {
@Assert[iterWithoutNone]([true, false, Option<Bool>.None])
}
[ FAILED ] CASE: customTest
Assert Failed: @Assert[iterWithoutNone]([true, false, Option < Bool >.None])
└── @Assert[checkNotNone](it):
└── Assert Failed: `('it' was expected to be Some(_) but got None)`
如果用户自定义的断言在被 @Expect 宏调用时抛出 AssertException 。它会被捕获,不会往外传递。
同样,如果用户自定义的断言失败在被 @Assert 宏调用时不引发异常,异常将被创建并抛出。
指定泛型类型
当指定泛型类型参数时,可使用与常规语法来完成。
例如:
@CustomAssertion
public func doesThrow<E>(ctx: AssertionCtx, codeblock: () -> Any): E where E <: Excepiton {
...
}
@Test
func customTest() {
let e = @Assert[doesThrow<NoneValueException>]({ => Option<Bool>.None.getOrThrow()})
}
@Expect 宏
功能:@Expect 声明 Expect 断言,测试函数内部使用,断言失败继续执行用例。
@Expect(leftExpr, rightExpr),比较leftExpr和rightExpr是否相同。@Expect(condition: Bool),比较condition是否为true,即@Expect(condition: Bool)等同于@Expect(condition: Bool, true)。@Expect[customAssertion](arguments...), 使用指定的参数arguments调用customAssertion函数。详见@CustomAssertion。
@ExpectThrows 宏
功能:声明预期异常的断言,测试函数内部使用,断言失败继续执行用例。
@Fail 宏
功能:声明预期失败的断言,测试函数内部使用,断言失败停止用例。
@FailExpect 宏
功能:声明预期失败的断言,测试函数内部使用,断言失败继续执行用例。
@Measure 宏
功能:用于为性能测试指定 Measurement 实例。只能应用于标有 @Test 宏的类或顶级函数的范围内。
对于每个 Measurement,都会进行不同的测量。因此,指定更多 Measurement 实例,将花费更多时间进行性能测试。
默认值为 TimeNow() ,它在内部使用 DateTime.now() 进行测量。
例如:
@Test
@Measure[TimeNow(), TimeNow(Nanos)]
class BenchClass {
@Bench
func someBench() {
for (i in 0..1000) {
1e3 * Float64(i)
}
}
}
输出的测试报告如下:
| Case | Measurement | Median | Err | Err% | Mean |
|:----------|:-------------|---------:|------------:|-------:|---------:|
| someBench | Duration | 6.319 us | ±0.00019 us | ±0.0% | 6.319 us |
| | | | | | |
| someBench | Duration(ns) | 6308 ns | ±0.147 ns | ±0.0% | 6308 ns |
CSV 报告如下:
Case,Args,Median,Err,Err%,Mean,Unit,Measurement
"someBench",,"6319","0.185632","0.0","6319","ns","Duration"
"someBench",,"6308","0.146873","0.0","6308","ns","Duration(ns)"
@Parallel 宏
功能:@Parallel 宏可以修饰测试类。被 @Parallel 修饰的测试类中的测试用例可并行执行。该配置仅在 --parallel 运行模式下生效。
- 所有相关的测试用例应该各自独立,不依赖于任何可变的共享的状态值。
beforeAll()和afterAll()应该是可重入的,以便可以在不同的进程中多次运行。- 需要并行化的测试用例本身应耗时较长。否则并行化引入的多次
beforeAll()和afterAll()可能会超过并行化的收益。 - 不允许与
@Bench同时使用。由于性能用例对底层资源敏感,用例是否并行执行,将影响性能用例的结果,因此禁止与@Bench同时使用。
@PowerAssert 宏
@PowerAssert(leftExpr, rightExpr),比较leftExpr和rightExpr值是否相同。@PowerAssert(condition: Bool),比较condition是否为true,即@PowerAssert(condition: Bool)等同于@PowerAssert(condition: Bool, true)。
@PowerAssert 宏对比 @Assert ,可显示表达式各个可被计算的子表达式的值的详细图表,包括步骤中的异常。
其打印的详细信息如下:
Assert Failed: `(foo(10, y: "test" + s) == foo(s.size, y: s) + bar(a))`
| | |_|| | |_| | |_|| | |_||
| | "123" | "123" | "123" | 1 |
| |__________|| | |______| | |______|
| "test123" | | 3 | 33 |
|______________________| |_________________| |
0 | 1 |
|__________________________|
34
--------------------------------------------------------------------------------------------------
请注意,返回的 Tokens 是初始表达式,但包装到一些内部包装器中,这些包装器允许进一步打印中间值和异常。
@Skip 宏
功能:@Skip 修饰已经被 @TestCase / @Bench 修饰的函数,使该测试用例被跳过。
语法规则为 @Skip[expr] 。
expr暂只支持true,表达式为true时,跳过该测试,其他均为false。- 默认
expr为true即@Skip[true]==@Skip。
@Strategy 宏
功能:在函数上使用 @Strategy 可从该函数创建新的 DataStrategy 。它是一个用于组合、映射和重用策略的便捷 API。
标记为 @Strategy 的函数必须满足以下条件:
- 必须显式指定返回类型。
- 参数必须与宏参数中指定的 DSL 相对应。
- 可以在
@Test标记的类的外部和内部使用。
实现说明:宏展开的结果是一个具有函数名称和 DataStrategyProcessor 类型的变量。 该变量可以在任何可以使用 DataStrategy 的地方使用。
@Tag 宏
@Tag 宏可以应用于 @Test 类和 @Test 或 @TestCase 或 @Bench 函数,提供测试实体的元信息。后续可以通过 --include-tags 和 --exclude-tags 运行选项过滤带有这些标签的测试实体。
支持的语法
-
单个
@Tag在测试函数上。@Tag[Unittest] func test() {} -
单个
@Tag包含多个标签名,用逗号分隔。@Tag[Unittest, TestAuthor] func test() {} -
多个
@Tag在测试函数上。@Tag[Smoke] @Tag[Backend, JiraTask3271] func test() {}
规则与约束
- 标签应为有效的仓颉语言标识符。
@Tag内的标签列表不应为空。- 如果
@Tag放在@Test类的顶部,它会将其标签传播到其中的@TestCase函数上。
例如:
@Test
@Tag[Unittest]
public class UnittestClass {
@TestCase[x in [1, 2, 3, 4, 5]]
@Tag[JiraTask3271]
func caseA(x: Int64) {}
@TestCase
func caseB() {}
}
等同于:
@Test
@Tag[Unittest]
public class UnittestClass {
@TestCase[x in [1, 2, 3, 4, 5]]
@Tag[Unittest]
@Tag[JiraTask3271]
func caseA(x: Int64) {}
@TestCase
@Tag[Unittest]
func caseB() {}
}
@Test 宏
功能:@Test 宏应用于顶级函数或顶级类,使该函数或类转换为单元测试类。
如果是顶级函数,则该函数新增一个具有单个测试用例的类提供给框架使用,同时该函数仍旧可被作为普通函数调用。
标有 @Test 的类必须满足以下条件:
- 它必须有一个无参构造函数。
- 不能从其他类继承。
实现说明:
@Test宏为任何用它标记的类引入了一个新的基类:unittest.TestCases。unittest.TestCases的所有公共和受保护成员(请参阅下面的 API 概述)将在标有@Test的类或函数中变得可用,包括两个字段: 1. 包含此测试的TestContext实例的ctx。 2. 包含类的名称的name。 单元测试框架的用户不应修改这些字段,因为这可能会导致不可预期的错误。
@TestBuilder 宏
功能:声明一个动态测试套。
@TestCase 宏
功能:@TestCase 宏用于标记单元测试类内的函数,使这些函数成为单元测试的测试用例。
标有 @TestCase 的函数必须满足以下条件:
- 该类必须用
@Test标记。 - 该函数返回类型必须是 Unit 。
@Test
class Tests {
@TestCase
func fooTest(): Unit {...}
}
测试用例可能有参数,在这种情况下,开发人员必须使用参数化测试 DSL 指定这些参数的值:
@Test[x in source1, y in source2, z in source3]
func test(x: Int64, y: String, z: Float64): Unit {}
此 DSL 可用于 @Test、@Strategy、@Bench 和 @TestCase 宏,其中 @Test 仅在顶级函数上时才可用。如果测试函数中同时存在 @Bench 和 @TestCase ,则只有 @Bench 可以包含 DSL 。
在 DSL 语法中,in 之前的标识符(在上面的示例中为 x 、y 和 z )必须直接对应于函数的参数,参数源(在上面的示例中为source1 、source2 和 source3)是任何有效的仓颉表达式(该表达式类型必须实现接口 DataStrategy<T> 或 DataStrategyProcessor<T>,详见下文)。
参数源的元素类型(此类型作为泛型参数 T 提供给接口 DataStrategy<T> )必须与相应函数参数的类型严格相同。
支持的参数源类型如下:
- Arrays:
x in [1,2,3,4]。 - Ranges:
x in 0..14。 - 随机生成的值:
x in random()。 - 从 json 文件中读取到的值:
x in json("filename.json")。 - 从 csv 文件中读取到的值:
x in csv("filename.csv")。 @Strategy修饰的函数:x in nameOfStrategyAnnotatedFunction。- 使用 DataStrategyProcessor 组合数据策略的结果。
高级用户可以通过定义自己的类型并且实现 DataStrategy<T> 接口来引入自己的参数源类型。
使用 random() 的随机生成函数默认支持以下类型:
若需要新增其他的类型支持
random(),可以让该类型扩展 Arbitrary 。 在参数有多个值时,beforeEach/afterEach不会在不同值下重复执行而仅会执行一次。若确实需要在每个值下做初始化和去初始化,需要在测试主体中写。对于性能测试方案,@Strategy应该用于需要从基准中排除的设置代码。没有为这种情况提供特殊的API,因为在大多数情况下,这样的代码依赖于特定的参数值。
@TestTemplate 宏
功能: @TestTemplate 宏可修饰抽象类,使得它成为一个 测试模版。
@Timeout 宏
功能:@Timeout 指示测试应在指定时间后终止。它有助于测试可能运行很长时间或陷入无限循环的复杂算法。
语法规则为 @Timeout[expr]
expr 的类型应为 std.time.Duration 。
其修饰测试类时为每个相应的测试用例提供超时时间。
@Types 宏
功能:@Types 宏为测试类或测试函数提供类型参数。它可以放置在测试类或测试函数上。
语法规则为 @Types[Id1 in <Type1, Type2, Type3>, Id2 in <Type4, Type5> ...]
其中 Id1、Id2... 是有效类型参数标识符,Type1、Type2、Type3...是有效的仓颉类型。
@Types 宏有以下限制:
- 必须与
@Test,@TestCase或@Bench宏共同使用。 - 一个声明只能有一个
@Types宏修饰。 - 该声明必须是具有与
@Types宏中列出的相同类型参数的泛型类或函数。 - 类型列表中列出的类型不能相互依赖,例如
@Types[A in <Int64, String>, B in <List<A>>]将无法正确编译。但是,在为该类内的测试函数提供类型时,可以使用为测试类提供的类型。例如:
@Test
@Types[T in <...>]
class TestClass<T> {
@TestCase
@Types[U in <Array<T>>]
func testfunc<U>() {}
}
该机制可以与其他测试框架功能一起使用,例如 @Configure 等。
@UnittestOption 宏
该宏可用于注册自定义配置项。只有已注册的配置项才能与单元测试框架一起使用。宏的参数是类型、选项名称、可选的验证器回调和可选的描述。 对所有单元测试配置项的严格检查保证了控制台输入和源代码的正确性。它可以防止笔误和使用错误类型的值。
示例:
@UnittestOption[String, Int](optionName)
@UnittestOption[String](opt, /*validator*/ { str: String => str.size < 5 })
@UnittestOption[A, B](option3, { x: Any => ... })
@UnittestOption[Bool](needLog, /*description*/ "The option do ...")
@UnittestOption[Int](public myOpt)
具体规则如下:
@UnittestOption对同一个配置项不能重复使用。@UnittestOption必须在顶层。- 如果配置项有多种类型,则验证器回调参数应为 Any,如果只有一种类型对该选项有效,则验证器回调参数应为该具体类型。
- 验证器回调返回类型为 Bool 或 ?String。
true表示选项有效,false表示选项值无效。- ·
Some<String>包含选项无效原因的描述,None<String>表示选项值有效。
与 @Configuration 配合使用的示例如下:
配置项的键名称是通过首字母大写并以 Key 字符串开头构建的成员。例如,对于名为 zxc 的配置项,有效键名称将为 KeyZxc.zxc
@UnittestOption[String](opt)
@Test
func test_that_derived_type_overwrite_parent_type_value_in_configuration() {
let conf = Configuration()
conf.set(KeyOpt.opt, "a")
let value = conf.get(KeyOpt.opt).getOrThrow()
@PowerAssert(value == "a")
}
Configuration 类正确处理继承的情况。示例如下:
open class Base {
public open func str() {
"Base"
}
}
class Derived <: Base {
public func str() {
"Derived"
}
}
@UnittestOption[Base](opt)
@Test
func test_that_derived_type_overwrite_parent_type_value_in_configuration() {
let conf = Configuration()
conf.set(KeyOpt.opt, Base())
let first = conf.get(KeyOpt.opt).getOrThrow()
@PowerAssert(first.str() == "Base")
conf.set(KeyOpt.opt, Derived())
let second = conf.get(KeyOpt.opt).getOrThrow()
@PowerAssert(second.str() == "Derived")
}
std.unittest.common
功能介绍
unittest.common 为单元测试框架提供了打印所需的类型和一些通用方法。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| func registerOptionValidator(String, (Any) -> OptionValidity) | 用于注册自定义选项验证器。大多数情况下,用户应该使用 @UnittestOption 宏,而不是直接使用这个函数。 |
| func setOptionInfo(String, Array<String>, ?String) | 用于设置选项的描述的函数。 |
| setOrUpdateOptionInfo(String, ?String, String, String) | 将实现 ToString 的参数转换为字符串表达。 |
| toStringOrPlaceholder<T>(T) | 将实现 ToString 的参数转换为字符串表达。 |
接口
| 接口名 | 功能 |
|---|---|
| DataProvider | DataStrategy 的组件,用于提供测试数据, T 指定提供者提供的数据类型。 |
| DataShrinker | DataStrategy 的组件,用于在测试期间缩减数据,T 指定该收缩器处理的数据类型。 |
| DataStrategy | 为参数化测试提供数据的策略,T 指定该策略操作的数据类型。 |
| PrettyPrintable | 类型实现该接口表示可以较好地进行颜色及缩进格式的打印。 |
| KeyFor | Configuration 中配置型的键的类型。 |
类
| 类名 | 功能 |
|---|---|
| Configuration | 存储 @Configure 宏生成的 unittest 配置数据的对象。Configuration 是一个类似 HashMap 的类,但它的键不是键和值类型,而是 String 类型,和任何给定类型的值。 |
| ConfigurationKey | 配置项的键值对象。提供判等及 hashCode 方法。 |
| PrettyPrinter | 拥有颜色和对齐、缩进控制的打印器。 |
| PrettyText | 类似构造器的类,用于存储打印的输出。 |
枚举
| 枚举名 | 功能 |
|---|---|
| Color | 指定颜色。 |
| OptionValidity | 代表选项值验证的结果的枚举值。 |
结构体
| 结构体名 | 功能 |
|---|---|
| OptionInfo | 打印帮助页面时可以使用的选项的信息。 |
异常类
| 异常名 | 功能 |
|---|---|
| UnittestOptionValidationException | 框架验证选项值合法性过程中抛出的异常。 |
函数
func registerOptionValidator(String, (Any) -> OptionValidity)
public func registerOptionValidator(name: String, validator: (Any) -> OptionValidity): Unit
功能: 用于注册自定义选项验证器。大多数情况下,用户应该使用 @UnittestOption 宏,而不是直接使用这个函数。
参数:
- name: String - 选项名称。
- validator: (Any) -> OptionValidity - 检查选项是否合法的函数。
func setOptionInfo(String, Array<String>, ?String)
public func setOptionInfo(
name: String,
types: Array<String>,
description!: ?String = None
): Unit
功能: 用于设置选项的描述的函数。
参数:
func setOrUpdateOptionInfo(String, ?String, String, String)
public func setOrUpdateOptionInfo(
name: String,
description: ?String,
ty: String,
typeDescription: String
): Unit
功能: 用于设置具体类型的选项的描述。
参数:
- name: String - 选项名称。
- description: ?String - 选项的描述。如果值不为 None ,则覆盖先前的值。
- ty: String - 类型的字符串形式。
- typeDescription: String - 选项的类型描述。
func toStringOrPlaceholder<T>(T)
public func toStringOrPlaceholder<T>(value: T)
功能:将实现 ToString 的参数转换为字符串表达。不支持 ToString 的转换为默认字符串。
返回值:
- String - 参数的字符串表达。
接口
interface DataProvider
public interface DataProvider<T> {
func provide(): Iterable<T>
func positions(): Array<Int64>
prop isInfinite: Bool
}
功能:DataStrategy 的组件,用于提供测试数据,T 指定提供者提供的数据类型。
prop isInfinite
prop isInfinite: Bool
功能:是否无法穷尽。
类型:Bool
func provide()
func provide(): Iterable<T>
功能:获取数据迭代器。
返回值:
- Iterable<T> - 数据迭代器。
func positions()
func positions(): Array<Int64>
功能:获取位置信息。
返回值:
- Array<Int64> - 位置信息。
extend<T> Array<T> <: DataProvider<T>
extend<T> Array<T> <: DataProvider<T>
功能:为 Array 实现了 DataProvider<T> 接口。使如下配置形式可用:
@Test[x in [1,2,3]]
func test(x: Int64) {}
父类型:
- DataProvider<T>
extend<T> Range<T> <: DataProvider<T>
extend<T> Range<T> <: DataProvider<T>
功能:为 Range 实现了 DataProvider<T> 接口。使如下配置形式可用:
@Test[x in (0..5)]
func test(x: Int64) {}
父类型:
- DataProvider<T>
interface DataShrinker<T>
public interface DataShrinker<T> {
func shrink(value: T): Iterable<T>
}
功能:DataStrategy 的组件,用于在测试期间缩减数据,T 指定该收缩器处理的数据类型。
func shrink(T)
func shrink(value: T): Iterable<T>
功能:获取类型 T 的值并生成较小值的集合。什么被认为是“较小”取决于数据的类型。
参数:
- value: T - 被缩减的值。
返回值:
- Iterable<T> - 较小值的集合,当数据无法再被缩减时返回空集合。
interface DataStrategy
public interface DataStrategy<T> {
func provider(configuration: Configuration): DataProvider<T>
func shrinker(configuration: Configuration): DataShrinker<T>
}
功能:为参数化测试提供数据的策略,T 指定该策略操作的数据类型。
func provider(Configuration)
func provider(configuration: Configuration): DataProvider<T>
功能:获取提供测试数据组件。
参数:
- configuration: Configuration - 配置信息。
返回值:
- DataProvider<T> - 提供测试数据的组件对象。
func shrinker(Configuration)
open func shrinker(configuration: Configuration): DataShrinker<T>
功能:获取缩减测试数据的组件。
参数:
- configuration: Configuration - 配置信息。
返回值:
- DataShrinker<T> - 缩减测试数据的组件对象。
extend<T> Array<T> <: DataStrategy<T>
extend<T> Array<T> <: DataStrategy<T>
功能:为 Array 实现了 DataStrategy<T> 接口。使如下配置形式可用:
@Test[x in [1,2,3]]
func test(x: Int64) {}
父类型:
- DataStrategy<T>
extend<T> Range<T> <: DataStrategy<T>
extend<T> Range<T> <: DataStrategy<T>
功能:为 Range 实现了 DataStrategy<T> 接口。使如下配置形式可用:
@Test[x in (0..5)]
func test(x: Int64) {}
父类型:
- DataStrategy<T>
interface PrettyPrintable
public interface PrettyPrintable {
func pprint(to: PrettyPrinter): PrettyPrinter
}
功能:类型实现该接口表示可以较好地进行颜色及缩进格式的打印。
func pprint(PrettyPrinter)
func pprint(to: PrettyPrinter): PrettyPrinter
功能:将类型值打印到指定的打印器中。
参数:
- to: PrettyPrinter - 打印器。
返回值:
- PrettyPrinter - 打印器。
extend<T> Array<T> <: PrettyPrintable where T <: PrettyPrintable
extend<T> Array<T> <: PrettyPrintable where T <: PrettyPrintable {
}
功能:为 Array 类型扩展了 PrettyPrintable 接口。
父类型:
func pprint(PrettyPrinter)
public func pprint(to: PrettyPrinter): PrettyPrinter
功能:将 Array<T> 打印到指定的打印器中。
参数:
- to: PrettyPrinter - 打印器。
返回值:
- PrettyPrinter - 打印器。
extend<T> ArrayList<T> <: PrettyPrintable where T <: PrettyPrintable
extend<T> ArrayList<T> <: PrettyPrintable where T <: PrettyPrintable {
}
功能:为 ArrayList 类型扩展了 PrettyPrintable 接口。
父类型:
func pprint(PrettyPrinter)
public func pprint(to: PrettyPrinter): PrettyPrinter
功能:将 ArrayList<T> 打印到指定的打印器中。
参数:
- to: PrettyPrinter - 打印器。
返回值:
- PrettyPrinter - 打印器。
interface KeyFor
public interface KeyFor<T> {
prop name: String
}
功能:Configuration 中配置型的键的类型。
可以通过 @UnitestOption 定义自定义配置项键值。内置的 unittest 配置项可以根据命名规则获取。例如,可以通过 KeyRandomSeed.randomSeed 键从 Configuration 中提取 randomSeed 。
prop name
prop name: String
功能:Configuration 中使用的键名称的字符串表示形式。
类型:String
类
class Configuration
public class Configuration <: ToString {
public init()
}
功能:存储 @Configure 宏生成的 unittest 配置数据的对象。Configuration 与 HashMap 类似,但它的键是 KeyFor 类型,值为任何给定类型。
父类型:
init()
public init()
功能:构造一个空的Configuration实例。
func clone()
public func clone(): Configuration
功能:拷贝一份Configuration对象。
返回值:
- Configuration - 拷贝的对象。
func get<T>(KeyFor<T>)
public func get<T>(key: KeyFor<T>): ?T
功能:获取 key 对应的值。
T 为 泛型参数,用于在对象中查找对应类型的值。
参数:
- key: KeyFor - 配置项的键值。
返回值:
- ?T - 未找到时返回 None,找到对应类型及名称的值时返回 Some<T>(v) 。
func getByName<T>(name: String): ?T
public func getByName<T>(name: String): ?T
功能:获取 key 对应的值。
T 为 泛型参数,用于在对象中查找对应类型的值。
参数:
- name: String - 键名称。
func remove<T>(KeyFor<T>)
public func remove<T>(key: KeyFor<T>): ?T
功能:删除对应键名称和类型的值。
参数:
- key: KeyFor - 配置项的键值。
返回值:
- ?T - 当存在该值时返回该值,当不存在时返回 None。
func removeByName<T>(String)
public func removeByName<T>(name: String): ?T
功能:删除对应键名称和类型的值。
参数:
- key: String - 键名称。
返回值:
- ?T - 当存在该值时返回该值,当不存在时返回 None。
func set<T>(KeyFor<T>, T)
public func set<T>(key: KeyFor<T>, value: T)
功能:给对应键名称和类型设置值。
参数:
- key: KeyFor - 配置项的键值。
- value: T - 键值。
func setByName<T>(name: String, value: T)
public func setByName<T>(name: String, value: T): Unit
功能:给对应键名称和类型设置值。
参数:
- name: String - 键名称。
- value: T - 键值。
func toString()
public func toString(): String
功能:该对象的字符化对象,当内部对象未实现 ToString 接口时,输出 '<not printable>' 。
返回值:
- String - 字符串。
static func merge(Configuration, Configuration)
public static func merge(parent: Configuration, child: Configuration): Configuration
功能:合并 child 到 parent 配置中。其中如有同名键值 child 覆盖 parent 。
参数:
- parent:Configuration - 需要合并的配置
- child:Configuration - 需要合并的配置
返回值:
- Configuration - 合并完成的配置
extend Configuration <: BenchmarkConfig
extend Configuration <: BenchmarkConfig {}
功能:为 Configuration 扩展 BenchmarkConfig 接口。
父类型:
func batchSize(Int64)
public func batchSize(b: Int64)
功能:配置性能测试时一个批次的执行次数。
参数:
- b: Int64 - 执行次数。
func batchSize(Range<Int64>)
public func batchSize(x: Range<Int64>)
功能:配置性能测试时一个批次的执行次数范围。
参数:
- b: Range<Int64> - 执行次数范围。
func explicitGC(ExplicitGcType)
public func explicitGC(x: ExplicitGcType)
功能:配置性能测试时执行 GC 的方式。
参数:
- x: ExplicitGcType - GC 执行的方式。
func minBatches(Int64)
public func minBatches(x: Int64)
功能:配置性能测试时最少的批次数。
参数:
- x: Int64 - 最少的批次数。
func minDuration(Duration)
public func minDuration(x: Duration)
功能:配置性能测试时最短的执行时长。
参数:
- x: Duration - 最短的执行时长。
func warmup(Int64)
public func warmup(x: Int64)
功能:配置性能测试时预热的秒数。
参数:
- x: Int64 - 预热的秒数。
func warmup(Duration)
public func warmup(x: Duration)
功能:配置性能测试时预热的时长。
参数:
- x: Duration - 预热的时长。
class ConfigurationKey
abstract sealed class ConfigurationKey <: Equatable<ConfigurationKey> & Hashable {}
功能:配置项的键值对象。提供判等及 hashCode 方法。
父类型:
func equals(ConfigurationKey)
protected func equals(that: ConfigurationKey): Bool
功能:判断是否相等。
参数:
- that: ConfigurationKey - 被对比的对象。
返回值:
- Bool - 是否相等。
func hashCode
public override func hashCode(): Int64
功能:获取 hashCode 值。
返回值:
- Int64 - hashCode 值。
operator func ==(ConfigurationKey)
public override operator func ==(that: ConfigurationKey)
功能:判等。
参数:
- that: ConfigurationKey - 被对比的数据
返回值:
- Bool - 是否相等。
public override operator func !=(that: ConfigurationKey)
public override operator func !=(that: ConfigurationKey)
功能:判不等。
参数:
- that: ConfigurationKey - 被对比的数据
返回值:
- Bool - 是否不相等。
class PrettyPrinter
public abstract class PrettyPrinter {
public PrettyPrinter(let indentationSize!: UInt64 = 4, let startingIndent!: UInt64 = 0)
}
功能:拥有颜色和对齐、缩进控制的打印器。
PrettyPrinter(UInt64,UInt64)
public PrettyPrinter(let indentationSize!: UInt64 = 4, let startingIndent!: UInt64 = 0)
功能:PrettyPrinter构造器。
参数:
prop isTopLevel
public prop isTopLevel: Bool
功能:获取是否在打印的缩进顶层。
类型:Bool 。
func append(String)
public func append(text: String): PrettyPrinter
功能:增加一个字符串到打印器中。不支持多行字符串,对多行字符串不支持缩进。
参数:
- text: String - 被增加的字符串。
返回值:
- PrettyPrinter - 打印器。
func append<PP>(PP)where PP <: PrettyPrintable
public func append<PP>(value: PP): PrettyPrinter where PP <: PrettyPrintable
功能:增加一个实现了 PrettyPrintable 的对象到打印器中。
参数:
- value: PP - 一个实现了 PrettyPrintable 的对象。
返回值:
- PrettyPrinter - 打印器。
func appendCentered(String, UInt64)
public func appendCentered(text: String, space: UInt64): PrettyPrinter
功能:增加一个字符串到打印器中。居中对齐至指定字符数,不足的字符由空格补齐。不支持多行字符串,对多行字符串不支持缩进。
参数:
返回值:
- PrettyPrinter - 打印器。
func appendLeftAligned(String, UInt64)
public func appendLeftAligned(text: String, space: UInt64): PrettyPrinter
功能:增加一个字符串到打印器中。左对齐至指定字符数,不足的字符由空格补齐。不支持多行字符串,对多行字符串不支持缩进。
参数:
返回值:
- PrettyPrinter - 打印器。
func appendLine(String): PrettyPrinter
public func appendLine(text: String): PrettyPrinter
功能:增加一个字符串到打印器中,跟着一个换行符。
参数:
- text: String - 被增加的字符串。
返回值:
- PrettyPrinter - 打印器。
func appendLine<PP>(PP) where PP <: PrettyPrintable
public func appendLine<PP>(value: PP): PrettyPrinter where PP <: PrettyPrintable
功能:增加一个实现了 PrettyPrintable 的对象到打印器中,跟着一个换行符。
参数:
- value: PP - 一个实现了 PrettyPrintable 的对象。
返回值:
- PrettyPrinter - 打印器。
func appendRightAligned(String, UInt64)
public func appendRightAligned(text: String, space: UInt64): PrettyPrinter
功能:增加一个字符串到打印器中。右对齐至指定字符数。不支持多行字符串,对多行字符串不支持缩进。
参数:
返回值:
- PrettyPrinter - 打印器。
func colored(Color, body: () -> Unit)
public func colored(color: Color, body: () -> Unit): PrettyPrinter
功能:对闭包中给打印器增加的字符串指定颜色。 常见的用法如下:
pp.colored(RED) {
pp.appendLine("1")
pp.appendLine("2")
pp.appendLine("3")
}
此时字符串 "1" "2" "3" 均被打印为红色。
参数:
- color: Color - 指定打印的颜色。
- body: () -> Unit - 添加字符串的闭包。
返回值:
- PrettyPrinter - 打印器。
func colored(Color, String)
public func colored(color: Color, text: String): PrettyPrinter
功能:对给打印器增加的字符串指定颜色。
参数:
返回值:
- PrettyPrinter - 打印器。
func customOffset(UInt64, body: () -> Unit)
public func customOffset(symbols: UInt64, body: () -> Unit): PrettyPrinter
功能:对闭包中给打印器增加的字符串指定额外缩进的个数。 常见的用法如下:
pp.customOffset(5) {
pp.appendLine("1")
pp.appendLine("2")
pp.appendLine("3")
}
此时字符串 "1" "2" "3" 均额外缩进5个字符。
参数:
- symbols: UInt64 - 指定缩进个数。
- body: () -> Unit - 添加字符串的闭包。
返回值:
- PrettyPrinter - 打印器。
func indent(body: () -> Unit)
public func indent(body: () -> Unit): PrettyPrinter
功能:对闭包中给打印器增加的字符串指定额外缩进一次。 常见的用法如下:
pp.indent {
pp.appendLine("1")
pp.appendLine("2")
pp.appendLine("3")
}
此时字符串 "1" "2" "3" 均额外缩进一次。
参数:
- body: () -> Unit - 添加字符串的闭包。
返回值:
- PrettyPrinter - 打印器。
func indent(UInt64, body: () -> Unit)
public func indent(indents: UInt64, body: () -> Unit): PrettyPrinter
功能:对闭包中给打印器增加的字符串指定额外缩进指定次数。 常见的用法如下:
pp.indent(2) {
pp.appendLine("1")
pp.appendLine("2")
pp.appendLine("3")
}
此时字符串 "1" "2" "3" 均额外缩进2次。
参数:
- indents: UInt64 - 指定额外缩进的次数。
- body: () -> Unit - 添加字符串的闭包。
返回值:
- PrettyPrinter - 打印器。
func newLine()
public func newLine(): PrettyPrinter
功能:增加新行。
返回值:
- PrettyPrinter - 打印器。
func put(String)
protected func put(s: String): Unit
功能:打印字符串。
参数:
- s: String - 需打印的字符串。
func putNewLine()
protected open func putNewLine(): Unit
功能:打印新行。
func setColor(Color)
protected func setColor(color: Color): Unit
功能:设置颜色。
参数:
- color: Color - 指定的颜色。
class PrettyText
public class PrettyText <: PrettyPrinter & PrettyPrintable & ToString {
public init()
public init(string: String)
}
功能:存储打印的输出。主要用途是中间存储和传递这些值。
实现了 PrettyPrinter(可以打印到)和 PrettyPrintable(可以从中打印)的方法。
父类型:
init()
public init()
功能:默认构造器,生成一个空的对象。
init(String)
public init(string: String)
功能:构造器,生成一个以入参开头的文本构造器。
参数:
- string : String - 希望放入打印文本开头的字符串。
func isEmpty()
public func isEmpty(): Bool
功能:返回当前构造器是否为空,即未有值传入给构造器。
返回值:
- Bool - 未有内容传入时返回
true,否则返回false。
func pprint(PrettyPrinter)
public func pprint(to: PrettyPrinter): PrettyPrinter
功能:打印信息到打印器上。
参数:
- to: PrettyPrinter - 打印器。
返回值:
- PrettyPrinter - 打印器。
func toString()
public func toString(): String
功能:打印文本到字符串上。
返回值:
- String - 打印文本的字符串。
static func of<PP>(PP) where PP <: PrettyPrintable
public static func of<PP>(pp: PP) where PP <: PrettyPrintable
功能:通过打印从 PrettyPrintable 创建 PrettyText。
参数:
- pp: PP - 一个实现了 PrettyPrintable 的类型。
返回值:
- PrettyText - 打印文本对象。
枚举
enum Color
public enum Color <: Equatable<Color> {
| RED
| GREEN
| YELLOW
| BLUE
| CYAN
| MAGENTA
| GRAY
| DEFAULT_COLOR;
}
功能:指定颜色。
父类型:
RED
RED
功能:红色。
GREEN
GREEN
功能:绿色。
YELLOW
YELLOW
功能:黄色。
BLUE
BLUE
功能:蓝色。
CYAN
CYAN
功能:青色。
MAGENTA
MAGENTA
功能:品红色。
GRAY
GRAY
功能:灰色。
DEFAULT_COLOR
DEFAULT_COLOR
功能:默认色。
operator func ==(Color)
public operator func ==(that: Color): Bool
功能:判断颜色是否相等。
参数:
- that: Color - 被对比的颜色。
返回值:
- Bool - 相等时返回
true,否则返回false。
operator func !=(Color)
public operator func !=(that: Color): Bool
功能:判断颜色是否不相等。
参数:
- that: Color - 被对比的颜色。
返回值:
- Bool - 不相等时返回
true,否则返回false。
enum OptionValidity
public enum OptionValidity {
| UnknownOptionType
| InvalidOption(String)
| ValidOption(ConfigurationKey)
}
功能:代表选项值验证的结果的枚举值。
UnknownOptionType
UnknownOptionType
功能: 未知状态,仅在验证出现内部错误时出现。
InvalidOption(String)
InvalidOption(String)
功能: 选项验证无效,包含无效的原因。
ValidOption(ConfigurationKey)
ValidOption(ConfigurationKey)
功能: 选项值有效,包含选项值在配置项中对应键值对的键名。
结构体
struct OptionInfo
public struct OptionInfo {
public let description: ?String
public let name: String
public let types!: HashMap<String, ?String> = HashMap()
public let userDefined: Bool
}
功能: 打印帮助页面时可以使用的选项的信息。
let description
public let description: ?String
功能:选项描述信息。
类型:?String
let name
public let name: String
功能:选项名称。
类型:String
let types
public let types!: HashMap<String, ?String> = HashMap()
功能:从选项类型名称映射到值的含义。
let userDefined
public let userDefined: Bool
功能:选项是否已被定义。
类型:Bool
异常
class UnittestOptionValidationException
public class UnittestOptionValidationException <: Exception
功能:框架验证选项值合法性过程中抛出的异常。
父类型:
std.unittest.diff
功能介绍
unittest.diff 为单元测试框架提供了打印差异对比信息所需的 API 。
API 列表
接口
| 接口名 | 功能 |
|---|---|
| AssertPrintable | 提供打印 @Assert/@Expect 的检查结果的方法。 |
接口
interface AssertPrintable
public interface AssertPrintable<T> {
prop hasNestedDiff: Bool
func pprintForAssertion(
pp: PrettyPrinter, that: T, thisPrefix: String, thatPrefix: String, level: Int64
): PrettyPrinter
}
功能:提供打印 @Assert/@Expect 的检查结果的方法。
prop hasNestedDiff
prop hasNestedDiff: Bool
功能:获取是否有嵌套 diff 层级。
类型:Bool
func pprintForAssertion(PrettyPrinter, T, String, String, Int64)
func pprintForAssertion(
pp: PrettyPrinter, that: T, thisPrefix: String, thatPrefix: String, level: Int64
): PrettyPrinter
功能:打印 @Assert/@Expect 的检查结果的方法。
参数:
- pp: PrettyPrinter - 打印器。
- that: T - 待打印的信息。
- thisPrefix: String - 预期内容的前缀。
- thatPrefix: String - 实际内容的前缀。
- level: Int64 - 嵌套层级。
返回值:
- PrettyPrinter - 打印器。
std.unittest.prop_test
功能介绍
unittest.prop_test 为单元测试框架提供了参数化测试所需的类型和方法。
API 列表
函数
| 函数名 | 功能 |
|---|---|
| emptyIterable<T>() | 创建一个空的迭代器。 |
| random<T>() | 该函数生成 T 类型的随机数据,其中 T 必须实现接口 Arbitrary<T> 。该函数的返回值是参数化测试的一种参数源。 |
接口
| 接口名 | 功能 |
|---|---|
| Arbitrary<T> | 生成 T 类型随机值的接口。 |
| IndexAccess | 通过索引访问元组元素的实用程序接口。 |
| RandomSource | 提供 Arbitrary<T> 所需的随机生成基础类型数据的能力。 |
| Shrink | 将 T 类型的值缩减到多个“更小”的值。 |
类
| 类名 | 功能 |
|---|---|
| Generators | 包含辅助函数的类,可帮助开发人员编写自己的生成器。 |
| LazySeq<T> | 延迟计算的 T 类型值序列。用于在迭代时计算和记忆值。 |
| ShrinkHelpers | 提供对元组实现缩减迭代器的方法。 |
结构体
| 结构体名 | 功能 |
|---|---|
| Function0Wrapper | 将闭包封装为结构体。 |
| TupleWrapper2 | 将闭包封装为结构体。闭包带两个参数。 |
| TupleWrapper3 | 将闭包封装为结构体。闭包带三个参数。 |
| TupleWrapper4 | 将闭包封装为结构体。闭包带四个参数。 |
| TupleWrapper5 | 将闭包封装为结构体。闭包带五个参数。 |
函数
func emptyIterable<T>()
public func emptyIterable<T>(): Iterable<T>
功能:创建一个空的迭代器。
返回值:
- Iterator<T> - 空迭代器。
func random<T>() where T <: Arbitrary<T>
public func random<T>(): RandomDataStrategy<T> where T <: Arbitrary<T>
功能:该函数生成 T 类型的随机数据,其中 T 必须实现接口 Arbitrary<T> 。该函数的返回值是参数化测试的一种参数源。
返回值:
- Arbitrary<T> - 使用随机数据生成的 RandomDataStrategy 接口的实例。
接口
interface Arbitrary<T>
public interface Arbitrary<T> {
static func arbitrary(random: RandomSource): Generator<T>
}
功能:生成 T 类型随机值的接口。
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<T>
功能:获取生成 T 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<T> - 生成 T 类型随机值生成器。
extend Bool <: Arbitrary<Bool>
extend Bool <: Arbitrary<Bool>
功能:为 Bool 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Bool>
功能:获取生成 T 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Bool> - 生成 Bool 类型随机值生成器。
extend Float16 <: Arbitrary<Float16>
extend Float16 <: Arbitrary<Float16>
功能:为 Float16 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Float16>
功能:获取生成 T 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Float16> - 生成 Float16 类型随机值生成器。
extend Float32 <: Arbitrary<Float32>
extend Float32 <: Arbitrary<Float32>
功能:为 Float32 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Float32>
功能:获取生成 T 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Float32> - 生成 Float32 类型随机值生成器。
extend Float64 <: Arbitrary<Float64>
extend Float64 <: Arbitrary<Float64>
功能:为 Float64 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Float64>
功能:获取生成 T 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Float64> - 生成 Float64 类型随机值生成器。
extend Int16 <: Arbitrary<Int16>
extend Int16 <: Arbitrary<Int16>
功能:为 Int16 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Int16>
功能:获取生成 T 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Int16> - 生成 Int16 类型随机值生成器。
extend Int32 <: Arbitrary<Int32>
extend Int32 <: Arbitrary<Int32>
功能:为 Int32 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Int32>
功能:获取生成 T 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Int32> - 生成 Int32 类型随机值生成器。
extend Int64 <: Arbitrary<Int64>
extend Int64 <: Arbitrary<Int64>
功能:为 Int64 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Int64>
功能:获取生成 Int64 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Int64> - 生成 Int64 类型随机值生成器。
extend Int8 <: Arbitrary<Int8>
extend Int8 <: Arbitrary<Int8>
功能:为 Int8 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Int8>
功能:获取生成 Int8 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Int8> - 生成 Int8 类型随机值生成器。
extend IntNative <: Arbitrary<IntNative>
extend IntNative <: Arbitrary<IntNative>
功能:为 IntNative 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<IntNative>
功能:获取生成 IntNative 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<IntNative> - 生成 IntNative 类型随机值生成器。
extend Ordering <: Arbitrary<Ordering>
extend Ordering <: Arbitrary<Ordering>
功能:为 Ordering 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Ordering>
功能:获取生成 Ordering 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Ordering> - 生成 Ordering 类型随机值生成器。
extend Rune <: Arbitrary<Rune>
extend Rune <: Arbitrary<Rune>
功能:为 Rune 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Rune>
功能:获取生成 Rune 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Rune> - 生成 Rune 类型随机值生成器。
extend String <: Arbitrary<String>
extend String <: Arbitrary<String>
功能:为 String 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<String>
功能:获取生成 String 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<String> - 生成 String 类型随机值生成器。
extend UInt16 <: Arbitrary<UInt16>
extend UInt16 <: Arbitrary<UInt16>
功能:为 UInt16 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<UInt16>
功能:获取生成 UInt16 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<UInt16> - 生成 UInt16 类型随机值生成器。
extend UInt32 <: Arbitrary<UInt32>
extend UInt32 <: Arbitrary<UInt32>
功能:为 UInt32 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<UInt32>
功能:获取生成 UInt32 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<UInt32> - 生成 UInt32 类型随机值生成器。
extend UInt64 <: Arbitrary<UInt64>
extend UInt64 <: Arbitrary<UInt64>
功能:为 UInt64 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<UInt64>
功能:获取生成 UInt64 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<UInt64> - 生成 UInt64 类型随机值生成器。
extend UInt8 <: Arbitrary<UInt8>
extend UInt8 <: Arbitrary<UInt8>
功能:为 UInt8 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<UInt8>
功能:获取生成 UInt8 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<UInt8> - 生成 UInt8 类型随机值生成器。
extend UIntNative <: Arbitrary<UIntNative>
extend UIntNative <: Arbitrary<UIntNative>
功能:为 UIntNative 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<UIntNative>
功能:获取生成 UIntNative 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<UIntNative> - 生成 UIntNative 类型随机值生成器。
extend Unit <: Arbitrary<Unit>
extend Unit <: Arbitrary<Unit>
功能:为 Unit 实现了 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Unit>
功能:获取生成 Unit 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Unit> - 生成 Unit 类型随机值生成器。
extend<T> Array<T> <: Arbitrary<Array<T>> where T <: Arbitrary<T>
extend<T> Array<T> <: Arbitrary<Array<T>> where T <: Arbitrary<T>
功能:为 Array<T> 实现了 Arbitrary<Array<T>> 接口,且 T 需实现 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<Array<T>>
功能:获取生成 Array<T> 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<Array<T>> - 生成 Array<T> 类型随机值生成器。
extend<T> Option<T> <: Arbitrary<Option<T>> where T <: Arbitrary<T>
extend<T> option<T> <: Arbitrary<Option<T>> where T <: Arbitrary<T>
功能:为 Option<T> 实现了 Arbitrary<Option<T>> 接口,且 T 需实现 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<option<T>>
功能:获取生成 option<T> 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<option<T>> - 生成 option<T> 类型随机值生成器。
extend<T> ArrayList<T> <: Arbitrary<ArrayList<T>> where T <: Arbitrary<T>
extend<T> ArrayList<T> <: Arbitrary<ArrayList<T>> where T <: Arbitrary<T>
功能:为 ArrayList<T> 实现了 Arbitrary 接口,且 T 需实现 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<ArrayList<T>>
功能:获取生成 ArrayList<T> 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<ArrayList<T>> - 生成 ArrayList<T> 类型随机值生成器。
extend<T> HashSet<T> <: Arbitrary<HashSet<T>> where T <: Arbitrary<T>
extend<T> HashSet<T> <: Arbitrary<HashSet<T>> where T <: Arbitrary<T>
功能:为 HashSet<T> 实现了 Arbitrary 接口,且 T 需实现 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<HashSet<T>>
功能:获取生成 HashSet<T> 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<HashSet<T>> - 生成 HashSet<T> 类型随机值生成器。
extend<K, V> HashMap<K, V> <: Arbitrary<HashMap<K, V>> where K <: Arbitrary<K>, V <: Arbitrary<V>
extend<K, V> HashMap<K, V> <: Arbitrary<HashMap<K, V>> where K <: Arbitrary<K>, V <: Arbitrary<V>
功能:为 HashMap<T> 实现了 Arbitrary 接口,且 T 需实现 Arbitrary<T> 接口。
父类型:
static func arbitrary(RandomSource)
static func arbitrary(random: RandomSource): Generator<HashMap<K, V>>
功能:获取生成 HashMap<K, V> 类型随机值生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<HashMap<K, V>> - 生成 HashMap<K, V> 类型随机值生成器。
interface IndexAccess
public interface IndexAccess {
func getElementAsAny(index: Int64): ?Any
}
功能:通过索引访问元组元素的实用程序接口。
func getElementAsAny(Int64)
func getElementAsAny(index: Int64): ?Any
功能:通过索引访问元组元素。
参数:
- index: Int64 - 索引值。
返回值:
- ?Any - 元素值。若未获取到则为
None。
interface RandomSource
public interface RandomSource {
func nextBool(): Bool
func nextInt8(): Int8
func nextInt16(): Int16
func nextInt32(): Int32
func nextInt64(): Int64
func nextInt8(max: Int8): Int8
func nextInt16(max: Int16): Int16
func nextInt32(max: Int32): Int32
func nextInt64(max: Int64): Int64
func nextUInt8(): UInt8
func nextUInt16(): UInt16
func nextUInt32(): UInt32
func nextUInt64(): UInt64
func nextUInt8(max: UInt8): UInt8
func nextUInt16(max: UInt16): UInt16
func nextUInt32(max: UInt32): UInt32
func nextUInt64(max: UInt64): UInt64
func nextFloat16(): Float16
func nextFloat32(): Float32
func nextFloat64(): Float64
func nextGaussianFloat64(mean!: Float64, sigma!: Float64): Float64
func nextIntNative(): IntNative
func nextUIntNative(): UIntNative
func suggestUInt8(): UInt8
func suggestUInt16(): UInt16
func suggestUInt32(): UInt32
func suggestUInt64(): UInt64
func suggestUIntNative(): UIntNative
func suggestInt8(): Int8
func suggestInt16(): Int16
func suggestInt32(): Int32
func suggestInt64(): Int64
func suggestIntNative(): IntNative
func suggestFloat16(): Float16
func suggestFloat32(): Float32
func suggestFloat64(): Float64
func suggestBool(): Bool
func suggestRune(): Rune
}
功能:提供 Arbitrary 所需的随机生成基础类型数据的能力。
func nextBool()
public open func nextBool(): Bool
功能:获取一个布尔类型的伪随机值。
返回值:
func nextFloat16()
public open func nextFloat16(): Float16
功能:获取一个 Float16 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
func nextFloat32()
public open func nextFloat32(): Float32
功能:获取一个 Float32 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
func nextFloat64()
public open func nextFloat64(): Float64
功能:获取一个 Float64 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
func nextGaussianFloat64(Float64, Float64)
public func nextGaussianFloat64(mean!: Float64 = 0.0, sigma!: Float64 = 1.0): Float64
功能:获取一个 Float64 类型的符合指定均值与标准差的高斯分布的随机数。
默认获取一个 Float64 类型且符合均值为 0.0 标准差为 1.0 的高斯分布的随机数。其中均值是期望值,可解释为位置参数,决定了分布的位置,标准差可解释为尺度参数,决定了分布的幅度。此函数调用了函数 nextGaussianFloat64Implement 得到返回值,所以当子类继承 Random 并覆写 nextGaussianFloat64Implement 函数时,调用子类的该函数将会返回覆写的函数的返回值。
参数:
返回值:
func nextInt16()
public open func nextInt16(): Int16
功能:获取一个 Int16 类型的伪随机数。
返回值:
func nextInt16(Int16)
public open func nextInt16(upper: Int16): Int16
功能:获取一个范围在 [0, upper) 的 Int16 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
func nextInt32()
public open func nextInt32(): Int32
功能:获取一个 Int32 类型的伪随机数。
返回值:
func nextInt32(Int32)
public open func nextInt32(upper: Int32): Int32
功能:获取一个范围在 [0, upper) 的 Int32 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
func nextInt64()
public open func nextInt64(): Int64
功能:获取一个 Int64 类型的伪随机数。
返回值:
func nextInt64(Int64)
public open func nextInt64(upper: Int64): Int64
功能:获取一个范围在 [0, upper) 的 Int64 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
func nextInt8()
public open func nextInt8(): Int8
功能:获取一个 Int8 类型的伪随机数。
返回值:
func nextInt8(Int8): Int8
public open func nextInt8(upper: Int8): Int8
功能:获取一个范围在 [0, upper) 的 Int8 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper小于等于 0,抛出异常。
func nextIntNative():IntNative
public func nextIntNative(): IntNative
功能:获取一个 IntNative 类型的伪随机数。
返回值:
func nextUInt16()
public open func nextUInt16(): UInt16
功能:获取一个 UInt16 类型的伪随机数。
返回值:
func nextUInt16(UInt16)
public open func nextUInt16(upper: UInt16): UInt16
功能:获取一个范围在 [0, upper) 的 UInt16 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
func nextUInt32()
public open func nextUInt32(): UInt32
功能:获取一个 UInt32 类型的伪随机数。
返回值:
func nextUInt32(UInt32)
public open func nextUInt32(upper: UInt32): UInt32
功能:获取一个范围在 [0, upper) 的 UInt32 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
func nextUInt64()
public open func nextUInt64(): UInt64
功能:获取一个 UInt64 类型的伪随机数。
返回值:
func nextUInt64(UInt64)
public open func nextUInt64(upper: UInt64): UInt64
功能:获取一个范围在 [0, upper) 的 UInt64 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
func nextUInt8()
public open func nextUInt8(): UInt8
功能:获取一个 UInt8 类型的伪随机数。
返回值:
func nextUInt8(UInt8)
public open func nextUInt8(upper: UInt8): UInt8
功能:获取一个范围在 [0, upper) 的 UInt8 类型的伪随机数。
参数:
返回值:
异常:
- IllegalArgumentException - 如果
upper等于 0,抛出异常。
func nextUIntNative():UIntNative
public func nextUIntNative(): UIntNative
功能:获取一个 UIntNative 类型的伪随机数。
返回值:
- UIntNative - 一个 UIntNative 类型的伪随机数。
func suggestBool()
public open func suggestBool(): Bool
功能:获取一个布尔类型的伪随机值。
返回值:
func suggestRune()
public open func suggestRune(): Rune
功能:获取一个 Rune 类型的伪随机值。
返回值:
func suggestFloat16()
public open func suggestFloat16(): Float16
功能:获取一个 Float16 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
func suggestFloat32()
public open func suggestFloat32(): Float32
功能:获取一个 Float32 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
func suggestFloat64()
public open func suggestFloat64(): Float64
功能:获取一个 Float64 类型的伪随机数,其范围为 [0.0, 1.0)。
返回值:
func suggestInt16()
public open func suggestInt16(): Int16
功能:获取一个 Int16 类型的伪随机数。
返回值:
func suggestInt32()
public open func suggestInt32(): Int32
功能:获取一个 Int32 类型的伪随机数。
返回值:
func suggestInt64()
public open func suggestInt64(): Int64
功能:获取一个 Int64 类型的伪随机数。
返回值:
func suggestInt8()
public open func suggestInt8(): Int8
功能:获取一个 Int8 类型的伪随机数。
返回值:
func suggestIntNative():IntNative
public func suggestIntNative(): IntNative
功能:获取一个 IntNative 类型的伪随机数。
返回值:
func suggestUInt16()
public open func suggestUInt16(): UInt16
功能:获取一个 UInt16 类型的伪随机数。
返回值:
func suggestUInt32()
public open func suggestUInt32(): UInt32
功能:获取一个 UInt32 类型的伪随机数。
返回值:
func suggestUInt64()
public open func suggestUInt64(): UInt64
功能:获取一个 UInt64 类型的伪随机数。
返回值:
func suggestUInt8()
public open func suggestUInt8(): UInt8
功能:获取一个 UInt8 类型的伪随机数。
返回值:
func suggestUIntNative():UIntNative
public func suggestUIntNative(): UIntNative
功能:获取一个 UIntNative 类型的伪随机数。
返回值:
- UIntNative - 一个 UIntNative 类型的伪随机数。
interface Shrink<T>
public interface Shrink<T> {
func shrink(): Iterable<T>
}
功能:将 T 类型的值缩减到多个“更小”的值。
func shrink()
func shrink(): Iterable<T>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<T> - 一组可能的“较小”值的迭代器。
extend Bool <: Shrink<Bool>
extend Bool <: Shrink<Bool>
父类型:
func shrink()
func shrink(): Iterable<Bool>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Bool> - 一组可能的“较小”值的迭代器。
extend Int16 <: Shrink<Int16>
extend Int16 <: Shrink<Int16>
父类型:
func shrink()
func shrink(): Iterable<Int16>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Int16> - 一组可能的“较小”值的迭代器。
extend Int32 <: Shrink<Int32>
extend Int32 <: Shrink<Int32>
父类型:
func shrink()
func shrink(): Iterable<Int32>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Int32> - 一组可能的“较小”值的迭代器。
extend Int64 <: Shrink<Int64>
extend Int64 <: Shrink<Int64>
父类型:
func shrink()
func shrink(): Iterable<Int64>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Int64> - 一组可能的“较小”值的迭代器。
extend Int8 <: Shrink<Int8>
extend Int8 <: Shrink<Int8>
父类型:
func shrink()
func shrink(): Iterable<Int8>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Int8> - 一组可能的“较小”值的迭代器。
extend IntNative <: Shrink<IntNative>
extend IntNative <: Shrink<IntNative>
功能:为 IntNative 实现了 Shrink<T> 接口。
父类型:
func shrink()
func shrink(): Iterable<IntNative>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<IntNative> - 一组可能的“较小”值的迭代器。
extend Rune <: Shrink<Rune>
extend Rune <: Shrink<Rune>
父类型:
func shrink()
func shrink(): Iterable<Rune>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Rune> - 一组可能的“较小”值的迭代器。
extend String <: Shrink<String>
extend String <: Shrink<String>
父类型:
func shrink()
func shrink(): Iterable<String>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<String> - 一组可能的“较小”值的迭代器。
extend UInt16 <: Shrink<UInt16>
extend UInt16 <: Shrink<UInt16>
父类型:
func shrink()
func shrink(): Iterable<UInt16>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<UInt16> - 一组可能的“较小”值的迭代器。
extend UInt32 <: Shrink<UInt32>
extend UInt32 <: Shrink<UInt32>
父类型:
func shrink()
func shrink(): Iterable<UInt32>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<UInt32> - 一组可能的“较小”值的迭代器。
extend UInt64 <: Shrink<UInt64>
extend UInt64 <: Shrink<UInt64>
父类型:
func shrink()
func shrink(): Iterable<UInt64>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<UInt64> - 一组可能的“较小”值的迭代器。
extend UInt8 <: Shrink<UInt8>
extend UInt8 <: Shrink<UInt8>
父类型:
func shrink()
func shrink(): Iterable<UInt8>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<UInt8> - 一组可能的“较小”值的迭代器。
extend UIntNative <: Shrink<UIntNative>
extend UIntNative <: Shrink<UIntNative>
功能:为 UIntNative 实现了 Shrink<T> 接口。
父类型:
func shrink()
func shrink(): Iterable<UIntNative>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<UIntNative> - 一组可能的“较小”值的迭代器。
extend Unit <: Shrink<Unit>
extend Unit <: Shrink<Unit>
父类型:
func shrink()
func shrink(): Iterable<Unit>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Unit> - 一组可能的“较小”值的迭代器。
extend Float16 <: Shrink<Float16>
extend Float16 <: Shrink<Float16>
功能:为 Float16 实现了 Shrink<T> 接口。
父类型:
func shrink()
func shrink(): Iterable<Float16>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Float16> - 一组可能的“较小”值的迭代器。
extend Float32 <: Shrink<Float32>
extend Float32 <: Shrink<Float32>
功能:为 Float32 实现了 Shrink<T> 接口。
父类型:
func shrink()
func shrink(): Iterable<Float32>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Float32> - 一组可能的“较小”值的迭代器。
extend Float64 <: Shrink<Float64>
extend Float64 <: Shrink<Float64>
功能:为 Float64 实现了 Shrink<T> 接口。
父类型:
func shrink()
func shrink(): Iterable<Float64>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Float64> - 一组可能的“较小”值的迭代器。
extend<T> Array<T> <: Shrink<Array<T>>
extend<T> Array<T> <: Shrink<Array<T>>
功能:为 Array<T> 实现了 Shrink<Array<T>> 接口。
父类型:
func shrink()
func shrink(): Iterable<Array<T>>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Array<T>> - 一组可能的“较小”值的迭代器。
extend<T> Option<T> <: Shrink<Option<T>>
extend<T> Option<T> <: Shrink<Option<T>>
功能:为 Option<T> 实现了 Shrink<Option<T>> 接口。
父类型:
func shrink()
func shrink(): Iterable<Option<T>>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<Option<T>> - 一组可能的“较小”值的迭代器。
extend<T> ArrayList<T> <: Shrink<ArrayList<T>>
extend<T> ArrayList<T> <: Shrink<ArrayList<T>>
功能:为 ArrayList<T> 实现了 Shrink<ArrayList<T>> 接口。
父类型:
func shrink()
func shrink(): Iterable<ArrayList<T>>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<ArrayList<T>> - 一组可能的“较小”值的迭代器。
extend<T> HashSet<T> <: Shrink<HashSet<T>>
extend<T> HashSet<T> <: Shrink<HashSet<T>>
功能:为 HashSet<T> 实现了 Shrink<HashSet<T>> 接口。
父类型:
func shrink()
func shrink(): Iterable<HashSet<T>>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<HashSet<T>> - 一组可能的“较小”值的迭代器。
extend<K, V> HashMap<K, V> <: Shrink<HashMap<K, V>>
extend<K, V> HashMap<K, V> <: Shrink<HashMap<K, V>>
功能:为 HashMap<T> 实现了 Shrink<HashMap<T>> 接口。
父类型:
func shrink()
func shrink(): Iterable<HashMap<K, V>>
功能:将该值缩小为一组可能的“较小”值。
返回值:
- Iterable<HashMap<K, V>> - 一组可能的“较小”值的迭代器。
类
class Generators
public class Generators {}
功能:包含辅助函数的类,可帮助开发人员编写自己的生成器。
static func generate<T>(() -> T)
public static func generate<T>(body: () -> T): Generator<T>
功能:通过重复调用函数生成值的生成器。
参数:
- body: () -> T - 被调用的生成器闭包。
返回值:
- Generator<T> - 生成器。
static func iterable<T>(RandomSource, Array<T>)
public static func iterable<T>(random: RandomSource, collection: Array<T>): Generator<T>
功能:通过从数组中随机选取来生成值的生成器。
参数:
- random: RandomSource - 随机数。
- collection: Array<T> - 被选取数字的数组。
返回值:
- Generator<T> - 生成器。
static func lookup<T>(RandomSource) where T <: Arbitrary<T>
public static func lookup<T>(random: RandomSource): Generator<T> where T <: Arbitrary<T>
功能:通过 T 的 Arbitrary 实例提供的生成器。
参数:
- random: RandomSource - 随机数。
返回值:
- Generator<T> - 生成器。
static func mapped<T, R>(RandomSource,(T) -> R) where T <: Arbitrary<T>
public static func mapped<T, R>(random: RandomSource, body: (T) -> R): Generator<R> where T <: Arbitrary<T>
功能:获取 T 的 Arbitrary 实例提供的生成器,并使用函数体生成 R 类型的值。
参数:
- random: RandomSource - 随机数。
- body: (T) -> R - 生成 R 类型的值。
返回值:
- Generator<T> - 生成器。
static func mapped<T1, T2, R>(RandomSource, (T1, T2) -> R) where T1 <: Arbitrary<T1>, T2 <: Arbitrary<T2>
public static func mapped<T1, T2, R>(random: RandomSource, body: (T1, T2) -> R): Generator<R> where T1 <: Arbitrary<T1>, T2 <: Arbitrary<T2>
功能:获取 T1,T2 的 Arbitrary 实例提供的生成器,并使用函数体生成 R 类型的值。
参数:
- random: RandomSource - 随机数。
- body: (T1, T2) -> R - 生成 R 类型的值。
返回值:
- Generator<T> - 生成器。
static func mapped<T1, T2, T3, R>(RandomSource, (T1, T2, T3) -> R) where T1 <: Arbitrary<T1>, T2 <: Arbitrary<T2>, T3 <: Arbitrary<T3>
public static func mapped<T1, T2, T3, R>(random: RandomSource, body: (T1, T2, T3) -> R): Generator<R>
where T1 <: Arbitrary<T1>, T2 <: Arbitrary<T2>, T3 <: Arbitrary<T3>
功能:获取 T1,T2,T3 的 Arbitrary 实例提供的生成器,并使用函数体生成 R 类型的值。
参数:
- random: RandomSource - 随机数。
- body: (T1, T2,T3) -> R - 生成 R 类型的值。
返回值:
- Generator<T> - 生成器。
static func mapped<T1, T2, T3, T4, R>(RandomSource, (T1, T2, T3, T4) -> R) where T1 <: Arbitrary<T1>, T2 <: Arbitrary<T2>, T3 <: Arbitrary<T3>, T4 <: Arbitrary<T4>
public static func mapped<T1, T2, T3, T4, R>(random: RandomSource, body: (T1, T2, T3, T4) -> R): Generator<R>
where T1 <: Arbitrary<T1>, T2 <: Arbitrary<T2>, T3 <: Arbitrary<T3>, T4 <: Arbitrary<T4>
功能:获取 T1,T2,T3,T4 的 Arbitrary 实例提供的生成器,并使用函数体生成 R 类型的值。
参数:
- random: RandomSource - 随机数。
- body: (T1, T2,T3,T4) -> R - 生成 R 类型的值。
返回值:
- Generator<T> - 生成器。
static func pick<T>(RandomSource, Array<Generator<T>>)
public static func pick<T>(random: RandomSource, variants: Array<Generator<T>>): Generator<T>
功能:通过从生成器数组中随机选取来生成值的生成器。
参数:
- random: RandomSource - 随机数。
- variants: Array<Generator<T>> - 生成器数组。
返回值:
- Generator<T> - 生成器。
static func single<T>(T)
public static func single<T>(value: T): Generator<T>
功能:生成器始终返回同一个值。
参数:
- value: T - 生成器返回的值。
返回值:
- Generator<T> - 生成器。
static func weighted<T>(RandomSource, Array<(UInt64, Generator<T>)>)
public static func weighted<T>(random: RandomSource, variants: Array<(UInt64, Generator<T>)>): Generator<T>
功能:通过从成对数组(权重、生成器)中随机选取来生成值的生成器。
参数:
- random: RandomSource - 随机数。
- variants: Array<(UInt64, Generator<T>)> - 数组(权重、生成器)。
返回值:
- Generator<T> - 生成器。
class LazySeq<T>
public class LazySeq<T> <: Iterable<T> {
public init()
public init(element: T)
}
功能:延迟计算的 T 类型值序列。用于在迭代时计算和记忆值。 这是完全不可变的,每次操作都会产生一个新的序列。
父类型:
- Iterable<T>
init()
public init()
功能:构造器。
init(T)
public init(element: T)
功能:构造器。
参数:
- element: T - 初始元素。
func append(T)
public func append(element: T): LazySeq<T>
功能:增加一个元素。
参数:
- element: T - 被增加的元素。
返回值:
- LazySeq<T> - 增加元素后的序列。
func concat(LazySeq<T>)
public func concat(other: LazySeq<T>): LazySeq<T>
功能:增加一个序列到此序列中。复杂度为 O(1) 。
参数:
- other: LazySeq<T> - 被增加的序列。
返回值:
- LazySeq<T> - 增加元素后的序列。
func iterator()
public func iterator(): Iterator<T>
功能:实现序列的迭代器。
返回值:
- Iterator<T> - 序列迭代器。
func map<U>((T) -> U)
public func map<U>(body: (T) -> U): LazySeq<U>
功能:对序列中的每个元素执行闭包处理。
参数:
- body: (T) -> U - 对每个元素执行的闭包。
返回值:
- LazySeq<U> - 处理后的序列。
func mixWith(LazySeq<T>)
public func mixWith(other: LazySeq<T>): LazySeq<T>
功能:将新序列穿插进原序列中。
例如:{1,2,3,4}.mixWith({5,6,7}) -> {1,5,2,6,3,7,4}
参数:
- other: LazySeq<T> - 待插入的序列。
返回值:
- LazySeq<U> - 处理后的序列。
func prepend(T)
public func prepend(element: T): LazySeq<T>
功能:将新序列插进原序列的开头。
参数:
- other: LazySeq<T> - 待插入的序列。
返回值:
- LazySeq<U> - 处理后的序列。
static func mix(LazySeq<T>,LazySeq<T>)
public static func mix(l1: LazySeq<T>, l2: LazySeq<T>)
功能:两个序列穿插混合成一个。
例如:mix({1,2,3,4}, {5,6,7}) -> {1,5,2,6,3,7,4}
参数:
返回值:
- LazySeq<U> - 处理后的序列。
static func mix(LazySeq<T>,LazySeq<T>,LazySeq<T>)
public static func mix(l1: LazySeq<T>, l2: LazySeq<T>, l3: LazySeq<T>)
功能:三个序列穿插混合成一个。
参数:
返回值:
- LazySeq<U> - 处理后的序列。
static func mix(LazySeq<T>,LazySeq<T>,LazySeq<T>,LazySeq<T>)
public static func mix(l1: LazySeq<T>, l2: LazySeq<T>, l3: LazySeq<T>, l4: LazySeq<T>)
功能:四个序列穿插混合成一个。
参数:
返回值:
- LazySeq<U> - 处理后的序列。
static func mix(LazySeq<T>,LazySeq<T>,LazySeq<T>,LazySeq<T>,LazySeq<T>)
public static func mix(l1: LazySeq<T>, l2: LazySeq<T>, l3: LazySeq<T>, l4: LazySeq<T>, l5: LazySeq<T>)
功能:五个序列穿插混合成一个。
参数:
- l1: LazySeq<T> - 待穿插的序列。
- l2: LazySeq<T> - 待穿插的序列。
- l3: LazySeq<T> - 待穿插的序列。
- l4: LazySeq<T> - 待穿插的序列。
- l5: LazySeq<T> - 待穿插的序列。
返回值:
- LazySeq<U> - 处理后的序列。
static func of(Iterable<T>)
public static func of(iterable: Iterable<T>)
功能:从迭代器构造一个序列。
参数:
- iterable: Iterable<T> - 待处理的迭代器。
返回值:
- LazySeq<U> - 处理后的序列。
static func of(Array<T>)
public static func of(array: Array<T>)
功能:从数组构造一个序列。
参数:
- array: Array<T> - 待处理的数组。
返回值:
- LazySeq<U> - 处理后的序列。
class ShrinkHelpers
public class ShrinkHelpers {}
功能:提供对元组实现缩减迭代器的方法。
static func shrinkTuple<T0, T1>((T0, T1),Iterable<T0>,Iterable<T1>)
public static func shrinkTuple<T0, T1>(
tuple: (T0, T1),
t0: Iterable<T0>,
t1: Iterable<T1>
): Iterable<(T0, T1)>
功能:实现元组的缩减迭代器。
参数:
返回值:
- Iterable<(T0, T1)> - 元组缩减迭代器。
static func shrinkTuple<T0, T1, T2>((T0, T1, T2),Iterable<T0>,Iterable<T1>,Iterable<T2>)
public static func shrinkTuple<T0, T1, T2>(
tuple: (T0, T1, T2),
t0: Iterable<T0>,
t1: Iterable<T1>,
t2: Iterable<T2>
): Iterable<(T0, T1, T2)>
功能:实现元组的缩减迭代器。
参数:
- tuple: (T0, T1, T2) - 被缩减的元组。
- t0: Iterable<T0> - 第一个元组成员的缩减迭代器。
- t1: Iterable<T1> - 第二个元组成员的缩减迭代器。
- t2: Iterable<T2> - 第三个元组成员的缩减迭代器。
返回值:
- Iterable<(T0, T1, T2)> - 元组缩减迭代器。
static func shrinkTuple<T0, T1, T2, T3>((T0, T1, T2, T3),Iterable<T0>,Iterable<T1>,Iterable<T2>,Iterable<T3>)
public static func shrinkTuple<T0, T1, T2, T3>(
tuple: (T0, T1, T2, T3),
t0: Iterable<T0>,
t1: Iterable<T1>,
t2: Iterable<T2>,
t3: Iterable<T3>
): Iterable<(T0, T1, T2, T3)>
功能:实现元组的缩减迭代器。
参数:
- tuple: (T0, T1, T2, T3) - 被缩减的元组。
- t0: Iterable<T0> - 第一个元组成员的缩减迭代器。
- t1: Iterable<T1> - 第二个元组成员的缩减迭代器。
- t2: Iterable<T2> - 第三个元组成员的缩减迭代器。
- t3: Iterable<T3> - 第四个元组成员的缩减迭代器。
返回值:
- Iterable<(T0, T1, T2,T3)> - 元组缩减迭代器。
static func shrinkTuple<T0, T1, T2, T3, T4>((T0, T1, T2, T3, T4),Iterable<T0>,Iterable<T1>,Iterable<T2>,Iterable<T3>,Iterable<T4>)
public static func shrinkTuple<T0, T1, T2, T3, T4>(
tuple: (T0, T1, T2, T3, T4),
t0: Iterable<T0>,
t1: Iterable<T1>,
t2: Iterable<T2>,
t3: Iterable<T3>,
t4: Iterable<T4>
): Iterable<(T0, T1, T2, T3, T4)>
功能:实现元组的缩减迭代器。
参数:
- tuple: (T0, T1, T2, T3, T4) - 被缩减的元组。
- t0: Iterable<T0> - 第一个元组成员的缩减迭代器。
- t1: Iterable<T1> - 第二个元组成员的缩减迭代器。
- t2: Iterable<T2> - 第三个元组成员的缩减迭代器。
- t3: Iterable<T3> - 第四个元组成员的缩减迭代器。
- t4: Iterable<T4> - 第五个元组成员的缩减迭代器。
返回值:
- Iterable<(T0, T1, T2,T3,T4)> - 元组缩减迭代器。
结构体
struct Function0Wrapper<R>
public struct Function0Wrapper<R> {
public Function0Wrapper(public let function: () -> R)
}
功能:将闭包封装为结构体。
Function0Wrapper(() -> R)
public Function0Wrapper(public let function: () -> R)
功能:Function0Wrapper构造器。
参数:
- function: () -> R - 被封装的闭包。
operator func ()()
public operator func () (): R
功能:调用操作符函数。将闭包转换为结构体的调用操作符函数。
返回值:
- R - 同闭包的返回值。
extend<R> Function0Wrapper<R> <: Arbitrary<Function0Wrapper<R>> where R <: Arbitrary<R>
extend<R> Function0Wrapper<R> <: Arbitrary<Function0Wrapper<R>> where R <: Arbitrary<R>
功能:为 Function0Wrapper 扩展 Arbitrary 实现。
父类型:
static func arbitrary(RandomSource)
public static func arbitrary(random: RandomSource): Generator<Function0Wrapper<R>>
功能:获取生成 Function0Wrapper<R> 类型随机值生成器。
struct TupleWrapper2<T0, T1>
public struct TupleWrapper2<T0, T1> {
public TupleWrapper2(public let tuple: (T0, T1))
}
功能:将闭包封装为结构体。闭包带两个参数。
TupleWrapper2((T0, T1))
public TupleWrapper2(public let tuple: (T0, T1))
功能:TupleWrapper2构造器。
参数:
- tuple: (T0, T1) - 闭包的两个入参。
func apply<R>(f: (T0, T1) -> R)
public func apply<R>(f: (T0, T1) -> R): R
功能:执行闭包函数。
参数:
- f: (T0, T1) -> R - 待执行的闭包。
返回值:
- R - 闭包的执行结果。
extend<T0, T1> TupleWrapper2<T0, T1> <: ToString
extend<T0, T1> TupleWrapper2<T0, T1> <: ToString
功能:为 TupleWrapper2 扩展 ToString 实现。
父类型:
func toString()
public func toString()
功能:TupleWrapper2 的字符串表达。
extend<T0, T1> TupleWrapper2<T0, T1> <: Equatable<TupleWrapper2<T0, T1>>
extend<T0, T1> TupleWrapper2<T0, T1> <: Equatable<TupleWrapper2<T0, T1>>
功能:为 TupleWrapper2 扩展 Equatable 实现。
父类型:
- Equatable<TupleWrapper2<T0, T1>>
operator func ==(TupleWrapper2<T0, T1>)
public operator func ==(other: TupleWrapper2<T0, T1>)
功能:比较两个二元元组。
参数:
- other: TupleWrapper2<T0, T1> - 待比较的元组。
返回值:
- Bool - 相等时返回
true,否则返回false。
operator func !=(TupleWrapper2<T0, T1>)
public operator func !=(other: TupleWrapper2<T0, T1>)
功能:比较两个二元元组。
参数:
- other: TupleWrapper2<T0, T1> - 待比较的元组。
返回值:
- Bool - 不相等时返回
true,否则返回false。
extend<T0, T1> TupleWrapper2<T0, T1> <: IndexAccess
extend<T0, T1> TupleWrapper2<T0, T1> <: IndexAccess
功能:为 TupleWrapper2 扩展 IndexAccess 实现。
父类型:
func getElementAsAny(Int64)
public func getElementAsAny(index: Int64): ?Any
功能:按索引获取元组内的值。
参数:
- index: Int64 - 索引值。
返回值:
- ?Any - 获取到的元组内的值。索引不合法时返回
None。
extend<T0, T1> TupleWrapper2<T0, T1> <: Arbitrary<TupleWrapper2<T0, T1>> where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>
extend<T0, T1> TupleWrapper2<T0, T1> <: Arbitrary<TupleWrapper2<T0, T1>> where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>
功能:为 TupleWrapper2 扩展 Arbitrary 实现。
父类型:
- Arbitrary<TupleWrapper2<T0, T1>>
static func arbitrary(RandomSource)
public static func arbitrary(random: RandomSource): Generator<TupleWrapper2<T0, T1>>
功能:获取生成 TupleWrapper2<T0, T1> 类型随机值生成器。
struct TupleWrapper3<T0, T1, T2>
public struct TupleWrapper3<T0, T1, T2> {
public TupleWrapper3(public let tuple: (T0, T1,T2))
}
功能:将闭包封装为结构体。闭包带两个参数。
TupleWrapper3((T0, T1,T2))
public TupleWrapper3(public let tuple: (T0, T1,T2))
功能:TupleWrapper3构造器。
参数:
- tuple: (T0, T1,T2) - 闭包的两个入参。
func apply<R>(f: (T0, T1,T2) -> R)
public func apply<R>(f: (T0, T1,T2) -> R): R
功能:执行闭包函数。
参数:
- f: (T0, T1,T2) -> R - 待执行的闭包。
返回值:
- R - 闭包的执行结果。
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: ToString
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: ToString
功能:为 TupleWrapper3 扩展 ToString 实现。
父类型:
func toString()
public func toString()
功能:TupleWrapper3 的字符串表达。
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: Equatable<TupleWrapper3<T0, T1, T2>>
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: Equatable<TupleWrapper3<T0, T1, T2>>
功能:为 TupleWrapper3 扩展 Equatable 实现。
父类型:
- Equatable<TupleWrapper3<T0, T1, T2>>
operator func ==(TupleWrapper3<T0, T1, T2>)
public operator func ==(other: TupleWrapper3<T0, T1, T2>)
功能:比较两个元组。
参数:
- other: TupleWrapper3<T0, T1, T2> - 待比较的元组。
返回值:
- Bool - 相等时返回
true,否则返回false。
operator func !=(TupleWrapper3<T0, T1, T2>)
public operator func !=(other: TupleWrapper3<T0, T1, T2>)
功能:比较两个元组。
参数:
- other: TupleWrapper3<T0, T1, T2> - 待比较的元组。
返回值:
- Bool - 不相等时返回
true,否则返回false。
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: IndexAccess
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: IndexAccess
功能:为 TupleWrapper3 扩展 IndexAccess 实现。
父类型:
func getElementAsAny(Int64)
public func getElementAsAny(index: Int64): ?Any
功能:按索引获取元组内的值。
参数:
- index: Int64 - 索引值。
返回值:
- ?Any - 获取到的元组内的值。索引不合法时返回
None。
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: Arbitrary<TupleWrapper3<T0, T1, T2>> where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>,T2 <: Arbitrary<T2>
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: Arbitrary<TupleWrapper3<T0, T1, T2>> where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>,T2 <: Arbitrary<T2>
功能:为 TupleWrapper3 扩展 Arbitrary 实现。
父类型:
- Arbitrary<TupleWrapper3<T0, T1, T2>>
static func arbitrary(RandomSource)
public static func arbitrary(random: RandomSource): Generator<TupleWrapper3<T0, T1, T2>>
功能:获取生成 TupleWrapper3<T0, T1, T2> 类型随机值生成器。
struct TupleWrapper4<T0, T1, T2, T3>
public struct TupleWrapper4<T0, T1, T2, T3> {
public TupleWrapper4(public let tuple: (T0, T1, T2, T3))
}
功能:将闭包封装为结构体。闭包带两个参数。
TupleWrapper4((T0, T1, T2, T3))
public TupleWrapper4(public let tuple: (T0, T1, T2, T3))
功能:TupleWrapper4构造器。
参数:
- tuple: (T0, T1, T2, T3) - 闭包的4个入参。
func apply<R>(f: (T0, T1, T2, T3) -> R)
public func apply<R>(f: (T0, T1, T2, T3) -> R): R
功能:执行闭包函数。
参数:
- f: (T0, T1, T2, T3) -> R - 待执行的闭包。
返回值:
- R - 闭包的执行结果。
extend<T0, T1, T2, T3> TupleWrapper4<T0, T1, T2, T3> <: ToString
extend<T0, T1, T2, T3> TupleWrapper4<T0, T1, T2, T3> <: ToString
功能:为 TupleWrapper4 扩展 ToString 实现。
父类型:
func toString()
public func toString()
功能:TupleWrapper4 的字符串表达。
extend<T0, T1, T2, T3> TupleWrapper4<T0, T1, T2, T3> <: Equatable<TupleWrapper4<T0, T1, T2, T3>>
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: Equatable<TupleWrapper3<T0, T1, T2>>
功能:为 TupleWrapper4 扩展 Equatable 实现。
父类型:
- Equatable<TupleWrapper3<T0, T1, T2>>
operator func ==(TupleWrapper4<T0, T1, T2, T3>)
public operator func ==(other: TupleWrapper4<T0, T1, T2, T3>)
功能:比较两个元组。
参数:
- other: TupleWrapper4<T0, T1, T2, T3> - 待比较的元组。
返回值:
- Bool - 相等时返回
true,否则返回false。
operator func !=(TupleWrapper4<T0, T1, T2, T3>)
public operator func !=(other: TupleWrapper4<T0, T1, T2, T3>)
功能:比较两个元组。
参数:
- other: TupleWrapper4<T0, T1, T2, T3> - 待比较的元组。
返回值:
- Bool - 不相等时返回
true,否则返回false。
extend<T0, T1, T2, T3> TupleWrapper4<T0, T1, T2, T3> <: IndexAccess
extend<T0, T1, T2, T3> TupleWrapper4<T0, T1, T2, T3> <: IndexAccess
功能:为 TupleWrapper4 扩展 IndexAccess 实现。
父类型:
func getElementAsAny(Int64)
public func getElementAsAny(index: Int64): ?Any
功能:按索引获取元组内的值。
参数:
- index: Int64 - 索引值。
返回值:
- ?Any - 获取到的元组内的值。索引不合法时返回
None。
extend<T0, T1, T2, T3> TupleWrapper4<T0, T1, T2, T3><: Arbitrary<TupleWrapper4<T0, T1, T2, T3>> where where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>,T2 <: Arbitrary<T2>,T3 <: Arbitrary<T3>
extend<T0, T1, T2, T3> TupleWrapper4<T0, T1, T2, T3><: Arbitrary<TupleWrapper4<T0, T1, T2, T3>> where where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>,T2 <: Arbitrary<T2>,T3 <: Arbitrary<T3>
功能:为 TupleWrapper4 扩展 Arbitrary 实现。
父类型:
- Arbitrary<TupleWrapper4<T0, T1, T2, T3>>
static func arbitrary(RandomSource)
public static func arbitrary(random: RandomSource): Generator<TupleWrapper2<T0, T1, T2, T3>>
功能:获取生成 TupleWrapper4<T0, T1, T2, T3> 类型随机值生成器。
struct TupleWrapper5<T0, T1, T2, T3, T4>
public struct TupleWrapper5<T0, T1, T2, T3, T4> {
public TupleWrapper5(public let tuple: (T0, T1, T2, T3, T4))
}
功能:将闭包封装为结构体。闭包带两个参数。
TupleWrapper5((T0, T1, T2, T3, T4))
public TupleWrapper5(public let tuple: (T0, T1, T2, T3, T4))
功能:TupleWrapper5构造器。
参数:
- tuple: (T0, T1, T2, T3, T4) - 闭包的5个入参。
func apply<R>(f: (T0, T1, T2, T3, T4) -> R)
public func apply<R>(f: (T0, T1, T2, T3, T4) -> R): R
功能:执行闭包函数。
参数:
- f: (T0, T1, T2, T3, T4) -> R - 待执行的闭包。
返回值:
- R - 闭包的执行结果。
extend<T0, T1, T2, T3, T4> TupleWrapper5<T0, T1, T2, T3, T4> <: ToString
extend<T0, T1, T2, T3, T4> TupleWrapper5<T0, T1, T2, T3, T4> <: ToString
功能:为 TupleWrapper5 扩展 ToString 实现。
父类型:
func toString()
public func toString()
功能:TupleWrapper5 的字符串表达。
extend<T0, T1, T2, T3, T4> TupleWrapper5<T0, T1, T2, T3, T4> <: Equatable<TupleWrapper5<T0, T1, T2, T3, T4>>
extend<T0, T1, T2> TupleWrapper3<T0, T1, T2> <: Equatable<TupleWrapper3<T0, T1, T2>>
功能:为 TupleWrapper5 扩展 Equatable 实现。
父类型:
- Equatable<TupleWrapper3<T0, T1, T2>>
operator func ==(TupleWrapper5<T0, T1, T2, T3, T4>)
public operator func ==(other: TupleWrapper5<T0, T1, T2, T3, T4>)
功能:比较两个二元元组。
参数:
- other: TupleWrapper5<T0, T1, T2, T3> - 待比较的元组。
返回值:
- Bool - 相等时返回
true,否则返回false。
operator func !=(TupleWrapper5<T0, T1, T2, T3, T4>)
public operator func !=(other: TupleWrapper2<T0, T1, T2, T3, T4>)
功能:比较两个元组。
参数:
- other: TupleWrapper5<T0, T1, T2, T3, T4> - 待比较的元组。
返回值:
- Bool - 不相等时返回
true,否则返回false。
extend<T0, T1, T2, T3, T4> TupleWrapper5<T0, T1, T2, T3, T4> <: IndexAccess
extend<T0, T1, T2, T3, T4> TupleWrapper5<T0, T1, T2, T3, T4> <: IndexAccess
功能:为 TupleWrapper5 扩展 IndexAccess 实现。
父类型:
func getElementAsAny(Int64)
public func getElementAsAny(index: Int64): ?Any
功能:按索引获取元组内的值。
参数:
- index: Int64 - 索引值。
返回值:
- ?Any - 获取到的元组内的值。索引不合法时返回
None。
extend<T0, T1, T2, T3, T4> TupleWrapper5<T0, T1, T2, T3, T4> <: Arbitrary<TupleWrapper2<T0, T1, T2, T3, T4>> where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>,T2 <: Arbitrary<T2>,T3 <: Arbitrary<T3>,T4 <: Arbitrary<T4>
extend<T0, T1, T2, T3, T4> TupleWrapper5<T0, T1, T2, T3, T4> <: Arbitrary<TupleWrapper2<T0, T1, T2, T3, T4>> where T0 <: Arbitrary<T0>,T1 <: Arbitrary<T1>,T2 <: Arbitrary<T2>,T3 <: Arbitrary<T3>,T4 <: Arbitrary<T4>
功能:为 TupleWrapper5 扩展 Arbitrary 实现。
父类型:
- Arbitrary<TupleWrapper2<T0, T1, T2, T3, T4>>
static func arbitrary(RandomSource)
public static func arbitrary(random: RandomSource): Generator<TupleWrapper5<T0, T1, T2, T3, T4>>
功能:获取生成 TupleWrapper5<T0, T1, T2, T3, T4> 类型随机值生成器。
仓颉语言 IDE 插件使用指南
仓颉语言提供了 Visual Studio Code(简称 VSCode) 插件,通过在 VSCode 中安装仓颉插件和仓颉 SDK,为开发者提供语言服务、工程管理、编译构建、调试服务、格式化、静态检查和代码覆盖率统计的功能。本文档介绍如何在 VSCode 中安装仓颉插件,以及如何使用插件提供的功能。
安装指导
说明:
本文档部分图片截取于 VSCode 软件界面,仅用于说明仓颉插件在 VSCode 中的使用方法。
下载软件
请在 VSCode 官网下载 VSCode 安装包,建议使用 1.67 或更新版本。仓颉语言 VS Code 插件已上架 VS Code 扩展市场,可以前往仓颉下载中心,点击Cangjie vscode plugin下面的立即查看,可以跳转到 VSCode 扩展市场进行安装,或在 VSCode 内部扩展界面直接进行安装。
| 下载项 | 说明 | 是否必选 |
|---|---|---|
| Visual Studio Code | IDE | 必选 |
安装 VSCode
Windows 平台
运行 VSCode 安装文件(例如 VSCodeUserSetup-x64.exe),根据提示选择安装路径,完成 VSCode 的安装。
Linux 平台
本地安装
参考 VSCode 官网安装适合的 Linux 发行版的 VSCode。
远程安装
-
在 VSCode 中搜索并安装 Remote - SSH 插件。
-
使用 Remote - SSH 进行远程工作,VSCode 会自动在远程主机上安装 Server。linux_arm64 暂时只支持使用 Remote - SSH 的方式进行操作。
macOS 平台
解压下载的压缩包(例如 VSCode-darwin-universal.zip),将解压后的 .app 文件拖拽到应用程序,完成 VSCode 的安装。
安装仓颉插件
仓颉插件可以通过 VSCode 扩展市场直接安装。
-
启动 VSCode。
-
点击左侧边栏的扩展图标进入扩展市场(或按 Ctrl+Shift+X/Cmd+Shift+X)。

-
搜索插件仓颉,在搜索栏输入关键词Cangjie,找到Cangjie插件后,点击 Install 按钮安装。

-
已经安装的插件可以在 INSTALLED 目录下查看。

安装仓颉 SDK
仓颉 SDK 主要提供了仓颉语言编译命令(cjc)、仓颉语言官方包管理工具(Cangjie Package Manager,简称 CJPM),以及仓颉格式化工具(Cangjie Formatter,简称 cjfmt)等命令行工具。正确安装并配置仓颉 SDK 后,可使用工程管理、编译构建、格式化、静态检查和覆盖率统计等功能。开发者可以通过以下两种方式下载 SDK:
- 离线手动安装。在官网下载 SDK 安装包,并在本地安装部署仓颉 SDK。
- 通过 VSCode 安装。仓颉插件提供了仓颉 SDK 最新版本的下载和更新功能,开发者可以在 VSCode 完成最新版本仓颉 SDK 的下载和本地环境部署。
下载 SDK
开发者可以自行前往仓颉下载中心,手动下载仓颉 SDK。
Windows 平台
Windows 平台的 SDK 下载内容为:cangjie-sdk-windows-x64-x.y.z.exe 或 cangjie-sdk-windows-x64-x.y.z.zip。
下载 SDK 并放置在本地。若下载 .exe 文件,运行该文件,根据提示选择安装路径并记录该路径。若下载 .zip 文件,解压该文件,记录存储的路径。
SDK 文件夹的目录结构如下:
cangjie
├── bin
├── lib
├── modules
├── runtime
├── third_party
├── tools
├── envsetup.bat
├── envsetup.ps1
└── envsetup.sh
Linux 平台
Linux_x64 平台的 SDK 下载内容为:cangjie-sdk-linux-x64-x.y.z.tar.gz。
Linux_AArch64 平台的 SDK 下载内容为:cangjie-sdk-linux-aarch64-x.y.z.tar.gz。
下载 SDK 并放置在本地,记录存储的路径。目录结构如下:
cangjie
├── bin
├── include
├── lib
├── modules
├── runtime
├── third_party
├── tools
└── envsetup.sh
macOS 平台
macOS_AArch64 平台的 SDK 下载内容为:cangjie-sdk-mac-aarch64-x.y.z.tar.gz。
下载 SDK 并放置在本地,记录存储的路径。目录结构如下:
cangjie
├── bin
├── lib
├── modules
├── runtime
├── third_party
├── tools
└── envsetup.sh
SDK 路径配置
安装完仓颉插件后,即可配置 SDK 的路径。单击左下角齿轮图标,选择设置选项。

或直接右键单击插件,选择 Extension Settings,进入配置页面。

在搜索栏输入 Cangjie,选择侧边栏的 Cangjie Language Support 选项。

配置 CJNative 后端
-
找到 Cangjie Sdk: Option 选项,选择后端类型为 CJNative(默认是此选项)。
-
找到 Cangjie Sdk Path: CJNative Backend 选项,输入 CJNative 后端 SDK 文件夹所在绝对路径。
-
重启 VSCode 生效。

安装验证
通过快捷键 Ctrl + Shift + P(macOS 系统的快捷键为 Command + Shift + P) 调出 VSCode 的命令面板,选择 cangjie: Create Cangjie Project View 命令。

弹出创建仓颉项目页面,说明仓颉 SDK 安装成功。

语言服务
说明:
本文档部分图片截取于 VSCode 软件界面,仅用于说明仓颉插件在 VSCode 中的使用方法。
语言服务工具为开发者提供如下功能:语法高亮、自动补全、定义跳转、查找引用、诊断报错、选中高亮、悬浮提示、签名帮助和重命名等。
说明:
- 项目根目录 (PROJECTROOT):仓颉语言服务插件以开发者当前打开的文件夹作为项目根目录 PROJECTROOT,且仅对该目录下的仓颉源码提供语言服务支持。
- 模块命名:如如未显式指定模块名称,默认将项目根目录 PROJECTROOT 名称作为模块名,便于导入 src 目录下的包。
- 源码支持范围:PROJECTROOT/src 下称为src 下仓颉源码(支持语言服务);除了 src 下仓颉源码,项目根目录 PROJECTROOT 下的其他所有源码称为非 src 下仓颉源码(支持语言服务);项目根目录 PROJECTROOT 之外的仓颉源码称为外部源码(暂不支持语言服务)。
- 导入能力:非 src 下仓颉源码中,每个文件夹都作为一个包,包名的声明和包的编译方式与src 下仓颉源码顶层包(即 default 包)处理方式保持一致。非 src 下仓颉源码可以导入标准库的包以及src 下仓颉源码中自定义的包,非 src 下仓颉源码的包无法被其他包导入。
- 宏展开依赖:仓颉语言服务的宏展开依赖宏的动态库,如果涉及自定义宏展开的代码,需要先编译出动态库,然后再启动语言服务。
- 日志开关:仓颉语言服务的日志默认关闭。开发者如果需要开启语言服务日志输出,可以在插件设置中开启Cangjie Log选项后重启 VSCode,日志可以在插件安装目录下的log.txt文件查看。
代码高亮
VSCode 打开仓颉工程中的 .cj 文件,即可看到代码高亮效果。VSCode 不同主题显示的代码高亮颜色不同,支持对代码运算符、类、注释、函数、关键字、数字、包名、字符串、变量等进行高亮显示。

自动补全
VSCode 打开仓颉工程中的 .cj 文件,输入关键字、变量或 . 符号,在光标右侧提示候选内容。可以用上下方向键快速选择想要的内容(需要切换为系统默认输入法),使用 Enter 键或 Tab 键补全。


对于带参数的函数或者泛型提供模块化补齐,即当函数有参数或者带泛型时,选择函数补齐项之后会出现参数格式化补齐,如下图所示。填充数值之后按下 Tab 键可以切换到下一个参数补齐,直至模块化补齐结束,或按下 Esc 键提前退出除当前选中模块。

定义跳转
VSCode 打开仓颉工程中的 .cj 文件,鼠标悬停在目标上方,按下 Ctrl 键并单击鼠标左键触发定义跳转;或使用鼠标右键单击目标符号,选择 Go to Definition 执行定义跳转;或按下快捷键 F12 执行定义跳转。

说明:
在符号使用的地方使用定义跳转会跳转到符号定义处,支持跨文件跳转。 在符号定义处使用定义跳转,如果此符号没被引用过,光标会跳转到符号左端。 如果符号在其他地方被引用,会触发查找引用。
查找引用
VSCode 打开仓颉工程中的 .cj 文件,使用鼠标右键单击目标符号,选择 Find All References 执行符号引用预览,单击预览条目,可以跳转到对应引用处。

诊断报错
VSCode 打开仓颉工程中的 .cj 文件,当源码文件出现不符合仓颉语法或语义规则的代码时,会在相关代码段出现红色波浪下划线,如下图所示,当鼠标悬停在上面,可以提示相应的报错信息。修改正确后,诊断报错自行消失。

选中高亮
VSCode 打开仓颉工程中的 .cj 文件,光标定位在一个变量或函数名处,当前文件中该变量的声明处以及其使用处都会高亮显示。

悬浮提示
VSCode 打开仓颉工程中的 .cj 文件,光标悬浮在变量处,可以提示类型信息。

悬浮在函数名处,可以提示函数原型。

定义搜索
VSCode 打开仓颉工程中的 .cj 文件,同时按下 Ctrl 键和 T 键,弹出搜索框,输入想要搜索的符号定义名,会显示出符合条件的搜索结果。单击搜索结果条目,可以跳转到对应的定义位置处。

目前支持搜索的定义类型有:class、interface、enum、struct、typealias、toplevel 的函数、toplevel 的变量、prop、enum 构造器、成员函数和成员变量。
重命名
VSCode 打开仓颉工程中的 .cj 文件,光标定位在想要修改的自定义名称上,右键选择 Rename Symbol 或按下快捷键 F2 打开重命名编辑框。

编辑完毕按下回车键,完成重命名的实现。

目前支持重命名的类型有:class、interface、enum、struct、func、type、泛型、变量和自定义宏。
大纲视图显示
VSCode 打开仓颉工程中的 .cj 文件,在左侧 OUTLINE 视图中显示当前文件的大纲。目前支持两层结构的显示,第一层主要为 toplevel 中定义的声明,第二层主要为构造器及成员。

目前支持大纲视图显示的类型有:class、interface、enum、struct、typealias、toplevel 的函数、toplevel 的变量、prop、enum 构造器、成员函数和成员变量。
面包屑导航
VSCode 打开仓颉工程中的任意 .cj 文件,光标定位在符号处,点击面包屑导航,显示符号当前所处的位置,以及该符号在整个工程中的位置路径。

目前支持面包屑导航的类型有:class、interface、enum、struct、typealias、toplevel 的函数、toplevel 的变量、prop、enum 构造器、成员函数和成员变量。
签名帮助
VSCode 在输入左括号和逗号时会触发签名帮助。触发后,只要还在函数参数范围内,提示框会一直随光标移动(可与补全共存)。如下图所示,开发者可以看到当前函数的参数信息,以及当前函数位置参数的高亮效果。

显示类型层次结构
VSCode 打开仓颉工程中的 .cj 文件,光标定位在想要查看的自定义名称上,右键选择 Show Type Hierarchy,在左侧就会显示该类型层次结构。Object 类型默认为所有类的父类,该功能下不会显示。
目前支持显示层次结构的类型有:class、interface、enum 和 struct。

单击如图标记所示位置,可以在显示子类和父类之间切换。

调用类型层次结构
VSCode 打开仓颉工程中的 .cj 文件,光标定位在函数名上,右键选择 Show Call Hierarchy,在左侧就会显示该函数的调用类型层次结构。

通过单击标识位置可以在显示调用函数和被调用函数之间切换。

创建仓颉工程
说明:
本文档部分图片截取于 VSCode 软件界面,仅用于说明仓颉插件在 VSCode 中的使用方法。
仓颉工程目录结构如下所示。
Project_name:开发者输入的名称
├── src:代码目录
│ └── main.cj:源码文件
└── cjpm.toml:默认的 cjpm.toml 配置文件
使用 VSCode 命令面板
在 VSCode 中使用快捷键 F1,或同时按下 Ctrl + Shift + P(macOS 系统为 Command + Shift + P)打开命令面板,按照以下步骤创建仓颉工程。
第一步:选择创建仓颉工程命令

第二步:选择仓颉后端

第三步:选择工程模板

第四步:选择工程路径

第五步:输入工程名称
选择工程的存储路径,输入工程名称。
第六步:完成创建并打开

使用可视化界面
在 VSCode 中使用快捷键 F1,或同时按下 Ctrl + Shift + P(macOS 系统为 Command + Shift + P)打开命令面板,按照以下步骤创建仓颉工程。
第一步:选择创建仓颉可视化工程命令

第二步:打开可视化创建仓颉工程界面

第三步:选择工程模板

第四步:选择工程路径

第五步:输入工程名称

第六步:单击 Confirm 完成创建并打开

编译构建
说明:
本文档部分图片截取于 VSCode 软件界面,仅用于说明仓颉插件在 VSCode 中的使用方法。
VSCode 中可视化方式提供的仓颉功能编译构建能力依赖 cjpm 工具,该工具要求打开的仓颉工程的模块内必须包含规范的 cjpm.toml 文件。若没有该文件,仍想执行工程的编译构建,可在终端使用 cjc 命令。
在 VSCode 中提供在命令面板执行命令、在终端进行执行命令、单击运行按钮运行工程,以及单击锤子按钮编译工程四种方式,来实现仓颉工程的编译构建。
编译构建方式
在命令面板执行命令
在 VSCode 中使用快捷键 F1,或同时按下 Ctrl + Shift + P(macOS 系统为 Command + Shift + P)打开命令面板,输入分类词 Cangjie 来快速找到以下编译相关命令。
-
选择
Cangjie: Parallelled Build选项执行并行编译。
执行并行编译后,在工程文件夹下会生成
target目录,target目录下有一个release文件夹,release文件夹下包含三个目录:.build-logs目录、bin目录,以及工程名同名的目录。bin目录下存放可执行文件(可执行文件只有在cjpm.toml的output-type为executable时才会生成),工程名同名目录下存放编译的中间产物。在 output Panel 上会打印编译是否成功的信息。
-
选择
Cangjie: Build With Verbose选项执行编译并展示编译日志。
该编译参数除了执行编译外,还会打印编译日志。
-
选择
Cangjie: Build With Debug选项生成 debug 版本的目标文件。该命令的编译结果中带有 debug 信息,供调试使用。
-
选择
Cangjie: Build With Coverage选项生成覆盖率信息。该命令在编译结果中带有覆盖率信息。
-
选择
Cangjie: Build With Alias执行编译并指定输出可执行文件的名称。
执行该命令,按下回车键后,会弹出一个输入栏,需要开发者为工程的编译结果赋予一个新的名字。该命令只对
cjpm.toml的output-type为executable时有效。 -
选择
Cangjie: Build With Increment选项执行增量编译。用来指定增量编译。
-
选择
Cangjie: Build With CustomizedOption选项按条件透传cjpm.toml中的命令。
使用该选项需要先在
cjpm.toml中配置customized-option字段。然后在命令面板输入Build With CustomizedOption,按下回车键后可以选择需要的参数,参数可以多选,选择后按下回车键即可。
若没有在
cjpm.toml中配置customized-option字段,并执行了该条命令,插件会提示开发者先配置改字段。 -
选择
Cangjie: Build With TargetDir选项执行编译并在指定路径生成编译产物。选择该命令执行后,可指定编译产物的输出路径,默认不作输入操作则以
cjpm.toml中的target-dir字段为路径。
当输入的编译产物路径与 cjpm.toml 中的
target-dir字段不同时,会弹出提示是否覆盖 cjpm.toml 中的target-dir字段。若选择 Yes 覆盖,则会将 cjpm.toml 中target-dir字段覆盖成输入的值。
该命令执行成功后,会在指定的路径下生成编译产物。
-
选择
Cangjie: Build With Jobs选项,执行编译前自定义最大并发度。支持通过执行该命令在编译之前自定义最大并发度,输入参数为任意数字,设置范围为 (0, CPU 核数 * 2]。
当在输入框输入非数字时,会终止操作,并提示开发者输入数字内容:“Invaild input! The input should be number.”
当在输入框输入的范围超出所支持的范围 (0, CPU 核数 * 2] 时,会默认采用 CPU 核数,并提示超出可选范围的告警信息。
-
选择
Cangjie: Build With CodeCheck选项,执行编译时进行 CodeCheck 静态代码检查。执行该命令编译工程时,会对当前工程进行 CodeCheck 静态代码检查,如果检查到【要求】级别的代码规范违规,则编译失败,检查到【建议】级别的违规仅告警,正常完成编译。
-
选择
Cangjie: Build With MultiParameter选项执行多参数编译。仓颉工程的编译可以叠加多个参数,在命令面板搜索到
Build With MultiParameter命令后,选择需要叠加的参数,其中--target参数会根据cjpm.toml中的target字段的设置来决定是否显示。如果开发者没有配置target的内容,则--target参数选项会隐藏;--<customized-option>参数会根据 cjpm.toml 中的customized-option字段的设置来决定是否显示,如果开发者没有配置customized-option的内容,则--<customized-option>参数选项会隐藏。
勾选想叠加的参数,按下回车键或者单击 ok 按钮。也可单击界面中的向左箭头,重新选择编译参数。
如果叠加的参数中选择了
cjpm build --output=<name>,那么需要输入一个别名字符串,然后按下回车键执行叠加命令操作。
如果叠加参数中选择了
cjpm build --target=<name>,那么可以选择一个想要交叉编译的平台。如果叠加参数中选择了
cjpm build --<customized-option>,那么可以选择透传参数。
叠加命令的编译结果就是这些命令分别执行的总和。
-
选择
Cangjie: Update Cjpm.toml选项更新 cjpm.lock 文件。在修改完
cjpm.toml文件后,需要执行该命令,更新cjpm.lock文件。如果是通过 UI 界面修改的cjpm.toml文件,则不需要手动执行该操作。 -
选择
Cangjie: Execute Test File选项编译单元测试产物,执行对应的单元测试用例,并直接打印测试结果。 -
选择
Cangjie: Test With NoRun选项编译对应测试产物。 -
选择
Cangjie: Test With SkipBuild选项测试产物存在的前提下,用于执行对应测试产物。 -
选择
Cangjie: Test With Jobs选项执行单元测试之前自定义最大并发度,操作与Build With Jobs相同。 -
选择
Cangjie: Test With MultiParameter选项执行多参数执行仓颉工程的单元测试。在选择该条命令后,可以选择指定包路径、模块或者成员执行单元测试。只有打开工作空间,才显示成员选择选项。

如果选择
Specify the test paths选项,则可以输入指定待测试的包路径。若不需要指定,则直接按 Enter 键。
此步骤可通过输入多个包的路径并用空格分隔,可以实现多包并发单元测试。

如果选择
Specify the test modules选项,则可以输入指定待测试的模块。若不需要指定,则直接按 Enter 键。
此步骤可通过输入多个模块并用空格分隔,可以实现多模块单元测试。

如果选择
Specify a test member选项,则可以输入指定待测试的成员。若不需要指定,则直接按 Enter 键。
选择要叠加的参数。

如果选择了
--filter=<value>参数,则需要输入对应的过滤测试子集的表达式。
输入过滤测试子集的表达式后,可以执行
cjpm test的完整命令。执行结果会在 Output 面板输出。如果在 cjpm.toml 中配置了
target和customized-option,则可以选择的参数有--target=<name>和--<customized-option>。
如果选择了
--target=<name>参数,则需要选择对应的平台。
如果选择了
--<customized-option>参数,则需要选择条件选项。
-
选择
Cangjie: Clean Build Result选项清除编译结果(工程目录下的 build 目录)。 -
选择
Cangjie: Check Circular Dependencies选项检测文件依赖。 -
选择
Cangjie: Edit Configuration (UI)选项打开 UI 配置界面。 -
选择
Cangjie: Install With Verbose选项展示安装日志。 -
选择
Cangjie: Install With Debug选项生成 debug 版本的安装产物。 -
选择
Cangjie: Install With RootPath选项指定可执行文件的安装路径。在选择该条命令后,在弹出的输入框中输入期望可执行文件的安装路径,最终会将可执行文件安装到输入的自定义路径中。不配置时,Linux 系统和 macOS 系统下默认为
$HOME/.cjpm,Windows 系统下默认为%USERPROFILE%/.cjpm。
-
选择
Cangjie: Install With TargetDir选项指定编译产物的存放路径。安装可执行文件前会先进行编译,选择该条命令后,在弹出的输入框中输入期望编译产物的存放路径,最终会将编译产物安装到输入的自定义路径中。

-
选择
Cangjie: Install With Alias选项指定最终安装的产物名。选择该条命令后,在弹出的输入框中输入期望安装产物的名字。

-
选择
Cangjie: Install With Git选项安装远端 git 代码仓产物。选择该条命令后,在弹出的输入框中输入远端 git url。

输入远端 git url 后,键入回车可进一步选择关于远端 git 代码仓的分支、tag 或 commit 信息。

选择自定义代码仓 branch / tag / commit 号选项,在弹出框内输入 branch / tag / commit 号信息,即可安装远端 git 代码仓产物。
-
选择
Cangjie: Install With List选项打印已安装产物列表。 -
选择
Cangjie: Install With SkipBuild选项跳过编译阶段以直接安装产物,需要项目处于编译完成状态。 -
选择
Cangjie: Install With Jobs选项指定并行编译的最大并发数。选择该条命令后,在弹出的输入框中输入期望安装时的最大并发数。

-
选择
Cangjie: Install With CustomizedOption选项按条件透传cjpm.toml中的命令。
使用该选项需要先在
cjpm.toml中配置customized-option字段。然后在命令面板选择Install With CustomizedOption,按下回车键后可以选择需要的参数,参数可多选,选择后按下回车键即可。
开发者需要在
cjpm.toml中配置customized-option字段,才能执行该条命令。 -
选择
Cangjie: Install With SkipScript选项跳过待安装模块的构建脚本的编译运行。 -
选择
Cangjie: Install With CustomParameter选项执行自定义的安装命令参数选项。单击 VSCode 页面左下角齿轮图标,选择设置选项。或直接右键单击插件,选择 Extension Settings,进入配置页面。在搜索栏输入 Cangjie,选择侧边栏的 Cangjie Language Support 选项。该页面有输入框
Cangjie: Cjpm Install: Custom,在此输入cjpm install相关的命令选项,如-V -g --name \<value\>。然后在命令面板选择Install With CustomParameter命令,最终将该输入框中的内容带到cjpm install中。
-
选择
Cangjie: Uninstall Binary选项卸载仓颉项目,清除对应的可执行文件和依赖文件。选择该命令后,在弹出的输入框中输入需要卸载的可执行文件名字。

-
选择
Cangjie: Uninstall With Root选项指定卸载时搜索的目标路径。选择该命令后,在弹出的输入框中输入期望卸载时搜索的目标路径,最终会将该路径下的指定可执行文件和依赖文件卸载。不配置时,Linux 系统和 macOS 系统下默认为 $HOME/.cjpm,在 Windows 系统下默认为
%USERPROFILE%/.cjpm。
在终端进行执行命令
开发者可以直接在 VSCode 的终端面板使用编译构建命令(cjpm)对仓颉工程进行编译构建。初次使用需要重新启动 VSCode,即可在终端执行 cjpm 操作。

单击运行按钮运行工程
开发者可以单击 .cj 文件编辑区的运行按钮来运行整个仓颉工程。

若整个工程中配置的 output-type 为 executable,则会在终端面板打印运行结果,否则只会显示编译的结果。
单击运行按钮执行的编译过程是结合当前的 cjpm.toml 和 cjpm_build_args.json 的配置来进行的。
单击锤子按钮编译工程
开发者可以单击 .cj 文件编辑区的锤子按钮来编译整个仓颉工程。

单击锤子按钮执行的编译过程与运行按钮一致,也是结合当前的 cjpm.toml 和 cjpm_build_args.json 的配置来进行的。不同的是,若整个工程中配置的 output-type 为 executable,则运行按钮在编译完成后再运行整个工程,而锤子按钮只会编译工程,无后续运行动作。
可视化配置编译构建参数
在编译构建过程中需要配置工程目录中的 cjpm.toml 和 cjpm_build_args.json 文件,方法如下:
- 直接修改
cjpm.toml和cjpm_build_args.json文件。

- 使用快捷键 F1,或同时按下 Ctrl + Shift + P(macOS 系统为 Command + Shift + P)打开命令面板,在命令面板执行
Cangjie: Edit Configuration (UI)命令打开可视化编辑的 UI 界面。

- 单击编辑页面右上角的画笔按钮,跳转到可视化编辑的 UI 界面。

对于工程文件中 .vscode 目录下的 cjpm_build_args.json 的配置,通过复选框或者输入框的形式确定编译要使用的参数,修改后会同步到 cjpm_build_args.json 文件中。
对于工程中 cjpm.toml 文件的配置,开发者输入内容并将光标移至输入框外,即可生效到 cjpm.toml 文件中。
注意:
当仓颉工程中的
cjpm.toml文件和参数配置界面同时在 VSCode 的编辑区显示时,对cjpm.toml文件的修改不会同步到 UI 界面上。
对于构建参数 cross-compile-configuration,可以在 cross-compile-configuration 下单击 Add Configuration 按钮添加选项。
在 key 和 compile-option 处填写对应内容,单击对勾按钮或按下回车键,与 cjpm.toml 保持同步。若想删除该条配置,只需单击该条选项的叉号按钮。
添加的配置在不填写第一个字段 key 就直接单击对勾按钮或按下回车键,会出现必须要填写第一个字段的提示,该场景下提交的内容不会同步到 cjpm.toml 中。在 UI 界面目前不会直接删除该条配置,刷新 UI 界面后会自动删除,内容与 cjpm.toml 保持一致。package-configuration 和 cross-compile-configuration 类似,package-configuration 新增配置时第一个字段为空的场景如下图所示。

对于 package-configuration 参数,其添加和修改方式与 cross-compile-configuration 一致。其中 output-type 字段为下拉框选项,其可选的类型有 executable、static、dynamic 和 null。新添加的配置字段的初始化类型为 null,开发者可以根据自己的需要进行选择。当选择为 null 时,该字段同步到 cjpm.toml 后会删除该字段。
注意:
在 UI 界面配置
cjpm.toml的内容时,只有对于customized-option参数中配置的--cfg中路径中的=需要转义,其他符号不需要添加转义符号。比如:
在 UI 界面对
customized-option参数配置的--cfg路径中包含=时,=需要转义,即--cfg="D:/projects/cang\=jie"。在 UI 界面对
package-configuration字段的 p1 配置compile-option时,对--link-options设置内容时不需要转义,只需要加引号即可,即--link-options="-rpath=xxx"。直接在
cjpm.toml中填写时,符号都需要加转义符号。比如:
在
cjpm.toml中对customized-option参数配置的--cfg路径中包含=时,所有符号都需要转义,即--cfg=\"D:/projects/cang\\=jie\"。在
cjpm.toml中对package-configuration字段的 p1 配置compile-option时,所有符号都需要转义,即--link-options=\"-rpath=xxx\"。
对于 customized-option 参数,其添加修改方式与 cross-compile-configuration 一致。
注意:
customized-option的条件不能设置内置的条件(@When[os == "Linux"] 不能作为customized-option的条件,即 "cfg1" : "--cfg ="os=Linux"" 是不允许的),只能添加开发者自定义条件。具体请参见 《仓颉编程语言开发指南》 的条件编译 章节。
三方库便捷导入
导入方式
注意:
三方库便捷导入仅适用于当前打开的仓颉工程的主模块。如果其他子模块需要便捷导入三方库,可以单独以工程的方式打开使用。
在仓颉工程中,可以导入外部的三方库,并且在 cjpm.toml 中进行配置。
dependencies:当前仓颉模块依赖项目,包含了当前构建所需要的其它模块的配置信息,包含版本号和路径。这两个选项必须全部配置,否则会执行失败并报错。在使用过程中,优先使用此方式进行项目依赖导入。
dev-dependencies:使用方式与 dependencies 一致,具有与 dependencies 字段相同的格式。用于指定仅在开发过程中使用的依赖项,而不是构建主项目所需的依赖项,例如仅在测试中使用的依赖项。如果开发者是库作者,则应将此字段用于此库的下游用户不需要使用的依赖项。
bin-dependencies:非特殊需求场景下,建议使用 dependencies 的方式导入依赖。目前仓颉插件仅支持本地的 bin-dependencies 配置。
当前仓颉模块依赖已编译好的 package,有两种导入形式。以导入下述 pro0 模块和 pro1 模块的三个包来举例说明。
test
├── pro0
│ ├── libpro0_xoo.so
│ ├── xoo.cjo
│ ├── libpro0_yoo.so
│ └── yoo.cjo
├── pro1
│ ├── libpro1_zoo.so
│ └── zoo.cjo
├── src
│ └── main.cj
└── cjpm.toml
方式一:通过 package-option 导入。
[target]
[target.x86_64-w64-mingw32]
[target.x86_64-w64-mingw32.bin-dependencies]
[target.x86_64-w64-mingw32.bin-dependencies.package-option]
pro0_xoo = "./test/pro0/xoo.cjo"
pro0_yoo = "./test/pro0/yoo.cjo"
pro1_zoo = "./test/pro1/zoo.cjo"
该选项是 map 结构,pro0_xoo 名称作为 key,与 libpro0_xoo.so 相对应,前端文件 .cjo 的路径作为 value,对应于该 .cjo 的 .a 和 .so 需放置在相同路径下,且对应的 .cjo 模块文件必须与模块名来源文件放置在相同的文件夹下,该文件夹下不能有任何其他文件或文件夹。
方式二:通过 path-option 导入。
[target]
[target.x86_64-w64-mingw32]
[target.x86_64-w64-mingw32.bin-dependencies]
path-option = ["./test/pro0", "./test/pro1"]
该选项是字符串数组结构,每个元素代表待导入的路径名称。cjpm 会自动导入该路径下所有符合规则的仓颉库包,这里的合规性是指库名称的格式为模块名_包名。库名称不满足该规则的包只能通过 package-option 选项进行导入。
如果同时通过 package-option 和 path-option 导入相同的包,则 package-option 字段的优先级更高。
导航栏视图呈现如下形式。

开发者可以在其对应的导入方式子目录下导入工程需要的模块。在导航栏单击画笔进入 UI 界面。

ffi:当前仓颉模块外部依赖 C 库,配置了依赖该库所需要的信息,包含名称和路径字段。资源管理器的视图栏中的 CANGJIE LIBRARY 栏,可以方便开发者添加这几类外部库。
在工程初始化后,可以通过单击分类栏的加号按钮添加对应的三方库。

也可以通过单击三方库上的减号删除对应的库。
可以通过单击视图栏的编辑按钮,打开三方库导入的可视化界面来导入或删除三方库。

以上删除和添加操作均同步到工程的 module.json 文件中。
导入限制
- 项目中需要链接动态库(C 库和仓颉库)时,需自行设置
LD_LIBRARY_PATH,执行export LD_LIBRARY_PATH=xxx:$LD_LIBRARY_PATH。 - 在
cjpm.toml中修改内容不会直接影响 treeView 和 UI 界面,需要单击 treeView 或 UI 界面进行手动更新。 - 在 treeView 中的库分类处添加外部库,且此时库分类目录是关闭状态,则添加后需要打开目录才能查看。
- UI 界面的字段暂不支持 hover 显示内容的功能。
- UI 界面非开发者添加的外部库,其路径与
cjpm.toml保持一致。开发者添加的库和 treeView 均显示绝对路径。
调试服务
说明:
本文档部分图片截取于 VSCode 软件界面,仅用于说明仓颉插件在 VSCode 中的使用方法。
仓颉编程语言提供了可视化调试服务,方便开发者调试仓颉程序。该插件提供如下功能:
- Launch:启动调试进程
- Attach:附加到已启动的进程
- 支持源码断点、函数断点、数据断点、汇编断点
- 支持源码内单步调试、运行到光标处、步入、步出、继续、暂停、重启、停止调试
- 支持仓颉-C 互操作调试,仓颉代码 continue、步入到 C 代码
- 支持汇编内单步、步入、步出
- 支持表达式求值
- 支持变量查看和修改
- 支持在调试控制台中查看变量
- 支持查看被调试程序的输出信息
- 支持反向调试
- 支持 Unittest 的运行和调试
说明:
- 如果第一次使用 VSCode 调试功能,可以查看 VSCode 调试服务使用手册。
- 调试服务当前支持在 Windows 和 Linux 版本的 VSCode 中安装使用。
- 受调试器限制,循环代码中存在条件断点时,执行 PAUSE 操作可能导致后续调试无法进行。
- VARIABLES 视图修改变量时,不会触发存在依赖关系的变量的刷新。
- 调试服务依赖仓颉 SDK 包内 liblldb 动态库文件时,请提前配置仓颉 SDK 路径。
- 调试插件客户端与服务端通过 Socket 通信,插件自动从 9995 端口开始查找可用端口,并在 127.0.0.1 上启动 Socket server 监听该端口。
启动调试
Launch 模式
仓颉工程调试
- 未创建
launch.json文件时,单击 Run and Debug > Cangjie(cjdb) Debug 启动调试。 - 已创建
launch.json文件时,在launch.json文件中单击 Add Configuration > Cangjie Debug (CJNative) : launch > Build And Debug Cangjie Project 添加调试配置,选择添加的配置启动调试。
单文件调试
针对单文件调试,可以选中需要调试的仓颉源文件,右键选择 Cangjie: Build and Debug File,该操作会生成编译配置文件 task.json 和编译脚本,并且会根据 task.json 配置执行脚本,编译出可调试的二进制文件,然后启动调试。
调试手动编译的可执行文件
- 使用 cjc 编译器或 cjpm 手动编译出可调试的二进制文件。
- 单击 Run and Debug > Cangjie(cjdb) Debug > Cangjie (CJNative): launch > Choose Executable File Later 启动调试。
Launch debugMacro 模式仓颉工程调试宏展开后的代码
调试宏展开后的代码文件(后缀为 .marcocall),此时宏对应的原文件无法调试。
调试远程进程(支持 Linux 远程到 Linux)
Launch 模式下调试远程进程时,调试服务会将本地编译的二进制文件推送到远程平台,然后调试远程平台的二进制文件。
- 在远程平台启动 lldb-server。建议使用 cjdb 自带的 lldb-server,路径为 /cangjie/third_party/llvm/lldb/bin/lldb-server,启动命令
/**/**/cangjie/third_party/llvm/lldb/bin/lldb-server p --listen "*:1234" --server。 - 在本地机器使用 cjc 编译器或 cjpm 手动编译出可调试的二进制文件。
- 单击 Run and Debug 按钮启动调试。
launch.json 配置示例如下:
{
"name": "Cangjie Debug (cjdb): test",
"program": "/**/**/test",
"request": "launch",
"type": "cangjieDebug",
"externalConsole": false,
"remote": true,
"remoteCangjieSdkPath": "/**/**/cangjie",
"remoteFilePath": "/**/**/test",
"remoteAddress": "127.0.0.1:1234",
"remotePlatform": "remote-linux"
}
配置属性
| 属性 | 类型 | 描述 |
|---|---|---|
| program | string | 被调试进程的全路径,该文件将推送到远程平台,例如:/home/cangjieProject/build/bin/main |
| remote | boolean | 启动远程 Launch 进程,remote 为 true |
| remoteCangjieSdkPath | string | 远程平台仓颉 SDK 路径 |
| remoteFilePath | string | 远程平台存放推送文件的全路径,请确保路径 /home/test/ 合法且存在,main 为推送到远程的文件名,例如:/home/cangjieProject/build/bin/main |
| remoteAddress | string | 被调试进程所在的机器 IP 和 lldb-server 监听的端口号,数据格式:ip:port |
| remotePlatform | string | 远程的平台,仅支持 remote-linux(远程 Linux 平台) |
| env | object | 为被调试程序设置运行时的环境变量,该配置将覆盖系统环境变量,如需在系统配置基础上追加配置,在配置项结尾增加 ${env:PATH}。例如:"PATH":"/home/user/bin: ${env:PATH}", "LD_LIBRARY_PATH":"/home/user/bin:${env:LD_LIBRARY_PATH}"。 |
Attach 模式
调试本地进程
- 在
launch.json文件中单击 Add Configuration > Cangjie Debug (CJNative) : attach 添加调试配置,选择添加的配置启动调试。 - 在弹出界面选择要调试的进程即可启动调试。
调试远程进程
- 在本地机器编译出可调试二进制文件并将该文件拷贝到远程机器。
- 在远程机器启动 lldb-server,建议使用 cjdb 自带 lldb-server,路径为 /cangjie/third_party/llvm/lldb/bin/lldb-server,启动命令
/**/**/cangjie/third_party/llvm/lldb/bin/lldb-server p --listen "*:1234" --server。 - 在远程机器启动被调试的二进制文件。
- 在本地机器配置
launch.json文件,并启动调试。
launch.json 配置属性:
{
"name": "Cangjie Debug (cjdb): test",
"processId": "8888",
"program": "/**/**/test",
"request": "attach",
"type": "cangjieDebug",
"remote": true,
"remoteAddress": "127.0.0.1:1234",
"remotePlatform": "remote-linux"
}
配置属性
| 属性 | 类型 | 描述 |
|---|---|---|
| processId | string | 被调试进程的 pid(配置 pid 时优先 attach pid,未配置 pid 则 attach program) |
| program | string | 被调试进程的全路径,例如:/home/cangjieProject/build/bin/main |
| remote | boolean | attach 本机器进程,remote 为 false;若 attach 远程进程,将 remote 设置为 true |
| remoteAddress | string | 远程调试时被调试进程所在的机器 IP 和 lldb-server 监听的端口号,数据格式:ip:port |
| remotePlatform | string | 远程调试时远程的平台,仅支持 remote-linux(远程 linux 平台) |
查看调试信息
当进程处于 stopped 状态时,可以在 VSCode 界面左侧查看断点、当前线程、堆栈信息和变量,支持编辑断点和修改变量。也可以在 Editor 窗口将鼠标悬停在变量名称上方查看变量值。支持在 TERMINAL 窗口查看被调试程序的输出信息。

表达式求值
- 在 WATCH 窗口添加按钮或空白处双击键入表达式。
- 在 Debug Console 窗口键入表达式。
- 在 Editor 窗口双击选中变量,右键选择 Evaluate in Debug Console。
程序控制
-
单击顶部调试工具栏上的图标控制程序,包括单步执行、步入、步出、继续、暂停、重启或停止程序。

-
在鼠标光标处单击右键选择 Run to Cursor。

-
在源码视图右键选择 Open Disassembly View 进入汇编视图。

调试控制台
执行 cjdb 命令
在调试控制台中输入 cjdb 命令来调试程序,命令的格式需要以 -exec 开头,要执行的子命令必须是正确的 cjdb 命令。
使用 cjdb 命令 n 执行单步调试的示例如下:
-exec n

查看变量
在调试控制台中输入变量名称查看变量值:

反向调试
说明:
- 反向调试基于记录重放,开启反向调试功能后,调试服务会记录开发者正向调试的所有停止点(断点 + 单步),以及停止点的线程、堆栈和变量等调试信息。进入反向调试模式,支持查看历史记录点的调试信息。
配置
单击左下角齿轮图标,选择设置(Settings)选项,在搜索栏输入 cangjie,找到 Reverse Debug 选项,勾选 Enable reverse debug,开启程序调试历史停止点信息的自动记录。同时可以配置自动记录的线程个数、堆栈个数、变量作用域、复杂类型变量子变量的展开层数和子变量个数。修改配置后,需要重新启动仓颉调试。

工具栏
单击顶部调试工具栏上的时钟图标进入反向调试模式,使用工具栏上正反向继续、正反向单步控制程序,查看历史记录的线程、堆栈、变量信息,如下图所示。

单击顶部调试工具栏上的方块图标退出反向调试模式,调试会回到正向调试的最后停止点,如下图所示。

反向断点
说明:
- 反向断点是一种特殊的源码断点(Log Point),正向调试过程中不会停止,也不会输出自动生成的 Log Message(用于标记反向断点)。
- 在正向调试时,开发者提前设置反向断点,调试服务后台会记录进程走过的反向断点的调试信息。
- 在进入反向调试模式时,反向断点会作为停止点(断点型),可以查看该断点处的线程堆栈变量等调试信息。
- 在进入反向调试模式时,不支持设置反向断点。
反向断点设置方式:
-
在仓颉源文件编辑器视图内右键选择 Cangjie: Add Reverse Breakpoint,为光标所在行设置一个反向断点。

-
在仓颉源文件上右键选择 Cangjie: Add Auto Reverse Breakpoints 插件会分析该文件内函数的入口和出口位置并自动设置反向断点。

-
在文件夹上右键选择 Cangjie: Add Auto Reverse Breakpoints 插件会分析该文件夹内仓颉源文件中的函数的入口和出口位置并自动设置反向断点。

时间线
说明:
时间线展示了反向调试模式下记录的所有停止点(断点+单步),通过时间线拖拽,可以查看历史停止点的信息。
时间线入口位于 VSCode 右下方区域,可以在右下方的 Tab 标签行右键将时间线 Cangjie Debug Timeline 开启或隐藏,也可以在 View 菜单中选择 Open View 开启,如下图所示。

- 主时间线上有左右游标,可以分别拖动左右游标选出某一段时间区域。在选中一段区域之后,鼠标放在选中区域上方时会变为手的形状,此时可以左右拖动此区域。
- 将鼠标放在主时间线上,鼠标变为十字光标的形状,此时按住鼠标往前或往后拖动,可以将鼠标滑过的区域设为新的时间区域。
- 可以通过 Ctrl + 鼠标滚轮的方式,放大和缩小选中区域。
- 每条时间线标识一个仓颉线程或者系统线程。
单击时间线上的记录点,editor 界面同步刷新(定位到源码的行),调试信息界面同步刷新(展示该记录点的线程、栈帧和变量)。
unittest 运行和调试
前置条件
模块的单元测试代码应采用如下结构,其中 .cj 文件表示包的源码,对应单元测试代码文件命名应以 _test.cj 结尾。具体单元测试代码的写法可参考标准库用户手册。
├── src
│ ├── koo
│ │ ├── koo.cj
│ │ └── koo_test.cj
│ ├── zoo
│ │ ├── zoo.cj
│ │ └── zoo_test.cj
│ ├── main.cj
│ └── main_test.cj
└── cjpm.toml
使用方式
- 单击
@Test/@TestCase声明行上的 run 按钮,运行该单元测试类/单元测试 case。 - 单击
@Test/@TestCase声明行上的 debug 按钮,调试该单元测试类/单元测试 case。
DAP 通信日志
调试服务客户端和服务端采用 DAP 协议通信,通信日志可用于定位问题。日志路径在用户目录下 /.cangjie/debug/logs/server。
可以通过点击左下角齿轮图标,选择设置(Settings)选项,在搜索栏输入 cangjie,找到 Debug 选项,勾选 Enable DAPCommunication Log,开启调试服务通信日志。

命令行工具集成
说明:
本文档部分图片截取于 VSCode 软件界面,仅用于说明仓颉插件在 VSCode 中的使用方法。
格式化
针对仓颉文件,在 VSCode 的代码编辑区右键选择 [Cangjie] Format 或用快捷键 Ctrl + Alt + F 执行格式化命令,可以对当前仓颉文件进行格式化。如下图所示。

针对仓颉项目,支持在 VSCode 的资源管理器中选择文件或右键单击文件夹执行 [Cangjie] Format 命令,对选择的文件或者文件夹进行格式化。如下图所示。

静态检查
IDE 中的静态检查功能基于静态检查工具 cjlint,该功能可以识别代码中不符合编程规范的问题,帮助开发者发现代码中的漏洞,写出满足 Clean Source 要求的仓颉代码。
说明:
静态检查目前只能检测工程目录 src 文件夹下的所有仓颉文件。
静态检查的入口有两处:
-
在 VSCode 的代码编辑区右键选择 [Cangjie] CodeCheck 或用快捷键 Ctrl + Alt + C 执行静态检查命令,如下图所示。

-
在 VSCode 的资源管理器处右键选择 [Cangjie] CodeCheck 执行静态检查命令,如下图所示。

执行静态检查命令后,如果有不符合编码规范的问题,会展示在右侧的表格中。单击表格中的文件链接,可以跳转到问题代码所在文件的行列。

当前支持代码保存后自动触发静态检查:
开发者可以通过点击左下角齿轮图标,选择设置选项,在搜索栏输入 cangjie,找到 Code Check On Save 选项,勾选该选项,即可开启自动触发静态检查。如下图:

开启自动静态检查后会在项目根目录生成一个 cjlintignore.cfg 配置文件,配置文件中可支持三类屏蔽方式,包括屏蔽文件、文件夹和正则表达式。每条配置项为相对该配置文件所在目录的相对路径(支持正则),无需双引号包含,自动静态检查支持将配置项匹配的仓颉文件屏蔽,不会产生关于这些文件的告警。例如在 cjlintignore.cfg 中有以下配置,则自动静态检查会将 src/subdir1/ 目录和 src/subdir2/a.cj 文件加入屏蔽。

覆盖率统计
覆盖率统计功能用于生成仓颉语言程序的覆盖率报告。
注意:
当选择的文件夹中不含有仓颉文件时,将不会生成覆盖率报告。
覆盖率统计的入口有两处:
-
在 VSCode 的代码编辑区右键选择 [Cangjie] Coverage 或用快捷键 Ctrl + Alt + G 执行生成当前仓颉文件覆盖率报告的命令,如下图所示。

-
在 VSCode 的资源管理器中选择文件或右键单击文件夹执行 [Cangjie] Coverage 命令,对选择的文件或者文件夹生成覆盖率报告,如下图所示。

在生成的覆盖率报告页面,可以单击文件名查看覆盖率详情。
仓颉语言命令行工具使用指南
仓颉语言为开发者提供了丰富的命令行工具,涵盖包管理、命令行调试、代码格式化和覆盖率统计等功能。在成功安装仓颉工具链后,即可根据手册说明使用这些命令行工具。仓颉工具链安装说明请参见安装仓颉工具链。
包管理工具
功能简介
CJPM(Cangjie Package Manager) 是仓颉语言的官方包管理工具,用于对仓颉项目模块系统进行全面管理与维护,涵盖模块初始化、依赖检查与更新等操作。它提供统一的编译入口,支持增量编译、并行编译等,支持自定义编译命令。
使用说明
执行 cjpm -h 命令,查阅包管理工具的使用说明,如下所示。
Cangjie Package Manager
Usage:
cjpm [subcommand] [option]
Available subcommands:
init Init a new cangjie module
check Check the dependencies
update Update cjpm.lock
tree Display the package dependencies in the source code
build Compile the current module
run Compile and run an executable product
test Unittest a local package or module
bench Run benchmarks in a local package or module
clean Clean up the target directory
install Install a cangjie binary
uninstall Uninstall a cangjie binary
Available options:
-h, --help help for cjpm
-v, --version version for cjpm
Use "cjpm [subcommand] --help" for more information about a command.
基本的使用操作命令如下所示:
cjpm build --help
cjpm 是主程序的名称, build 是当前执行的可用命令, --help 是当前可用命令可用的配置项(配置项通常有长和短两种写法,效果相同)。
成功执行后会显示如下结果:
Compile a local module and all of its dependencies.
Usage:
cjpm build [option]
Available options:
-h, --help help for build
-i, --incremental enable incremental compilation
-j, --jobs <N> the number of jobs to spawn in parallel during the build process
-V, --verbose enable verbose
-g enable compile debug version target
--coverage enable coverage
--cfg enable the customized option 'cfg'
-m, --member <value> specify a member module of the workspace
--target <value> generate code for the given target platform
--target-dir <value> specify target directory
-o, --output <value> specify product name when compiling an executable file
-l, --lint enable cjlint code check
--mock enable support of mocking classes in tests
--skip-script disable script 'build.cj'.
命令说明
init
init 用于初始化一个新的仓颉模块或者工作空间。初始化模块时,默认在当前文件夹创建配置文件 cjpm.toml,并新建 src 源码文件夹。如果该模块的产物为可执行类型,则会在 src 下生成默认的 main.cj 文件,并在编译后打印输出 hello world。初始化工作空间时仅会创建 cjpm.toml 文件,默认会扫描该路径下已有的仓颉模块并添加到 members 字段中。若已存在 cjpm.toml 文件,或源码文件夹内已存在 main.cj,则会跳过对应的文件创建步骤。
init 有多个可配置项:
--name <value>指定新建模块的root包名,不指定时默认为上一级子文件夹名称--path <value>指定新建模块的路径,不指定时默认为当前文件夹--type=<executable|static|dynamic>指定新建模块的产物类型,缺省时默认为executable--workspace新建一个工作空间配置文件,指定该选项时以上其它选项无效会自动忽略
例如:
输入: cjpm init
输出: cjpm init success
输入: cjpm init --name demo --path project
输出: cjpm init success
输入: cjpm init --type=static
输出: cjpm init success
check
check 命令用于检查项目中所需的依赖项,执行成功将会打印有效的包编译顺序。
check 有多个可配置项:
-m, --member <value>仅可在工作空间下使用,可用于指定单个模块作为检查入口--no-tests配置后,测试相关的依赖将不会被打印--skip-script配置后,将会跳过构建脚本的编译运行
例如:
输入: cjpm check
输出:
The valid serial compilation order is:
b.pkgA -> b
cjpm check success
输入: cjpm check
输出:
Error: cyclic dependency
b.B -> c.C
c.C -> d.D
d.D -> b.B
输出说明:上述输出中,b.B 代表以 b 为 root 包的模块中的一个名为 b.B 的子包
输入: cjpm check
输出:
Error: can not find the following dependencies
pro1.xoo
pro1.yoo
pro2.zoo
update
update 用于将 cjpm.toml 里的内容更新到 cjpm.lock。当 cjpm.lock 不存在时,将会生成该文件。cjpm.lock 文件记录着 git 依赖的版本号等元信息,用于下次构建使用。
update 有以下可配置项:
--skip-script配置后,将会跳过构建脚本的编译运行
输入: cjpm update
输出: cjpm update success
tree
tree 命令用于可视化地展示仓颉源码中的包依赖关系。
tree 有多个可配置项:
-p, --package <value>指定某个包为根节点,从而展示它的子依赖包,需要配置的值是包名--invert <value>指定某个包为根节点并反转依赖树,从而展示它被哪些包所依赖,需要配置的值是包名--depth <N>指定依赖树的最大深度,可选值是非负整数。指定该选项时,默认会以所有包作为根节点。其中,N 的值代表每个依赖树的子节点最大深度--target <value>将指定目标平台的依赖项加入分析,并展示依赖关系--no-tests排除test-dependencies字段的依赖项-V, --verbose增加包节点的详细信息,包括包名、版本号和包路径--skip-script配置后,将会跳过构建脚本的编译运行
例如,模块 a 的源代码目录结构如下:
src
├── main.cj
├── aoo
│ └── a.cj
├── boo
│ └── b.cj
├── coo
│ └── c.cj
├── doo
│ └── d.cj
├── eoo
│ └── e.cj
└── cjpm.toml
依赖关系为:包 a 导入包 a.aoo、a.boo,子包 aoo 导入包 a.coo,子包 boo 导入包 coo,子包 doo 导入包 coo。
输入: cjpm tree
输出:
|-- a
└── a.aoo
└── a.coo
└── a.boo
└── a.coo
|-- a.doo
└── a.coo
|-- a.eoo
cjpm tree success
输入: cjpm tree --depth 2 -p a
输出:
|-- a
└── a.aoo
└── a.coo
└── a.boo
└── a.coo
cjpm tree success
输入: cjpm tree --depth 0
输出:
|-- a
|-- a.eoo
|-- a.aoo
|-- a.boo
|-- a.doo
|-- a.coo
cjpm tree success
输入: cjpm tree --invert a.coo --verbose
输出:
|-- a.coo 1.2.0 (.../src/coo)
└── a.aoo 1.1.0 (.../src/aoo)
└── a 1.0.0 (.../src)
└── a.boo 1.1.0 (.../src/boo)
└── a 1.0.0 (.../src)
└── a.doo 1.3.0 (.../src/doo)
cjpm tree success
build
build 用于构建当前仓颉项目,执行该命令前会先检查依赖项,检查通过后调用 cjc 进行构建。
build 有多个可配置项:
-i, --incremental用于指定增量编译,默认情况下是全量编译-j, --jobs <N>用于指定并行编译的最大并发数,最终的最大并发数取N和2倍 CPU 核数的最小值-V, --verbose用于展示编译日志-g用于生成debug版本的输出产物--mock带有此选项的构建版本中的类可用于在测试中进行mock测试--coverage用于生成覆盖率信息,默认情况下不开启覆盖率功能--cfg指定后,能够透传cjpm.toml中的自定义cfg选项,cjpm.toml中的配置可参考 profile.customized-option 章节-m, --member <value>仅可在工作空间下使用,可用于指定单个模块作为编译入口--target-dir <value>用于指定输出产物的存放路径-o, --output <value>用于指定输出可执行文件的名称,默认名称为main(Windows系统下则默认为main.exe)。注意,当前不支持编译名称为cjc的可执行文件--target <value>指定后,可交叉编译代码到目标平台,cjpm.toml中的配置可参考 target 章节-l, --lint用于在编译时调用仓颉语言静态检查工具进行代码检查--skip-script配置后,将会跳过构建脚本的编译运行
注意:
-i, --incremental选项仅会开启cjpm包级别的增量编译。开发者可以在配置文件的compile-option字段自行透传--incremental-compile和--experimental编译选项,从而开启cjc编译器提供的函数粒度增量功能。-i, --incremental选项目前仅支持基于源码的增量分析。如果导入的库内容有变更,需要开发者重新使用全量方式构建。
编译生成的中间文件默认会存放在 target 文件夹,而可执行文件会根据编译模式存放到 target/release/bin 或 target/debug/bin 文件夹。运行可执行文件的方式可参考 run。
为了提供可复制的构建,此命令会创建 cjpm.lock 文件,该文件包含所有可传递依赖项的确切版本,这些依赖项将用于所有后续构建,需要更新该文件时请使用 update 命令。如果有必要保证每个项目参与者都有可复制的构建,那么此文件应提交到版本控制系统中。
例如:
输入: cjpm build -V
输出:
compile package module1.package1: cjc --import-path "target/release" --output-dir "target/release/module1" -p "src/package1" --output-type=staticlib -o libmodule1.package1.a
compile package module1: cjc --import-path "target/release" --output-dir "target/release/bin" -p "src" --output-type=exe -o main
cjpm build success
输入: cjpm build
输出: cjpm build success
注意:
根据仓颉包管理规格,只有符合要求的有效源码包才能被正确纳入编译范围。如果编译时出现
no '.cj' file相关的告警,很可能是因为对应包不符合规范导致源码文件不被编译。如果出现这种情况,请参考仓颉包管理规格说明修改代码目录结构。
cjpm build 配置 -l, --lint 选项时,会在编译期间调用仓颉语言静态检查工具 cjlint 进行代码检查。如果检查到【要求】级别的代码规范违规,则此次编译会失败,相应检查结果会输出至错误流;检查到【建议】级别的违规时仅会告警,并正常完成编译。cjlint 支持检查的代码规则列表及其级别详见 cjlint 用户手册。
在执行 cjpm build 之前,cjpm 会对当前模块或工作空间进行包依赖关系检查。若发现包之间存在相互导入关系形成依赖闭环,构建将被中止并返回错误信息,提示循环依赖路径。
例如,模块 demo 的源代码目录结构如下:
src
├── main.cj
├── aoo
│ └── a.cj
├── boo
│ └── b.cj
├── coo
│ └── c.cj
└── cjpm.toml
依赖关系为:包 demo.aoo 导入包 demo.boo,包 demo.boo 导入包 demo.coo,包 demo.coo 导入包 demo.aoo,三个包之间的依赖导入形成闭环,导致循环依赖:
输入: cjpm build
输出:
cyclic dependency:
demo.boo -> demo.coo
demo.coo -> demo.aoo
demo.aoo -> demo.boo
Error: cjpm build failed
出现循环依赖后,开发者可以基于报错信息进行依赖关系排查。上例中,导入关系为 demo.aoo -> demo.boo -> demo.coo -> demo.aoo,开发者可依次从各包对应的目录下找到导入点并分析是否可以删除导入,从而解决循环依赖。例如,开发者可先从 demo.aoo 开始分析,在该包对应的代码目录中,查询哪些源码文件存在 demo.boo 包的导入,若这些文件实际上并没有功能依赖 demo.boo,则可以删除对应的导入。用同样的方法依次排查 demo.boo 和 demo.coo,删除冗余导入,从而尝试解决循环依赖问题。
若经过上述排查,发现确实存在功能上的循环依赖情况,可以尝试下面的几个解决方法:
- 重构导入顺序:尽量让依赖关系保持单向,避免回环,例如上例中
demo.coo中依赖demo.aoo的部分可独立实现,即可拆解闭环; - 拆分模块:将相互引用的代码拆分到独立包,例如上例中可将三个子包合成一个包。
在涉及到包依赖关系解析的其他命令中(例如 tree),若存在循环依赖,也会有相同的报错出现,也可以基于上述处理方式解决。
run
run 用于运行当前项目构建出的二进制产物。run 命令会默认执行 build 命令的流程,以生成最终用于运行的二进制文件。
run 有多个可配置项:
--name <value>指定运行的二进制名称,不指定时默认为main,工作空间下的二进制产物默认存放在target/release/bin路径下--build-args <value>控制build编译流程的参数--skip-build跳过编译流程,直接运行--run-args <value>透传参数给本次运行的二进制产物--target-dir <value>用于指定运行产物的存放路径-g用于运行debug版本的产物-V, --verbose用于展示运行日志--skip-script配置后,将会跳过构建脚本的编译运行
例如:
输入: cjpm run
输出: cjpm run success
输入: cjpm run -g // 此时会默认执行 cjpm build -i -g 命令
输出: cjpm run success
输入: cjpm run --build-args="-s -j16" --run-args="a b c"
输出: cjpm run success
test
test 用于编译并运行仓颉文件的单元测试用例,运行后打印测试结果,编译产物默认存放在 target/release/unittest_bin 文件夹。单元测试用例代码的写法可参考《仓颉编程语言标准库 API》中 std.unittest 库的说明。
该命令可以指定待测试的单包路径(支持指定多个单包,形如 cjpm test path1 path2),不指定路径时默认执行模块级别的单元测试。执行模块级别的单元测试时,默认只进行当前模块的单元测试,直接或间接依赖的其他所有模块内的测试均不会被执行。test 执行前提是当前项目能够 build 编译成功。
模块的单元测试代码结构如下所示,其中 xxx.cj 存放该包的源码,xxx_test.cj 存放单元测试代码:
└── src
│ ├── koo
│ │ ├── koo.cj
│ │ └── koo_test.cj
│ ├── zoo
│ │ ├── zoo.cj
│ │ └── zoo_test.cj
│ ├── main.cj
│ └── main_test.cj
└── cjpm.toml
-
单模块测试场景
输入: cjpm test 进度报告: group test.koo 100% [||||||||||||||||||||||||||||] ✓ (00:00:01) group test.zoo 0% [----------------------------] (00:00:00) test TestZ.sayhi (00:00:00) passed: 1, failed: 0 33% [|||||||||-------------------] 1/3 (00:00:01) 输出: -------------------------------------------------------------------------------------------------- TP: test, time elapsed: 177921 ns, RESULT: TCS: TestM, time elapsed: 177921 ns, RESULT: [ PASSED ] CASE: sayhi (177921 ns) Summary: TOTAL: 1 PASSED: 1, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- TP: test.koo, time elapsed: 134904 ns, RESULT: TCS: TestK, time elapsed: 134904 ns, RESULT: [ PASSED ] CASE: sayhi (134904 ns) Summary: TOTAL: 1 PASSED: 1, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- TP: test.zoo, time elapsed: 132013 ns, RESULT: TCS: TestZ, time elapsed: 132013 ns, RESULT: [ PASSED ] CASE: sayhi (132013 ns) Summary: TOTAL: 1 PASSED: 1, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- Project tests finished, time elapsed: 444838 ns, RESULT: TP: test.*, time elapsed: 312825 ns, RESULT: PASSED: TP: test.zoo, time elapsed: 132013 ns TP: test.koo, time elapsed: 312825 ns TP: test, time elapsed: 312825 ns Summary: TOTAL: 3 PASSED: 3, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- cjpm test success -
单包测试场景
输入: cjpm test src/koo 输出: -------------------------------------------------------------------------------------------------- TP: test.koo, time elapsed: 160133 ns, RESULT: TCS: TestK, time elapsed: 160133 ns, RESULT: [ PASSED ] CASE: sayhi (160133 ns) Summary: TOTAL: 1 PASSED: 1, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- Project tests finished, time elapsed: 160133 ns, RESULT: TP: test.*, time elapsed: 160133 ns, RESULT: PASSED: TP: test.koo, time elapsed: 160133 ns Summary: TOTAL: 1 PASSED: 1, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- cjpm test success -
多包测试场景
输入: cjpm test src/koo src 输出: -------------------------------------------------------------------------------------------------- TP: test.koo, time elapsed: 168204 ns, RESULT: TCS: TestK, time elapsed: 168204 ns, RESULT: [ PASSED ] CASE: sayhi (168204 ns) Summary: TOTAL: 1 PASSED: 1, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- TP: test, time elapsed: 171541 ns, RESULT: TCS: TestM, time elapsed: 171541 ns, RESULT: [ PASSED ] CASE: sayhi (171541 ns) Summary: TOTAL: 1 PASSED: 1, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- Project tests finished, time elapsed: 339745 ns, RESULT: TP: test.*, time elapsed: 339745 ns, RESULT: PASSED: TP: test.koo, time elapsed: 339745 ns TP: test, time elapsed: 339745 ns Summary: TOTAL: 2 PASSED: 2, SKIPPED: 0, ERROR: 0 FAILED: 0 -------------------------------------------------------------------------------------------------- cjpm test success
test 有多个可配置项:
--no-run用于仅编译单元测试产物--skip-build用于仅执行单元测试产物-i, --incremental用于指定测试代码的增量编译,默认情况下是全量编译-j, --jobs <N>用于指定并行编译的最大并发数,最终的最大并发数取N和2倍 CPU 核数的最小值-V, --verbose配置项开启后,会输出单元测试的日志-g用于生成debug版本的单元测试产物,此时的产物存放在target/debug/unittest_bin文件夹--module <value>用于指定目标测试模块,指定的模块需要被当前模块直接或间接依赖(或者是该模块本身),也可以通过--module "module1 module2"的方式指定多个符合要求的模块。不指定时默认只测试当前模块--target-dir <value>用于指定单元测试产物的存放路径--coverage配合cjcov命令可以生成单元测试的覆盖率报告。使用cjpm test --coverage统计覆盖率时,源代码中的main不会再作为程序入口执行,因此会显示为未被覆盖。建议使用cjpm test之后,不再手写多余的main--cfg指定后,能够透传cjpm.toml中的自定义cfg选项-m, --member <value>仅可在工作空间下使用,可用于指定测试单个模块--target <value>指定后,可交叉编译生成目标平台的单元测试结果,cjpm.toml中的配置可参考 target 章节--dry-run配置后,将不执行用例,仅打印--filter <value>用于过滤测试的子集,value的形式如下所示:--filter=*匹配所有测试类--filter=*.*匹配所有测试类的所有测试用例(结果和*相同)--filter=*.*Test,*.*case*匹配所有测试类中以Test结尾的用例,或者所有测试类中名字中带有case的测试用例--filter=MyTest*.*Test,*.*case*,-*.*myTest匹配所有MyTest开头测试类中以Test结尾的用例,或者名字中带有case的用例,或者名字中不带有myTest的测试用例
--include-tags <value>用于获取由@Tag宏指定的测试类别的子集。value的形式如下:--include-tags=Unittest运行所有标记为@Tag[Unittest]的测试--include-tags=Unittest,Smoke运行所有标记为@Tag[Unittest]、@Tag[Smoke]任一或同时都有的测试--include-tags=Unittest+Smoke运行所有标记为@Tag[Unittest]、@Tag[Smoke]同时都有的测试--include-tags=Unittest+Smoke+JiraTask3271,Backend运行所有标记为@Tag[Backend]、@Tag[Unittest, Smoke, JiraTask3271]其一的测试
--exclude-tags <value>用于排除由@Tag宏指定的测试类别的子集。value的形式如下:--exclude-tags=Unittest运行所有未被标记为@Tag[Unittest]的测试--exclude-tags=Unittest,Smoke运行所有未被标记为@Tag[Unittest]、@Tag[Smoke]其一或同时都有的测试--exclude-tags=Unittest+Smoke+JiraTask3271运行所有未被标记为@Tag[Unittest, Smoke, JiraTask3271]同时都有的测试--include-tags=Unittest --exclude-tags=Smoke运行所有被标记为@Tag[Unittest]且不带有@Tag[Smoke]的测试
--random-seed <N>用于指定随机种子的值--no-color关闭控制台颜色显示--timeout-each <value>value 的格式为%d[millis|s|m|h],为每个测试用例指定默认的超时时间--parallel用于指定测试用例并行执行的方案,value的形式如下所示:<BOOL>可为true或false,指定为true时,测试类可被并行运行,并行进程个数将受运行系统上的 CPU 核数控制nCores指定了并行的测试进程个数应该等于可用的 CPU 核数NUMBER指定了并行的测试进程个数值。该数值应该为正整数NUMBERnCores指定了并行的测试进程个数值为可用的 CPU 核数的指定数值倍。该数值应该为正数(支持浮点数或整数)
--show-all-output启用测试输出打印,包括通过的测试用例--no-capture-output禁用测试输出捕获,输出将在测试执行期间立即打印--report-path <value>指定测试执行后的报告生成路径--report-format <value>指定报告输出格式,当前单元测试报告仅支持xml格式(可忽略大小写),使用其它值将会抛出异常--skip-script配置后,将会跳过构建脚本的编译运行--no-progress禁用进度报告。如果指定选项--dry-run,则隐含选项--no-progress--progress-brief显示简短(单行)进度报告而不是详细进度报告--progress-entries-limit <value>限制进度报告中显示的条目数量。默认值:0。允许的值:0不限制条目数n其中n是正整数,指定终端上可以同时显示的最大条目
cjpm test 参数选项使用示例:
输入:
cjpm test src --coverage
cjcov --root=./ --html-details -o html_output
输出:cjpm test success
覆盖率生成:在 html_output 目录下会生成 html 文件,总的覆盖率报告文件名固定为 index.html
输入: cjpm test --filter=*
输出: cjpm test success
输入: cjpm test src --report-path=reports --report-format=xml
输出: cjpm test success
注意:
cjpm test会自动构建所有带有mock支持的包,因此在测试中,开发者可以对自定义的类或依赖源模块的类进行mock测试。为了能够从一些二进制依赖中mock类,应该通过cjpm build --mock来构建带有mock支持的类。
bench
bench 用于执行测试文件的性能用例并直接打印测试结果。编译产物默认存放在 target/release/unittest_bin 文件夹中。性能用例由 @Bench 宏标注。更多关于如何编写性能用例代码的详细信息,请参见《仓颉编程语言标准库 API》中对 std.unittest 库的描述。
该命令可以指定待测试的单包路径(支持指定多个单包,形如 cjpm bench path1 path2),不指定路径时默认执行模块级别的单元测试。与 test 一样,执行模块级别的单元测试时,默认只进行当前模块的单元测试。bench 执行前提是当前项目能够 build 编译成功。
与 test 子命令类似,如果您有 xxx.cj 文件,则 xxx_test.cj 也可以包含性能测试用例。
输入: cjpm bench
输出:
TP: bench, time elapsed: 8107939844 ns, RESULT:
TCS: Test_UT, time elapsed: 8107939844 ns, RESULT:
| Case | Median | Err | Err% | Mean |
|:-----------|---------:|------------:|-------:|---------:|
| Benchmark1 | 5.438 ns | ±0.00439 ns | ±0.1% | 5.420 ns |
Summary: TOTAL: 1
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
Project tests finished, time elapsed: 8107939844 ns, RESULT:
TP: bench.*, time elapsed: 8107939844 ns, RESULT:
PASSED:
TP: bench, time elapsed: 8107939844 ns, RESULT:
Summary: TOTAL: 1
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 0
bench 有多个可配置项:
--no-run用来仅编译单元测试产物--skip-build用来仅执行单元测试产物-i, --incremental用于指定测试代码的增量编译,默认情况下是全量编译-j, --jobs <N>用来指定并行编译的最大并发数,最终的最大并发数取N和2倍 CPU 核数的最小值-V, --verbose配置项开启后,会输出单元测试的日志-g用来生成debug版本的单元测试产物,此时的产物存放在target/debug/unittest_bin文件夹--module <value>用于指定目标测试模块,指定的模块需要被当前模块直接或间接依赖(或者是该模块本身),也可以通过--module "module1 module2"的方式指定多个符合要求的模块。不指定时默认只测试当前模块--target-dir <value>用来指定单元测试产物的存放路径--cfg指定后,能够透传cjpm.toml中的自定义cfg选项-m, --member <value>仅可在工作空间下使用,可用来指定测试单个模块--target <value>指定后,可交叉编译生成目标平台的单元测试结果,cjpm.toml中的配置可参考cross-compile-configuration部分--dry-run配置后,将不执行用例,仅打印--filter <value>用于过滤测试的子集,value的形式如下所示:--filter=*匹配所有测试类--filter=*.*匹配所有测试类所有测试用例(结果和*相同)--filter=*.*Test,*.*case*匹配所有测试类中以Test结尾的用例,或者所有测试类中名字中带有case的测试用例--filter=MyTest*.*Test,*.*case*,-*.*myTest匹配所有MyTest开头测试类中以Test结尾的用例,或者名字中带有case的用例,或者名字中不带有myTest的测试用例
--include-tags <value>用于获取由@Tag宏指定的测试类别的子集。value的形式如下:--include-tags=Unittest运行所有标记为@Tag[Unittest]的测试--include-tags=Unittest,Smoke运行所有标记为@Tag[Unittest]、@Tag[Smoke]任一或同时都有的测试--include-tags=Unittest+Smoke运行所有标记为@Tag[Unittest, Smoke]同时都有的测试--include-tags=Unittest+Smoke+JiraTask3271,Backend运行所有标记为@Tag[Backend]、@Tag[Unittest, Smoke, JiraTask3271]其一的测试
--exclude-tags <value>用于排除由@Tag宏指定的测试类别的子集。value的形式如下:--exclude-tags=Unittest运行所有未被标记为@Tag[Unittest]的测试--exclude-tags=Unittest,Smoke运行所有未被标记为@Tag[Unittest]、@Tag[Smoke]其一或同时都有的测试--exclude-tags=Unittest+Smoke+JiraTask3271运行所有未被标记为@Tag[Unittest, Smoke, JiraTask3271]同时都有的测试--include-tags=Unittest --exclude-tags=Smoke运行所有被标记为@Tag[Unittest]且不带有@Tag[Smoke]的测试
--random-seed <N>用来指定随机种子的值--no-color关闭控制台颜色显示--report-path <value>指定执行后生成报告的路径。与test子命令不同,它具有默认值bench_report--baseline-path <value>与当前性能结果进行比较的现有报告的路径。默认情况下它使用--report-path值--compile-option <string>指定专门用于性能测试的附加编译器选项--report-format <value>性能测试报告仅支持csv和csv-raw格式--skip-script配置后,将会跳过构建脚本的编译运行
cjpm bench 参数选项使用示例:
输入: cjpm bench
输出: cjpm bench success
输入: cjpm bench src
输出: cjpm bench success
输入: cjpm bench src --filter=*
输出: cjpm bench success
输入: cjpm bench src --report-format=csv
输出: cjpm bench success
注意:
带有
cjpm bench并不包含完全的mock支持,以避免在基准测试中由于在编译器中的mock处理而增加的任何开销。 使用cjpm bench选项时,如果使用mock,编译器不会报错,以便能够将常规测试和基准测试一起编译。但是要避免运行使用mock的基准测试,否则会抛出运行时异常。
clean
clean 用于清理构建过程中的临时产物(target 文件夹)。该命令支持通过短选项 -g 指定仅清理 debug 版本的产物。该命令支持通过长选项 --target-dir <value> 用于指定清理的产物存放路径,开发者需自身保证清理该目录行为的安全性。如果使用了 cjpm build --coverage 或者 cjpm test --coverage 功能,还会清除 cov_output 文件夹,以及当前目录下的 *.gcno 文件和 *.gcda 文件。同时,该命令也支持通过 --skip-script 配置跳过构建脚本的编译运行。
例如:
输入: cjpm clean
输出: cjpm clean success
输入: cjpm clean --target-dir temp
输出: cjpm clean success
注意:
在
Windows平台上,在子进程执行完成后立即清理子进程的可执行文件或父目录可能会失败。如果遇到该问题,可以在一小段延迟后重新尝试clean命令。
install
install 用于安装仓颉项目,执行该命令前会先进行编译,然后将编译产物安装到指定路径,安装产物以仓颉项目名命名(Windows 系统上会有 .exe 后缀)。install 安装的项目产物类型需要是 executable。
install 有多个可配置项:
-V, --verbose用于展示安装日志。-g用于生成debug版本的安装产物。--path <value>用于指定本地安装项目的路径,默认为当前路径下的项目。--root <value>用于指定可执行文件的安装路径。不配置时Linux/macOS系统下默认为$HOME/.cjpm,Windows系统下默认为%USERPROFILE%/.cjpm;配置时将会安装于value。-m, --member <value>仅可在工作空间下使用,可用于指定单个模块作为编译入口以安装单一模块。--target-dir <value>用于指定编译产物的存放路径。--name <value>用于指定最终安装的产物名。--git <value>用于指定git安装的项目url。--branch <value>用于指定git安装的项目分支。--tag <value>用于指定git安装的项目tag。--commit <value>用于指定git安装的项目commit ID。--list用于打印已安装产物列表。--skip-build用于跳过编译阶段以直接安装产物,需要项目处于编译完成状态,且仅在本地安装场景下生效。-j, --jobs <N>用于指定并行编译的最大并发数,最终的最大并发数取N和2倍 CPU 核数的最小值。--cfg指定后,能够透传cjpm.toml中的自定义cfg选项。--skip-script配置后,将会跳过待安装模块的构建脚本的编译运行。
install 功能有如下注意事项:
install共有两种安装方式:安装本地项目(通过--path配置项目路径)和安装git项目(通过--git配置项目url)。这两种安装方式至多只能配置一种,否则install将报错。任意一种均未配置时,默认安装当前目录下的本地项目。install编译项目时,默认开启增量编译。git相关配置仅在配置--git后生效,否则会被忽略,包括--branch,--tag和--commit。当配置多个git相关配置时,仅会生效优先级更高的配置,优先级排序为--commit>--branch>--tag。- 若已存在同名可执行文件被安装,则原来的文件将被替换。
- 假设安装路径为
root(root为配置的安装路径,不配置则为默认路径),则可执行文件将被安装于root/bin。 - 若项目存在动态库依赖,可执行程序所需动态库会被安装到
root/libs,按程序名分隔为若干目录,开发者需要将对应目录加入相应路径(Linux中为LD_LIBRARY_PATH,Windows中为PATH,macOS中为DYLD_LIBRARY_PATH)方可使用。 - 默认安装路径(
Linux/macOS系统下默认为$HOME/.cjpm,Windows系统下默认为%USERPROFILE%/.cjpm)会在envsetup中被加入PATH。 install在安装git项目后,对应的编译产物目录会被清除。- 在待安装项目仅存在一个可执行文件产物时,指定
--name会将其更名后安装;若存在多个可执行文件产物,指定--name会仅安装对应名称的产物。 - 配置
--list时,install会打印已安装产物列表,此时除--root以外的所有配置项均会被忽略。配置--root后,--list会打印配置路径下已安装的产物列表,否则会打印默认路径下的列表。
例如:
cjpm install --path path/to/project # 从本地路径 path/to/project 中安装
cjpm install --git url # 从 git 对应地址安装
uninstall
uninstall 用于卸载仓颉项目,清除对应的可执行文件和依赖文件。
uninstall 需要配置参数 name,以卸载名为 name 的产物,配置多个 name 时会依次删除。uninstall 可以通过 --root <value> 指定卸载的可执行文件路径,不配置时 Linux / macOS 系统下默认为 $HOME/.cjpm,Windows 系统下默认为 %USERPROFILE%/.cjpm,配置时将会卸载安装于 value/bin 的产物和安装于 value/libs 的依赖。
注意:
cjpm在Windows平台暂不支持在中文路径下使用,如果遇到问题,请通过修改目录名规避。
模块配置文件说明
模块配置文件 cjpm.toml 用于配置一些基础信息、依赖项、编译选项等内容,cjpm 主要通过这个文件进行解析执行。其中,模块名可以在 cjpm.toml 中进行重命名,但是包名不能在 cjpm.toml 中进行重命名。
配置文件代码如下所示:
[package] # 单模块配置字段,与 workspace 字段不能同时存在
cjc-version = "0.49.1" # 所需 `cjc` 的最低版本要求,必需
name = "demo" # 模块名及模块 root 包名,必需
description = "nothing here" # 描述信息,非必需
version = "1.0.0" # 模块版本信息,必需
compile-option = "" # 额外编译命令选项,非必需
override-compile-option = "" # 额外全局编译命令选项,非必需
link-option = "" # 链接器透传选项,可透传安全编译命令,非必需
output-type = "executable" # 编译输出产物类型,必需
src-dir = "" # 指定源码存放路径,非必需
target-dir = "" # 指定产物存放路径,非必需
package-configuration = {} # 单包配置选项,非必需
[workspace] # 工作空间管理字段,与 package 字段不能同时存在
members = [] # 工作空间成员模块列表,必需
build-members = [] # 工作空间编译模块列表,需要是成员模块列表的子集,非必需
test-members = [] # 工作空间测试模块列表,需要是编译模块列表的子集,非必需
compile-option = "" # 应用于所有工作空间成员模块的额外编译命令选项,非必需
override-compile-option = "" # 应用于所有工作空间成员模块的额外全局编译命令选项,非必需
link-option = "" # 应用于所有工作空间成员模块的链接器透传选项,非必需
target-dir = "" # 指定产物存放路径,非必需
[dependencies] # 源码依赖配置项,非必需
coo = { git = "xxx",branch = "dev" , version = "1.0.0"} # 导入 `git` 依赖,`version`字段可缺省
doo = { path = "./pro1" ,version = "1.0.0"} # 导入源码依赖,`version`字段可缺省
[test-dependencies] # 测试阶段的依赖配置项,格式和 dependencies 相同,非必需
[script-dependencies] # 构建脚本的依赖配置项,格式和 dependencies 相同,非必需
[replace] # 依赖替换配置项,格式和 dependencies 相同,非必需
[ffi.c] # 导入 C 语言的库依赖,非必需
clib1.path = "xxx"
[profile] # 命令剖面配置项,非必需
build = {} # build 命令配置项
test = {} # test 命令配置项
bench = {} # bench 命令配置项
customized-option = {} # 自定义透传选项
[target.x86_64-unknown-linux-gnu] # 后端和平台隔离配置项,非必需
compile-option = "value1" # 额外编译命令选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
override-compile-option = "value2" # 额外全局编译命令选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
link-option = "value3" # 链接器透传选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
[target.x86_64-w64-mingw32.dependencies] # 适用于对应 target 的源码依赖配置项,非必需
[target.x86_64-w64-mingw32.test-dependencies] # 适用于对应 target 的测试阶段依赖配置项,非必需
[target.x86_64-unknown-linux-gnu.bin-dependencies] # 仓颉二进制库依赖,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必需
path-option = ["./test/pro0", "./test/pro1"] # 以文件目录形式配置二进制库依赖
[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option] # 以单文件形式配置二进制库依赖
"pro0.xoo" = "./test/pro0/pro0.xoo.cjo"
"pro0.yoo" = "./test/pro0/pro0.yoo.cjo"
"pro1.zoo" = "./test/pro1/pro1.zoo.cjo"
当以上字段在 cjpm.toml 中没有使用时,默认为空(对于路径,默认为配置文件所在的路径)。
"cjc-version"
仓颉编译器最低版本要求,必须和当前环境版本兼容才可以执行。一个合法的仓颉版本号是由三段数字组成,中间使用 . 隔开,每个数字均为自然数,且没有多余的前缀 0。例如:
0.49.1是一个有效的版本号;0.049.1不是一个有效的版本号,因为049中含有多余的前缀0;0.2e.1不是一个有效的版本号,因为2e不是自然数。
"name"
当前仓颉模块名称,同时也是模块 root 包名。
一个合法的仓颉模块名称必须是一个合法的标识符。标识符可由字母、数字、下划线组成,标识符的开头必须是字母,例如 cjDemo 或者 cj_demo_1。
注意:
当前仓颉模块名暂不支持使用 Unicode 字符,仓颉模块名必须是一个仅含 ASCII 字符的合法的标识符。
"description"
当前仓颉模块描述信息,仅作说明用,不限制格式。
"version"
当前仓颉模块版本号,由模块所有者管理,主要供模块校验使用。模块版本号的格式同 cjc-version。
"compile-option"
传给 cjc 的额外编译选项。多模块编译时,每个模块设置的 compile-option 对该模块内的所有包生效。
例如:
compile-option = "-O1 -V"
这里填入的命令会在 build 执行时插入到编译命令中间,多个命令可以用空格隔开。可用的命令请参见《仓颉编程语言开发指南》的编译选项章节内容。
"override-compile-option"
传给 cjc 的额外全局编译选项。多模块编译时,编译入口模块设置的 override-compile-option 对该模块及依赖的所有其他模块的包生效。
例如:
override-compile-option = "-O1 -V"
这里填入的命令会在 build 执行时插入到编译命令中间,并且拼接于模块配置的 compile-option 内容之后,优先级高于 compile-option。可用的命令参考《仓颉编程语言开发指南》的编译选项章节内容。
注意:
override-compile-option会生效于依赖模块内的包,开发者需保证配置的cjc编译选项与依赖模块内配置的compile-option没有冲突,否则编译过程中执行cjc将出现相应报错。对于不冲突的同类cjc编译选项,override-compile-option内的选项优先级高于compile-option。- 在工作空间编译场景下,仅
workspace内配置的override-compile-option选项会应用于工作空间内所有模块所有包的编译;即使使用-m指定以单模块为入口模块进行编译,也不会使用入口模块的override-compile-option。
"link-option"
传给链接器的编译选项,可用于透传安全编译命令,如下所示:
link-option = "-z noexecstack -z relro -z now --strip-all"
注意:
link-option中配置的命令在编译时只会自动透传给动态库和可执行产物对应的包。
"output-type"
编译输出产物的类型,包含可执行程序和库两种形式,相关的输入如下表格所示。如果想生成 cjpm.toml 时该字段自动填充为 static,可使用命令 cjpm init --type=static --name=modName,不指定类型时默认生成为 executable。只有主模块的该字段可以为 executable。
| 输入 | 说明 |
|---|---|
| "executable" | 可执行程序 |
| "static" | 静态库 |
| "dynamic" | 动态库 |
| 其它 | 报错 |
"src-dir"
该字段可以指定源码的存放路径,不指定时默认为 src 文件夹。
"target-dir"
该字段可以指定编译产物的存放路径,不指定时默认为 target 文件夹。若该字段不为空,执行 cjpm clean 时会删除该字段所指向的文件夹,开发者需自身保证清理该目录行为的安全性。
注意:
若在编译时同时指定了
--target-dir选项,则该选项的优先级会更高。
target-dir = "temp"
"package-configuration"
每个模块的单包可配置项。该选项是个 map 结构,需要配置的包名作为 key,单包配置信息作为 value。当前可配置的信息包含:
output-type:包编译产物类型,取值同output-typecompile-option:仅用于该包的额外编译选项combine-all-deps:工程级编译产物合并开关,取值为true/false,仅可配置于root包
上述选项均可按需配置。
如下所示,demo 模块中的 demo.aoo 包的输出类型会被指定为动态库类型,-g 命令会在编译时透传给 demo.aoo 包。
[package.package-configuration."demo.aoo"]
output-type = "dynamic"
compile-option = "-g"
如果在不同字段配置了相互兼容的编译选项,生成命令的优先级如下所示。
[package]
compile-option = "-O1"
[package.package-configuration.demo]
compile-option = "-O2"
# profile字段会在下文介绍
[profile.customized-option]
cfg1 = "-O0"
输入: cjpm build --cfg1 -V
输出: cjc --import-path build -O0 -O1 -O2 ...
通过配置这个字段,可以同时生成多个二进制产物(生成多个二进制产物时,-o, --output <value> 选项将会失效),示例如下:
源码结构的示例,模块名为 demo:
src
├── aoo
│ └── aoo.cj
├── boo
│ └── boo.cj
├── coo
│ └── coo.cj
└── main.cj
配置方式的示例:
[package.package-configuration."demo.aoo"]
output-type = "executable"
[package.package-configuration."demo.boo"]
output-type = "executable"
多个二进制产物的示例:
输入:cjpm build
输出:cjpm build success
输入:tree target/release/bin
输出:target/release/bin
|-- demo.aoo
|-- demo.boo
`-- demo
combine-all-deps = true 配置后,可以开启工程级别的编译产物合并。该配置仅在以下条件下生效:
- 开启模块级动态库合并
profile.build.combined和LTO编译优化profile.build.lto(参考profile.build字段); - 配置的模块为当前执行的
cjpm build命令对应的模块,并且配置的包为该模块的root包。配置在当前模块的非root包中,或配置在被依赖的模块中的该字段将被忽略。
在满足上述配置条件后,该模块会按照如下方式编译:
- 除该模块
root包以外的所有包(该模块下的所有子包,以及该模块直接、间接依赖的其他模块的包含root包的所有包),会以LTO优化编译模式编译成.bc文件; - 该模块的
root包会被编译成动态库,并且链入上述所有.bc文件,无论对应的包是否被该root包导入。
"workspace"
该字段可管理多个模块作为一个工作空间,支持以下配置项:
members = ["aoo", "path/to/boo"]:列举包含在此工作空间的本地源码模块,支持绝对路径和相对路径。该字段的成员必须是一个模块,不允许是另一个工作空间build-members = []:本次编译的模块,不指定时默认编译该工作空间内的所有模块。该字段的成员必须被包含在members字段中test-members = []:本次测试的模块,不指定时默认单元测试该工作空间内的所有模块。该字段的成员必须被包含在build-members字段中compile-option = "":工作空间的公共编译选项,非必需override-compile-option = "":工作空间的公共全局编译选项,非必需link-option = "":工作空间的公共链接选项,非必需target-dir = "":工作空间的产物存放路径,非必需,默认为target
工作空间内的公共配置项,对所有成员模块生效。例如:配置了 [dependencies] xoo = { path = "path_xoo" } 的源码依赖,则所有成员模块可以直接使用 xoo 模块,无需在每个子模块的 cjpm.toml 中再配置。
注意:
package字段用于配置模块的通用信息,不允许和workspace字段出现在同一个cjpm.toml中,除package外的其它字段均可在工作空间中使用。
工作空间目录举例:
root_path
├── aoo
│ ├── src
│ └── cjpm.toml
├── boo
│ ├── src
│ └── cjpm.toml
├── coo
│ ├── src
│ └── cjpm.toml
└── cjpm.toml
工作空间的配置文件使用举例:
[workspace]
members = ["aoo", "boo", "coo"]
build-members = ["aoo", "boo"]
test-members = ["aoo"]
compile-option = "-Woff all"
override-compile-option = "-O2"
[dependencies]
xoo = { path = "path_xoo" }
[ffi.c]
abc = { path = "libs" }
"dependencies"
该字段通过源码方式导入依赖的其它仓颉模块,里面配置了当前构建所需要的其它模块的信息。目前,该字段支持本地路径依赖和远程 git 依赖。
要指定本地依赖项,请使用 path 字段,并且它必须包含有效的本地路径。例如,下面的两个子模块 pro0 和 pro1 和主模块的代码结构如下:
├── pro0
│ ├── cjpm.toml
│ └── src
│ └── zoo
│ └── zoo.cj
├── pro1
│ ├── cjpm.toml
│ └── src
│ ├── xoo
│ │ └── xoo.cj
│ └── yoo
│ └── yoo.cj
├── cjpm.toml
└── src
├── aoo
│ └── aoo.cj
├── boo
│ └── boo.cj
└── main.cj
在主模块的 cjpm.toml 中进行如下配置后,即可在源码中使用 pro0 和 pro1 模块:
[dependencies]
pro0 = { path = "./pro0" }
pro1 = { path = "./pro1" }
要指定远程 git 依赖项,请使用 git 字段,并且它必须包含 git 支持的任何格式的有效 url。要配置 git 依赖关系,最多可以有一个 branch、tag 和 commitId 字段,这些字段允许分别选择特定的分支、标记或提交哈希,若配置多个此类字段则仅会生效优先级最高的配置,优先级顺序为 commitId > branch > tag。例如,进行如下配置后,即可在源码中使用特定 git 仓库地址的 pro0 和 pro1 模块:
[dependencies]
pro0 = { git = "git://github.com/org/pro0.git", tag = "v1.0.0"}
pro1 = { git = "https://gitee.com/anotherorg/pro1", branch = "dev"}
在这种情况下, cjpm 将下载对应存储库的最新版本,并将当前 commit-hash 保存在 cjpm.lock 文件中。所有后续的 cjpm 调用都将使用保存的版本,直到使用 cjpm update。
通常需要一些身份验证才能访问 git 存储库。 cjpm 不要求提供所需的凭据,因此应使用现有的 git 身份验证支持。如果用于 git 的协议是 https ,则需要使用一些现有的 git 凭据帮助程序。在 Windows 上,可在安装 git 时一起安装凭据帮助程序,默认使用。在 Linux/macOS 上,请参见 git 官方文档中 git-config 的配置说明,了解有关设置凭据帮助程序的详细信息。如果协议是 ssh 或 git ,则应使用基于密钥的身份验证。如果密钥受密码短语保护,则开发者应确保 ssh-agent 正在运行,并且在使用 cjpm 之前通过 ssh-add 添加密钥。
dependencies 字段可以通过 output-type 属性指定编译产物类型,指定的类型可以与源码依赖自身的编译产物类型不一致,且仅能为 static 或者 dynamic, 如下所示:
[dependencies]
pro0 = { path = "./pro0", output-type = "static" }
pro1 = { git = "https://gitee.com/anotherorg/pro1", output-type = "dynamic" }
进行如上配置后,将会忽略 pro0 和 pro1 的 cjpm.toml 中的 output-type 配置,将这两个模块的产物分别编译成 static 和 dynamic 类型。
"test-dependencies"
具有与 dependencies 字段相同的格式。它用于指定仅在测试过程中使用的依赖项,而不是构建主项目所需的依赖项。模块开发者应将此字段用于此模块的下游用户不需要感知的依赖项。
test-dependencies 内的依赖仅可用于文件名形如 xxx_test.cj 的测试文件,在编译时这些依赖将不会被编译。test-dependencies 在 cjpm.toml 中的配置格式与 dependencies 相同。
"script-dependencies"
具有与 dependencies 字段相同的格式。它用于指定仅在编译构建脚本中使用的依赖项,而不是构建主项目所需的依赖项。构建脚本相关功能将在其他-构建脚本章节中详述。
"replace"
具有与 dependencies 字段相同的格式。它用于指定间接依赖的同名替换项,配置的依赖项会作为编译该模块时最终使用的依赖版本。
例如,如下模块 aaa 依赖了一个本地模块 bbb:
[package]
name = "aaa"
[dependencies]
bbb = { path = "path/to/bbb" }
主模块 demo 依赖 aaa 的情况下,bbb 即成为 demo 的间接依赖模块。在这种情况下,主模块 demo 若想替换 bbb 为另一个同名模块,例如在另一个路径 new/path/to/bbb 下的 bbb 模块,则可以进行如下配置:
[package]
name = "demo"
[dependencies]
aaa = { path = "path/to/aaa" }
[replace]
bbb = { path = "new/path/to/bbb" }
配置后,编译 demo 模块时实际使用的间接依赖 bbb 即为new/path/to/bbb 下的 bbb 模块,aaa 中配置的 path/to/bbb 下的 bbb 模块不会被编译。
注意:
仅入口模块的
replace字段会在编译时生效。
"ffi.c"
当前仓颉模块外部依赖 c 库的配置。该字段配置了依赖该库所需要的信息,包含库名和路径。
开发者需要自行编出动态库或静态库放到设置的 path 下,可参考下面的例子。
仓颉调用外部 c 动态库的方法说明:
- 自行将相应的
hello.c文件编成.so库(在该文件路径执行clang -shared -fPIC hello.c -o libhello.so) - 修改该项目的
cjpm.toml文件,配置ffi.c字段,如下面的例子所示。其中,./src/是编出的libhello.so相对当前目录的地址,hello为库名。 - 执行
cjpm build,即可编译成功。
[ffi.c]
hello = { path = "./src/" }
"profile"
profile 作为一种命令剖面配置项,用于控制某个命令执行时的默认配置项。目前支持四种场景:build、test、run 和 customized-option。
"profile.build"
[profile.build]
lto = "full" # 是否开启 `LTO` (Link Time Optimization 链接时优化)优化编译模式,仅 `Linux` 平台支持该功能。
performance_analysis = true # 开启编译性能分析功能
incremental = true # 是否默认开启增量编译
[profile.build.combined]
demo = "dynamic" # 将模块整体编译成一个动态库文件,key 值为模块名
编译流程的控制项,所有字段均可缺省,不配置时不生效,顶层模块设置的 profile.build 项才会生效。
lto 配置项的取值为 full 或 thin,对应 LTO 优化支持的两种编译模式:full LTO 将所有编译模块合并到一起,在全局上进行优化,这种方式可以获得最大的优化潜力,同时也需要更长的编译时间;thin LTO 在多模块上使用并行优化,同时默认支持链接时增量编译,编译时间比 full LTO 短,但是因为失去了更多的全局信息,所以优化效果不如 full LTO。
performance_analysis 配置项的取值为 true 或 false,代表是否开启编译性能分析功能。当开启此功能时,cjpm 会在编译产物目录下的 performance_analysis 目录中生成 .prof 和 .json 文件,这些文件记录了编译过程中的时间和内存消耗。例如,编译产物目录默认为 target 目录,且编译模式为 debug,则产物目录结构如下:
demo
├── cjpm.toml
├── src
| └── demo.cj
└── target
└── debug
└── performance_analysis
├── xxx1.prof
├── ...
├── xxxN.prof
├── xxx1.json
├── ...
└── xxxN.json
combined 配置项是一个键值对,其中键为模块名,即 package.name,值为 dynamic。配置该配置项之前,该模块会根据 package.output-type 配置将各个包编译成独立的动态库或静态库文件;配置后,该模块的编译方式改为:
- 模块内除
root包以外的子包以静态库形式编译; root包以动态库形式编译,并且链接所有子包的静态库,无论子包是否被root包依赖。其他模块以二进制依赖形式依赖该动态库时,可以使用所有子包内的符号。
例如,假设模块 demo 的结构如下:
demo
├── cjpm.toml
└── src
├── aoo
| └── aoo.cj
├── boo
| └── boo.cj
└── demo.cj
模块配置文件 cjpm.toml 内配置如下:
[package]
name = "demo"
[profile.build.combined]
demo = "dynamic"
在编译之后,最终的编译产物目录 target/release/demo 中的产物列表如下(以 Linux 为例):
|-- libdemo.so
|-- libdemo.aoo.a
|-- libdemo.boo.a
|-- demo.cjo
|-- demo.aoo.cjo
|-- demo.boo.cjo
模块开发者可以将上述产物列表中的所有 cjo 文件和 root 包动态库 libdemo.so 提供给其他模块作为二进制依赖,无需提供子包的静态库文件。其他模块依赖该动态库之后,可以在代码中依赖其所有子包,例如可以通过 import demo.aoo 的方式依赖 demo.aoo 包。
注意:
- 在应用此配置时,编译
root包动态库需要使用其所有子包的静态库,因此需要保证root包不被其子包直接或间接导入。- 目前
profile.build.combined配置项为实验特性,暂不稳定,开发者若想启用该配置,需要注意如下限制:
- 如果配置了该字段的模块直接或间接依赖了其他源码模块,那么这些依赖模块也需要配置该字段;
- 构建脚本依赖的源码模块中,若配置了
profile.build.combined,不会生效;- 编译产物目标平台为
macOS时,暂不支持profile.build.combined选项。
若启用了 combined 配置,可能会出现无法通过导入关系识别的循环依赖,导致出现 cyclic dependency 循环依赖报错,解决方式如下:
- 若报错信息中包含形如
because of combined module 'demo'的报错,说明模块demo被配置成了combined模块,并且存在demo的子包直接或间接依赖demo包的情况,开发者可以查找并删去该模块子包中存在的对root包的导入,或者直接去除combined配置,从而解决此类循环依赖; - 若报错信息中包含形如
between combined modules的报错,说明该条目中两个root包对应模块都被配置成了combined模块,且存在模块间(包括子包之间)的相互依赖,开发者可以查找并删去其中一个combined模块对另一个combined模块的包导入,或者直接去除两个模块的combined配置,从而解决此类循环依赖。
"profile.test"
[profile.test] # 使用举例
parallel=true
filter=*.*
no-color = true
timeout-each = "4m"
random-seed = 10
bench = false
report-path = "reports"
report-format = "xml"
verbose = true
[profile.test.build]
compile-option = ""
lto = "thin"
mock = "on"
[profile.test.env]
MY_ENV = { value = "abc" }
cjHeapSize = { value = "32GB", splice-type = "replace" }
PATH = { value = "/usr/bin", splice-type = "prepend" }
测试配置支持指定编译和运行测试用例时的选项,所有字段均可缺省,不配置时不生效,顶层模块设置的 profile.test 项才会生效。选项列表与 cjpm test 提供的控制台执行选项一致。如果选项在配置文件和控制台中同时被配置,则控制台中的选项优先级高于配置文件中的选项。profile.test 支持的运行时选项:
filter指定用例过滤器,参数值类型为字符串,格式与 test 命令说明中--filter的值格式一致timeout-each <value>中value的格式为%d[millis|s|m|h],为每个测试用例指定默认的超时时间parallel指定测试用例并行执行的方案,value的形式如下所示:<BOOL>值为true或false,指定为true时,测试类可被并行运行,并行进程个数将受运行系统上的 CPU 核数控制nCores指定并行的测试进程个数应该等于可用的 CPU 核数NUMBER指定并行的测试进程个数值。该数值应该为正整数NUMBERnCores指定并行的测试进程个数值为可用的 CPU 核数的指定数值倍。该数值应该为正数(支持浮点数或整数)
option:<value>与@Configure协同定义运行选项。例如,如下选项:random-seed用来指定随机种子的值,参数值类型为正整数no-color指定执行结果在控制台中是否无颜色显示,值为true或falsereport-path指定测试执行后的报告生成路径(不能通过@Configure配置)report-format指定报告输出格式,当前当前单元测试报告仅支持xml格式(可忽略大小写),使用其它值将会抛出异常(不能通过@Configure配置),性能测试报告仅支持csv和csv-raw格式verbose指定显示编译过程详细信息,参数值类型为BOOL,即值可为true或false
"profile.test.build"
用于指定支持的编译选项,其列表如下:
compile-option是一个包含附加cjc编译选项的字符串。为顶级compile-option字段做补充lto指定是否开启LTO优化编译模式,该值可为thin或full,仅Linux平台支持该功能mock显式设置mock模式,可能的选项:on、off、runtime-error。对test/build子命令默认值为on,对于bench子命令默认值为runtime-error
"profile.test.env"
用于在 test 命令时运行可执行文件时配置临时环境变量,key 值为需要配置的环境变量的名称,有如下配置项:
value指定配置的环境变量值splice-type指定环境变量的拼接方式,非必填,不配置时默认为absent,共有以下四种取值:absent: 该配置仅在环境内不存在同名环境变量时生效,若存在同名环境变量则忽略该配置replace: 该配置会替代环境中已有的同名环境变量prepend: 该配置会拼接在环境中已有的同名环境变量之前append: 该配置会拼接在环境中已有的同名环境变量之后
"profile.bench"
[profile.bench] # 使用举例
no-color = true
random-seed = 10
report-path = "bench_report"
baseline-path = ""
report-format = "csv"
verbose = true
测试配置支持指定编译和运行测试用例时的选项,所有字段均可缺省,不配置时不生效,顶层模块设置的 profile.bench 项才会生效。选项列表与 cjpm bench 提供的控制台执行选项一致。如果选项在配置文件和控制台中同时被配置,则控制台中的选项优先级高于配置文件中的选项。profile.bench 支持的运行时选项:
filter指定用例过滤器,参数值类型为字符串, 格式与 bench 命令说明中--filter的值格式一致option:<value>与@Configure协同定义运行选项。例如,如下选项:random-seed用来指定随机种子的值, 参数值类型为正整数no-color指定执行结果在控制台中是否无颜色显示,值为true或falsereport-path指定测试执行后的报告生成路径(不能通过@Configure配置)report-format指定报告输出格式,当前当前单元测试报告仅支持xml格式(可忽略大小写),使用其它值将会抛出异常(不能通过@Configure配置), 性能测试报告仅支持csv和csv-raw格式verbose指定显示编译过程详细信息,参数值类型为BOOL, 即值可为true或falsebaseline-path与当前性能结果进行比较的现有报告的路径。默认情况下它使用--report-path值。
"profile.bench.build"
用于指定为 cjpm bench 构建可执行文件时使用的附加编译选项。与 profile.test.build 具有相同的配置。
"profile.bench.env"
支持配置在 bench 命令时运行可执行文件时的环境变量配置,配置方式同 profile.test.env。
"profile.run"
运行可执行文件时的选项,支持配置在 run 命令时运行可执行文件时的环境变量配置 env,配置方式同 profile.test.env。
"profile.customized-option"
[profile.customized-option]
cfg1 = "--cfg=\"feature1=lion, feature2=cat\""
cfg2 = "--cfg=\"feature1=tiger, feature2=dog\""
cfg3 = "-O2"
自定义透传给 cjc 的选项,通过 --cfg1 --cfg3 使能,每个模块设置的 customized-option 对该模块内的所有包生效。例如,执行 cjpm build --cfg1 --cfg3 命令时,透传给 cjc 的命令则为 --cfg="feature1=lion, feature2=cat" -O2。
注意:
这里的条件值必须是一个合法的标识符。
"target"
多后端、多平台隔离选项,用于配置不同后端、不同平台情况下的一系列不同配置项。以 Linux 系统为例,target 配置方式如下:
[target.x86_64-unknown-linux-gnu] # Linux 系统的配置项
compile-option = "value1" # 额外编译命令选项
override-compile-option = "value2" # 额外全局编译命令选项
link-option = "value3" # 链接器透传选项
[target.x86_64-unknown-linux-gnu.dependencies] # 源码依赖配置项
[target.x86_64-unknown-linux-gnu.test-dependencies] # 测试阶段依赖配置项
[target.x86_64-unknown-linux-gnu.bin-dependencies] # 仓颉二进制库依赖
path-option = ["./test/pro0", "./test/pro1"]
[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option]
"pro0.xoo" = "./test/pro0/pro0.xoo.cjo"
"pro0.yoo" = "./test/pro0/pro0.yoo.cjo"
"pro1.zoo" = "./test/pro1/pro1.zoo.cjo"
[target.x86_64-unknown-linux-gnu.debug] # Linux 系统的 debug 配置项
[target.x86_64-unknown-linux-gnu.debug.test-dependencies]
[target.x86_64-unknown-linux-gnu.release] # Linux 系统的 release 配置项
[target.x86_64-unknown-linux-gnu.release.bin-dependencies]
开发者可以通过配置 target.target-name 字段为某个 target 添加一系列配置项。target 的名称可以在相应的仓颉环境下通过命令 cjc -v 获取,命令输出中的 Target 项目即为该环境对应的 target 名称。上述用例应用于 Linux 系统,其他平台也适用,同样可以通过命令 cjc -v 获取 target 名称。
可为特定 target 配置的专用配置项,将会适用于该 target 下的编译流程,同时也会适用于其他 target 指定该 target 作为目标平台的交叉编译流程。配置项列表如下:
compile-option:额外编译命令选项override-compile-option:额外全局编译命令选项link-option:链接器透传选项dependencies:源码依赖配置项,结构同dependencies字段test-dependencies:测试阶段依赖配置项,结构同test-dependencies字段bin-dependencies:仓颉二进制库依赖,结构在下文中介绍compile-macros-for-target:交叉编译时的宏包控制项,该选项不支持区分下述的debug和release编译模式
开发者可以通过配置 target.target-name.debug 和 target.target-name.release 字段为该 target 额外配置在 debug 和 release 编译模式下特有的配置,可配置的配置项同上。配置于此类字段的配置项将仅应用于该 target 的对应编译模式。
"target.target-name[.debug/release].bin-dependencies"
该字段用于导入已编译好的、适用于指定 target 的仓颉库产物文件,以导入下述的 pro0 模块和 pro1 模块的三个包来举例说明。
注意:
非特殊需求场景,不建议使用该字段,请使用上文介绍的
dependencies字段导入模块源码。
├── test
│ ├── pro0
│ │ ├── libpro0.xoo.so
│ │ ├── pro0.xoo.cjo
│ │ ├── libpro0.yoo.so
│ │ └── pro0.yoo.cjo
│ └── pro1
│ ├── libpro1.zoo.so
│ └── pro1.zoo.cjo
├── src
│ └── main.cj
└── cjpm.toml
方式一,通过 path-option 导入:
[target.x86_64-unknown-linux-gnu.bin-dependencies]
path-option = ["./test/pro0", "./test/pro1"]
path-option 选项为字符串数组结构,每个元素代表待导入的路径名称。cjpm 会自动导入该路径下所有符合规则的仓颉库包,这里的合规性是指库名称的格式为 完整包名。例如,上述例子中的 pro0.xoo.cjo 对应的库名称应为 libpro0.xoo.so 或 libpro0.xoo.a。库名称不满足该规则的包只能通过 package-option 选项进行导入。
方式二,通过 package-option 导入:
[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option]
"pro0.xoo" = "./test/pro0/pro0.xoo.cjo"
"pro0.yoo" = "./test/pro0/pro0.yoo.cjo"
"pro1.zoo" = "./test/pro1/pro1.zoo.cjo"
package-option 选项为 map 结构,pro0.xoo 名称作为 key (toml 配置文件中含有 . 的字符串作为整体时,需要用 "" 包含),所以 key 的值为 libpro0.xoo.so 。前端文件 cjo 的路径作为 value,对应于该 cjo 的 .a 或 .so 需放置在相同路径下。
注意:
如果同时通过
package-option和path-option导入了相同的包,则package-option字段的优先级更高。
其中,源码 main.cj 调用 pro0.xoo、pro0.yoo、pro1.zoo 包的代码示例如下所示。
import pro0.xoo.*
import pro0.yoo.*
import pro1.zoo.*
main(): Int64 {
var res = x + y + z // x, y, z 分别为 pro0.xoo, pro0.yoo, pro1.zoo 中定义的值
println(res)
return 0
}
注意:
依赖的仓颉动态库文件可能是其他模块通过配置
profile.build.combined生成的root包编译产物,包含其所有子包的符号。因此,在依赖检查时,如果找不到某个包对应的仓颉库,会使用该包对应的root包作为依赖,并打印告警提示。开发者需要保证以此方式导入的root包是通过对应方式生成的仓颉库文件,否则该库文件可能不会包含子包的符号,导致编译报错。 例如,源码中通过import demo.aoo导入了demo.aoo包,在二进制依赖中没有找到该包对应的仓颉库,cjpm会尝试寻找该包对应的root包的动态库,即libdemo.so,如果找到则使用该库作为依赖。
"target.target-name.compile-macros-for-target"
该字段用于配置宏包的交叉编译方式,有如下三种情况:
方式一:宏包在交叉编译时默认仅编译本地平台的产物,不编译目标平台的产物,对该模块内的所有宏包生效
[target.目标平台]
compile-macros-for-target = ""
方式二:在交叉编译时同时编译本地平台和目标平台的产物,对该模块内的所有宏包生效
[target.目标平台]
compile-macros-for-target = "all" # 配置项为字符串形式,可选值必须为 all
方式三:指定该模块内的某些宏包在交叉编译时同时编译本地平台和目标平台的产物,其它未指定的宏包采取方式一的默认模式
[target.目标平台]
compile-macros-for-target = ["pkg1", "pkg2"] # 配置项为字符串数字形式,可选值是宏包名
"target" 相关字段合并规则
target 配置项中的内容可能同时存在于 cjpm.toml 的其他选项中,例如 compile-option 字段在 package 字段中也可以存在,区别在于 package 中的该字段会应用于全部 target。cjpm 对这些重复的字段会按照特定的方式将所有可应用的配置合并。以 x86_64-unknown-linux-gnu 的 debug 编译模式为例,有如下的 target 配置:
[package]
compile-option = "compile-0"
override-compile-option = "override-compile-0"
link-option = "link-0"
[dependencies]
dep0 = { path = "./dep0" }
[test-dependencies]
devDep0 = { path = "./devDep0" }
[target.x86_64-unknown-linux-gnu]
compile-option = "compile-1"
override-compile-option = "override-compile-1"
link-option = "link-1"
[target.x86_64-unknown-linux-gnu.dependencies]
dep1 = { path = "./dep1" }
[target.x86_64-unknown-linux-gnu.test-dependencies]
devDep1 = { path = "./devDep1" }
[target.x86_64-unknown-linux-gnu.bin-dependencies]
path-option = ["./test/pro1"]
[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option]
"pro1.xoo" = "./test/pro1/pro1.xoo.cjo"
[target.x86_64-unknown-linux-gnu.debug]
compile-option = "compile-2"
override-compile-option = "override-compile-2"
link-option = "link-2"
[target.x86_64-unknown-linux-gnu.debug.dependencies]
dep2 = { path = "./dep2" }
[target.x86_64-unknown-linux-gnu.debug.test-dependencies]
devDep2 = { path = "./devDep2" }
[target.x86_64-unknown-linux-gnu.debug.bin-dependencies]
path-option = ["./test/pro2"]
[target.x86_64-unknown-linux-gnu.debug.bin-dependencies.package-option]
"pro2.xoo" = "./test/pro2/pro2.xoo.cjo"
target 配置项在与 cjpm.toml 公共配置项或者相同 target 的其他级别的配置项共存时,按照如下的优先级合并:
debug/release模式下对应target的配置debug/release无关的对应target的配置- 公共配置项
以上述的 target 配置为例,target 各个配置项按照以下规则合并:
compile-option:将所有适用的同名配置项按照优先级拼接,优先级更高的配置拼接在后方。在本例中,在x86_64-unknown-linux-gnu的debug编译模式下,最终生效的compile-option值为compile-0 compile-1 compile-2,在release编译模式下为compile-0 compile-1,在其他target中为compile-0。override-compile-option:同上。由于override-compile-option优先级高于compile-option,在最后的编译命令中,拼接完成的override-compile-option会整体置于拼接完成的compile-option之后。link-option:同上。dependencies:源码依赖将被直接合并,如果其中存在依赖冲突则会报错。在本例中,在x86_64-unknown-linux-gnu的debug编译模式下,最终生效的dependencies为dep0,dep1和dep2,而在release编译模式下仅有dep0和dep1生效。在其他target中,仅有dep0生效。test-dependencies:同上。bin-dependencies:二进制依赖将按照优先级合并,如果有冲突则仅有优先级更高的依赖将会被加入,同优先级的配置先加入package-option配置。在本例中,在x86_64-unknown-linux-gnu的debug编译模式下,./test/pro1和./test/pro2内的二进制依赖将被加入,而在release模式下仅会加入./test/pro1。由于bin-dependencies没有公共配置,因此在其他target中不会有二进制依赖生效。
在本例的交叉编译场景中,若在其他平台中指定了 x86_64-unknown-linux-gnu 作为目标 target,则 target.x86_64-unknown-linux-gnu 的配置也会按照上述规则与公共配置项合并并应用;如果处于 debug 编译模式,也将应用 target.x86_64-unknown-linux-gnu.debug 的配置项。
环境变量配置
在 cjpm.toml 中可以用环境变量配置字段值,cjpm 会从当前运行环境中获取对应的环境变量值,并替换到实际的配置值中。例如,以下的 dependencies 字段中使用环境变量进行了路径配置:
[dependencies]
aoo = { path = "${DEPENDENCY_PATH}/aoo" }
则在读取模块 aoo 时,cjpm 会获取 DEPENDENCY_PATH 变量值并进行替换,得到模块 aoo 的最终路径。
支持使用环境变量配置的字段列表如下:
- 单模块配置字段
package中的如下字段:- 单包配置项
package-configuration中的单包编译选项compile-option
- 单包配置项
- 工作空间管理字段
workspace中的如下字段:- 成员模块列表
members - 编译模块列表
build-members - 测试模块列表
test-members
- 成员模块列表
package与workspace中均存在的如下字段:- 编译选项
compile-option - 全局编译选项
override-compile-option - 链接选项
link-option - 编译产物存放路径
target-dir
- 编译选项
- 构建依赖列表
dependencies中本地依赖项的path字段 - 测试依赖列表
test-dependencies中本地依赖项的path字段 - 构建脚本依赖列表
script-dependencies中本地依赖项的path字段 - 命令剖面配置项
profile中的自定义透传选项customized-option - 外部
c库配置项ffi.c中的path字段 - 平台隔离选项
target中的如下字段:- 编译选项
compile-option - 全局编译选项
override-compile-option - 链接选项
link-option - 构建依赖列表
dependencies中本地依赖项的path字段 - 测试依赖列表
test-dependencies中本地依赖项的path字段 - 构建脚本依赖列表
script-dependencies中本地依赖项的path字段 - 二进制依赖字段
bin-dependencies中的path-option和package-option字段
- 编译选项
配置和缓存文件夹
cjpm 通过 git 下载文件的存储路径可以通过 CJPM_CONFIG 环境变量指定。如果未指定,则 Linux/macOS 上的默认位置为 $HOME/.cjpm,Windows 上的默认位置为 %USERPROFILE%/.cjpm 。
仓颉包管理规格说明
在仓颉包管理规格中,对于一个文件目录,被识别为一个有效源码包的要求如下:
- 必须直接包含至少一个仓颉代码文件;
- 其父包(包括父包的父包,直至
root包)也为有效源码包。其中,模块root包不存在父包,因此仅需满足条件 1。
例如,有如下名为 demo 的 cjpm 项目:
demo
├──src
│ ├── main.cj
│ └── pkg0
│ ├── aoo
│ │ └── aoo.cj
│ └── boo
│ └── boo.cj
└── cjpm.toml
其中,demo.pkg0 对应目录内没有直接包含仓颉代码,因此 demo.pkg0 不是一个有效源码包;demo.pkg0.aoo 和 demo.pkg0.boo 包虽然直接包含仓颉代码文件 aoo.cj 和 boo.cj,但由于其上游包 demo.pkg0 不是有效源码包,因此这两个包也不是有效源码包。
当 cjpm 识别到 demo.pkg0 这样的不直接包含仓颉文件的包时,会将其视为非源码包,忽略其所有子包,并打印如下告警:
Warning: there is no '.cj' file in directory 'demo/src/pkg0', and its subdirectories will not be scanned as source code
因此,如果开发者需要配置一个有效的源码包,则该包内必须直接包含至少一个仓颉代码文件,并且其上游包都需要是有效源码包。以上述项目 demo 为例,如果想要让 demo.pkg0,demo.pkg0.aoo 和 demo.pkg0.boo 均被识别为有效源码包,则可以在 demo/src/pkg0 内添加一个仓颉代码文件,如下所示:
demo
├── src
│ ├── main.cj
│ └── pkg0
│ ├── pkg0.cj
│ ├── aoo
│ │ └── aoo.cj
│ └── boo
│ └── boo.cj
└── cjpm.toml
demo/src/pkg0/pkg0.cj 需要是一个符合包管理规格的仓颉代码文件,可以不包含功能代码,例如如下形式:
package demo.pkg0
命令扩展
cjpm 提供命令扩展机制,开发者可以通过文件名形如 cjpm-xxx(.exe) 的可执行文件扩展 cjpm 的命令。
针对可执行文件 cjpm-xxx(Windows 系统中为 cjpm-xxx.exe),若系统环境变量 PATH 中配置了该文件所在的路径,则可以使用如下的命令运行该可执行文件:
cjpm xxx [args]
其中 args 为可能需要的输入给 cjpm-xxx(.exe) 的参数列表。上述命令等价于:
cjpm-xxx(.exe) [args]
运行 cjpm-xxx(.exe) 可能会依赖某些动态库,在这种情况下,开发者需要手动将需要使用的动态库所在的目录添加到环境变量中。
下面以 cjpm-demo 为例,该可执行文件由以下仓颉代码编译得到:
import std.process.*
import std.collection.*
main(): Int64 {
var args = ArrayList<String>(Process.current.arguments)
if (args.size < 1) {
eprintln("Error: failed to get parameters")
return 1
}
println("Output: ${args[0]}")
return 0
}
则在将其目录添加到 PATH 之后,运行对应命令,会运行该可执行文件并获得对应的输出。
输入:cjpm demo hello,world
输出:Output: hello,world
cjpm 内部已有的命令优先级更高,因此无法用此方式扩展这些命令。例如,即使系统环境变量中存在名为 cjpm-build 的可执行文件,cjpm build 也不会运行该文件,而是运行 cjpm 并将 build 作为参数输入 cjpm。
构建脚本
cjpm 提供构建脚本机制,开发者可以在构建脚本中定义需要 cjpm 在某个命令前后的行为。
构建脚本源文件固定命名为 build.cj,位于仓颉项目主目录下,即与 cjpm.toml 同级。执行 init 命令新建仓颉项目时,cjpm 默认不创建 build.cj,开发者若有相关需求,可以自行按如下的模板格式在指定位置新建并编辑 build.cj。
// build.cj
import std.process.*
// Case of pre/post codes for 'cjpm build'.
/* called before `cjpm build`
* Success: return 0
* Error: return any number except 0
*/
// func stagePreBuild(): Int64 {
// // process before "cjpm build"
// 0
// }
/*
* called after `cjpm build`
*/
// func stagePostBuild(): Int64 {
// // process after "cjpm build"
// 0
// }
// Case of pre/post codes for 'cjpm clean'.
/* called before `cjpm clean`
* Success: return 0
* Error: return any number except 0
*/
// func stagePreClean(): Int64 {
// // process before "cjpm clean"
// 0
// }
/*
* called after `cjpm clean`
*/
// func stagePostClean(): Int64 {
// // process after "cjpm clean"
// 0
// }
// For other options, define stagePreXXX and stagePostXXX in the same way.
/*
* Error code:
* 0: success.
* other: cjpm will finish running command. Check target-dir/build-script-cache/module-name/script-log for error outputs defind by user in functions.
*/
main(): Int64 {
match (Process.current.arguments[0]) {
// Add operation here with format: "pre-"/"post-" + optionName
// case "pre-build" => stagePreBuild()
// case "post-build" => stagePostBuild()
// case "pre-clean" => stagePreClean()
// case "post-clean" => stagePostClean()
case _ => 0
}
}
cjpm 针对一系列命令支持使用构建脚本定义命令前后行为。例如,针对 build 命令,可在 main 函数中的 match 内定义 pre-build,执行想要在 build 命令执行前需要执行的功能函数 stagePreBuild(功能函数的命名不做要求)。build 命令后的行为可以以相同的方式通过添加 post-build 的 case 选项定义。针对其他命令的命令前后行为的定义类似,只需要添加相应的 pre/post 选项和对应的功能函数即可。
在定义某一命令前后的行为后,cjpm 在执行该命令时会首先编译 build.cj,并在执行前后执行对应的行为。同样以 build 为例,在定义了 pre-build 和 post-build 后运行 cjpm build,则会按照如下步骤运行整个 cjpm build 流程:
- 进行编译流程前,首先编译
build.cj; - 执行
pre-build对应的功能函数; - 进行
cjpm build编译流程; - 编译流程顺利结束后,
cjpm会执行post-build对应的功能函数。
构建脚本支持的命令如下:
build,test,bench:同时支持执行依赖模块构建脚本中定义的pre和post流程run,install:仅支持运行对应模块的pre和post构建脚本流程,或者在进行编译时执行依赖模块的pre-build和post-build流程check,tree,update,publish:仅支持运行对应模块的pre和post构建脚本流程clean:仅支持运行对应模块的pre构建脚本流程
在执行这些命令时,若配置了 --skip-script 选项,则会跳过所有构建脚本的编译运行,包括依赖模块的构建脚本。
构建脚本的使用说明如下:
- 功能函数的返回值需要满足一定要求:当功能函数执行成功时,需要返回
0;执行失败时返回除0以外的任意Int64类型变量。 build.cj中的所有输出都将被重定向到项目目录下,路径为build-script-cache/[target|release]/[module-name]/bin/script-log。开发者如果在功能函数中添加了一些输出内容,可在该文件中查看。- 若项目根目录下不存在
build.cj,则cjpm将按正常流程执行;若存在build.cj并定义了某一命令的前后行为,则在build.cj编译失败或者功能函数返回值不为0时,即使该命令本身能够顺利执行,命令也将异常中止。 - 多模块场景下,被依赖模块的
build.cj构建脚本会在编译和单元测试流程中生效。被依赖模块构建脚本中的输出同样重定向到build-script-cache/[target|release]下对应模块名目录中的日志文件。
例如,下面的构建脚本 build.cj 定义了 build 前后的行为:
import std.process.*
func stagePreBuild(): Int64 {
println("PRE-BUILD")
0
}
func stagePostBuild(): Int64 {
println("POST-BUILD")
0
}
main(): Int64 {
match (Process.current.arguments[0]) {
case "pre-build" => stagePreBuild()
case "post-build" => stagePostBuild()
case _ => 0
}
}
则在执行 cjpm build 命令时,cjpm 将会执行 stagePreBuild 和 stagePostBuild。cjpm build 执行完成后,script-log 日志文件内会有如下输出:
PRE-BUILD
POST-BUILD
构建脚本可以通过 cjpm.toml 中的 script-dependencies 字段导入依赖模块,格式同 dependencies。例如,在 cjpm.toml 中有如下配置,导入了 aoo 模块,并且 aoo 模块内有一个名为 aaa() 的方法:
[script-dependencies]
aoo = { path = "./aoo" }
则可以在构建脚本中导入该依赖,使用依赖中的接口 aaa():
import std.process.*
import aoo.*
func stagePreBuild(): Int64 {
aaa()
0
}
func stagePostBuild(): Int64 {
println("POST-BUILD")
0
}
main(): Int64 {
match (Process.current.arguments[0]) {
case "pre-build" => stagePreBuild()
case "post-build" => stagePostBuild()
case _ => 0
}
}
构建脚本依赖 script-dependencies 与源码相关依赖(源码依赖项 dependencies 和测试依赖项 test-dependencies)相互独立,源码和测试代码无法使用 script-dependencies 中的依赖模块,构建脚本也无法使用 dependencies 和 test-dependencies 中的依赖模块。若需要在构建脚本和源码/测试代码中使用同一模块,需要在 script-dependencies 和 dependencies/test-dependencies 中同时配置。
使用示例
以下面仓颉项目的目录结构为例,介绍 cjpm 的使用方法,该目录下对应的源码文件示例可见源代码。该仓颉项目的模块名为 test。
cj_project
├── pro0
│ ├── cjpm.toml
│ └── src
│ ├── zoo
│ │ ├── zoo.cj
│ │ └── zoo_test.cj
│ └── pro0.cj
├── src
│ ├── koo
│ │ ├── koo.cj
│ │ └── koo_test.cj
│ ├── main.cj
│ └── main_test.cj
└── cjpm.toml
init、build 的使用
-
新建仓颉项目并编写源码
xxx.cj文件,如示例结构所示的koo包和main.cj文件。cjpm init --name test --path .../cj_project mkdir koo此时,会自动生成
src文件夹和默认的cjpm.toml配置文件。 -
当前模块需要依赖外部的
pro0模块时,可以新建pro0模块及该模块的配置文件,接下来编写该模块的源码文件,需要自行在pro0下新建src文件夹,在src下新建pro0的 root 包pro0.cj,并将编写的仓颉包放置在src下,如示例结构所示的zoo包。mkdir pro0 && cd pro0 cjpm init --name pro0 --type=static mkdir src/zoo -
主模块依赖
pro0时,需要按照手册说明去配置主模块配置文件的dependencies字段。配置无误后,执行cjpm build即可,生成的可执行文件在target/release/bin/目录下。cd cj_project vim cjpm.toml cjpm build cjpm run
test、clean 的使用
-
按示例结构,编写完每个文件对应的
xxx_test.cj单元测试文件后,可以执行下述代码进行单元测试,生成的文件在target/release/unittest_bin目录下。cjpm test或者
cjpm test src src/koo pro/src/zoo -
想要手动删除
target、cov_output文件夹、*.gcno、*.gcda等中间件时,执行如下命令:cjpm clean
示例的源代码
// cj_project/src/main.cj
package test
import pro0.zoo.*
import test.koo.*
main(): Int64 {
let res = z + k
println(res)
let res2 = concatM("a", "b")
println(res2)
return 0
}
func concatM(s1: String, s2: String): String {
return s1 + s2
}
// cj_project/src/main_test.cj
package test
import std.unittest.* // testfame
import std.unittest.testmacro.* // macro_Defintion
@Test
public class TestM{
@TestCase
func sayhi(): Unit {
@Assert(concatM("1", "2"), "12")
@Assert(concatM("1", "3"), "13")
}
}
// cj_project/src/koo/koo.cj
package test.koo
public let k: Int32 = 12
func concatk(s1: String, s2: String): String {
return s1 + s2
}
// cj_project/src/koo/koo_test.cj
package test.koo
import std.unittest.* // testfame
import std.unittest.testmacro.* // macro_Defintion
@Test
public class TestK{
@TestCase
func sayhi(): Unit {
@Assert(concatk("1", "2"), "12")
@Assert(concatk("1", "3"), "13")
}
}
// cj_project/pro0/src/pro0.cj
package pro0
// cj_project/pro0/src/zoo/zoo.cj
package pro0.zoo
public let z: Int32 = 26
func concatZ(s1: String, s2: String): String {
return s1 + s2
}
// cj_project/pro0/src/zoo/zoo_test.cj
package pro0.zoo
import std.unittest.* // testfame
import std.unittest.testmacro.* // macro_Defintion
@Test
public class TestZ{
@TestCase
func sayhi(): Unit {
@Assert(concatZ("1", "2"), "12")
@Assert(concatZ("1", "3"), "13")
}
}
# cj_project/cjpm.toml
[package]
cjc-version = "0.40.2"
description = "nothing here"
version = "1.0.0"
name = "test"
output-type = "executable"
[dependencies]
pro0 = { path = "pro0" }
# cj_project/pro0/cjpm.toml
[package]
cjc-version = "0.40.2"
description = "nothing here"
version = "1.0.0"
name = "pro0"
output-type = "static"
附录
交叉编译使用说明
CJPM cjnative 后端支持将项目交叉编译到其他平台并运行。例如,假设目标平台为 arch-sys-abi,编译步骤如下:
-
配置目标平台所需的工具链。
-
在入口模块的
cjpm.toml中,添加目标平台需要的编译选项配置:[target.arch-sys-abi] override-compile-option = "value"此配置会应用于所有依赖的模块。单模块编译模式下,可以替换成
compile-option。 -
若项目存在二进制依赖,则需要进行如下配置:
[target.arch-sys-abi.bin-dependencies] path-option = [...] [target.arch-sys-abi.bin-dependencies.package-option] "..." = "..." -
使用如下命令进行编译构建或测试代码构建:
cjpm build --target=arch-sys-abi # 交叉编译目标平台的产物 cjpm test --target=arch-sys-abi # 交叉编译目标平台的可执行测试文件 -
将二进制产物导入到目标平台,即可正常运行。
注意:
- 编译产物位于用户配置的
target-dir目录下以目标平台target命名的目录。- 若存在动态库依赖,则需要将动态库配置于运行环境的环境变量
LD_LIBRARY_PATH中。
cjdb 工具介绍
cjdb 是一款基于 lldb 开发的仓颉程序命令行调试工具。当前 cjdb 工具是在llvm15.0.4基础上适配演进出来的工具。为仓颉开发者提供程序调试的能力。
cjdb 工具获取
获取方式
通过 Cangjie 的 SDK 获取,获取路径:每日构建。
cjdb 工具在 SDK 中的路径:cangjie\tools\bin 。
使用举例
下面以 Windows 平台使用方式举例
解压,直接在 cjdb 工具所在路径 cangjie\tools\bin 运行 cjdb.exe 即可。
说明:
表
system参数取值说明
system 参数取值 说明 windows 适用于 Windows 平台的工具 linux 适用于 Linux 平台的工具 darwin 适用于 macOS 平台的工具 ohos 适用于 OpenHarmony 平台的工具 注意
尽可能保证待调试的 ELF 文件或应用编译时使用的编译器和获取的
cjdb调试器工具来源同一版本的工具链。
cjdb 命令
说明:
更多原始命令可参考GDB to LLDB command map。
获取更多命令,可以在命令行窗口执行
help:(cjdb) help Debugger commands: apropos -- List debugger commands related to a word or subject. breakpoint -- Commands for operating on breakpoints (see 'help b' for shorthand.) cjthread -- Commands for operating on one or more cjthread in the current process. command -- Commands for managing custom LLDB commands. disassemble -- Disassemble specified instructions in the current target. Defaults to the current function for the current thread and stack frame. expression -- Evaluate an expression on the current thread. Displays any returned value with LLDB's default formatting. frame -- Commands for selecting and examing the current thread's stack frames. ...
日志
为了方便定位问题,可以使用 log <subcommand> [<command-options>] 命令记录 cjdb 日志。
-
help log查看log命令帮助(cjdb) help log Commands controlling LLDB internal logging. Syntax: log <subcommand> [<command-options>] The following subcommands are supported: disable -- Disable one or more log channel categories. enable -- Enable logging for a single log channel. list -- List the log categories for one or more log channels. If none specified, lists them all. timers -- Enable, disable, dump, and reset LLDB internal performance timers. For more help on any particular subcommand, type 'help <command> <subcommand>'. -
log list查看支持的日志列表(cjdb) log list其他命令可结合 help 命令自行获取。
平台
cjdb 中用于管理和创建平台的命令有platform [connect|disconnect|info|list|status|select] ...
-
windows平台查看platform帮助的信息。(cjdb) help platform Commands to manage and create platforms. Syntax: platform [connect|disconnect|info|list|status|select] ... The following subcommands are supported: connect -- Select the current platform by providing a connection URL. disconnect -- Disconnect from the current platform. file -- Commands to access files on the current platform. get-file -- Transfer a file from the remote end to the local host. get-size -- Get the file size from the remote end. list -- List all platforms that are available. mkdir -- Make a new directory on the remote end. process -- Commands to query, launch and attach to processes on the current platform. put-file -- Transfer a file from this system to the remote end. select -- Create a platform if needed and select it as the current platform. settings -- Set settings for the current target's platform, or for a platform by name. shell -- Run a shell command on the current platform. Expects 'raw' input (see 'help raw-input'.) status -- Display status for the current platform. target-install -- Install a target (bundle or executable file) to the remote end. For more help on any particular subcommand, type 'help <command> <subcommand>'. (cjdb)
函数
是否进入带调试信息的函数
可以使用thread step-over <cmd-options> [<thread-id>](thread step-over 可简写为 next 或n)不进入函数,会直接执行下一行代码。
(cjdb) n
Process 2884 stopped
* thread #1, name = 'test', stop reason = step over
frame #0: 0x0000000000401498 test`default.main() at test.cj:5:7
2 main(): Int64 {
3
4 var a : Int32 = 12
-> 5 a = a + 23
6 a = test(10, 34)
7 return 1
8 }
(cjdb)
使用 cjdb 调试遇到函数时,用thread step-in <cmd-options> [<thread-id>](thread step-in可简写为step或s)命令可以进入函数(函数必须有调试信息)。
(cjdb) n
Process 5240 stopped
* thread #1, name = 'test', stop reason = step over
frame #0: 0x00000000004014d8 test`default.main() at test.cj:6:7
3
4 var a : Int32 = 12
5 a = a + 23
-> 6 a = test(10, 34)
7 return 1
8 }
9
(cjdb) s
Process 5240 stopped
* thread #1, name = 'test', stop reason = step in
frame #0: 0x0000000000401547 test`default.test(a=10, b=34) at test.cj:12:10
9
10 func test(a : Int32, b : Int32) : Int32 {
11
-> 12 return a + b
13 }
14
(cjdb)
退出正在调试的函数
执行 finish 命令,退出当前函数,返回到上一个调用栈函数。
(cjdb) s
Process 5240 stopped
* thread #1, name = 'test', stop reason = step in
frame #0: 0x0000000000401547 test`default.test(a=10, b=34) at test.cj:12:10
9
10 func test(a : Int32, b : Int32) : Int32 {
11
-> 12 return a + b
13 }
14
(cjdb) finish
Process 5240 stopped
* thread #1, name = 'test', stop reason = step out
Return value: (int) $0 = 44
frame #0: 0x00000000004014dd test`default.main() at test.cj:6:7
3
4 var a : Int32 = 12
5 a = a + 23
-> 6 a = test(10, 34)
7 return 1
8 }
9
(cjdb)
断点
设置源码断点
breakpoint set --file test.cj --line line_number
--line 指定行号。
--file 指定文件。
对于单文件,只需要输入行号即可,对于多文件,需要加上文件名字。
b test.cj:4 是 breakpoint set --file test.cj --line 4 的缩写。
例:breakpoint set --line 2
(cjdb) b 2
Breakpoint 1: where = test`default.main() + 13 at test.cj:4:3, address = 0x0000000000401491
(cjdb) b test.cj : 4
Breakpoint 2: where = test`default.main() + 13 at test.cj:4:3, address = 0x0000000000401491
(cjdb)
设置函数断点
breakpoint set --name function_name
--name 指定要设置函数断点的函数名。
b test 是 breakpoint set --name test 的缩写。
例:breakpoint set --name test
(cjdb) b test
Breakpoint 3: where = test`default.test(int, int) + 19 at test.cj:12:10, address = 0x0000000000401547
(cjdb)
设置条件断点
breakpoint set --file xx.cj --line line_number --condition expression
--file 指定文件。
--line 指定行号。
--condition 指定条件。
例:breakpoint set --file test.cj --line 4 --condition a==12
(cjdb) breakpoint set --file test.cj --line 4 --condition a==12
Breakpoint 2: where = main`default::main() + 60 at test.cj:4:9, address = 0x00005555555b62d0
(cjdb) c
Process 3128551 resuming
Process 3128551 stopped
* thread #1, name = 'schmon', stop reason = breakpoint 2.1
frame #0: 0x00005555555b62d0 main`default::main() at test.cj:4:9
1 main(): Int64 {
2
3 var a : Int32 = 12
-> 4 a = a + 23
5 return 1
6 }
执行到下一个断点停止
(cjdb) c
Process 2884 resuming
Process 2884 stopped
* thread #1, name = 'test', stop reason = breakpoint 3.1
frame #0: 0x0000000000401547 test`default.test(a=10, b=34) at test.cj:12:10
9
10 func test(a : Int32, b : Int32) : Int32 {
11
-> 12 return a + b
13 }
14
(cjdb)
观察点
watchpoint set variable -w read variable_name
-w 指定观察点点类型,有 read、write、read_write 三种类型。
wa s v是watchpoint set variable的缩写。
例:watchpoint set variable -w read a
(cjdb) wa s v -w read a
Watchpoint created: Watchpoint 1: addr = 0x7fffddffed70 size = 8 state = enabled type = r
declare @ 'test.cj:27'
watchpoint spec = 'a'
new value: 10
(cjdb)
只支持在基础类型设置观察点。在 Windows 上程序的观察点设置条件时,程序最多只会暂停一次。
表达式计算
cjdb 中使用expression <cmd-options> -- <expr>(expression 简写为expr)可以实现表达式求值。
- 查看字面量
例:expr 3
(cjdb) expr 3
(Int64) $0 = 3
(cjdb)
- 查看变量名
例:expr a
(cjdb) expr a
(Int64) $0 = 3
(cjdb)
- 查看算术表达式
例:expr a + b
(cjdb) expr a + b
(Int64) $0 = 3
(cjdb)
- 查看关系表达式
例:expr a > b
(cjdb) expr a > b
(Bool) $0 = false
(cjdb)
- 查看逻辑表达式
例:expr a && b
(cjdb) expr true && false
(Bool) $0 = false
(cjdb)
- 查看后缀表达式
例:expr a.b
(cjdb) expr value.member
(Int64) $0 = 1
(cjdb)
例:expr a[b]
(cjdb) expr array[2]
(Int64) $0 = 3
(cjdb)
- 查看泛型实例化变量
例:expr a
(cjdb) expr a
(default.A<Int32>) $0 = {
member = 1
}
(cjdb)
支持的表达式计算:包含但不限于字面量、变量名、括号表达式、算术表达式、关系表达式、条件表达式、循环表达式、成员访问表达式、索引访问表达式、流表达式、普通try表达式、区间表达式、位运算表达式、泛型实例化变量等。
注意:
不支持的表达式计算:带命名参数的函数调用、互操作、扩展、属性、别名、插值字符串、函数名,
Windows平台不支持 Float16 类型,且不支持异常抛出。
变量查看
- 查看局部变量,
locals
(cjdb) locals
(Int32) a = 12
(Int64) b = 68
(Int32) c = 13
(Array<Int64>) array = {
[0] = 2
[1] = 4
[2] = 6
}
(pkgs.Rec) newR2 = {
age = 5
name = "string"
}
(cjdb)
当调试器停到程序的某个位置时,使用 locals 可以看到程序当前位置所在函数生命周期范围内,所有的局部变量,只能正确查看当前位置已经初始化的变量,当前未初始化的变量无法正确查看。
- 查看单个变量,
print variable_name
例:print b
(cjdb) print b
(Int64) $0 = 110
(cjdb)
使用print命令(简写p),后跟要查看具体变量的名字。
- 查看 String 类型变量
(cjdb) print newR2.name
(String) $0 = "string"
(cjdb)
- 查看 struct、class 类型变量
(cjdb) print newR2
(pkgs.Rec) $0 = {
age = 5
name = "string"
}
(cjdb)
- 查看数组
(cjdb) print array
(Array<Int64>) $0 = {
[0] = 2
[1] = 4
[2] = 6
[3] = 8
}
(cjdb) print array[1..3]
(Array<Int64>) $1 = {
[1] = 4
[2] = 6
}
(cjdb)
支持查看基础类型(Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float16,Float32,Float64,Bool,Unit,Rune)。
支持范围查看,区间 [start..end) 为左闭右开区间,暂不支持逆序。
对于非法区间或对非数组类型查看区间会有报错提示。
(cjdb) print array
(Array<Int64>) $0 = {
[0] = 0
[1] = 1
}
(cjdb) print array[1..3]
error: unsupported expression
(cjdb) print array[0][0]
error: unsupported expression
- 查看 CString 类型变量
(cjdb) p cstr
(cro.CString) $0 = "abc"
(cjdb) p cstr
(cro.CString) $1 = null
- 查看全局变量,
globals
(cjdb) globals
(Int64) pkgs.Rec.g_age = 100
(Int64) pkgs.g_var = 123
(cjdb)
使用 print 命令查看单个全局变量时,不支持 print + 包名 + 变量名查看全局变量,仅支持 print + 变量名 进行查看,例如查看全局变量 g_age 应该用如下命令查看。
(cjdb) p g_age
(Int64) $0 = 100
(cjdb)
- 变量修改
(cjdb) set a=30
(Int32) $4 = 30
(cjdb)
可以使用 set 修改某个局部变量的值,只支持基础数值类型(Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float32,Float64)。
对于 Bool 类型的变量,可以使用数值 0(false)和非 0(true)进行修改,Rune 类型变量,可以使用对应的 ASCII 码进行修改。
(cjdb) set b = 0
(Bool) $0 = false
(cjdb) set b = 1
(Bool) $1 = true
(cjdb) set c = 0x41
(Rune) $2 = 'A'
(cjdb)
如果修改的值为非数值,或是超出变量的范围,则会报错提示。
(cjdb) p c
(Rune) $0 = 'A'
(cjdb) set c = 'B'
error: unsupported expression
(cjdb) p b
(Bool) $1 = false
(cjdb) set b = true
error: unsupported expression
(cjdb) p u8
(UInt8) $3 = 123
(cjdb) set u8 = 256
error: unsupported expression
(cjdb) set u8 = -1
error: unsupported expression
仓颉线程
支持查看仓颉线程 id 状态以及 frame 信息,暂不支持仓颉线程切换。
显示当前目标进程中的仓颉线程
(cjdb) cjthread list
cjthread id: 1, state: running name: cjthread1
frame #0: 0x000055555557c140 main`ab::main() at varray.cj:16:1
cjthread id: 2, state: pending name: cjthread2
frame #0: 0x00007ffff7d8b9d5 libcangjie-runtime.so`CJ_CJThreadPark + 117
(cjdb)
堆栈回溯
- 查看指定仓颉线程调用栈。
(cjdb) cjthread backtrace 1
cjthread #1 state: pending name: cangjie
frame #0: 0x00007ffff7d8b9d5 libcangjie-runtime.so`CJ_CJThreadPark + 117
frame #1: 0x00007ffff7d97252 libcangjie-runtime.so`CJ_TimerSleep + 66
frame #2: 0x00007ffff7d51b5d libcangjie-runtime.so`CJ_MRT_FuncSleep + 33
frame #3: 0x0000555555591031 main`std/sync::sleep(std/time::Duration) + 45
frame #4: 0x0000555555560941 main`default::lambda.0() at complex.cj:9:3
frame #5: 0x000055555555f68b main`default::std/core::Future<Unit>::execute(this=<unavailable>) at future.cj:124:35
frame #6: 0x00007ffff7d514f1 libcangjie-runtime.so`___lldb_unnamed_symbol1219 + 7
frame #7: 0x00007ffff7d4dc52 libcangjie-runtime.so`___lldb_unnamed_symbol1192 + 114
frame #8: 0x00007ffff7d8b09a libcangjie-runtime.so`CJ_CJThreadEntry + 26
(cjdb)
cjthread backtrace 1 命令中 1 为指定的 cjthread ID。
可执行文件调试
launch 方式
launch 方式有两种加载方式,如下:
-
启动调试器的同时加载被调程序。
~/0901/cangjie_test$ cjdb test (cjdb) target create "test" Current executable set to '/0901/cangjie-linux-x86_64-release/bin/test' (x86_64). (cjdb) -
先启动调试器,然后通过
file命令加载被调程序。~/0901/cangjie_test$ cjdb (cjdb) file test Current executable set to '/0901/cangjie/test' (x86_64). (cjdb)
attach 方式
attach 方式调试被调程序
针对正在运行的程序,支持 attach 方式调试被调程序,如下:
~/0901/cangjie-linux-x86_64-release/bin$ cjdb
(cjdb) attach 15325
Process 15325 stopped
* thread #1, name = 'test', stop reason = signal SIGSTOP
frame #0: 0x00000000004014cd test`default.main() at test.cj:7:9
4 var a : Int32 = 12
5 a = a + 23
6 while (true) {
-> 7 a = 1
8 }
9 a = test(10, 34)
10 return 1
thread #2, name = 'FinalProcessor', stop reason = signal SIGSTOP
frame #0: 0x00007f48c12fc065 libpthread.so.0`__pthread_cond_timedwait at futex-internal.h:205
thread #3, name = 'PoolGC_1', stop reason = signal SIGSTOP
frame #0: 0x00007f48c12fbad3 libpthread.so.0`__pthread_cond_wait at futex-internal.h:88
thread #4, name = 'MainGC', stop reason = signal SIGSTOP
frame #0: 0x00007f48c12fc065 libpthread.so.0`__pthread_cond_timedwait at futex-internal.h:205
thread #5, name = 'schmon', stop reason = signal SIGSTOP
frame #0: 0x00007f48c0fe17a0 libc.so.6`__GI___nanosleep(requested_time=0x00007f48a8ffcb70, remaining=0x0000000000000000) at nanosleep.c:28
Executable module set to "/0901/cangjie-linux-x86_64-release/bin/test".
Architecture set to: x86_64-unknown-linux-gnu.
FAQ
-
docker环境下 cjdb 报error: process launch failed: 'A' packet returned an error: 8。root@xxx:/home/cj/cangjie-example#cjdb ./hello (cjdb) target create "./hello" Current executable set to '/home/cj/cangjie-example/hello' (x86_64). (cjdb) b main Breakpoint 1: 2 locations. (cjdb) r error: process launch failed: 'A' packet returned an error: 8 (cjdb)问题原因:
docker创建容器时,未开启 SYS_PTRACE 权限。解决方案:创建新容器时加上如下选项,并且删除已存在容器。
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined -
cjdb 报
stop reason = signal XXX。Process 32491 stopped * thread #2, name = 'PoolGC_1', stop reason = signal SIGABRT frame #0: 0x00007ffff450bfb7 lib.so.6`__GI_raise(sig=2) at raise.c:51问题原因:程序持续产生
SIGABRT信号触发调试器暂停。解决方案:可执行如下命令屏蔽此类信号。
(cjdb) process handle --pass true --stop false --notify true SIGBUS NAME PASS STOP NOTIFY =========== ===== ===== ====== SIGBUS true false true (cjdb) -
cjdb 没有捕获
SIGSEGV信号。问题原因:cjdb 在启动时会默认不捕获
SIGSEGV信号。解决方案:开发者如果需要在调试时捕获此信号,可使用如下命令重新设置。
(cjdb)process handle -p true -s true -n true SIGSEGV NAME PASS STOP NOTIFY =========== ===== ===== ====== SIGSEGV true true true (cjdb) -
cjdb 无法通过
next/s等调试指令进入catch块。问题原因:仓颉使用
LLVM的LandingPad机制来实现异常处理,而该机制无法通过控制流明确try语句块中抛出的异常会由哪一个catch语句块捕获,所以无法明确执行的代码。类似问题在clang++中也存在。解决方案:开发者如果需要调试
catch块中的代码,可以在catch中打上断点。(cjdb) b 31 Breakpoint 2: where = main`default::test(Int64) + 299 at a.cj:31:18, address = 0x000055555557caff (cjdb) n Process 1761640 stopped * thread #1, name = 'schmon', stop reason = breakpoint 2.1 frame #0: 0x000055555557caff main`default::test(a=0) at a.cj:31:18 28 s = 12/a 29 } catch (e:Exception) { 30 ->31 error_result = e.toString() 32 println(error_result) 33 } 34 s (cjdb) -
macOS平台表达式计算报错Expression can't be run, because there is no JIT compiled function。问题原因:表达式暂不支持在
macOS平台使用。 -
macOS平台表达式计算aarch64架构有一部分环境调试时报Connection shut down by remote side while waiting for reply to initial handshake packet。问题原因:部分系统会导致调试服务异常退出。
解决方案:删除
third_party/llvm/bin/debugserver文件,重新启动调试。 -
在打断点调试时,如果该断点处有泛型变元,则泛型变元的名字为 T0, T1, ... Tn。举例如下:
func global_func_02<K, G>() { 0 } public struct Pair<T, U> { let x: T let y: U public init(a: T, b: U) { x = a y = b } } main() { var a: Pair<String, Int64> = Pair<String, Int64>("hello", 0) global_func_02<Int64, String>() 0 } ======================================== (cjdb) b 1 Breakpoint 1: where = main`default::global_func_02<T0,T1>() + 9 at test.cj:1:33, address = 0x0000000000019989 (cjdb) b 6 Breakpoint 2: where = main`default::Pair<T0,T1>::init(T0, T1) + 150 at test.cj:6:9, address = 0x000000000001982a
问题原因:仓颉为了满足泛型变元的 ABI 兼容,即开发者侧泛型变元改变,仓颉侧二进制符号表中的符号名不变。
解决方案:将开发者编写的泛型变元的名称修改为 T0, T1, ... Tn。
附录
cjdb 特有命令
| 命令 | 简写 | 简要描述 | 参数说明 |
|---|---|---|---|
| globals | 无 | 查看全局变量 | 无参数 |
| locals | 无 | 查看局部变量 | 无参数 |
| p | 查看单个变量 | 参数为变量名称,例 print variable_name | |
| exprssion | expr | 查看表达式 | 参数为表达式,例 expr variable_name + 1 |
| set | 无 | 修改变量 | 参数为表达式,例 set variable_name = value |
| finish | 无 | 函数退出 | 无参数 |
| cjthread | 无 | 轻量级线程查看 | 无参数 |
静态检查工具
功能简介
CJLint(Cangjie Lint)是一款静态检查工具,该工具是基于仓颉语言编程规范开发。通过它可以识别代码中不符合编程规范的问题,帮助开发者发现代码中的漏洞,写出满足 Clean Source 要求的仓颉代码。
使用说明
cjlint -h 帮助信息,选项介绍。
Options:
-h Show usage
eg: ./cjlint -h
-f <value> Detected file directory, it can be absolute paths or relative paths, if it is directory, default file name is cjReport
eg: ./cjlint -f fileDir -c . -m .
eg: ./cjlint -f "fileDir1 fileDir2" -c . -m .
-e <v1:v2:...> Excluded files, directories or configurations, splitted by ':'. Regular expressions are supported
eg: ./cjlint -f fileDir -e fileDir/a/:fileDir/b/*.cj
-o <value> Output file path, it can be absolute path or relative path
eg: ./cjlint -f fileDir -o ./out
-r [csv|json] Report file format, it can be csv or json, default is json
eg: ./cjlint -f fileDir -r csv -o ./out
-c <value> Directory path where the config directory is located, it can be absolute path or relative path to the executable file
eg: ./cjlint -f fileDir -c .
-m <value> Directory path where the modules directory is located, it can be absolute path or relative path to the executable file
eg: ./cjlint -f fileDir -m .
--import-path <value> Add .cjo search path
cjlint -f 指定检查目录。
cjlint -f fileDir [option] fileDir...
注意:
-f后面指定的是*.cj 文件所在src目录。 若需要指定多个路径,则在 "" 中以空格相隔。
正例:
cjlint -f xxx/xxx/src
cjlint -f "fileDir1 fileDir2"
反例:
cjlint -f xxx/xxx/src/xxx.cj
说明:
上述限制来自编译器模块编译限制, 因为当前编译器编译选项正在重构,相关 API 不稳定;而模块编译较为稳定,因此工具当前仅支持模块编译方式。最终工具支持的编译选项会与编译器一致,支持其他编译方式。
-r 用来指定生成扫描报告的格式,目前支持json格式和csv格式。
-r需要与-o选项配合使用,如果没有-o指定输出到文件,即使指定了-r也不会生成扫描报告。如果指定了-o没有指定-r,那么默认生成json格式的扫描报告。
cjlint -f ./src -r csv -o ./report // 生成report.csv文件
cjlint -f ./src -r csv -o ./output/report // 在output目录下生成report.csv文件
-c, -m 在开发者需要时用以指定config和modules所在的目录路径。
在默认情况下,cjlint会调用其所在目录下的config和modules作为默认的配置目录和依赖目录。若有需要,开发者可以用命令行选项 -c, -m来指定config和modules所在的目录路径。
例:指定的 config 和 modules 的路径分别为:./tools/cjlint/config 和 ./tools/cjlint/modules。
则config和modules所在的目录路径同为./tools/cjlint, 所以命令应为:
cjlint -f ./src -c ./tools/cjlint -m ./tools/cjlint
--import-path 在开发者需要时用以指定 cjo 所在的目录路径,且支持多个路径。
cjlint --import-path fileDir
// 若需要指定多个路径,则在 "" 中以空格相隔
cjlint --import-path "fileDir1 fileDir2"
规则级告警屏蔽
可执行文件cjlint同目录下的config配置目录中,有cjlint_rule_list.json和exclude_lists.json两个配置文件。其中,cjlint_rule_list.json为规则列表配置文件,开发者可以通过增减其中的配置信息来决定进行哪些规则的检查。exclude_lists.json为告警屏蔽配置文件,开发者可以通过添加告警信息来屏蔽某一条规则的某一条告警。
例: 若开发者只想检查如下 5 条规则,则cjlint_rule_list.json配置文件中只添加要检查的 5 条规则。
{
"RuleList": [
"G.FMT.01",
"G.ENU.01",
"G.EXP.03",
"G.OTH.01",
"G.OTH.02"
]
}
例: 若开发者想要屏蔽某一条规则的某一条告警,可以在exclude_lists.json配置文件中添加屏蔽信息。
注意:
path不必填写绝对路径,但必须有xxx.cj格式,为模糊匹配。line为告警行号,为精确匹配。colum为告警列号,可选择性填写进行列号精确匹配。
{
"G.OTH.01" : [
{"path":"xxx/example.cj", "line":"42"},
{"path":"xxx/example.cj", "line":"42", "colum": "2"},
{"path":"example.cj", "line":"42", "colum": "2"}
]
}
源代码注释告警屏蔽
特殊注释 BNF
<content of cjlint-ignore comment> ::= "cjlint-ignore" [-start] <ignore-rule>{...} [description] | cjlint-ignore <-end> [description]
<ignore-rule> ::="!"<rule-name>
<rule-name> ::= <letters>
注意:
- 特殊注释的
cjlint-ignore与选项-start和-end以及屏蔽的规则需要写在同一行上,否则无法进行告警屏蔽。描述信息可以写在不同行。- 单行屏蔽,屏蔽规则与屏蔽规则间需要用空格隔开,
cjlint会将特殊注释所在行的对应规则告警进行屏蔽。- 多行屏蔽,
cjlint会以含有-start的特殊注释为起始行,以含有-end的特殊注释为结束行,将其间对应的规则进行屏蔽。含有-end的特殊注释会与其上方最近的含有-start的特殊注释相匹配。
单行屏蔽正确示例 1,屏蔽 G.CHK.04 告警
void fetctl_process(const void *para)
{
if (para == NULL)
{
return; /*cjlint-ignore !G.CHK.04 */
}
}
单行屏蔽正确示例 2,屏蔽 G.CHK.04 告警
void fetctl_process(const void *para)
{
if (para == NULL)
{
return; // cjlint-ignore !G.CHK.04 description
}
}
多行屏蔽正确示例 1,屏蔽 G.CHK.04 告警
/*cjlint-ignore -start !G.CHK.04 description */
void fetctl_process(const void *para)
{
if (para == NULL)
{
return;
}
}
/* cjlint-ignore -end description */
多行屏蔽正确示例 2,屏蔽 G.CHK.04 告警
// cjlint-ignore -start !G.CHK.04 description
void fetctl_process(const void *para)
{
if (para == NULL)
{
return;
}
}
// cjlint-ignore -end description
多行屏蔽正确示例 3,屏蔽 G.CHK.04 告警
/**
* cjlint-ignore -start !G.CHK.04 description
*/
void fetctl_process(const void *para)
{
if (para == NULL)
{
return;
}
}
// cjlint-ignore -end description
单行屏蔽错误示例 1,屏蔽 G.CHK.04 告警
void fetctl_process(const void *para)
{
if (para == NULL)
{
return; /*cjlint-ignore !G.CHK.04!G.CHK.02 */
// ERROR: 规则间没用空格隔开,屏蔽告警失败
}
}
单行屏蔽错误示例 2,屏蔽 G.CHK.04 告警
void fetctl_process(const void *para)
{
if (para == NULL)
{
return; /*cjlint-ignore !G.CHK.04description */
// ERROR: 规则与描述信息没用空格隔开,屏蔽告警失败
}
}
多行屏蔽错误示例 1,屏蔽 G.CHK.04 告警
/* cjlint-ignore -start
* !G.CHK.04 description */
void fetctl_process(const void *para)
{
if (para == NULL)
{
return;
}
}
/* cjlint-ignore -end description */
// ERROR: 屏蔽规则没与 'cjlint-ignore' 在同一行,屏蔽告警失败
文件级告警屏蔽
-
cjlint可以通过-e选项支持文件级别的告警屏蔽。通过在
-e后添加屏蔽规则,即可将规则匹配的仓颉文件屏蔽,不会产生关于这些文件的告警。输入的规则为相对-f源码目录的相对路径(支持正则),输入字符串需要用双引号包含,多条屏蔽规则用空格分隔。例如,下面这条命令屏蔽了src/dir1/目录内的所有仓颉文件,src/dir2/a.cj文件和src/目录下所有形如test*.cj的仓颉文件。cjlint -f src/ -e "dir1/ dir2/a.cj test*.cj" -
cjlint可以通过后缀为.cfg的配置文件批量导入屏蔽规则。通过
-e选项导入配置文件,与其他屏蔽规则或配置文件用空格分隔。例如,下面这条命令屏蔽了src/dir1目录和src/exclude_config_1.cfg、src/dir2/exclude_config_2.cfg内配置的所有屏蔽规则对应的文件。cjlint -f src/ -e "dir1/ exclude_config_1.cfg dir2/exclude_config_2.cfg".cfg配置文件中可以配置多条屏蔽规则,每行均为一条屏蔽规则,屏蔽规则为相对该配置文件所在目录的相对路径(支持正则),无需双引号包含。例如在src/dir2/exclude_config_2.cfg中有以下配置,则上述的命令会将src/dir2/subdir1/目录和src/dir2/subdir2/a.cj文件加入屏蔽。subdir1/ subdir2/a.cj -
cjlint可以通过默认配置文件批量导入屏蔽规则。cjlint屏蔽功能的默认配置文件名为cjlint_file_exclude.cfg,位置在-f源码目录下。例如,当src/目录下存在src/cjlint_file_exclude.cfg这一配置文件时,cjlint -f src/命令会屏蔽src/cjlint_file_exclude.cfg内配置的屏蔽规则对应的文件。如果开发者已经在-e选项中配置了其他有效的.cfg配置文件,则cjlint不会检查默认配置文件。
支持检查的规范列表(持续新增中)
cjlint 默认启用的规范列表:
- G.NAM.01 包名采用全小写单词,允许包含数字和下划线。
- G.NAM.02 源文件名采用全小写加下划线风格。
- G.NAM.03 接口,类,struct、枚举类型和枚举成员构造,类型别名,采用大驼峰命名。
- G.NAM.04 函数名称应采用小驼峰命名。
- G.NAM.05 let 的全局变量和 static let 变量的名称采用全大写。
- G.FMT.01 源文件编码格式(包括注释)必须是 UTF-8。
- G.FMT.15 禁止省略浮点数小数点前的 0。
- G.DCL.01 避免遮盖(shadow)。
- G.DCL.02 显式声明 public 变量的类型和 public 函数的返回类型。
- G.FUN.01 函数功能要单一。
- G.FUN.02 禁止函数有未被使用的参数。
- G.FUN.03 避免在无关的函数之间重用名字,构成重载。
- G.CLS.01 override 父类函数时不要增加函数的可访问性。
- G.ITF.01 对于需要原地修改对象自身的抽象函数,尽量使用 mut 修饰,以支持 struct 类型实现或扩展该接口。
- G.ITF.02 尽量在类型定义处就实现接口,而不是通过扩展实现接口。
- G.ITF.03 类型定义时避免同时声明实现父接口和子接口。
- G.ITF.04 尽量通过泛型约束使用接口,而不是直接将接口作为类型使用。
- G.OPR.01 尽量避免违反使用习惯的操作符重载。
- G.OPR.02 尽量避免在枚举类型内定义
()操作符重载函数。 - G.ENU.01 避免枚举的构造成员与顶层元素同名。
- G.ENU.02 尽量避免不同的 enum 的 constructor 之间不必要的重载。
- G.VAR.01 优先使用不可变变量。
- G.VAR.02 保持变量的作用域尽可能小。
- G.TYP.03 判断变量是否为 NaN 时必须使用 isNaN() 方法。
- G.EXP.01 match 表达式同一层尽量避免不同类别的 pattern 混用。
- G.EXP.02 不要期望浮点运算得到精确的值。
- G.EXP.03 && 、 ||、? 和 ?? 操作符的右侧操作数不要包含副作用。
- G.EXP.04 尽量避免副作用发生依赖于操作符的求值顺序。
- G.EXP.05 用括号明确表达式的操作顺序,避免过分依赖默认优先级。
- G.EXP.06 Bool 类型比较应避免多余的 == 或 !=。
- G.EXP.07 比较两个表达式时,左侧倾向于变化,右侧倾向于不变。
- G.ERR.01 恰当地使用异常或错误处理机制。
- G.ERR.02 防止通过异常抛出的内容泄露敏感信息。
- G.ERR.03 避免对 Option 类型使用 getorthrow 函数。
- G.ERR.04 不要使用 return、break、continue 或抛出异常使 finally 块非正常结束。
- G.PKG.01 避免在 import 声明中使用通配符*。
- G.CON.01 禁止将系统内部使用的锁对象暴露给不可信代码。
- P.01 使用相同的顺序请求锁,避免死锁。
- G.CON.02 在异常可能出现的情况下,保证释放已持有的锁。
- G.CON.03 禁止使用非线程安全的函数来覆写线程安全的函数。
- P.02 避免数据竞争(data race)。
- G.CHK.01 跨信任边界传递的不可信数据使用前必须进行校验。
- G.CHK.02 禁止直接使用外部数据记录日志。
- G.CHK.03 使用外部数据构造的文件路径前必须进行校验,校验前必须对文件路径进行规范化处理。
- G.CHK.04 禁止直接使用不可信数据构造正则表达式。
- G.FIO.01 临时文件使用完毕必须及时删除。
- G.SER.01 禁止序列化未加密的敏感数据。
- G.SER.02 防止反序列化被利用来绕过构造方法中的安全操作。
- G.SER.03 保证序列化和反序列化的变量类型一致。
- G.SEC.01 进行安全检查的方法禁止声明为
open。 - P.03 对外部对象进行安全检查时需要进行防御性拷贝。
- G.OTH.01 禁止在日志中保存口令、密钥和其他敏感数据。
- G.OTH.02 禁止将敏感信息硬编码在程序中。
- G.OTH.03 禁止代码中包含公网地址。
- G.OTH.04 不要使用 String 存储敏感数据,敏感数据使用结束后应立即清 0。
- FFI.C.7 强制进行指针类型转换时避免出现截断错误。
cjlint 能够检测,但默认不启用的规范列表(开发者可通过将规范添加至 cjlint_rule_list.json 以启用这类规则):
- G.NAM.06 变量的名称采用小驼峰。
- G.VAR.03 避免使用全局变量。
- G.FMT.13 文件头注释应该包含版权许可。
规格说明
-
G.CON.02 在异常可能出现的情况下,保证释放已持有的锁。
lock() 函数和 unlock() 函数赋值给变量,赋值后的变量再去加解锁的场景,该规则检查不覆盖。
-
G.OTH.03 暂不支持宏检查。
-
只有当宏包在正确的路径下时,
cjlint才能支持宏检查。例:a.cj 为宏包源码,其正确路径应为 xxx/src/a/a.cj。
-
cjlint只有在宏被调用时才能对其进行检查,且无法对宏包中的冗余代码进行检查。
支持语法禁用检查
-
cjlint可以通过将 G.SYN.01 添加至cjlint_rule_list.json以启用禁用语法的检查。如果使用了禁用的语法元素,cjlint将会报错。 -
当前所支持
cjlint检查的禁用语法如表中所示:禁用语法 关键词 说明 导入包 Import 不允许随意导入包 let 变量 Let 只用 var 变量,不引入不可写变量的概念 创建线程 Spawn 不允许创建线程 线程同步 Synchronized 防止死锁 主函数 Main 禁止提供入口主函数 定义宏 MacroQuote 禁止定义宏(但允许使用宏) 跨语言 Foreign 禁止跨语言混合编程 while 循环 While 防止复杂循环和死循环 扩展 Extend 禁止使用扩展语法 类型别名 Type 禁止自行定义类型别名 操作符重载 Operator 禁止重载操作符 全局变量 GlobalVariable 禁止声明和使用全局变量,防止副作用和内存泄漏 定义枚举 Enum 禁用 Enum,避免复杂代码 定义类 Class 禁用 Class,避免复杂代码 定义接口 Interface 禁用 Interface,避免复杂代码 定义结构 Struct 禁用 Struct,避免复杂代码 定义泛型 Generic 禁用 Generic,避免复杂代码 条件编译 When 禁止平台相关代码 模式匹配 Match 函数式编程范式,开发者不易掌握 捕获异常 TryCatch 避免自行处理异常,易导致错误被忽略 高阶函数 HigherOrderFunc 函数类型的参数或返回值, 避免复杂代码 其他基础类型 PrimitiveType 不应使用 Int64、float64、bool 之外的其他基础类型 其他容器类型 ContainerType 应使用 List,Map,Set -
通过将上述表格中的关键字添加到
structural_rule_G_SYN_01.json中启用对应语法的禁用检查。举例:禁用导入包
{
"SyntaxKeyword": [
"Import"
]
}
格式化工具
功能简介
CJFMT(Cangjie Formatter)仓颉格式化工具是一款基于仓颉语言编程规范开发的代码自动格式化工具。
使用说明
- 可以在 DevEco 安装本工具插件进行使用
- 使用命令行操作
cjfmt [option] file [option] file
cjfmt -h 帮助信息,选项介绍
Usage:
cjfmt -f fileName [-o fileName]
cjfmt -d fileDir [-o fileDir]
Options:
-v Show version
eg: cjfmt -v
-h Show usage
eg: cjfmt -h
-f Specifies the file in the required format. The value can be a relative path or an absolute path.
eg: cjfmt -f test.cj
-d Specifies the file directory in the required format. The value can be a relative path or an absolute path.
eg: cjfmt -d test/
-o <value> Output. If a single file is formatted, '-o' is followed by the file name. Relative and absolute paths are supported;
If a file in the file directory is formatted, a path must be added after -o. The path can be a relative path or an absolute path.
eg: cjfmt -f a.cj -o ./fmta.cj
eg: cjfmt -d ~/testsrc -o ./testout
-c <value> Specify the format configuration file, relative and absolute paths are supported.
If the specified configuration file fails to be read, cjfmt will try to read the default configuration file in CANGJIE_HOME.
eg: cjfmt -f a.cj -c ./config/cangjie-format.toml
eg: cjfmt -d ~/testsrc -c ~/home/project/config/cangjie-format.toml
-l <region> Only format lines in the specified region for the provided file. Only valid if a single file was specified.
Region has a format of [start:end] where 'start' and 'end' are integer numbers representing first and last lines to be formated in the specified file.
Line count starts with 1.
eg: cjfmt -f a.cj -o ./fmta.cj -l 1:25
文件格式化
cjfmt -f
- 格式化并覆盖源文件,支持相对路径和绝对路径。
cjfmt -f ../../../test/uilang/Thread.cj
- 选项
-o新建一个.cj文件导出格式化后的代码,源文件和输出文件支持相对路径和绝对路径。
cjfmt -f ../../../test/uilang/Thread.cj -o ../../../test/formated/Thread.cj
目录格式化
cjfmt -d
- 选项
-d让开发者指定扫描仓颉源代码目录,对文件夹下的仓颉源码格式化,支持相对路径和绝对路径。
cjfmt -d test/ //源文件目录为相对目录。
cjfmt -d /home/xxx/test //源文件目录为绝对目录。
- 选项
-o为输出目录,可以是已存在的路径,若不存在则会创建相关的目录结构,支持相对路径和绝对路径;目录的最大长度 MAX_PATH 不同的系统之间存在差异,如 Windows 上这个值一般不能超过 260;在 Linux 上这个值一般建议不能超过 4096。
cjfmt -d test/ -o /home/xxx/testout
cjfmt -d /home/xxx/test -o ../testout/
cjfmt -d testsrc/ -o /home/../testout // 源文件文件夹testsrc/不存在;报错:error: Source file path not exist!
格式化配置文件
cjfmt -c
- 选项
-c允许开发者指定客制化的格式化工具配置文件。
cjfmt -f a.cj -c ./cangjie-format.toml
默认 cangjie-format.toml 所含配置文件如下,其值也为 cjfmt 工具内置配置选项的值:
# indent width
indentWidth = 4 # Range of indentWidth: [0, 8]
# limit length
linelimitLength = 120 # Range of indentWidth: [1, 120]
# line break type
lineBreakType = "LF" # "LF" or "CRLF"
# allow Multi-line Method Chain when it's level equal or greater than multipleLineMethodChainLevel
allowMultiLineMethodChain = false
# if allowMultiLineMethodChain's value is true,
# and method chain's level is equal or greater than multipleLineMethodChainLevel,
# method chain will be formatted to multi-line method chain.
# e.g. A.b().c() level is 2, A.b().c().d() level is 3
# ObjectA.b().c().d().e().f() =>
# ObjectA
# .b()
# .c()
# .d()
# .e()
# .f()
multipleLineMethodChainLevel = 5 # Range of multipleLineMethodChainLevel: [2, 10]
# allow Multi-line Method Chain when it's length greater than linelimitLength
multipleLineMethodChainOverLineLength = true
说明:
若客制化的格式化工具配置文件读取失败,则读取 CANGJIE_HOME 环境下的默认格式化工具配置文件
cangjie-format.toml。 CANGJIE_HOME 环境下的默认格式化工具配置文件路径为:CANGJIE_HOME/tools/config。 若 CANGJIE_HOME 环境下的默认格式化工具配置文件cangjie-format.toml同样读取失败,则使用cjfmt内置格式化配置选项。 若格式化工具配置文件中的某个配置选项读取失败,则该配置选项使用cjfmt内置格式化配置选项。
片段格式化
cjfmt -l
- 选项
-l允许开发者指定应格式化文件的某一部分进行格式化,格式化程序将仅对提供的行范围内的源代码应用规则。 -l选项仅适用于格式化单个文件(选项-f)。如果指定了目录(选项-d),则-l选项无效。
cjfmt -f a.cj -o .cj -l 10:25 //仅格式化第10行至第25行
格式化规则
- 一个源文件按顺序包含版权、package、import、顶层元素,且用空行分隔。
【正例】
// 第一部分,版权信息
/*
* Copyright (c) [Year of First Pubication]-[Year of Latest Update]. [Company Name]. All rights reserved.
*/
// 第二部分,package 声明
package com.myproduct.mymodule
// 第三部分,import 声明
import std.collection.HashMap // 标准库
// 第四部分,public 元素定义
public class ListItem <: Component {
// CODE
}
// 第五部分,internal 元素定义
class Helper {
// CODE
}
说明:
仓颉格式化工具不会强制用空行将版权信息部分与其他部分分隔,若开发者在版权信息下方留有一个或多个空行,则格式化工具会保留一个空行。
- 采用一致的空格缩进,每次缩进 4 个空格。
【正例】
class ListItem {
var content: Array<Int64> // 符合:相对类声明缩进 4 个空格
init(
content: Array<Int64>, // 符合:函数参数相对函数声明缩进 4 个空格
isShow!: Bool = true,
id!: String = ""
) {
this.content = content
}
}
- 使用统一的大括号换行风格,对于非空块状结构,大括号使用 K&R 风格。
【正例】
enum TimeUnit { // 符合:跟随声明放行末,前置 1 空格
Year | Month | Day | Hour
} // 符合:右大括号独占一行
class A { // 符合:跟随声明放行末,前置 1 空格
var count = 1
}
func fn(a: Int64): Unit { // 符合:跟随声明放行末,前置 1 空格
if (a > 0) { // 符合:跟随声明放行末,前置 1 空格
// CODE
} else { // 符合:右大括号和 else 在同一行
// CODE
} // 符合:右大括号独占一行
}
// lambda 函数
let add = { base: Int64, bonus: Int64 => // 符合: lambda 表达式中非空块遵循 K&R 风格
print("符合 news")
base + bonus
}
- 按照仓颉语言编程规范中的规则 G.FMT.10,使用空格突出关键字和重要信息。
【正例】
var isPresent: Bool = false // 符合:变量声明冒号之后有一个空格
func method(isEmpty!: Bool): RetType { ... } // 符合:函数定义(命名参数 / 返回类型)中的冒号之后有一个空格
method(isEmpty: isPresent) // 符合: 命名参数传值中的冒号之后有一个空格
0..MAX_COUNT : -1 // 符合: range 操作符区间前后没有空格,步长冒号前后两侧有一个空格
var hundred = 0
do { // 符合:关键字 do 和后面的括号之间有一个空格
hundred++
} while (hundred < 100) // 符合:关键字 while 和前面的括号之间有一个空格
func fn(paramName1: ArgType, paramName2: ArgType): ReturnType { // 符合:圆括号和内部相邻字符之间不出现空格
...
for (i in 1..4) { // 符合:range 操作符左右两侧不留空格
...
}
}
let listOne: Array<Int64> = [1, 2, 3, 4] // 符合:方括号和圆括号内部两侧不出现空格
let salary = base + bonus // 符合:二元操作符左右两侧留空格
x++ // 符合:一元操作符和操作数之间不留空格
- 减少不必要的空行,保持代码紧凑。
【反例】
class MyApp <: App {
let album = albumCreate()
let page: Router
// 空行
// 空行
// 空行
init() { // 不符合:类型定义内部使用连续空行
this.page = Router("album", album)
}
override func onCreate(): Unit {
println( "album Init." ) // 不符合:大括号内部首尾存在空行
}
}
- 减少不必要的分号,以代码简洁优先。
【格式化前】
package demo.analyzer.filter.impl; // 冗余的分号
internal import demo.analyzer.filter.StmtFilter; // 冗余的分号
internal import demo.analyzer.CJStatment; // 冗余的分号
func fn(a: Int64): Unit {
println( "album Init." );
}
【格式化后】
package demo.analyzer.filter.impl // 删除冗余的分号
internal import demo.analyzer.filter.StmtFilter // 删除冗余的分号
internal import demo.analyzer.CJStatment // 删除冗余的分号
func fn(a: Int64): Unit {
println( "album Init." ); // 表达式的分号予以保留,删除可能影响语义
}
- 按照仓颉语言编程规范中的规则 G.FMT.12 规定的优先级排列修饰符关键字。
以下是推荐的顶层元素的修饰符排列优先级:
public
open/abstract
以下是推荐的实例成员函数或实例成员属性的修饰符排序优先级:
public/protected/private
open
override
以下是推荐的静态成员函数的修饰符排序优先级:
public/protected/private
static
redef
以下是推荐的成员变量的修饰符排序优先级:
public/protected/private
static
- 多行注释的格式化行为
以 * 开头的注释, * 会互相对齐, 不以 * 开头的注释,则会保持注释原样。若*后存在多余空格,则会将多余空格删除。
// 格式化前
/*
* comment
*/
/*
comment
*/
//格式化后
/*
* comment
*/
/*
comment
*/
注意事项
-
仓颉格式化工具暂不支持语法错误的代码的格式化。
-
仓颉格式化工具暂不支持元编程的格式化。
覆盖率统计工具
功能简介
cjcov(Cangjie Coverage)是一款面向仓颉语言的覆盖率统计工具,用于生成仓颉语言程序的覆盖率报告。
使用说明
cjcov -h 获取帮助信息,选项介绍如下:
Usage: cjcov [options]
A tool used to summarize the coverage in html reports.
Options:
-v, --version Print the version number, then exit.
-h, --help Show this help message, then exit.
-r ROOT, --root=ROOT The root directories of your source files, defaults to '.', the current directory.
File names are reported relative to this root.
-o OUTPUT, --output=OUTPUT The output directories of html reports, defaults to '.', the current directory.
-b, --branches Report the branch coverage. (It is an experimental feature and may generate imprecise branch coverage.)
--verbose Print some detail messages, including parsing data for the gcov file.
--html-details Generate html reports for each source file.
-x, --xml Generate a xml report.
-j, --json Generate a json report.
-k, --keep Keep gcov files after processing.
-s SOURCE, --source=SOURCE The directories of cangjie source files.
-e EXCLUDE, --exclude=EXCLUDE
The cangjie source files starts with EXCLUDE will not be showed in coverage reports.
-i INCLUDE, --include=INCLUDE
The cangjie source files starts with INCLUDE will be showed in coverage reports.
基本的命令使用方法如下所示,cjcov 为主程序名称,--version 表示为显示 cjcov 的版本号。部分配置项支持长短选项两种写法,效果相同,具体可以使用 cjcov --help 命令参考用法。
cjcov -version 或者 cjcov -v
使用步骤
单文件场景
仓颉版本包准备 --> 仓颉源码准备 --> 使用 --coverage 编译选项构建仓颉源码,生成二进制文件 --> 执行二进制文件 --> cjcov 生成覆盖率统计结果
以 hello world 为例(假设当前目录是 WORKPATH):
-
仓颉版本包准备
对于
Linux平台,假设仓颉版本包解压在WORKPATH目录下,则执行source WORKPATH/cangjie/envsetup.sh命令即可。 -
仓颉源码准备
源码目录结构如下:
src/ └── main.cjmain.cj源码内容如下:main(): Int64 { print("hello world\n") return 0 } -
编译源码
在
WORKPATH目录下执行以下命令:cjc --coverage main.cj编译完成之后在
WORKPATH目录下会生成default.gcno和main文件。 -
运行编译出来的二进制
在
WORKPATH目录下执行./main命令,运行完成之后WORKPATH目录下会生成default.gcda文件。 -
cjcov生成html在
WORKPATH目录执行cjcov -o output --html-details,更多cjcov参数使用可参考命令说明章节。
执行完 cjcov 命令之后,在 WORKPATH/output 目录会有以下文件:
output
├── cjcov_logs (该目录存放一些 cjcov 执行过程的详细日志,可不用关注)
│ ├── cjcov.log
│ └── gcov_parse.log
├── index.html (总的覆盖率报告,通过浏览器打开)
└── src_main.cj.html (单个文件的覆盖率,可以通过打开 index.html 自动跳转到该文件)
多文件场景
对于多文件场景,推荐使用包管理工具的命令cjpm build --coverage 或 cjpm test --coverage ,具体用法请参见包管理工具。
命令说明
cjcov -h | --help
显示 cjcov 基本使用方法。
cjcov -v | --version
显示 cjcov 的版本号。指定 -v 或者 --version 参数后,输入其他任何选项参数都不生效,只会显示版本号。如 --version 和 --help 同时使用,则显示 version 信息后退出。
cjcov --verbose
指定该选项后会将一些日志信息生成到 cjcov_logs 目录中,该参数默认不生效,即默认不会打印中间信息。gcov 文件是 cjcov 工具生成的中间文件,cjcov 解析 gcov 文件的格式如下:
==================== start: main.cj.gcov =====================
noncode line numbers:
[0, 0, 0, 0, 1, 2, 6, 7, 9, 10, 11, 15, 17, 18]
uncovered line numbers:
[5]
covered data:
[(16, 1), (3, 1), (4, 1), (8, 1), (12, 1), (13, 1), (14, 1)]
branches data:
line number: 4 ==> data: [(0, 0), (1, 1)]
===================== end: main.cj.gcov =======================
指定该选项参数,会显示每个 gcov 文件的详细覆盖率数据。
具体字段解释如下:
start: xxx.gcov, end: xxx.gcov:两行中间的文本是对应xxx.gcov文件解析到的覆盖率数据。noncode line numbers:显示的是不统计到总代码行的行号,在html中是以白色底呈现,对应gcov中的以-开头的行数。uncovered line numbers:显示的是没有覆盖到的数据,在html中是以红色底呈现,对应gcov文件中以#####开头的行数。covered data:显示的是覆盖到的数据,以(代码行数, 覆盖次数)呈现,在对应html中以绿色呈现,只要覆盖次数大于 0,在html中的Exec一列中显示为Y,对应于gcov文件以数字开头的行数。branches data:显示的分支覆盖数据,以(代码行数, 分支覆盖次数)呈现,在对应html中的Branch一列中,有一个倒三角形,显示的是分支覆盖数/总分支数。该数据对应于gcov文件中以branch开头的数据。
cjcov --html-details
如果指定该参数,表示会生成仓颉文件对应的 html。在总的 index 文件里面会有每个子 html 的索引。子 html 文件和 index.html 放在同一个目录。
子 html 文件名是由目录和文件名由下划线拼接起来。如源文件是 src/main.cj,生成的 html 名字为 src_main.cj.html。如果源文件路径带有特殊字符会被替换成 =,下文文件名包含特殊字符章节会有更详细的描述。
如果没有指定该参数,表示不会生成子 html 。在总的 index 文件里面会显示每个子 html 的覆盖率数据,但是不能跳转到对应的子 html 文件。
该参数默认不生效。即默认只会生成一个 index.html, 不会生成子 html 文件。
cjcov -x | --xml
如果指定该参数,则会在指定输出路径生成 coverage.xml 文件,coverage.xml 记录的是所有文件的覆盖率数据。
cjcov -j | --json
如果指定该参数,则会在指定输出路径生成 coverage.json 文件,coverage.json 记录的是所有文件的覆盖率数据。
cjcov -k | --keep
指定该参数后则不会删除生成的 gcov 中间文件。如果 gcov 文件不删除,会造成执行次数的累加,可能会影响覆盖率数据的准确性。
默认该参数不生效,即默认会删除 gcov 中间文件。
cjcov -b | --branches
指定该参数后则会生成分支覆盖率信息。
默认该参数不生效,即默认不生成分支的覆盖率信息,此时在 html 报告中的分支覆盖率数据百分比显示为 -。
cjcov -r ROOT | --root=ROOT
该参数指定的 ROOT 参数,表示在 ROOT 目录或者在其递归子目录能找到 gcda 文件,gcda 和 gcno 文件默认会生成在一起,建议不要手动特意去把 gcda 文件和 gcno 文件分开存放,不然可能会发生程序不能运行的情况。
参数指定的 ROOT 目录如果不存在,cjcov 工具会有报错提示。
不指定该参数,默认会以当前目录为 ROOT 目录。
cjcov -o OUTPUT | --output=OUTPUT
该参数指定的 OUTPUT 参数,表示 html 覆盖率报告的输出路径。
如果该 OUTPUT 目录不存在,而且其父目录也不存在,cjcov 工具会有报错提示;如果 OUTPUT 目录不存在,但其父目录存在,cjcov 会帮助创建 OUTPUT 目录。
不指定该参数,默认会以当前目录为 OUTPUT 目录来存放 html 文件。
-s SOURCE | --source=SOURCE
该参数指定的 SOURCE 参数,表示仓颉源文件的代码路径,html 总覆盖率报告 index.html 会有各个源文件的索引,这些文件路径记录的是一个相对路径。如果指定 -s SOURCE |--source SOURCE 参数,优先以 SOURCE 路径列表中的路径作为相对路径的参考路径,如果没有指定该参数,则以 -r ROOT | --root=ROOT 作为相对路径的参考路径,如果都没有指定,则以当前路径作为相对路径的参考路径。
示例:
仓颉代码目录结构如下:
/work/cangjie/tests/API/test01/src/1.cj
/work/cangjie/tests/API/test01/src/2.cj
/work/cangjie/tests/cjnative/test02/src/3.cj
/work/cangjie-tools/tests/cjnative/test01/src/4.cj
/work/cangjie-tools/tests/cjnative/test02/src/5.cj
-
在
/work目录执行命令:cjcov --root=./ -s "/work/cangjie /work/cangjie-tools/tests" --html-details --output=html_output最后 html 中呈现的源文件相对路径是:
tests/API/test01/src/1.cj tests/API/test01/src/2.cj tests/cjnative/test02/src/3.cj cjnative/test01/src/4.cj cjnative/test02/src/5.cj -
在
/work目录执行命令, 没有指定--root参数和--source参数,默认当前所在路径为相对路径的参考路径,执行命令如下:cjcov --html-details --output=html_output最后 html 中呈现的源文件相对路径是:
cangjie/tests/API/test01/src/1.cj cangjie/tests/API/test01/src/2.cj cangjie/tests/cjnative/test02/src/3.cj cangjie-tools/tests/cjnative/test01/src/4.cj cangjie-tools/tests/cjnative/test02/src/5.cj
-e EXCLUDE | --exclude=EXCLUDE
该参数指定的 EXCLUDE 参数,表示不需要生成覆盖率信息的源文件列表,支持指定目录和文件。
示例:
仓颉代码目录结构如下:
/usr1/cangjie/tests/API/test01/src/1.cj
/usr1/cangjie/tests/API/test01/src/2.cj
/usr1/cangjie/tests/cjnative/test02/src/3.cj
/usr1/cangjie-tools/tests/cjnative/test01/src/4.cj
/usr1/cangjie-tools/tests/cjnative/test02/src/5.cj
在 /usr1 目录执行命令:
cjcov --root=./ -s "/usr1/cangjie" -e "/usr1/cangjie-tools/tests/cjnative" --html-details --output=html_output
最后 html 中呈现的源文件相对路径是,其中以 /usr1/cangjie-tools/tests/cjnative 路径开头的文件不会出现在 html 的文件列表中。
tests/API/test01/src/1.cj
tests/API/test01/src/2.cj
tests/cjnative/test02/src/3.cj
-i INCLUDE | --include=INCLUDE
该参数指定的 INCLUDE 参数,表示以 INCLUDE 开头的文件会显示在 index.html 的文件列表中,支持指定目录和文件。如果 -e | --exclude 和 -i | --include 指定的参数有路径重复,会有报错提示。
示例:
仓颉代码目录 /usr1/cangjie/tests 结构如下:
├── API
│ └── test01
│ └── src
│ ├── 1.cj
│ └── 2.cj
└── cjnative
└── test02
└── src
└── 3.cj
在 /usr1 目录执行命令, 其中 -i 参数表示需要体现在覆盖率报告 index.html 的文件,命令如下:
cjcov --root=./ -s "/usr1/cangjie" -i "/usr1/cangjie/tests/API/test01/src/1.cj /usr1/cangjie/tests/cjnative/test02" --html-details --output=html_output
上面命令执行后, 在 index.html 中文件路径列表如下(tests/API/test01/src/2.cj 不在 -i 参数指定的列表里面,所以不会出现在 html 的文件列表中):
tests/API/test01/src/1.cj
tests/cjnative/test02/src/3.cj
特殊场景
二进制无法正常执行结束
对于常驻的网络服务程序无法正常结束二进制文件并生成 gcda 覆盖率数据的场景,需要手动执行退出脚本生成 gcda 覆盖率数据。
1)将以下脚本内容保存为 stop.sh(此脚本执行依赖 gdb)
#!/bin/sh
SERVER_NAME=$1
pid=`ps -ef | grep $SERVER_NAME | grep -v "grep" | awk '{print $2}'`
echo $pid
gdb -q attach $pid <<__EOF__
p exit(0)
__EOF__
2)常驻服务程序完成业务逻辑操作覆盖后,执行 stop.sh {service_name},如通过 ./main 启动常驻服务进程,通过如下方式停止进程产生 gcda 数据
sh stop.sh ./main
文件名包含特殊字符
建议遵循仓颉编程规范命名文件,不建议包含除 [0-9a-zA-Z_] 之外的字符,特殊字符会被替换成 =。
如果文件名有特殊字符,为保证 html 跳转正确,index.html 中呈现的 html 名字和 html 本身文件名会不一致,html 文件名的特殊字符都会被替换成 =。
示例如下:
代码结构:
src
├── 1file#.cj
├── file10_abc.cj
├── file11_.aaa-bbb.cj
├── file12!#aaa!bbb.cj
├── file13~####.cj
├── file14*aa.cj
├── file15`.cj
├── file16(#).cj
├── file2;aa.cj
├── file3,?.cj
├── file4@###.cj
├── file5&cc.cj
├── file6=.cj
├── file7+=.cj
├── file8$.cj
├── file9-aaa.cj
└── main.cj
生成 html 文件名,其中除了 [0-9a-zA-Z_.=] 之外,其他特殊字符都被替换成了 '=':
.
├── index.html
├── src_1file=.cj.html
├── src_file10_abc.cj.html
├── src_file11_.aaa=bbb.cj.html
├── src_file12==aaa=bbb.cj.html
├── src_file13=####.cj.html
├── src_file14=aa.cj.html
├── src_file15=.cj.html
├── src_file16===.cj.html
├── src_file2=aa.cj.html
├── src_file3==.cj.html
├── src_file4=###.cj.html
├── src_file5=cc.cj.html
├── src_file6=.cj.html
├── src_file7==.cj.html
├── src_file8=.cj.html
├── src_file9=aaa.cj.html
└── src_main.cj.html
分支覆盖率功能
分支覆盖率是一个试验阶段的功能,会出现分支覆盖率数据不准确的情况。
目前已知会出现分支覆盖率数据不准确的场景包含以下几种表达式:
-
try-catch-finally表达式 -
循环表达式(包括
for表达式、while表达式) -
if-else表达式
部分代码未记录到行覆盖率数据中
部分代码不会记录到行覆盖率数据中,属于正常情况。整体而言,如果一行代码仅包含定义、声明而没有实际的可执行代码,那么这一行代码不会被统计到覆盖率中。目前已知不会统计的场景有:
-
全局变量的定义,示例如下:
let HIGH_1_UInt8: UInt8 = 0b10000000; -
成员变量仅声明未初始化赋值,示例如下:
public class StringBuilder <: Collection & ToString { private var myData: Array private var mySize: Int64 private var endIndex: Int64 } -
仅有函数声明未包含函数体(包括
foreign函数等),示例如下:foreign func cj_core_free(p: CPointer): Unit -
枚举类型定义,示例如下:
enum Numeric { NumDay | NumYearDay | NumYearWeek | NumHour12 | NumHour24 | NumMinute | NumSecond } -
class、extend 等定义,其中 extend 和 class 所在的一行不会记录到覆盖率数据中,示例如下:
extend Int8 <: Formatter { // This line wil not account for the coverage. ... } public class StringBuilder <: Collection & ToString { // This line will not account for the coverage. ... }
源代码中的 main 函数未被覆盖
原因: 使用 cjc --test 编译,仓颉测试框架会生成一个新的 main 作为程序入口,源代码中的 main 不再作为程序入口并且不会被执行。
建议: 在使用 cjc --test 之后,建议不用再手写多余的 main 。
FAQ
报错找不到 llvm-cov 命令
解决方法:
方法 1:设置 CANGJIE_HOME 环境变量, cjcov 可通过 CANGJIE_HOME 环境变量找到 llvm-cov 命令,设置方法如下:
假设 which cjc 显示 /work/cangjie/bin/cjc, 并且 /work/cangjie/bin/llvm/bin 和 /work/cangjie/bin/llvm/lib 目录都存在,则可设置:
export CANGJIE_HOME=/work/cangjie
方法 2:在 /root/.bashrc 里面直接设置环境变量,如 cjc 放在 /work/cangjie/bin/cjc 目录下,则设置方法如下:
export PATH=/work/cangjie/bin/llvm/bin:$PATH
export LIBRARY_PATH=/work/cangjie/bin/llvm/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=/work/cangjie/bin/llvm/lib:$LD_LIBRARY_PATH
方法 3:手动安装 llvm-cov 命令,如 ubuntu 上可执行命令:
apt install llvm-cov
出现 VirtualMachineError OutOfMemoryError
问题现象:
An exception has occurred:
Error VirtualMachineError OutOfMemoryError
解决方法: 仓颉默认规格 stack 1MB,heap 256 MB,建议根据文件数量大小将堆内存调到合适的大小。通常 2GB 的内存能够满足大多数情况,如果不够用则根据具体情况再增加内存大小。
示例:
把堆内存扩大到2GB:
export cjHeapSize=2GB
性能分析工具
功能简介
cjprof(Cangjie Profile)是仓颉语言的性能分析工具,支持以下功能:
-
对仓颉语言程序进行 CPU 热点函数采样,导出采样数据。
-
对热点函数采样数据进行分析,生成 CPU 热点函数统计报告或火焰图。
-
导出仓颉语言应用程序堆内存,并对其进行分析生成分析报告。
目前 cjprof 仅支持 Linux 系统。
使用说明
通过 cjprof --help 即可查看命令使用方法。支持 record,report 和 heap 子命令,分别用于采集 CPU 热点函数信息, 生成 CPU 热点函数报告(包含火焰图)和导出与分析堆内存。
cjprof --help
Usage: cjprof [--help] COMMAND [ARGS]
The supported commands are:
-v Print version of cjprof
heap Dump heap into a dump file or analyze the heap dump file
record Run a command and record its profile data into data file
report Read profile data file (created by cjprof record) and display the profile
注意:
由于
cjprof record依赖系统的perf权限,因此使用需要满足以下两个条件之一:
- 使用
root用户或sudo权限执行。- 系统的
perf_event_paranoid参数(通过/proc/sys/kernel/perf_event_paranoid文件)配置为 -1 。否则可能会出现权限不足的问题。
采集 CPU 热点函数信息
命令
cjprof record
格式
cjprof record [<options>] [<command>]
cjprof record [<options>] -- <command> [<options>]
选项
-f, --freq <freq> 指定采样频率,单位为赫兹(Hz),即每秒采样次数,默认为 5000 Hz,当指定为 max 或超过系统支持的最大频率时,取系统支持的最大频率。
-o, --output <file> 指定采样结束后生成的采样数据文件名,默认为 cjprof.data 。
-p, --pid <pid> 指定被采样应用程序的进程 ID,当指定 <command> 新启动应用程序进行采样时,该选项会被忽略。
示例
- 采样正在运行的应用程序。
# 以 10000 Hz 的采样频率对正在运行的应用程序(进程号为 12345)进行采样,采样结束后将采样数据生成在当前路径下名为 sample.data 的文件中。
cjprof record -f 10000 -p 12345 -o sample.data
- 新启动应用程序并对其进行采样。
# 执行当前路径下的 `test` 应用程序,参数为 `arg1 arg2` ,并以系统支持的最大采样频率对其进行采样,采样结束后将采样数据生成在当前路径下名为 `cjprof.data` (默认文件名)的文件中。
cjprof record -f max -- ./test arg1 arg2
注意事项
- 开始采样后,只有被采样程序退出后才会结束采样,如果需要提前结束采样,可以在采样过程中通过按
Ctrl+C主动停止采样。
生成 CPU 热点函数报告
命令
cjprof report
格式
cjprof report [<options>]
选项
-F, --flame-graph 生成 CPU 热点函数火焰图,而非默认的文本报告。
-i, --input <file> 采样数据文件名,默认为 cjprof.data 。
-o, --output <file> 生成的 CPU 热点函数火焰图文件名,默认为 FlameGraph.svg,仅当生成火焰图时才有效。
示例
- 生成默认的 CPU 热点函数文本报告。
# 分析 sample.data 中的采样数据,生成 CPU 热点函数文本报告。
cjprof report -i sample.data
- 生成 CPU 热点函数火焰图。
# 分析 cjprof.data(默认文件)中的采样数据,生成名为 test.svg 的 CPU 热点函数火焰图。
cjprof report -F -o test.svg
报告形式说明
-
文本形式的报告包含函数采样总占比(包含子函数)、函数采样占比(自身)以及函数名(如果没有对应的符号信息则显示为地址)三部分,报告结果以函数采样总占比降序排列。
-
火焰图中的横轴代表采样占比大小,越宽表示采样占比越大,即运行时间越长,纵轴表示调用栈,父函数在下,子函数在上。
导出和分析堆内存
命令
cjprof heap
格式
cjprof heap [<options>]
选项
-D, --depth <depth> 指定对象的引用/被引用关系最大展示深度,默认为 10 层,仅在指定了 --show-reference 时才能生效。
-d, --dump <pid> 导出仓颉应用程序当前时刻的堆内存,pid 为应用程序进程号,当指定为应用程序的子线程号时,同样可导出。
-i, --input <file> 指定进行分析的堆内存数据文件名,默认为 cjprof.data 。
-o, --output <file> 指定导出的堆内存数据文件名,默认为 cjprof.data 。
--show-reference[=<objnames>] 分析报告中展示对象的引用关系,objnames 为需要展示的对象名,多个对象使用 ; 隔开,不指定时默认展示所有对象。
--incoming-reference 展示对象的被引用关系,而非引用关系,需要与 --show-reference 配合使用。
-t, --show-thread 分析报告中展示仓颉线程栈,以及在栈中引用的对象。
-V, --verbose 维测选项,解析堆内存数据文件时打印解析日志。
示例
- 导出堆内存数据。
# 将正在运行的应用程序(进程号为 12345)当前时刻的堆内存导出到当前路径下名为 heap.data 的文件中。
cjprof heap -d 12345 -o heap.data
注意:
导出堆内存时会向进程发送
SIG_USR1信号,在不确定目标进程是否为仓颉应用程序时,需要谨慎操作,否则可能会给目标进程误发送信号导致非预期错误。 导出堆内存时,正在运行的仓颉程序目录和执行导出的目录都需要写权限,否则可能因为权限问题导致失败。
- 分析堆内存数据,展示对象信息。
# 解析并分析 ~ 目录下名为 heap.data 的堆内存数据文件,展示堆中各激活对象的对象类型名、实例个数、浅堆大小和深堆大小。
cjprof heap -i ~/heap.data
执行上述命令的效果如下:
Object Type Objects Shallow Heap Retained Heap
==================== ============= ============= =============
AAA 1 80 400
BBB 4 32 196
CCC 2 16 32
- 分析堆内存数据,展示仓颉线程栈及对象引用。
# 解析并分析当前目录下名为 cjprof.data(默认文件)的堆内存数据文件,展示仓颉线程栈与栈中引用的对象。
cjprof heap --show-thread
执行上述命令的效果如下:
Object/Stack Frame Shallow Heap Retained Heap
=================================== ============= =============
thread0
at Func2() (/home/test/test.cj:10)
<local> AAA @ 0x7f1234567800 80 400
at Func1() (/home/test/test.cj:20)
<local> CCC @ 0x7f12345678c0 16 16
at main (/home/test/test.cj:30)
- 分析堆内存数据,展示对象的引用关系。
# 解析并分析当前目录下名为 cjprof.data(默认文件)的堆内存数据文件,展示 AAA 和 BBB 类型对象的引用关系。
cjprof heap --show-reference="AAA;BBB"
执行上述命令的效果如下:
Objects with outgoing references:
Object Type Shallow Heap Retained Heap
=================================== ============= =============
AAA @ 0x7f1234567800 80 400
BBB @ 0x7f1234567880 32 48
CCC @ 0x7f12345678c0 16 16
CCC @ 0x7f12345678e0 16 16
BBB @ 0x7f1234567880 32 48
CCC @ 0x7f12345678c0 16 16
- 分析堆内存数据,展示对象的被引用关系。
# 解析并分析当前目录下名为 cjprof.data(默认文件)的堆内存数据文件,展示 CCC 类型对象的被引用关系。
cjprof heap --show-reference="CCC" --incoming-reference
执行上述命令的效果如下:
Objects with incoming references:
Object Type Shallow Heap Retained Heap
=================================== ============= =============
CCC @ 0x7f12345678c0 16 16
BBB @ 0x7f1234567880 32 48
AAA @ 0x7f1234567800 80 400
CCC @ 0x7f12345678e0 16 16
AAA @ 0x7f1234567800 80 400
堆内存分析报告说明
-
对象类型名使用
RawArray<Byte>[],RawArray<Half>[],RawArray<Word>[]和RawArray<DWord>[]分别表示 1 字节、2 字节、4 字节和 8 字节大小的基础数据类型原始数组。 -
浅堆(Shallow Heap)是指对象自身所占用的堆内存大小,深堆(Retained Heap)是指对象被垃圾回收后,可以被释放的所有对象(即通过该对象直接或间接引用到的对象)的浅堆大小之和。
-
当对象的引用关系层级超出最大展示深度后,或是存在循环引用出现重复对象后,会使用
...来省略后续引用。
异常堆栈信息还原工具
功能简介
cjtrace-recover 是仓颉语言的异常堆栈信息还原工具。
如果开发者在编译仓颉应用时开启了外形混淆,那么仓颉应用在运行时如果遇到问题,抛出的异常信息中的堆栈信息也是被混淆的状态,这导致开发者难以定位问题发生原因。cjtrace-recover 可以帮助开发者还原混淆过的异常堆栈信息,从而更好地定位和排查问题原因。具体来说,cjtrace-recover 可以还原异常堆栈信息中的以下两种信息:
- 被混淆的函数名
- 被混淆的路径名
使用说明
通过 cjtrace-recover -h 即可查看命令使用方法:
cjtrace-recover -h
Usage: cjtrace-recover OPTION
Use symbol mapping files to recover obfuscated exception stacktrace. The supported options are:
-f <file> path to the obfuscated exception stacktrace file
-m <file,...> path to the symbol mapping files
-h display this help and exit
-v print version of cjtrace-recover
开发者可以通过 -f 选项指定异常堆栈信息保存的文件,通过 -m 选项指定符号映射文件,cjtrace-recover 会根据符号映射文件中的映射关系还原异常堆栈信息中的符号名和路径名,并将还原后的异常堆栈信息通过标准输出(stdout)输出。
使用样例
假设有经过外形混淆的仓颉程序抛出的异常堆栈信息如下:
An exception has occurred:
MyException: this is myexception
at a0(SOURCE:0)
at ah(SOURCE:0)
at c3(SOURCE:0)
at cm0(SOURCE:0)
at cm1(SOURCE:0)
at ci0(:0)
并且在混淆编译时输出的符号映射文件 test.obf.map 的内容如下:
_ZN10mymod.mod111MyException6<init>ER_ZN8std.core6StringE a0 mymod/mod1/mod1.cj
_ZN10mymod.mod115my_common_func1Ev ah mymod/mod1/mod1.cj
_ZN10mymod.mod18MyClassA7myfunc1Eld c3 mymod/mod1/mod1.cj
_ZN7default6<main>Ev cm0 test1/test.cj
user.main cm1
cj_entry$ ci0
开发者需要将异常堆栈信息保存在文件中,假设为 test_stacktrace。然后通过以下指令还原异常堆栈信息:
cjtrace-recover -f test_stacktrace -m test.obf.map
运行该指令后,会得到如下输出:
An exception has occurred:
MyException: this is myexception
at mymod.mod1.MyException::init(std.core::String)(mymod/mod1/mod1.cj)
at mymod.mod1.my_common_func1()(mymod/mod1/mod1.cj)
at mymod.mod1.MyClassA::myfunc1(Int64, Float64)(mymod/mod1/mod1.cj)
at default.main()(/home/zzx/repos/obf_test/test1/test.cj)
cjtrace-recover 会根据符号映射文件还原异常堆栈信息,并通过标准输出流(stdout)输出。