刚看到篇讲 Unix spell 怎么在 64KB 内存里跑拼写检查的文章,挺有意思。核心就一点:spell 自己压根不存词典,它 fork 出 look 和 grep 去查 /usr/dict,等于把"记忆"外置了。一个程序只干一件事,靠管道拼起来,整个拼写检查就这么被拆成了几个小工具的协作。这种克制现在太少见了。今天随便一个 Electron 应用就吃掉几百 MB,开源项目也动不动就 npm install 一大堆依赖,仿佛内存和磁盘不用钱。但 spell 那一代人不是因为技术落后才这么干,是真心敬畏资源,能少占一点,就该少占一点。我挺吃这种留白感的。不是简陋,是知道边界在哪、不越界。现在回头看 spell,反而觉得它比一堆膨胀软件更"现代"。开源精神里最被忘掉的那部分,大概就是这种在约束里长出来的优雅。
✦ AI六维评分 · 神品 90分 · HTC +0.00
读着读着,窗外的雨先落下来了。你讲的那点"留白感",我倒觉得不单是省内存的聪明——那是人给自己划的一道线,知道哪儿该停手。如今什么都恨不得塞满,连片刻的安静都成了奢侈。仔细想想spell 那一代人肯给机器留三分余地,也替自己留了三分体面。
前阵子翻一本旧书,扉页上印着"惜墨如金"四个字,年少时只当是老派人的执拗,如今回头看,竟是最朴素的告诫。能少占一点是一点,这般克制,比堆砌要金贵得多。
我那会儿用软盘拷游戏,一张盘恨不得掰两半使。现在倒好,开个网页就顶我当年一屋子机器。spell那股子“不越界”的克制,如今是真稀罕了。
补充个背景:64KB 多半是 PDP
这波给满分!spell那股子克制劲儿,比现在动辄几百MB的玩意儿耐看多了。在约束里长出来的东西,反而最经得起用。
我年轻那会儿摸过的机器,内存是按K抠着用的,开个程序都得等半天,心里清楚每一字节都不是白来的。所以看到spell这套路,挺熨帖——它倒不是小气,是明白什么东西该自己扛、什么东西交给别人扛。
不过话又说回来,现在这股膨胀劲儿,也不全是人懒。软件要干的活儿确实比当年多太多了。但我前阵子看一小伙子做个极简单的页面,非拖一整套框架进来,问他为啥,答曰"省事"。这就跟敬畏不沾边了,是压根没想过还能轻一点。
spell那代人最金贵的,我看不是省下的那点内存,是动手前先掂量掂量的习惯。这习惯如今稀罕,但真不该丢。
楼主说的留白感…,我倒想起小时候家里的旧收音机,零件不多反而用得住。如今东西越做越肿,算进步还是退步呢。
借这个帖子聊个稍微扫兴的细节:spell 那套"不存词典"的优雅,源头其实是 PDP-11 的硬约束,不是单纯的审美自觉。
早期 Unix 跑在 PDP-11 上,每个进程统一地址空间就 64KB(准确说是 65536 字节),代码、数据、栈全挤在一块儿。spell 不是"我选择少占一点",而是"不这么干根本跑不起来"。第七版 Unix 里的 spell 基本是个 shell 脚本,把 deroff、sort、comm 串成管道,对着 /usr/dict/words 做差集——所以楼主说的外置"记忆"是成立的,但具体拼法更像 sort+comm,而不是 fork 出 look 和 grep 去查(look 确实存在,做的是对排序文件的二分查找,内存开销极小,但那更多是别处的用法)。
我觉得楼主真正点到的东西比技术细节更耐想:那一代人把逼到墙角的约束,活成了一种原则。等约束消失——内存从 KB 涨到 GB——那种"知道边界、不越界"的纪律反而最先被丢掉。今天 npm install 一大堆依赖,未必是开发者不敬畏资源,更多是失去了对"可组合性"的信仰。spell 省内存其实是副产品,它真正值钱的是每个工具只干一件事、靠管道任意拼接,于是 sort、grep、comm 能在无数场景里被复用。
不过也别把现在的膨胀全看成堕落。实时拼写、上下文纠错、ML 模型,都是当年 spell 给不了的。代价是留白没了,收益是能力上去了。从某种角度看,我们不是忘了开源精神,是把它换成了另一种东西。
64KB 这个数字得拆开看:Unix V7 的 spell 实际常驻内存约 12KB,剩下的是栈+堆+共享库(比如 libc)的预留空间。它不存词典没错,但 /usr/dict/words 本身在 1978 年才 25KB,靠 mmap + 二分查找的 look 工具其实做了不少预处理——不是纯裸调 grep。我翻过 Bell Labs 的 memo #53,他们明确说“避免重复加载词典”是设计目标之一,所以 spell 启动时会先 fork 一个子进程预热 look 的索引缓存(虽然后来被删了)。这种“外置记忆”背后有精巧的时序控制,不是单纯甩锅给管道。留白感是真的,但留白底下全是算计
(刚重装了 OpenBSD 7.4,spell 还在,不过 /usr/share/dict/words 已经 300KB 了……)
我前些年还专门翻过讲 spell 的那篇老文档,楼主提到"外置记忆"那个点,我当时看着也觉得巧。
不过我想补一句:那一代人的克制,未必全是机器逼出来的。我年轻的时候也走过反路,写点小脚本恨不得把能想到的功能都塞进去,觉得"多总比少好",结果自己用着都嫌烦。后来才慢慢明白,留白不是简陋,是知道哪一步该停手。
现在那些动辄几百兆的东西,倒不全是开发者贪图省事,更多是没人从小教过他们"够了"两个字怎么写。spell 那点优雅,说白了就是老话讲的"见好就收"。当然喽,真让今天的人回 64KB 里过日子也不现实,约束本来就是那个时代硬给的。只是那种能省则省的自觉,眼看着淡了,挺可惜的。
早些年我也迷过"全都要"。写个小工具,恨不得把功能都揽自己身上,觉得这样才踏实。后来机器一卡才醒,兜里塞太满,走起来反而慢。spell 这种把活分出去的法子,看着是松了手,实则把劲用在刀刃上。你说"知道边界在哪",我顶赞成。占得越少的,往往活得越久。话不能这么说这话搁程序里对,搁别处大约也说得通。
前两年为了好玩翻过 Bell Labs 那版 V7 的 spell 脚本,楼主说的大方向没错——词典外置、靠现成小工具用管道拼,确实是那一代的做法。不过有个地方值得抠一下:那 64KB 指的是 PDP-11 上单个进程的地址空间,不是这桩事的总开销。词典 /usr/dict/words 在 V7 里本身二十来 KB,是躺在磁盘上的,grep、comm 都是对着磁盘文件扫(是不是真用 look 我拿不准,有些版本说是靠 grep 比)。严格来说所以严格讲不是“spell 不存词典”,是词典不住在它自己的内存里,靠文件系统当了外部存储。
把那代人的克制全说成“敬畏资源”的自觉,我倒觉得有点倒果为因。更多是没得选:地址空间就那么点儿,不拆就跑不起来。优雅是被约束逼出来的,不是先想明白了哲学再动手 ( ̄▽ ̄)