作者一直想要一个用于编写类型安全数学的好库,例如在求解距离时要确保单位一致,避免像 NASA 因混合 imperial 和 metric 单位而损失火星轨道器的情况。
很多语言都有单位库,但都不能让作者满意,它们复杂、错误信息差且有作者不喜欢的权衡。
作者曾通过 Advent of Code 学习 Jai,之后一直未深入使用,但过去一年开始怀念其一些特性,于是用 Jai 写了一个小型单位库,在这个过程中了解到一些惊人的编译器特性,觉得 C++模板和 Rust traits 很古老。
作者不确定这个帖子是给 Jai 程序员、对 Jai 好奇的人还是 C++/Rust 程序员看的,它是混合的。
“类型安全单位”通过一个计算弹道轨迹范围的函数示例说明,函数中各种中间单位会抵消,最终结果应为“Meters”,否则会有编译错误,作者有一些要求,如单位逻辑必须在编译时且无运行时成本等。
作者 2019 年在 Rust 中写过自己的单位库,现有 crate 如“uom”但不满足所有要求,Rust 实现完全在类型系统中,依赖“typenum”crate,因为 Rust const 泛型不完善,但实现中 trait 地狱般复杂,类型系统逻辑丑陋且分散,“typenum”的错误信息也很糟糕,作者的 Rust 单位库实现约 1500 行,包含多个 struct、trait 和 impl,未发布是在等 const 泛型。
作者找不到好的 C++单位系统,若有也会涉及类似可怕的模板。
然后在 Jai 中实现了类型安全单位模块,起初尝试用嵌套 struct 未成功,后采用扁平化结构,如“SIQuantity”结构体定义九个 int 来定义 SI 单位,通过“#bake_arguments”等辅助函数声明各种类型,用“#modify”实现运算符如乘法,可确定函数参数类型和返回类型,还展示了更复杂的“combine_arrays”函数,最后用“#modify”实现“operator*”确定输出单位,整个过程在编译时完成无运行时开销,示例函数“calc_ballistic_range”在 Jai 中实现,还可以更通用,完整代码约 350 行,作者有两个对 Jai 语言团队的功能请求,同时介绍了 Jai 的一些其他特性如“#run”“#insert”“compile_time_code”“runtime_reflection”等,作者认为 Jai 的编译时特性比 C++和 Rust 更好,Jai 旨在用普通 Jai 代码解决编程中的难题,类型安全单位库是值得拥有的,最后给出“find_param”函数的实现和对比 Rust 中解决弹道轨迹问题的可怕代码。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。