Odin:一种务实的 C 语言替代品,带有 Go 的风格
Odin:一种务实的 C 语言替代品,带有 Go 的风格
2025年5月4日
Odin 是一种通用系统编程语言,由 Bill “gingerBill” Hall 开发。 Odin 被设计为 C 语言的现代替代品,强调简单性、性能和可读性,同时不牺牲对底层细节的控制。
该网站称其为“面向数据的”,并且诸如 SOA (structs-of-arrays) 和隐式零初始化等特性都与此相关。 尽管有这种关注点,但令人惊讶的是,该语言本身内置了动态 maps 和数组。 虽然内存仍然是手动管理的,但看到这样的内置特性并不常见。
这也许奠定了 Odin 的基调:它试图通过提供大量的开箱即用功能,使其符合人体工程学且易于编写。 Odin 还附带了 "vendor",其中包含与各种流行库的绑定。 这使得该语言非常容易上手。
设计理念
Odin 专注于解决现实世界编程挑战的实际解决方案——换句话说,它倾向于实用主义而非理想主义(稍后我将在讨论 Zig 时再回到这一点)。 Odin 专注于编写简单易读、易于推理的代码,而不是引入复杂的功能。 这与 Zig 尽可能地拥抱元编程形成了鲜明对比。
Odin 还有一种相当老式的类型观念。 目前的趋势是使编程语言变得越来越复杂,以便它们可以在语言本身中描述越来越多的类型。 Odin 则回归到内置类型蓬勃发展的旧语言。 因此,Odin 不仅提供上述的 hashmap 和动态数组,还提供诸如复数、向量、矩阵甚至四元数之类的数值类型。 这在很大程度上弥补了它对运算符重载的拒绝。 并非巧合的是,展示 Odin 功能的旗舰应用程序 EmberGen 是一款数学和图形密集型工具。
语法快速浏览
对于初学者来说,Odin 的语法相当简单明了。 事实上,没有过度纠缠可变性或常量性,这使得事情可以按预期工作。
声明在其他方面深受 Jai 的启发,并且非常简洁。 Odin 对现代潮流的让步体现在它删除了传统的 ;
。
Odin 生成的代码任何习惯 C 或其他低级语言的人都可以一目了然地阅读。 这是一个使用 Raylib 的简短的“在屏幕上移动点”的示例:
package test
import rl "vendor:raylib"
main :: proc()
{
rl.InitWindow(1280, 720, "Testing")
pos : rl.Vector2 = { 640, 320 }
for !rl.WindowShouldClose() {
rl.BeginDrawing()
rl.ClearBackground(rl.BLUE)
rl.DrawRectangleV(pos, {32, 32}, rl.GREEN)
if rl.IsKeyDown(.LEFT) {
pos.x -= 400 * rl.GetFrameTime()
}
if rl.IsKeyDown(.RIGHT) {
pos.x += 400 * rl.GetFrameTime()
}
if rl.IsKeyDown(.UP) {
pos.y -= 400 * rl.GetFrameTime()
}
if rl.IsKeyDown(.DOWN) {
pos.y += 400 * rl.GetFrameTime()
}
rl.EndDrawing()
}
rl.CloseWindow()
}
总而言之,即使函数声明语法等有所改变,Odin 的语法也大多感觉很熟悉。 没有深奥的怪癖; 这些变化是表面的。
Odin 的这种保守倾向也得到了其他人的呼应。 JangaFX 的 Dale Weiler 是早期采用者。 他在他的博客上写道:
总而言之,Odin 的语法大多感觉很熟悉,即使函数声明语法等有所改变。 没有深奥的怪癖,这些变化是表面的。
“Odin 是一种系统编程语言,它的设计比 Rust、Zig 和 Carbon 等其他较新的编程语言更保守。 Odin 的设计理念是提供一些急需的质量改进,以替代系统语言的通用语言:C,同时仍然像 C 一样简单。” link
很明显,即使语法与 C 大相径庭,Odin 也能给人一种熟悉的感觉。
错误处理
Odin 最具争议的选择可能是错误处理,它以 Go 的方式使用多个返回值。 虽然 Odin 通过 or_else
和 or_return
提供了更好的工程效率,但与其他解决方案相比,它可能会让人觉得笨拙。
就第一印象而言,这种选择可能并不理想。 这似乎是一个常见的批评点。 另一方面,这种概念上的简单性与 Odin 设计的直接性密不可分。
编程的乐趣
Odin 与 Jai 共享“编程的乐趣”的口号,但这种欣赏似乎是真实的。 引用一位用户的话:
“Odin 重新燃起了我编程的乐趣。 内置的边界检查、切片、独特的类型、没有未定义的行为、优化模式之间一致的语义、最小的隐式类型转换、上下文系统和标准库跟踪分配器结合在一起,消除了我在 C/C++ 中发现的大部分内存错误,我可以使用消毒剂来解决这些错误。” link
另一位用户写道:
“[…] 从 C 迁移到 Odin 是一个非常愉快且相当容易的体验。 这些语言非常相似,但 Odin 消除了痛苦的部分,让你专注于问题,而不是想知道为什么事情再次变得奇怪。” link
只需试用一下该语言,它就很友好,并且可以按照你的想法执行操作。 它本质上是一种平易近人的语言,用起来感觉很棒。
比较
Jai
Odin 和 Jai 在语法上相似,但它们的方法不同。 Jai 强调编译时执行和元编程,提供强大的抽象,而 Odin 则专注于简单性和大量的开箱即用功能。
虽然 Odin 在语法层面上显然受到了 Jai 的启发,但两种语言的发展却截然不同。 Jonathan Blow 在一段视频中表示,Jai 已经变得比他计划的更复杂。
另一方面,Odin 显然是一种学习和使用起来都很简单的语言。
Zig
Odin 和 Zig 都旨在实现系统编程的现代化,但它们的理念显然不同。 Zig 提供广泛的编译时元编程(尽管没有达到 Jai 的水平),而 Odin 仅保留条件编译所需的必要功能。
像 Jai 一样,Odin 具有运行时反射。 另一方面,Zig 的反射通常仅限于编译时。 在实践中,这意味着 Zig 依赖大量的元编程来通过类型检查进行序列化等操作,而在 Odin 中,它在运行时可用,因此代码更容易理解。
最大的区别在于它对程序员体验的态度。 Odin 试图简单化,使其编程变得有趣和愉快; 它具有简单明了、不拘一格的语法。
另一方面,Zig 很少关心用户体验,并且更喜欢冗长的显式性而不是方便的抽象。
一位开发者对两者进行了比较:
“Zig 非常冗长…… 相比之下,Odin 在打字方面非常简洁,同时基本上可以传达相同的信息。” link
批评
虽然 Odin 已经在项目中使用了很长时间,但官方文档仍然缺乏深度和示例。 最重要的是,主要的社区平台似乎是 Discord,并非所有人都可以访问。
有人批评缺少更广泛的元编程。 但是,由于可以在运行时访问类型信息以及相当广泛的内置函数,因此尚不清楚这是否有任何价值。
例如,Zig 和 Jai 都通过元编程提供对 struct-of-arrays 的支持。 但是,在 Odin 中,此功能已内置到该语言中。
结论
对于寻求现代、高效且可读的系统编程语言的开发人员来说,Odin 是一个引人注目的选择。 它在 EmberGen 等图形密集型应用程序中的成功证明了它的鲁棒性和性能。 虽然它在某些方面还有增长空间——尤其是在文档和社区可访问性方面——但 Odin 的务实设计和对开发人员体验的关注使其成为当代系统编程中 C 的一个值得关注的替代品。