技术语境中那些熟悉又陌生的英语动词

Dec. 25, 2025

不管是阅读计算机领域的英文内容,还是使用英文界面软件时,你可能都会见到很多生词。其中,有的词本身就长得张牙舞爪,或者在日常语境下用得很少,因此一眼就知道是个技术术语。

但又有这样一些眼熟又陌生的单词——尤以动词居多——它们本身并不生僻,很多甚至都是中小学阶段的基础单词;但第一次在技术语境下看到时,还是容易稍感意外,并在了解含义后产生「原来还可以用在这里」的感觉。了解这些词的含义和用法,能让阅读和使用更加顺畅;如果自己在工作或沟通中要表达相应含义,也可以借此让表达更加简洁、精准和生动(多用动词也是一个常被鼓励的写作优化技巧)。当然,即使没有这样的需求,知道点稀奇古怪的事情本身也挺有意思的。

接下来介绍的就是一些曾经让我产生过这种意外的动词。显然,这只能是一个不完全列举,并且筛选标准完全是个人的,因此欢迎补充指正。

>> abort

在计算机语境中,「终止」中大概有一百种不同说法,但 abort 肯定属于你特别不想看到的那种,一般特指在操作出现重大错误或故障的情况下,由程序自动、强制终止执行操作,并且跳过正常的收尾流程。因此,称一项操作为 abort,一般也暗示着可能造成一些不可逆的影响,或者至少事后需要通过额外步骤来「收拾残局」。

abort 作为一项操作的词源主要可以追溯到 C 语言标准库,其中的 abort() 函数就是用于执行异常强制退出的功能。当程序调用 abort() 时,系统会向程序发出信号 SIGABRT 强制其退出,并且不会执行原本应在退出时执行的其他操作。因此,它不同于通过按 Ctrl-C 造成的中断(interrupt,对应 SIGINT 信号),因为程序那时一般还有机会完成收尾;也不同于用 kill 命令导致的终止(terminate,对应 SIGKILL 信号),因为那是用户手动干预,而非程序自行要求终止。

abort 最出名的出镜场合大概是在 DOS 系统中。当时,系统找不到软盘、软驱仓门打开、软盘校验错误都被定义为所谓「严重错误」,命令行此时会显示一句灵魂拷问 Abort, Retry, Fail? 其中,Retry 的意思不言自明,Abort 和 Fail 的差异则在于,Fail 会给被终止的程序传回一个错误代码,程序可以据此决定是否以及如何做一些补救措施(例如要求用户换一个文件路径),而 Abort 是直接终止而不做任何通知。

显然,从用户交互设计的角度看,这种提示语只能得零分,因为普通人根本不可能轻易明白这句提示的含义,只会造成不必要的恐慌——毕竟在日常语境中,更为人所知的可能是这个词的名词形态 abortion,用来类比电脑故障无论如何太重了一点。更何况,abort 定义中的所谓「严重错误」是从程序自身的视角来看的,但不同程序的地位不同,其出错的实际后果可轻可重。如果 abort 的是一次复杂的系统升级(例如在 do-release-upgrade 期间),那么确实可能给你留下一个半残废的系统;相反,如果 abort 的只是一次 GCC 的编译流程,那么无非是清理目录、调试一下环境再来而已。

可能正是因为这些问题,abort 目前已经很少在面向最终用户的界面上看到了,而一般只出现在——也只应该出现在——编程调试、系统维护等场合。如果你某天在某次折腾中看到这个词,不要恐慌,一切还没有结束。

例句:

  • The installation hung for five minutes, so I had no choice but to abort the setup. [安装过程停滞了五分钟,我没得选,只能终止安装。]
  • If the pre-deployment checks fail, abort and generate a core dump for analysis. [如果部署前检查未通过,终止部署,生成核心转储以便分析。]

>> bin

在生产制造中,根据产品质量分级销售是非常常见的做法。传统上,这种分类是通过在质检阶段将产品放进不同的箱子(bin)里来实现的。由此,bin 就从「分箱」引申出「产品分档」的含义。

而在计算机行业中,把分档玩得最花的当然就是芯片厂商了。芯片生产是一项细活,也是运气活。受良率限制,即使同一片晶圆上切出来的芯片,也体质可能各不相同。因此,一种常见的做法就是将体质相对较差的芯片降低频率或屏蔽核心,然后作为低端产品销售;这个分类的行为就称为 bin。例如,早在 80 年代,英特尔就开始对当时的 80286 系列处理器做 binning,Reddit 上还能找到用马克笔标记着 Bin 3, 6 MHz 等字样的老产品照片。随着时间推移,binning 更成为一种产品线布局的必要策略。

binning 的过程伴随着很多随机性。有些时候,即使芯片本身的体质足以胜任更高端的定位,也会被厂商施加人为限制后用于底端产品。当这种情况在某些产品或某些批次中集中出现时,就会造就了一些所谓的「超频神 U」或「开核神卡」——例如能开四核的 AMD Phenom II、能刷成 Radeon HD 6970 的 6950 等等。

bin 的另一个含义则与摄影有关,是指将感官元件上的相邻像素合并为一个像素使用,从而变相提高画质。这大概也是借用了 bin 的本意「分装进箱子」,只不过是将多个像素封装在一起。如今,提 binning 最多的是手机厂商——往往冠以「超级像素」「超分辨率」之类的营销名称,但其实 binning 在几十年前就用于天文等领域专业摄影了。例如,美国太平洋天文学会会刊在 1987 年描述了一种天文相机,介绍称它支持 2×2 和 4×4 两种像素合并模式(尽管不是为了提高画质,而是为了让画面能放入有限的内存)。

例句:

  • The M1 Pro on the low-end 14-inch MacBook Pro is a binned version of the standard configuration.(低配 14 寸 MacBook Pro 上的 M1 Pro 是标准型号的屏蔽核心版本。)
  • To enable color cameras to pixel bin more effectively, camera sensor manufacturers have rearranged the entire grid of filters into a pattern called a quad-Bayer array.(为了让彩色相机更有效地合并像素,传感器厂商将整个滤镜网格重新排列为称作四拜尔阵列的样式。)

>> bump

如果经常逛 GitHub 的话,你会在很多软件的更新日志里看到 bump 这个词。虽然这个单音节词听起来有些活泼,但它显然不是指什么暴力举动,而是指提升版本号——可能是软件自身的版本号,也可能是其依赖的第三方组件版本号。不同于 upgrade,bump 对应的版本更新一般是小幅的,对于 X.Y.Z 式的语义化版本号,一般是指 Y(次版本号)和 Z(修订号)的提升。更宽泛地,bump 这个词也经常见于 bump the counter 这个固定组合中,指将计数器的值增加 1。

bump 为什么会被引申出「增量」的含义呢?一种说法认为这是来自机械计数器,它需要通过快速推动其附着的横杆(其后会弹回原位)来使得计数增加一次。这样的机械结构后来也出现在早期计算机中,bump 也就作为一种惯用表达沿用下来。在许多上世纪的大型机使用手册、汇编语言指南里,就已经可以见到 bump the counter 的说法。

作为一个术语,bump 说起来可谓简洁而有趣,但对于外行人确实有些理解门槛。实际上,开源项目常用于管理依赖项的工具 Dependabot 就收到过一条建议,要求减少在界面中使用 bump,而换成更好懂的 update。维护者很友好地接受了大部分建议,但决定还是在自动生成的合并请求标题里保留它。

例句:

  • Bump the API minor version from 2.0 to 2.1. [将 API 小版本号从 2.0 提升到 2.1。]
  • Bump some_dependency to 4.17.21 to resolve CVE-XXXX-YYYY. [将依赖项 some_dependency 版本提升到 4.17.21 以解决编号为 CVE-XXXX-YYYY 的漏洞。]

>> complain

用电脑是一件很容易生气的事。操作卡顿会生气,软件有 bug 会生气,游戏掉帧也会生气。但别忘了电脑也有脾气。当你试图要求程序接受它不喜欢的东西——不符合规范的值、格式错误的配置文件、已经弃用的语法,它会做的一件事就是「抱怨」(complain),也就是报错并显示诊断信息。

你经常可以在编译器(compiler)、代码检查器(linter)的语境下看到 complain 这个词。与人类相比,程序即使在抱怨的时候也是冷静(冷漠?)和有逻辑的,一般都会指出有问题的具体位置,以及说明实际情况和预期情况的差异。从程度上说,被 complain 的事情一般不是特别重大,很多时候是因为粗心大意导致的,在目前阶段还没有导致什么后果。

例如,如果你在写 C 代码的时候括号没有配平,那么 Clang 会抱怨:

error: expected ')' before ';' token
   (f = sqrt(pow(x, 3) - (2 * x));
                                 ^

如果你在终端脚本里引用变量的时候没有加引号,ShellCheck 会抱怨:

script.sh:3:5: SC2086: Double quote to prevent globbing and word splitting

对于 HTTP API 而言,传统上有一系列状态码来表示固定类型的客户端(4xx)或服务端(5xx)错误,因此技术社区中不时也能看到 [some website] complains 502 bad gateway 之类的说法。不过,状态码很多时候还是过于宽泛,因此一些尚处提议阶段的 RFC 主张统一要求 API 通过返回一个 JSON 来表达标准化的「抱怨」内容,例如说明一次 400 错误实际上是因为账户余额不足。

例句:

  • The compiler will complain if you try to assign a string to an integer variable. [如果你把字符串赋给整数型变量,编译器就会报错。]
  • The linter is complaining about the use of tabs instead of spaces. [检查器提示缩进用的是制表符而不是空格。]

>> drop

提到 drop,你一般可能觉得这是一个不怎么需要动脑子的动作,或者说,就是因为大脑不在线,才会把手上的东西给 drop 了。但在计算机语境下,drop 的决定还是需要经过一些思考和决策的。

这个词最常见的语境之一是管理资料库的 SQL 语法:DROP 是指永久删除整个数据结构,例如一个表、一个视图或者整个数据库。相比之下,DELETE 只是删除表中的数据,但仍然会保留一个空表。DROP 的「核平」能力导致它在正常操作中用的不多,但很受注入攻击者的青睐。如果一个在线数据库的安全配置不到位,就可能把用户恶意输入的 DROP 字样当成命令,导致「自爆」。

这方面的一个经典笑话是,2016 年有好事者模仿 XKCD 漫画里的馊主意,在英国注册了一家名叫 ; DROP TABLE "COMPANIES";-- LTD 的公司,而且竟然通过了。结果,英国议会后来专门通过立法,规定公司不得采用是国务大臣认为属于或包含程序代码的名称,而这家公司的名字也被「打码」成了 [NAME AVAILABLE ON REQUEST FROM COMPANIES HOUSE],致信询问才展示。(似乎没有报道表明有计算机或动物因为这个恶作剧受到伤害。)

另一个经常使用 drop 的语境是网络传输。在 iptables 等防火墙软件的规则中,DROP 是指直接「丢弃」匹配规则的数据包,不作任何处理、转发,也不向发送方报错。相比之下,REJECT 虽然也不处理数据包,但会返回一个「拒绝连接」的错误提示。对于安全防护规则而言,DROP 一般是更好的选择,因为客户端必须要等到超时才能确认连接失败,也不知道原因,从而可以拖慢攻击速度。(大部分本文读者可以通过访问谷歌体验到个中奥妙。)

作为上述数据库和网络场景中含义的引申,许多「删除」「丢弃」「断开」「放弃」之类的含义,也可以用 drop 来表示,例如你可以 drop commit(提交)、event(事件)、connection(连接)、privilege(权限)等等。此外,有时 drop 也可以作为 release 的时髦说法,表示发布一批功能(Pixel 用户请举手)。当然,也别忘了一个古老的交互手势 drag and drop。

例句:

  • Once the migration is complete, we can safely drop the legacy users table. [迁移完成后,就可以安全地删除旧的 users 表。]
  • Under heavy load, the router starts dropping low-priority packets to keep latency under control. [在高负载下,路由器会开始丢弃低优先级数据包,以便控制延迟。]

>> feed

feed 这个词的含义随着文明发展一直在不断扩充。从最开始的「给予食物」,到给火「添柴」,再到向机器「输送」原料。而在信息时代,它也把物理世界的隐喻搬到了数字世界,自然地继续获得了「输入信息或数据」的含义。

具体来说,在技术语境里,feed 一般是指把某些原料送入一个会消费它的过程或系统,经常出现在流、队列、批处理等场景中。而与其他表示「输入」的词相比,feed 通常暗示了一种持续(或增量)的、消耗性的过程。例如,你可以说向状态监控系统 feed 系统日志,向训练中的大语言模型 feed 数据集,向批处理队列 feed 消息,向用户的时间轴 feed 内容;但一般不会说向一个函数 feed 参数(最好用 pass 或者 supply),将甲命令的输出 feed 给乙命令(最好用 pipe),或者将程序数据 feed 给内存(最好用 load 或 write)。

此外,feed 还有一个目前已经很难亲眼看到的技术含义:在打字机中,让滚筒进纸一行(并且只进一行)的操作称为 line feed。与另一个操作「回车」(carriage return,将字车从行尾推回行首位置)结合,就是一次物理意义上的「换行」。如今,这两个操作被做成了控制字符 U+000A 和 U+000D,继续在数字文件中将文本推向下一行。

例句:

  • We need to feed the training data into the neural network in small batches to avoid running out of memory. [我们需要将训练数据分成小批次输入神经网络,以避免内存耗尽。]
  • Before you can start feeding events to Kafka, you have to enable data collection and create event streams. [必须启用数据收集并创建事件流,才能将事件输入给 Kafka 处理。]

>> hydrate

纣王在石台上站起身,张开双臂,仿佛要拥抱整个世界,他用一种很奇怪的歌唱般的音调喊道:「浸泡——」[…] 那些皮卷一遇到水,[…] 很快具有了生命的迹象,一个个挣扎着从齐腰深的湖水中站立起来。[…] 整个世界在复活。

这是《三体》中的一个名场面。随着三体世界进入三个太阳稳定运行、适宜生存的「恒纪元」,人们开始将同类从「脱水」状态恢复出来,而恢复的方式就是扔到水里「浸泡」。在计算机语境中,hydrate 也被用来表达这样一种将代码或数据从骨架「复苏」为更活跃、更完整状态的过程。与 initialize(初始化)、deserialize(反序列化)等相比,用 hydrate 描述一个恢复过程,往往暗示它并不是「从零开始」的,并且最终产物是一个更具实际功能的状态。

目前,这个词在前端开发的语境下最为常见。其背景是,如今很多网站采用所谓的「服务器端渲染」(server-side rendering)技术,在服务器端首先渲染好网页的外观骨架,传送给客户端后,再由客户端载入 JavaScript 代码,为这个骨架赋予实际交互功能。对于日渐庞大、复杂、动态的网页应用来说,这么做有助于加快加载速度(因为服务器承担了很大部分的渲染工作)、便于搜索引擎(因为爬虫可以直接看到最终网页的外观)。而所谓 hydrate,就是指这个将服务器渲染的、只能看不能「动」的骨架,转化为可交互的最终页面。(前端框架 React 中,用于将 React 组件连接到服务端传送 HTML 的函数就叫做 hydrateRoot。)

hydrate 也可以用于更宽泛的语境。根据 StackOverflow 上一个接受度较高的解释,所谓 hydrate,就是向一个对象中填充(来自数据库、网络或文件系统)的真实数据。因此,在 Redis 中,hydrate 可以指根据会话 ID 提取完整会话内容;在 Twitter/X API 中,hydrate 可以指将服务器分别传输的推文数据与其附属的用户信息和图片附件拼合,得到完整的推文内容;在 Kubernetes 中,hydrate 可以指将包含变量和占位符的 YAML 配置转换为填写完整、实际可用的版本;等等。

尽管 hydrate 是一个非常生动的说法,但要翻译成中文却不是特别容易。事实上,ReactVue 的中文文档翻译项目都讨论过这个问题,最后达成的共识似乎是把「水」藏到偏旁里——「激活」。(尽管在许多中文技术文章仍然使用直译的「水合」。)而在上述其他非前端语境中,可能根据实际技术含义翻译成「填充」「转换」等比较合适。

例句:

  • If your app’s HTML was generated by react-dom/server, you need to hydrate it on the client.(如果应用的 HTML 是由 react-dom/server 生成的,则需要在客户端激活。)
  • We permit limited redistribution of hydrated X content via non-automated means.(我们允许以非自动化的方式,对经扩充的 X 帖文内容做有限的再次分发。)

>> journal

在记账时,要保证账目的准确和可信,每笔交易(transaction)必须不可分割、前后一致、互不干扰,并且持久不变。为此,在复式记账中,有一项称为「日记账」(journal entries)的流程。这是指在将账目计入总账之前,按时间顺序记录交易,以供后续处理、查证以至纠错。

在计算机中,涉及数据库、文件系统等场景的操作——术语称为「事务」,同样对应英文 transaction——也需要遵循相同的 ACID 原则。为此,这类场景也常常包含 journal(事务日志)的步骤,也就是在执行一项事务之前或过程中,将操作记录追加到一个通常只会增加、不会删改的列表中,以便日后出现问题时调用。

journal 可以看作是更广义术语 log 的一种类型。当我们单独说 log 时,一般指的是为监测和分析而设计的应用或系统日志,它通常在操作同时或事后写入。而如上所述,journal 通常在数据操作之前写入,目的是为了保护数据完整性。

你可以经常在各类关系性数据库(PostgresSQL、SQLite 等)中见到 WAL(write-ahead log,预写日志)或 redo log(重做日志)等说法,写入这种日志的过程就称为 journal。尽管在实现机制上有细节差异,其共同点是在对数据库执行任何更改(即修改磁盘上的数据页)之前,必须先将描述这次操作的日志写入持久存储。这样,如果系统发生崩溃,数据库在重启时就能通过检查日志来恢复数据一致性。

许多文件系统也在不同程度上采用了 journal 机制。例如,旧版 macOS(OS X)的文件系统 HFS+ 和 Linux 常用的文件系统 ext4 都默认记录日志,Windows 的文件系统 NTFS 则始终记录日志。不过,文件系统记录的日志大多只包括元信息(metadata),例如文件大小、时间戳、权限、inode(数据在磁盘上的区块位置)等,而不包括变动的数据区块本身,否则对性能的影响就太大了。因此,这种日志并不能保证数据不丢失,而只能保证文件系统的结构正确,例如不存在已经写入数据、而文件系统不知道其存在的数据区块。

不过,journal 也不总是指记录事务日志,有时只是 log 的一种时髦说法。例如,许多 Linux 发行版采用的核心管理组件 systemd 中,用来记录系统状态的日志系统也叫做 journal (systemd-journald),但它在功能上更接近前文提到的宽泛意义上的 log(系统日志),主要用于监测和查询,并不具备数据库意义上的事务回滚和重放功能。

例句:

  • The database engine uses a write-ahead log to journal page modifications before they are flushed to disk. [数据库引擎使用预写日志记录页面修改,然后再写入磁盘。]
  • systemd will journal the unit’s stdout and stderr, so you do not need a separate log file for this service. [systemd记录服务单元的 stdoutstderr,因此你不需要另行使用日志文件。]

>> nuke

有一些时候,你是如此地厌恶某个东西,以至于希望它立刻从地球上消失,而且是彻底的、不可撤销地消失。在非正式英语中,人们有时会用 nuclear 的缩写 nuke 来表达这种「炮决」的含义,例如 I nuked the weeds [我把杂草都扬了]。而来到计算机语境,nuke 也很自然地引申为有意、完全、不可撤销地删除。

比如说,系统被你的手残操作折腾得奄奄一息,那么你可能想做的一件事就是「先炸毁再铺路」(nuke and pave),先抹除全盘数据,再重装系统。又比如,你不小心下了一个流氓软件,在你电脑里横行霸道,那么你会想知道怎么将它「从轨道上击落」(nuke it from orbit,一个来自电影《异形 2》的梗),也就是将它就地正法。当然,除此之外,你还可以 nuke 缓存、数据库、node_modules,等等等等。

还有一个处于灰色地带的社区特别喜欢 nuke 这个词,并为它赋予了不同的含义。在专业从事盗版资源发布的社区(warez scene)——是与你熟悉的那些电报群组和网盘分享站隔了很多层的上游——中,任何资源的发布都要遵循「先来后到」的行规,以及一套严格的文件命名规范(称为 Standards)。例如,一组影视剧集的视频资源,根据 X264/X265 发布组织的要求,必须被命名为:

Multiple.Episode.TV.Show.SXXEXX-EXX[Episode.Part].[Episode.Title].<TAGS>.[LANGUAGE].<RESOLUTION>.<FORMAT>.<x264|x265>-GROUP

如果发布了别人已经抢先发布的内容(称为 dupe),命名不符合 Standards,或者质量有瑕疵,发布帖就会被管理员 nuke,而且会公布示众,要求所有人避开这个发布版本。对于一个从争先发布稀有资源中寻求满足感的群体来说,这显然是一项值得避免的丢脸惩罚。

例句:

  • The workstation was compromised; policy is to nuke and pave, then re-enroll it in MDM. [这台工作站已经被入侵,根据政策,必须抹除重装,然后再重新注册到 MDM。]
  • The first release bad cropping and was nuked. [第一次发布的版本画面裁切不正确,被删帖了。]

>> phone

phone 作动词时,几乎总是和 home 组合,经常在一些非正式的技术讨论中出现。但这并不是你可能以为的那种温馨和睦的「打电话回家」,而一般都不是什么好事。当有人发帖提醒某个软件会 phone home 的时候,意思是它可能不经过你的明确同意就和开发者控制的服务器——它的老家——建立连接。这个说法似乎来自 1982 年的经典电影《E.T. 外星人》。其中流落地球的外星人 E.T. 用玩具、雨伞、咖啡罐和一些电子元件制作了一台设备来「打电话回家」,请求救援。

而在软件的世界中,「打电话回家」没有统一的目的,有些可能相对无害,例如验证密钥、检查更新、发送(合理范围内的)诊断数据;有的则完全是流氓行径,例如上传用户个人信息和隐私信息。但从尊重用户的角度出发,即使是收发无关隐私的数据,也应当征求明确同意、默认关闭或至少提供关闭选项;如果用户不愿意更新版本或者「帮助改进」,就不应该强人所难。

遗憾的是,这似乎越来越成为一个过高的道德要求。现实中,关于 phone home 的指控往往伴随着这样的固定桥段:一个原本有良好口碑(或者至少在隐私方面没有不良纪录)的软件,随着收购或者开发商转向逐利,开始悄悄修改隐私政策、在后台传输越来越多的数据,最终东窗事发,被愤怒的用户揭发和声讨。典型的翻车案例包括但不限于 AudacityCCleaner;当然,还有被微软接管的任何产品。

例句:

  • Many users were concerned about privacy when they discovered the new OS would phone home with their usage analytics by default. [许多用户在发现新系统会默认向服务器上传使用数据后,对隐私表示担心。]
  • The software has to phone home once upon installation to verify that the license key is authentic. [这个软件在安装后需要连接一次服务器,验证注册码的真实性。]

>> rotate

没有人能 7×24 小时工作,再勤奋的牛马也要互相轮班(rotate)。类似地,在计算机中,一些文件和配置也需要不时轮替(rotate),以便保证性能和安全。

例如,日志轮替就是一种常见的轮替形式,指的是在日志文件达到一定时间或大小时,就将其归档(直至一段时间后删除),并将日志写入到一个新文件(app.log, app.log.1, app.log.2, …),从而防止日志无限增长。在 Linux 中,内置的 logrotate(8) 就负责定期更换日志文件,通常作为一个每日的 cron 定时任务运行。logrotate(8) 通过 /etc/logrotate.conf 配置,可以自定义的选项包括轮替标准、要保留的日志版本、是否压缩、轮替前后要执行的脚本等。(BSD 和 macOS 中的类似工具是 newsyslog(8)。)

另一个经常需要轮替的东西是凭证。各类安全策略经常要求定期淘汰旧密码、加密密钥、API token 等凭证,许多企业管理平台都可以设置密码或 token 的最长有效期。但应注意,凭证轮替并不是万灵药,要不要轮替、多久轮替应当综合考虑用户类型、威胁模型等因素来决定。例如,对于单因素密码,美国国家标准技术研究所(NIST)反而建议不要强制定期更换,因为它的授权范围过于宽泛,只要泄漏就可能立即造成损失,强制更换是一种虚幻的安全,反而会引起用户的懒惰心理,导致设置更不安全的密码。相反,在支持向 IP 地址发放 TLS 证书时,Let’s Encrypt 就决定对此类证书采用仅 6 天的有效期,从而在原始申请者失去原有 IP 而未察觉时,尽量减少恶意接管方凭借未过期证书伪造身份的攻击时间窗口。

值得指出,rotate 其实不是一个特别准确的引申,因为现实里轮班的员工还会被再次轮到,而在电脑里被 rotate 的日志和凭证绝对不会被捡回来再用。而与更宽泛的 change 或 replace 相比,rotate 强调了是在执行一种定期、有计划的策略,而不是一次性的被动更改。因此,要注意根据语境选择更合适的词来使用。

例句:

  • The server ran out of disk space because it failed to rotate the logs last night.(服务器昨晚未能轮替日志,导致磁盘空间用尽。)
  • Our security policy requires us to rotate all database encryption keys every 90 days.(我们的安全政策要求每 90 天轮替一次所有数据库加密密钥。)

>> spawn

电脑中的进程彼此之间存在「亲属关系」,每个进程通常都是由一个父进程创建的(Unix 用户环境「初生」时创建的 initsystemd 和 Windows 启动早期的 smss.exe 等系统进程除外)。这个创建子进程的过程,很多时候就用动词 spawn 来描述。spawn 在日常用语中颇有些贬义,一般指通过产卵方式大规模孳生,不过在技术语境中是完全中性的;要怪就怪二十世纪的计算机先驱比较偏爱生物学术语吧。

不同操作系统 spawn 进程的方法有很大差异。在 Unix 一脉(包括 Linux 和 macOS)中,spawn 是种有点像细胞分裂和变异的过程:首先由父进程调用 fork(),使系统克隆一份父进程(在现代系统中,由于写时复制机制,此时并不需要物理上复制,因此效率更高)。随后,这个继承了父进程资源(如文件描述符、环境变量)的子进程调用 exec(),将要运行的程序代码替换进当前的内存空间,开始执行新任务。

而在 Windows 中,没有 fork()exec() 的分野,创建进程的主要方法是 CreateProcess。父进程必须在调用时,显式地在参数中指定子进程所需的信息(命令行参数、环境变量、启动目录、是否继承句柄等),然后 Windows 为子进程分配全新的内存空间,加载可执行文件。

这种差异反映了两种设计思路:Unix 强调轻量级和简单工具的配合,fork()exec() 的模式非常适合在进程之间共享资源。也正是凭借在 fork() 之后、exec() 之前修改子进程文件描述符的机会,Unix 命令中常用的管道(|)和重定向(>)才成为可能。(参见 OSTEP §5.4。)相反,Windows 作为更晚出现的系统,进程模型涉及大量图形界面与权限管理,更加复杂,囫囵克隆父进程容易导致状态混乱。因此,Windows 在 spawn 进程时采用了「另起炉灶」的方式,从头初始化一个全新的环境。

除了可以说 spawn 一个进程之外,线程(thread)、任务(task,常见于构建系统和持续集成等语境)和工作进程(worker,常见于 web 开发等语境)也经常与 spawn 搭配作宾语。最后,在游戏语境中,spawn 可以表示游戏引擎以程序化方式创建一个新实体(entity),例如物品、敌人或特效,将其「投放」在游戏世界中。

例句:

  • When you type a command into the terminal, the shell will spawn a child process to run that command, allowing you to remain in the shell. [当你在终端输入命令时,shell 会创建一个子进程来运行该命令,使你能够继续留在 shell 中。]
  • The main server loop spawns a new thread to handle each incoming request. [对于每个传入的请求,主服务器循环都生成一个新线程来处理。]

>> suppress

suppress 在计算机语境下可以说是一个特别有反差感的词。从它的本义——压制、封锁——推测,你可能以为要被 suppress 的会是一些非常严重的东西。但实际上,计算机中 suppress 的对象往往并不那么重要,而大多是指隐藏一些可看可不看的诊断、报错、日志、提示,或者阻止一些预设或非关键的程序行为。

suppress 很久以来就在技术领域用来指「隐藏」一些不重要的信息。例如,在 70 年代初的美国航空航天学会一次关于航空器设计的会议上,一篇文章指出「飞行员的需求是随着飞行的推进而变化的。仪表应当显示重要的信息,而当前而言不重要的信息应当隐藏(suppress)」。

如今,许多编程语言里都会提供用来 suppress 特定提示的机制,例如 Java 的 @SuppressWarnings、Python 的 contextlib.suppress。suppress 也是命令行工具手册页(manpages)里的常客。例如,grep(1) 的手册页说,-c-l (-L) 等选项的功能都是隐藏(suppress)常规输出,转而输出匹配计数、包含(或不包含)匹配内容的文件名;diff(1) 则提供了名为 --suppress-common-lines--suppress-blank-empty 的选项,分别用来隐藏输出中的相同行或空行。

由此可以看出,suppress 不同于 dismiss 或 ignore,因为后两个词是指提示已经弹出,只是将其关闭或置之不理,而 suppress 将使得提示完全不会出现;也不同于 disable,因为被 suppress 并不会取消或打断任何本应执行的程序(例如,即使传入了 -c-l 选项,grep(1) 还是要扫描每一个文件,只是不输出一些特定内容而已)。

同样具有反差感的是,虽然 suppress 看起来有点「暴力」,但也可以指通过「假意逢迎」的方式让电脑闭嘴。例如在 1980 年,一本用 Fortran 语言解数学问题的书就在循环语句 DO 251 J = 1,N 前写了一句 J = 1,并注释这是「为了避免报错」(TO SUPPRESS WARNINGS)。这是因为当时的一些 Fortran 编译器不允许直接直接在循环条件中使用未声明的变量,所以才要先为循环变量做一次并无实际意义的赋值,从而「安抚」编译器。又比如,在编写涉及删除操作 shell 脚本时,rm <some_files> || true 的写法也是一种 suppress 报错的技巧,因为这样即使 rm 因为找不到文件而报错,也会被 || true 接管从而维持正常的返回值 0

例句:

  • Passing the -q flag suppresses all non-critical output so the script runs silently.(传入 -q 选项会隐藏所有非关键输出,让脚本静默运行。)
  • Calling event.preventDefault() suppresses the browser’s default form submission behavior.(调用 event.preventDefault() 将会阻止浏览器默认的表单提交行为。)

>> walk

在日常生活中提到「走」(walk),你可能想到很多不同的走法:可能是快步走,也可能是漫无目的地走。但在计算机中,walk(一般译为「遍历」)是一个重复和单调的过程,指按某种规则进入一个有层级的结构,访问其中的每一个对象。

最常被 walk 的结构就是文件系统了。当你要求程序 walk 一个目录时,它会通过底层的系统调用(例如 readdir)读取目录中的每一个项目;如果遇到子目录,就进入其中,递归地对这个子目录执行相同步骤,直到「走完」所有可达的节点。这个过程本质上是提供了一种访问目录下所有内容的方式,几乎对于任何涉及文件的操作都是基础而必不可少的。因此,你可以在许多编程语言的标准函数库中找到以此为名的函数,例如 C 语言中的 ftw() (file tree walk)、Python 中的 os.walk() 等。

除了文件系统之外,经常被 walk 的结构还包括从 HTML 渲染出的 DOM 树、解析器处理过程中生成的抽象语法树(AST)、包管理场景中的依赖关系(一种有向图)、以及内核调试语境中的调用堆栈(call stack)等等。

有趣的是,尽管 walk 的目标通常是不重不漏地访问所有节点,但它的「步伐」却不见得符合直觉。例如,观察 Python 中 os.walk 的直接输出,会发现它给出的文件顺序是比较「乱」的。这是因为 walk 访问的顺序,完全取决于底层系统调用返回目录条目的顺序,而后者又取决于文件系统在物理(或逻辑)层面的存储方式。在许多文件系统中,文件的元数据(inode)或目录条目未必是按照字母顺序排列,因此 walk 的结果也往往需要进一步排序才比较易读。

在使用中,walk 大多数时候可以与看起来更正式的说法 traverse(也译为遍历)互换。类似的说法还有 iterate through(迭代)、scan(扫描)和 enumerate(枚举)等,不过这些更多是指处理扁平的、线性的结构(如列表或数组),缺乏 walk 所隐含的「深入层级」的含义。

例句:

  • While debugging a memory leak, the engineer had to manually walk the heap by following pointers in the memory dump to find the un-freed data. [调试内存泄漏时,工程师需要人工沿着内存转储中的指针遍历堆栈,从而找到未释放的数据。]
  • The scraper walks the DOM to extract prices. [这个爬虫通过遍历 DOM 来提取价格。]

>> wrap

在计算机语境中,当你将某个对象、函数、组件、库「包装」(wrap)起来时,就是将它放在另一层代码中,从而修改它的功能或行为,以便使用。例如,在 Python 中,Requests 包装了标准库 urllib,使得原本要写很多行代码的 web 请求可以简化为一两行,而中间的转换过程则由 Requests 在幕后完成。在 web 开发中,Tailwind 等框架包装了一组预先制定的样式,可以像积木一样复用。

值得区分几个与 wrap 有关但不同的词。首先是 shim,其本义为拼接零部件时放置的垫片,引申为「兼容层」,大多数时候是指一种特殊的包装方式,主要目的是在两个不同的接口之间创建兼容性。其次,encapsulate(封装)是指隐藏一个对象内部的接口和数据,使外界只能通过指定的接口访问;创建包装的过程经常会涉及封装,但并不必要(例如,egrep 只是通过隐式附加 -E 选项而「包装」了 grep,但除此之外并没有隐藏 grep 的任何功能或输出,因此不算「封装」);反之,如果一个封装内部并没有调用任何其他组件,就不构成包装。最后,abstract(抽象)是指隐藏实现细节,只向上层暴露其所需的功能,因此可以说 wrap 和 encapsulate 都是实现抽象的途径(但并不是全部途径,例如容器和虚拟机是对硬件平台的抽象)。

在一些口语化的用例中,wrap 也可以表示贬义,用来描述那种缺乏(甚至伪造)原创性,但实际上只是简单加工别人成果,就当作自己作品宣扬和谋利的行为。例如,许多收费不菲的所谓 YouTube 下载器、视频转码器,本质上只是把 yt-dlpffmpeg wrap 在一层简陋的图形界面里;许多所谓的「桌面应用」,只是用 Electron 打包并且毫无额外优化的网页版 wrapper;近年来许多所谓的 AI 项目,只是把用户输入拼接到提示词模板中,传给 OpenAI 等模型厂商的 API。

wrap 的另一个含义与文字显示有关,是指让一段连续的文字在特定边界处转入下一行——就像丝带缠绕到盒子的边缘后掉头一样。wrap 分为「软」「硬」两种方式。「硬换行」是指通过插入换行符而人为制造换行。这是在早期终端环境下唯一的选择,因此有命令行中的 fmt、Vim 中的 gq<motion> 等工具帮助自动插入换行符,将文本控制在指定宽度(一般为 72 或 80 字符)。即使今天,在开源社区邮件组、RFC 的文字版等场合,硬换行仍然是标准。「软换行」则是指通过软件计算,在遇到窗口、纸张或图片等装饰性元素的边界时,自动让文本换行显示。这听起来似乎不难,但当与两端对齐、连字符、避头尾规则等因素综合考虑时,从哪里断行就成了非常难判断的问题,可以说至今没有完美的算法。

例句:

  • We wrapped the legacy C library with a thin Rust layer to enforce safer types and lifetime management.(我们用一个 Rust 薄层包装了用 C 写的旧版库,以便确保类型安全和生命周期管理。)
  • The document is set to wrap text at 80 characters.(该文档设置为在 80 字符宽处换行。)

A version of this article appears on SSPAI as member-only posts (1, 2, 3). Learn more or subscribe

The article is permitted to be self-archived in the version as originally submitted for publication on the author’s personal website under CC BY-NC 4.0 pursuant to § 5.2(b) of the SSPAI Fellowship Contributor Agreement.