fn main {
// 用便捷构造函数,或用数值和单位直接构造物理量。
let distance = @qgeometry.meters(100.0)
let time = @quantity.Quantity::new(10.0, @si.second)
// 运算会自动组合单位。
let speed = distance / time
println(@quantity.format_quantity(speed))
// checked API 适合在 main 中使用:非法换算返回 None。
let in_meters = @qgeometry
.kilometers(2.0)
.checked_to(@si.meter)
.unwrap()
println(@quantity.format_quantity(in_meters))
// 解析完整物理量,同时避免在 main 中引入未处理的错误效果。
let catalog = @preset.all()
let gravity = @parser
.parse_quantity_opt(catalog, "9.8 m/s^2")
.unwrap()
println(@quantity.format_quantity(gravity))
// 非法量纲加法会被拒绝,但不会终止程序。
println(distance.checked_add(time) is None)
}
运行 moon run cmd/main 会输出:
10 m/s
2000 m
9.8 m/s^2
true
严格版本的 add/sub/to 和 parse_* API 会在操作非法时抛出类型化错误;
请在能够处理或继续传播错误的函数中使用它们。在 main 等非抛错入口中,
应使用 checked_* 和 *_opt。
更多完整示例(速度、加速度、力、能量、换算以及非法运算拒绝)见
examples/,它们都在 moon test 下运行验证。
LunarUnits
English | 简体中文
在线文档
如果需要更完整的上手指南、案例、设计说明和 OSC2026 评审入口,请优先查看在线文档站。
LunarUnits 是一个面向 MoonBit 的运行时量纲检查物理量与单位系统。它通过显式建模量纲与单位换算,帮助工程计算、科学计算、教学和数据处理代码避免单位错误。
单位错误是科学与工程计算中常见的 bug 来源。LunarUnits 为每个数值附带单位,在运算时检查量纲一致性,并拒绝无意义的组合(例如把长度加到时间上),而不是悄悄产生错误的数字。MVP 阶段的检查发生在运行时,而不是通过编译期量纲类型系统完成。
特性
Quantity—— 数值与单位的组合。m/s^2)、SI/Unicode(m/s²)和 LaTeX(\mathrm{m}/\mathrm{s}^{2})三种记法。notation/catalog),以及按领域分包的预置目录 (notation/preset),用于解析与扩展单位符号。notation/parser),解析单位与数量表达式 (m/s^2、9.8 m/s^2),错误分类清晰且不 panic。affine/),表示带 offset 的绝对点(如温度 °C、°F、K、°R), 用类型区分「绝对点」与「差值」。logarithmic/),表示电平(dBm、dBW、dBV)与增益(dB、Np), 功率类与根功率类严格区分。安装
在通过
moon new创建的标准项目中,将以下包加入cmd/main/moon.pkg(保留其中 现有的options("is-main": true)配置):快速开始
将
cmd/main/main.mbt替换为:运行
moon run cmd/main会输出:严格版本的
add/sub/to和parse_*API 会在操作非法时抛出类型化错误; 请在能够处理或继续传播错误的函数中使用它们。在main等非抛错入口中, 应使用checked_*和*_opt。更多完整示例(速度、加速度、力、能量、换算以及非法运算拒绝)见
examples/,它们都在moon test下运行验证。设计
LunarUnits 采用单向依赖的分层结构;上层依赖下层,反之绝不依赖。
core/algebra—— 最小化的规范化符号代数。由于单位与量纲只会做乘、除和整数幂,这套代数就是符号上的自由阿贝尔群:每个表达式都规范化为唯一的单项式(一个系数乘以若干symbol^exponent项的乘积)。这让比较、化简和规范排序都自动成立。core/dimension—— 用单项式表达七个 SI 基本量纲(长度、质量、时间、电流、温度、物质的量、发光强度)。两个量纲相等当且仅当它们的指数向量相同,这是量纲检查的基础。core/unit——Un,单位符号单项式与一个量纲的组合。系数承载相对相干 SI 单位的缩放因子,因此复合单位(如 m/s)和换算都由代数自动推导得出。core/quantity——Quantity,数值加单位。加减法和换算会做量纲检查;乘除法组合单位。Dimension、Un和Quantity支持*与/作为总是合法的代数组合语法糖;整数幂继续通过.pow(n)显式表达。格式化与
Show刻意分离:Show保持面向调试和测试 diff,而format_unit/format_quantity(及其*_with变体)用于用户可见的展示,支持 ASCII、SI/Unicode 与 LaTeX 三种记法。符号解析放在独立的
notation/层:notation/catalog提供不可变的「符号 → 单位」查找表,且不参与核心单位身份判断;notation/preset为每个单位包提供一份现成目录(外加all()取并集)。在二者之上,notation/parser解析单位与数量字符串——原子符号来自 catalog,*、/、^、整数指数与括号由 parser 处理,失败时返回分类化的ParseError(或*_opt变体的None)而非 panic。非线性标度同样不进乘法核心。
affine/包表示换算为value × scale + offset的绝对点(如温度),沿用 boost.units / Pint 的仿射空间范式:绝对点Point(20 °C)与差值(kelvin 上的普通Quantity)是不同类型——点 − 点得差值、点 + 差值得点,而无意义的点 + 点、点 × 标量根本不存在。Un不带 offset;泛型AffineUn/Point可由用户扩展(温度只是随附的预置)。logarithmic/包按同样的「绝对 vs 相对」原则处理分贝与奈培,沿用 Unitful.jl:Level是绝对量(带参考,30 dBm知道自己是 1 W),Gain是纯比(3 dB)。电平经to_linear/from_linear与线性量互转,增益平移电平,两电平之差是增益,两个相等的功率电平合成约 +3 dB(功率翻倍)而非 +6。功率类与根功率类标度(factor 10 vs 20)严格区分、绝不自动互转。错误处理遵循刻意的分层:底层查询返回
Option(如Un::conversion_factor),而上层操作用 raise(Quantity::add/sub/to在量纲不匹配时 raiseDimensionMismatch)。单位集合按领域组织,用户只需导入所需部分。扩展包可以引入额外维度,而不要求面向 SI 的核心层或既有单位领域依赖这些维度。
包结构
开发
_test.mbt,白盒测试用_wbtest.mbt)。公共 API 同时带可运行的文档示例。moon test构建并验证一切(包含文档示例)。moon info && moon fmt。许可证
Apache-2.0,见 LICENSE。