汤姆的命名空间:一篇 Odin 同人小说

Lobsters Hottest 工具

摘要

一篇叙事风格的技术文章,探讨 Odin 编程语言中的代码组织方式,着重指出其包系统特点、缺乏包级局部命名空间的现状,以及由此引发的开发者工作流挑战。

<p><a href="https://lobste.rs/s/sumyip/tom_s_namespaces_odin_fanfic">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/05/11 17:09

# Tom 的命名空间:一篇 Odin 同人小说 来源:https://zylinski.se/posts/toms-namespaces/ Tom 喜欢做游戏。他当过职业游戏开发者,但业余时间也喜欢自己做游戏,当成一种爱好。他做的这些业余游戏走的是“从零开始”的路子,也就是说,他只有一个`main`过程,导入一些库,然后按需构建。 最近,Tom 发现了一门叫*Odin*(https://odin-lang.org/)的编程语言。他发现这门语言修复了许多他对 C++ 和 C 不满的地方。他觉得用这门语言做游戏开发应该会很有意思。 很快,他就开始做自己的第一个小游戏了。最初他用 SDL 做了一些实验,但现在已经决定使用 Raylib。Raylib 是一个处理窗口、渲染、输入和音频的库,做游戏需要的东西它都有! 折腾了一段时间后,他写出了一个巨大的文件,叫`world.odin`。里面有一大堆过程!其中一个的签名是这样的: ``` world_add :: proc(w: ^World, e: Entity) ``` 他觉得有必要整理一下,或许可以把所有“世界相关的东西”放进它们自己的一个小隔间里。毕竟,Odin 语言可是相当现代的!Tom 了解到,有一种叫“包”的东西,可以让程序员用优雅的方式把东西拆分开。 他了解到,一个包就是一个子文件夹。于是 Tom 把`world.odin`移到了名为`world`的子文件夹里。他的游戏现在有了如下的文件夹结构: 在`game`包内部,他就可以这样导入`world`包里的东西: ``` import "world" ``` 从这个导入的`world`包里引入的东西,会被放到一个叫`world`的命名空间里。要使用里面的任何东西,你得写成`world.some_procedure_in_the_world_package()`。所以,为了调用`world_add`,Tom 必须写成`world.world_add`。这太傻了,于是他自然就去掉了`world_`前缀,过程就变成了: ``` add :: proc(w: ^World, e: Entity) ``` 这样他就可以优雅地写成`world.add(some_world, some_entity)`了。但在走到这一步之前,他突然想到:“哦不!那个`Entity`类型可是放在主 game 包里的啊!”……于是 Tom 试着让`world`包导入`game`包,像这样: ``` import game ".." ``` 然后他又喊了一声“哦不!”。编译错误!错误提示说 Odin 不允许循环包导入。`game`正在导入`world`,而`world`又在导入`game`。 然后他又想,也许他需要创建一个`entity`包,让`world`和`game`都可以导入,或者建一个`common`包来放“常用类型”。天啊,这开始变得有点麻烦了! Tom 随后登上 Odin 的 Discord 服务器,发起了一场关于这些东西到底该如何组织的讨论。他被告知,包并*不*是用于细粒度组织的:最好把它们看作独立的库,或程序中完全独立的部分。 有了这个认识,Tom 试着把一切都搬回`game`包里。他好像确实把事情弄复杂了一点。他轻轻拍拍笔记本电脑,对自己说:“对!保持简单!我就在`game`包内部找别的方法来做命名空间好了。” 哦不! Tom 四处看了看,又在 Odin Discord 上提问。他很快就得出了一个结论:在 Odin 中,除了导入包时产生的命名空间之外,没有其他命名空间特性。他没办法做出一个只存在于包内部的“包本地”命名空间。 Tom 很恼火,心想:其他语言就有这个特性啊!看看 C++,你可以写这样的东西: ``` namespace world { void add(World *w, const Entity *e) { } } ``` 为什么 Odin 里就不能有呢?哈!我自己 fork 一个 Odin 编译器,把它加上去不就行了! 于是 Tom 开始草拟对 Odin 编译器的一些修改,以支持包本地命名空间。 还没等他走多远,一封邮件来了:他接到了一份合同工作!这真是个好消息。钱快用完了。这份合同是去帮忙做一些 C++ 游戏引擎编程。工作要持续几周,于是他暂时搁置了 Odin 的实验。 Tom 已经很久没用过 C++ 了。在这个大型 C++ 游戏引擎项目里干活时,他已经开始怀念 Odin 里的许多好特性了。 但至少他能用上漂亮的 C++ 命名空间了吧!这个 C++ 代码库里甚至在一个叫`world`的命名空间里就有一个`add`函数! 当他在代码库的另一部分工作时,确实需要查看`world`命名空间里`add`函数的实现。于是他打开“查找符号”窗口,输入`add`。回车。他得到了 23 个匹配结果,要找到他需要的那一个可不太容易。 天啊,这个代码库真是太大了。而且里面还有好多命名空间!有很多函数名在许多不同的命名空间里被重复使用。Tom 发现要搜索命名空间里的函数实在太难了,以至于他忽然发现自己竟然在想:要是能直接输入类似`world_add`这样的东西就好了。 他和同事 Bob 聊起这件事。Tom 说这样导航有点烦人。Bob 说可能是 Tom 的编辑器不够好。一个好的编辑器应该能显示命名空间,并且允许你使用命名空间和函数名进行模糊搜索。“这是个工具问题!”Bob 说。 “可惜我试过的大多数工具都没解决这个问题呢……”Tom 回答道。 合同结束后,Tom 又回到了他的 Odin 业余项目上。他不再去想如何给 Odin 添加包本地命名空间了。他已经不想要这个东西了。在他简单的编辑器里,他可以很快地找到`world_add`。 --- Tom 其实就是我,Karl Zylinski。我经历了一段类似的命名空间哲学思考期,而且时间跨度更长。 我之所以曾经认为 C++ 命名空间很好,是因为我大部分时间都在小型 C++ 项目里工作。当项目变大时,它们基本上就变得很烦人了。在一个大项目里,你必须确保东西很容易找到。而最容易找到东西的方法,就是保证名字简单。这里“简单”并不意味着“短”,而是指这个名字没有歧义。 Tom 的同事 Bob 说这些都是工具问题。Tom 的回答“可惜我试过的大多数工具都没解决这个问题……”很重要:我试过的大多数工具确实并*没有*解决这些问题。在那个 C++ 项目里,我也看到其他人在代码库的导航上犯难。 这里还有一点需要考虑:如果你的代码库需要大量花哨的工具才能探索,那或许你的代码库可读性并不好。我想说,如果你的代码在最简单的源代码编辑器里都无法导航,那你就有问题了。你不能假定所有人都和你用一样的工具。 > 也许在一家大公司里,你可以让每个人在开发产品时都用同样的工具。不过,不管公司怎么想,人们往往还是会开始用自己个人最喜欢的文本编辑器。 这种通用过程名被大量复用的问题,其实在 Odin 的`core`集合里也存在。在`core`的很多包里,有很多常用的过程名。例如,过程名`init`在所有核心包里被重复使用了`40`次!使用符号搜索时,有时候找到正确的那一个会有点麻烦。自从我不再纠结包本地命名空间之后,我甚至有时候会想,或许 C 语言的方式是对的:或许在过程名上加上前缀是好的,从而不再需要导入处的命名空间。那样的话,Odin 的整个包系统就无效了。不过,我认为这里是可以找到一个折中方案的。这个问题必须和另一个事实权衡考虑:Odin 的导入处命名空间避免了名字冲突,因为你总可以给导入的包起个别名。这样一来,在设计库的时候,你就不用担心名字冲突了。 需要注意的是,一个库拥有自己的命名空间,与在程序内部使用命名空间来组织代码,是不同的问题领域。库的命名空间解决了一个特定问题:当别人把你的库和另一个库一起使用时,不会发生命名冲突。这证明了在该场景下使用命名空间是合理的。而在程序内部,代码是整体的,冲突因此也很容易解决。所以,在那个场景下,命名空间的这个特定用例就不相关了。相反,我们最终只会让代码更难导航。这就是我们必须考虑的那种取舍。有趣的是,要看清这些事情,有时需要花很长的时间。 通过阅读我的书*理解 Odin 编程语言*(https://odinbook.com/),了解更多关于 Odin 的知识。 /Karl Zylinski

相似文章

理解Odin编程语言

Hacker News Top

一本教授Odin编程语言的书,涵盖手动内存管理、参数多态和数据导向设计。1.10版本已发布并包含更新。

Odin 的新内联汇编模板

Lobsters Hottest

本文详细介绍了 Odin 编程语言的新内联汇编模板,其通用语法灵感来自 Go 的汇编器,并支持 amd64 目标架构。

Odin dev-2026-06 发布

Lobsters Hottest

Odin dev-2026-06 已发布。Odin 是一种面向数据的编程语言,专为高性能系统开发而设计。

一个简单的Odin Web框架

Lobsters Hottest

Gjallarhorn是一个从头为Odin编程语言构建的Web框架,提供HTTP服务器、路由、中间件、模板引擎以及支持PostgreSQL的ORM,且无需任何外部依赖。

Odin、Wikipedia 与互动诱导

Hacker News Top

本文探讨了 Odin 编程语言的 Wikipedia 页面通过文章删除讨论流程被删除一事,以及随后围绕关注度、可靠来源以及语言创建者被指控进行互动诱导的争议。