第一面:时间坐标(时 + 体)

中文的动词从来不变形,“我吃饭”和”我昨天吃饭”长得一模一样——那英文为什么非得变?它到底在变什么?更狠的问题是:如果英语真的那么在意时间,为什么它偏偏没有”将来时”这个形态?


1. 开场:中文动词不变形,怎么表达”过去”?

先别往下看,回答我一个问题。

下面两句中文,动词有什么区别?

a. 我昨天吃饭。
b. 我吃饭。

没有。一个字都没变。“吃”就是”吃”。

可你读 a 的时候,脑子里清清楚楚知道那是昨天的事;读 b 的时候,你觉得那是习惯或者此刻正在发生。你理解得毫无障碍,甚至从来没觉得这里有问题。

那问题就来了:既然中文这么省事,英文为什么非要搞出 eat / ate / eaten / will eat / is eating / has eaten / had eaten / will have been eating 这么一大堆?

先别急着背表。我想让你自己撞一下墙。

再给你一句:

c. 我吃饭了。
d. 我吃过饭。

这两句你分得出来吗?“了”和”过”不一样——“了”偏”这件事发生了/完成了”,“过”偏”这件事在我人生经历里出现过”。但请注意:“了”和”过”是两个独立的词,它们挂在动词外面,不是动词自己变出来的。

你可以说”我吃了饭”,也可以说”我吃饭了”,还可以说”我饭吃了”。位置能挪,词能删,动词”吃”本身纹丝不动。

现在把英文摆上来:

a'. I ate.
b'. I eat.
c'. I have eaten.
d'. I had eaten.

中文四句翻译出来大概率都是”我吃了”(顶多 d’ 加个”之前”),可英文四句长得完全不一样,而且不能互换。

这就是本书要你体会的第一件事:

中文是词汇化的语言——时间、数量、语气都挂在动词外面(“曾""正在""过""居然”),像便签纸,想贴就贴,想撕就撕。 英文是形态化的语言——时间、体、数、语气被焊进动词的骨头里,你只要开口说一个动词,就必须顺手把这几个维度一起声明了,一个都跑不掉。

所以”英文为什么有时态”这个问题问反了。真正的问题是:一个动词形态稀少的语言,是怎么活下来的?

答案是:中文把时间信息外包给了两个东西——时间词(昨天、上周、2024 年)和上下文。你把”昨天”三个字一放,动词什么都不用做,听的人自己会算。

你可以做个小实验。把时间词拿掉:

e. 我吃饭。

脱离上下文,这句是有歧义的:可以是习惯(我吃米饭,不吃面),可以是正在发生(我在吃饭,待会儿回你),可以是将要做(我吃饭 —— 然后就去)。中文靠上下文消歧,靠”了/过/正在/会”这几个助词和副词来补位。

英文怎么办?英文当然也有时间词,yesterday、last week、in 2024,一个都不少。但英文不信任时间词。英文的逻辑是:**时间词是可选的修饰,动词形态是强制的声明。**你可以不说 yesterday,但你不能不说 ate。

用你们后端的话说:中文的时间信息是运行时解析的(靠上下文现场推断),英文的时间信息是编译期就写进类型里的(动词形态就是类型标注)。运行时推断灵活但可能出错,编译期声明啰嗦但不可能漏。

这就是为什么你写英文时会觉得”烦”——因为你每写一个动词,编译器都在逼你做一次类型标注。而你的中文母语告诉你:这玩意儿不用标啊。

好,那既然标了,标的是什么?

绝大多数教材会告诉你:动词变位是”时态”(tense)。这个词害人不浅,因为它把两个完全不同的东西塞进了一个词里。

拆开来看看。


2. 时(tense)和体(aspect)是两个正交的轴

我问你:was walking 和 walked 的区别是什么?

先别往下看,想三秒,最好出声答一遍。

你八成会说:都是过去,但一个是”过去正在走”,一个是”过去走了”。

答得没错。但这个回答里其实挤着两个你没分开的信息:

  • 都是过去 —— 这是”时”(tense),说的是事件在时间轴上的位置。
  • 一个”正在”、一个”走了” —— 这是”体”(aspect),说的是事件的形状。

回扣卡点:你刚才那句话里,“都是过去”和”一个是正在一个是走了”是被你一口气说完的,中间没有停顿——因为在你的中文语感里它们是一件事。所以教材也把它们打包成一件事,起了个名字叫”时态”。而英文把它们切成两条独立的轴,每一条都能单独调,互不干涉。“时态”这个词骗了你十几年,骗的就是这一点。

这两件事完全独立。你可以随便换位置,也可以随便换形状:

一般(点/整体)进行(线/内部)完成(结果/回溯)完成进行(持续回溯)
过去walkedwas walkinghad walkedhad been walking
现在walk / walksam walkinghave walkedhave been walking

在往下讲之前,我想先卡你一下。这个卡点考的不是英语,是你脑子里那张贴了十几年的旧地图。

卡点 A:英语到底有几个”时态”?

先别往下看,想三秒,最好出声答一遍。

你八成会答”16 个”,或者”12 个”。

如果你当年用的是人教版老教材,你答的是 16;如果你后来翻过剑桥那套语法书,你答的是 12。数字不同,来源是同一张表——就是你中学教室后墙上贴的那张”英语时态表”:横着过去、现在、将来、过去将来,竖着一般、进行、完成、完成进行,四四一十六(把”过去将来”那行去掉就是十二)。

好,现在我给你第二个数字:

英语的”时”,动词屈折形态只有两个。

**两个。**不是十二,也不是十六。

我知道你要反驳。你可能已经在心里翻那张表了:“过去、现在、将来,明明三行啊?”

这就是我要打的那个脸——你把”搭出来的组合”当成了”变出来的形态”。

先别急着接受,我们做个实验。你随便抓一个动词,对它做”变成将来”这个操作:

walk  ->  walked        (过去,动词自己变了形:屈折)
walk  ->  walks         (现在,第三人称加 -s:屈折)
walk  ->  will walk     ("将来"?walk 一点没变,前面多了个词)

看见没有?前两行是动词自己变形,这叫屈折形态(inflection)。第三行动词纹丝不动,是在它前面加了一个独立的词。这在语言学上是完全不同的两件事——一种是词内部的形态变化,一种是句法上的词组搭配。

你再检查一遍所有”将来”的说法,没有一个是靠动词变出来的:

will walk
is going to walk
is walking
walks
is about to walk
is to walk

六种说法,六种外形,没有哪一种里 walk 自己变了。对比一下:过去时就一个 -ed,现在时就一个 -s,清清楚楚,独此一家,别无分号。

那张十六格的表是怎么来的?是把两条完全不同的轴交叉出来的:一条轴的格子靠变(过去 -ed / 现在 -s),另一条轴的格子靠搭(will / be / have)。表格把它们印成一样大小、一样颜色的方块,你就以为它们是一类东西。

所以”英语有几个时态”这个问法本身就是个陷阱:它诱导你去数那张表,而那张表恰恰是把”时”和”体”混在一起印出来的、最误导人的一张图。它不告诉你哪八格是形态、哪八格是拼装,更不告诉你将来那一整行——四格——一格都不算形态。

带着这个认知往下看。

2.1 英语的”时”只有两个形态

数一数上面那张表。过去、现在、将来——按理说应该有三行,对吧?

没有。第三行不存在。

英语动词的”时”,屈折形态只有两套:过去时(past) 和 现在时(present)。时态时态,英语其实只有两个”时”。

证据特别硬。你随便抓一个动词:

walk    -> walked      (过去,变形了)
walk    -> walks       (现在,第三人称加 -s,变形了)
walk    -> will walk   ("将来"?walk 本身一点没变,加的是 will)

看见没有?将来不是动词变出来的,是加了一个词。walk 在 will walk 里就是光秃秃的原形,跟 must walk、can walk、should walk 里的 walk 一模一样。

再看一遍所有”将来”的说法:

will walk
is going to walk
is walking          (明天走,用进行时)
walks               (火车九点开,用一般现在时)
is about to walk
is to walk

六种说法,六种动词形态,没有一种是”将来时专属形态”。对比一下:过去时就一个 -ed,现在时就一个 -s,清清楚楚,独此一家。

这不是巧合,也不是英语偷懒。这是一个可以追到印欧语祖先的事实:原始印欧语的动词系统里就有现在时、过去时(还有完成时、不定过去时),但从来没有过一个”将来时”形态。 希腊语没有,拉丁语没有,古英语没有,现代英语自然也没有。将来是后加的,是语法化的产物,是”借”来的。

好,现在我们把两条轴立起来。

2.2 时 = 锚点,体 = 形状

时(tense)解决的是”钉在哪”:这个事件相对于说话时刻,在时间轴的哪一侧?左边(过去)、脚下(现在),还是右边(将来)?

这是一个绝对坐标。参照物永远是”现在”这个原点,也就是英语里说的 deictic center(指示中心,直译”指称中心”,就是说话人站的地方)。

体(aspect)解决的是”长什么样”:我不关心它在哪,我关心你从哪个角度看它。

  • 看成一个点(一个完整的、有边界的事件)-> 一般体(simple),She walked to the car.
  • 看成一段线(走进事件内部,看它的进行过程)-> 进行体(progressive),She was walking to the car.
  • 看成结果(退后一步,看它留下的状态)-> 完成体(perfect),She had walked to the car.
  • 看成从过去持续过来的线(既看过程又看延续)-> 完成进行体(perfect progressive),She had been walking toward the car for a minute.

注意这里的关键:体不告诉你事件发生在什么时候,它只告诉你镜头怎么摆。

a. She was walking to the car.       (过去 + 进行)
b. She is walking to the car.        (现在 + 进行)
c. She will be walking to the car.   (将来 + 进行,想象那个画面)

三句时间完全不同,但”体”是一样的:都在事件内部,都在看那条线。反过来:

d. She walked to the car.            (过去 + 一般)
e. She was walking to the car.       (过去 + 进行)

时间位置一样,镜头完全不同:d 是把整件事打包成一个点告诉你”有这回事”,e 是把摄像机推进去,让你看见她一步一步走的画面。

**两条轴,互不干涉,随便组合。**这就是”正交”(orthogonal)的意思。

2.3 程序员版本:absolute 坐标 vs relative 视图

如果你觉得”时”和”体”还是抽象,换个说法。

想象你在写一个渲染引擎,场景里有一个物体。

  • 时(tense)是这个物体在世界坐标系里的绝对位置。 world_position = (x, y, z)。参照系是固定的世界原点,写死在场景里的。
  • 体(aspect)是摄像机的取景方式。 同一个物体,你可以:
    • 用广角把它当成一个整体的小点拍下来(一般体)
    • 推近,贴着它拍运动过程,画面里只有它的一段轨迹(进行体)
    • 拍”它已经经过了哪里”,画面里是它留下的痕迹(完成体)
    • 拍它一路留下的痕迹,一直连到现在(完成进行体)

物体没动,摄像机变了。位置没变,取景变了。

这就是体和时的关系。你写 was walking 的时候,你做了两件事:设置了世界坐标(past),设置了摄像机模式(progressive)。两件事互不干涉,但可以叠加。

再补一个对程序员特别友好的类比:时像绝对时间戳,体像采样窗口。

监控录像存了 24 小时。你调录像的时候:

  • 绝对时间戳告诉你”看哪一段”——seek to 15:40(时)
  • 采样/回放方式告诉你”怎么看”——是跳着看关键帧(一般体,只看有没有发生),是拖进度条连续播放(进行体,看过程),是只看”截至此刻累积了哪些事件”(完成体),是看”从 15:30 到 15:40 这个动作持续了多久”(完成进行体)

一段录像,四种看法。录像内容一点没变,变的是你的观察方式。

而中文的麻烦恰恰在这里:中文的”了/过/正在/已经”能表达体的区别,但它们是可选的词,而且是靠语感用的;英文的体是动词形态的一部分,你躲不掉。

你写 She walked. 的时候,英文不仅知道这是过去,还默认你知道”这时你在把事件当成一个点”。如果你想表达的不是点,你就必须显式地换形态。这是英文的强制性,也是英文的精确性来源。

2.4 中文翻译几乎一样,英文思维完全不同

回到母案例。给你三句:

a. The migration locked the orders table.
b. The migration was locking the orders table.
c. The migration had locked the orders table.

中文翻译:

a. 迁移锁住了订单表。
b. 迁移当时正在锁订单表。
c. 迁移此前已经锁住了订单表。

看出来了吗?中文要区分这三层意思,得加”当时正”、“此前已经”这些额外的词。不加呢?

迁移锁住了订单表。

三句都能这么翻。全都通顺,全都”对”。中文把选择权交给了读者,英文把选择权留给了说话人的动词形态。

这就是全书要反复打的那个点:**中文翻译几乎一样,但英文思维完全不同。**你以为你在翻译,其实你在做一次思维方式的切换。

后面整章,我们都在练这一件事。


3. 将来时是”借”来的:语言里的化石

上一节留了个炸弹:英语没有将来时形态。

那 will 是什么?be going to 又是什么?为什么英语表达”将来”能有四五种说法,而且它们还不能随便互换?

这一节我会给你一个答案,这个答案能解释一大堆你以前只能死记的”区别”:

因为英语从来没有造出过将来时,所以它是从别的地方借了几套表达来凑合用。每套借来的表达,都还带着它原来的意思。

带着原义,就是”不能互换”的原因。我们来一件一件验。

3.1 will:本来是”我想要”,不是”将会”

先做个直觉测试。

别急着往下看,先答这个:will 这个词,除了当”将要”讲,你还在哪儿见过它?

给三秒。

你大概能想起一两个:

  • 作名词:遗嘱(“立遗嘱”是 make a will)
  • 作动词:用意志力驱动、决意(“他执意要做”是 he willed himself to do it)
  • 作形容词:wilful(任性的、故意的)

发现了吗?这些义项全指向同一个东西:意愿、意志、决心。

而你刚才想起它们的时候,多半是分开想起来的——“遗嘱”是一回事,“将要”是另一回事,你从来没觉得它们之间有关系。

它们有。而且这个关系,就是这一节的全部内容。

古英语的 willan 意思就是”想要、希望、打算”。它的亲属词在德语里今天还活着:wollen = want(想要)。

那”我想要”怎么就变成”将会”了?漂移路径特别清楚:

  1. I will go. 原义:我想要去 / 我决意去。(主语的意志)
  2. 你决意去做的事,大概率会做。听的人开始推断:他要去了。
  3. 推断次数多了,“意愿”这层意思就被磨薄了,剩下的是”预测”。
  4. I will go. 现义:我将会去。(说话人的预测)

这就是语言学里说的语法化(grammaticalization):一个有实义的词,用得太多,实义被磨掉,最后变成纯语法标记。

但——重点来了——磨掉不等于消失。

will 到今天还留着”意志”的残渣。你把 will 放回第一人称,意志味就冒出来了:

a. I will help you.              (我帮你。—— 承诺,带着"我决意"的力度)
b. It will rain tomorrow.        (明天会下雨。—— 纯预测,没有谁在"决意"下雨)

a 句里那个 will,你能感觉到说话人的那股劲儿。b 句里没有。

再看:

c. The door won't open.

这句不是说”门拒绝打开”(虽然字面就这意思),而是”门打不开”。但为什么用 won’t 而不是 doesn’t?因为哪怕到了今天,will 用在否定上还是残留着”抗拒、不肯”的意思——门”不肯”开。 你拿这句去跟 The door doesn't open. 比,后者是冷冰冰的事实陈述(这扇门不打开,可能它本来就是装饰),前者有”我使劲了它也不听”的挫败感。

顺手来个工程味的:The deploy won't finish. 和 The deploy doesn't finish.——前者是”我等了半天它就是不肯跑完”,后者是”它跑不完(这是它的性质)”。

这就是化石。一个死了一千多年的意思,还在句子的缝隙里喘气。

3.2 be going to:本来是”正在去某个地方”

这个更直观。be going to 字面就是”正在去……”——空间的位移。

a. I am going to Seattle.                (我正在去西雅图。—— 空间,本义)
b. I am going to escalate to Priya.      (我要把这事升级给 Priya。—— 时间,引申义)

a 句是你在路上的车里能说的话。b 句跟走路没有半毛钱关系。

从”我正在去某地”到”我将要做某事”,中间那一步桥是什么?是意图。

你正在去机场,说明你打算飞。你正在伸手拿电话,说明你打算打。“已经在往目标移动”这个画面,被抽象成了”目标就在前方”。 空间上的”在途中”变成了时间上的”在途中”。

所以 be going to 到今天还带着两个不能丢的东西:

第一,它暗示”事情已经在推进了”。不是凭空的预测,是有迹可循的。

a. Look at the dashboards. It's going to page someone.     (看这曲线,马上就要触发呼叫了。—— 有迹象)
b. Look at the dashboards. It will page someone.           (?)

b 句不是语法错,但很别扭。为什么?因为曲线是当下的证据,你在做基于证据的推断。这个活儿天然属于 going to(有迹象、有前兆、事情已经在发生),不属于 will(纯预测或者纯意志)。

第二,它暗示”意图已经在说话人心里了”。

a. I'm going to rewrite the runbook.       (我打算重写 runbook。—— 我心里已经定了)
b. I will rewrite the runbook.             (我会重写 runbook。—— 更像当场下的决心/作出的承诺)

a 是”我早就想好了,现在告诉你一声”。b 是”此刻我向你承诺”。

3.3 现在进行时表将来:已经在路上了

还有第三种:I'm leaving tonight.(我今晚走。)

这句用的是现在进行时,但它说的是将来。为什么可以?

答案跟上一条同源:“我正在进行”意味着”这件事已经启动、已经不可撤销”。

你人已经在收拾行李了,流程已经跑起来了。这个动作严格说还没发生(今晚才走),但它的准备过程已经在现在发生了。所以英语允许你用进行时——因为进行时描述的不是”走”这个动作,而是”已经在走的那趟流程”。

这类句子的共同点:有安排、有票、有预约、有另一方的参与。

a. I'm meeting Priya at 10.                        (我十点跟 Priya 开会。—— 约好了)
b. I'm flying to Seattle on Tuesday.               (我周二飞西雅图。—— 票买好了)
c. Marcus is flying to Chicago on Thursday.        (Marcus 周四飞芝加哥。—— 定好了)

你不能说 *I'm raining tomorrow. 因为下雨不是安排出来的。你也不能说 *I'm meeting Priya at 10. 表示”我打算十点去找她但还没约”——那样就得说 I'm going to meet Priya at 10. 或者 I'll meet Priya at 10.

三种说法的差别,就是三块化石的差别:

说法化石原义残留到今天的语感
will意愿、意志主观预测;当场决定;承诺;正式宣告
be going to正在去某处(空间位移)有当下迹象;意图已定;事情已在推进
现在进行时正在进行已有安排;已购票/预约;不可撤销

再加第四个:

一般现在时永恒的、时刻表上的事实班次、日程、开会时间——写死的东西

第四个我们第 7 节细讲,它最反直觉,因为它压根没用任何”将来”标记。

3.4 为什么这四块化石不能互换

现在回头看这个经典考题。事故后的第二天上午,复盘会开完,三条行动项定下来了:

a. The team will adopt gh-ost in Q1.
b. The team is going to adopt gh-ost in Q1.
c. The team adopts gh-ost in Q1.
d. The team is adopting gh-ost in Q1.

四句都可以翻译成”团队第一季度采用 gh-ost”。中文几乎一模一样。但英文四句讲的故事完全不同:

  • a. 说话人在预测或宣告。这是复盘文档、对外通报的口吻,说话人跟这件事保持距离,只是陈述一个将要发生的事实。
  • b. 说话人看到了迹象——工单已经建好了,Priya 已经在 Canal 上发了公告,采购流程都走完了。或者:这就是计划好的下一步。
  • c. 这是路线图上的一行字。把 gh-ost 当成一趟列车,Q1 发车。最冷、最客观。
  • d. 采用工作已经排进日程了,有人在推,每周有站会同步进度。这件事在”推进中”。

**你想说什么,决定了你必须用哪一句。**不是语感,是语义残留。

这就是为什么”将来时”难:它不是一条规则,它是四块从不同地质层挖出来的化石,你每次开口都得选一块。

3.5 一个反向的验证

如果这个”化石”理论是对的,那它应该能预测一些你没背过的东西。试一个。

will 的化石原义是”意愿/意志”。那么,在条件句里,它应该很难用——因为条件句里说话人的意志被压制了(“如果……就……”不是你在决意,是世界在决定)。

验证:

a. If the error rate stays above 30%, Marcus will notify Northwind.        (对)
b. *If the error rate stays above 30%, Marcus is going to notify Northwind. (别扭)
c. If it rains, I'll stay home.                                            (对)

b 句为什么别扭?因为 be going to 要求”当下的迹象”或”已定的意图”,而条件句构造的是一个还没发生的假设世界,你在那个世界里找不到迹象可看。所以条件句默认用 will。

反过来,be going to 在有明显当下迹象时压过 will:

a. Careful! You're going to drop that.         (小心!你要掉了。—— 我看见它在滑)
b. Careful! You will drop that.                (?)

b 句像是在诅咒你,不像在提醒你。因为 will 是预测,而你明明看见杯子在滑了——有证据的时候还用纯预测,就成了”我预言你会掉”,语用上很怪。

这些”别扭”和”怪”,教材通常一笔带过,或者直接给你一张”will vs be going to 区别表”让你背。但区别表背下来你还是不会用,因为你不知道为什么。

现在你知道了:因为它们是四块化石,各自带着原义。你不是在选”将来时”,你是在选”我要调用哪一块化石的哪一层意思”。

3.6 这也解释了另一件事:为什么英语有”将来完成时”

顺手清掉一个疑问。既然没有将来时,那 will have done(将来完成时)是什么?

拆开看:will + have + done。

  • have done 是完成体,这是货真价实的形态
  • will 是借来的情态动词

所以 will have done 不是”将来时 + 完成体”,它是情态动词 will + 完成体。英语的完成体在将来方向上是这么搭出来的:形态还是那套形态,将来还是靠借。

By November 2025, the team will have gone twelve months without a P1 incident.
到 2025 年 11 月,团队将已经连续十二个月没有 P1 事故。

意思是:站在将来某个点(2025 年 11 月),往回看,累积了十二个月。

整个将来方向的所有表达,全是这么搭的。搭积木,不是变位。

好,三块(其实是四块)化石讲完了。下一节,我们把时和体这两条轴交叉,把整个矩阵铺开——并且用同一个事件把它填满。


4. 十二格矩阵:用母案例填满

先把这一节要解决的问题抛出来。

卡点 C:这句话是 12 格里的哪一格?

给你一句朴素到不能再朴素的话,跟技术一点关系都没有:

The noodle shop downstairs has been closed for a month.

先别往下看,想三秒:它是 12 格里的哪一格?你怎么判断的?

大部分人会立刻答:“现在完成。has been + 过去分词 closed,再加 for a month。”

答得挺快,但你只答对了一半,而且漏掉的那一半才是关键。

先说你答对的部分。确实,has been closed 在最正常的读法下是现在完成:楼下的面馆一个月前关了,到现在还关着。窗开着,从左沿一直开到现在。

现在说你漏的那一半。请你再念一遍这句话,然后回答我:这里的 closed,是动词还是形容词?

如果你觉得”当然是动词 close 的过去分词”——那我换一句给你看:

a. The noodle shop has been closed for a month.   (关了一个月了 —— 状态在持续)
b. The noodle shop is closed.                     (关着呢 —— 此刻的状态)
c. The noodle shop closed last month.             (上个月关了 —— 一个动作,一个点)

b 句里的 closed 你一定同意是形容词(“关着的”),它跟”有人去关了它”这个动作没关系,它描述的是门此刻的样子。那 a 句里的 closed 凭什么一定是动词?

事实是:a 句在形态上是彻底两可的。

  • 读法一:closed = 形容词,has been = 完成体的助动词,整句是现在完成,意思是”关着这个状态,持续一个月了”。
  • 读法二:has been closed = 现在完成 + 被动,整句是现在完成 + 被动,意思是”有人把它关了一个月了”(这个读法在语义上有点怪,但形态上完全成立)。

两种读法的中文翻译一模一样,都是”楼下面馆关了一个月了”。英文的动词形态没帮你区分,区分工作交给了语义和常识。

**这就是这一节真正要教你的东西的第一层:光看动词形态,有时候定不了格。**你得先判断这个词是动词还是形容词、是主动还是被动,然后才轮到”格”的事。形态是线索,不是答案。

第二层更要紧。再看这句:

I was cooking when the lights went out.

这一句里有几个格?

两个。was cooking 是过去进行,went out 是一般过去。一句话里出现两格,而且这不是特殊情况——这是英文叙事的常态。

所以”这句话是 12 格里的哪一格”这个问法,本身就藏着一个陷阱:它默认一句话只有一格。而真实的英文句子,几乎每个都含两三个动词短语,每个短语各自占格。12 格不是给句子准备的,是给动词短语准备的。

回扣卡点:你刚才被卡住,是因为你在找一个”整句的格”。而正确的问题是:这句话里有几个动词短语?每个短语的时是什么、体是什么?——把这句话问一遍,格自己就出来了。

现在把矩阵铺开。铺完之后你会发现,同一个事件能填满十二格,靠的不是换事件,是换动词短语的视角。

时有三档(过去、现在、将来),体有四档(一般、进行、完成、完成进行),交叉就是十二格。

先把话说清楚:这十二格里,“将来”那一行不是靠动词变位撑起来的(上一节讲过),它靠的是 will。所以严格说,英语的形态矩阵只有 2×4 = 8 格,第三行是搭出来的。但为了方便对照,我们还是按传统的十二格来摆。

全部例句都来自同一个事件:The Outage。事件核一句话:

Lin 执行的一条数据库迁移锁住了 orders 表,导致 51 分钟的服务降级,但没有造成数据丢失。

事件核一个字都不变,我们只转动”时间坐标”这个切面。

关于这个事件核,先花半分钟把事实摆平,后面全章都在这条时间线上做实验。2024 年 11 月 12 日,太平洋时间凌晨 2:14,Pallet 的后端工程师 Lin Wei 在旧金山家里对着主库执行了一条 ALTER TABLE orders ADD INDEX。他没用 online DDL 工具 gh-ost。2:17 第一条告警进来,2:19 PagerDuty 呼叫他——手机静音,没听见。2:26 他醒来。2:31 他定位到是迁移导致的锁表,但 runbook 里没有”如何安全中止一个正在跑的 ALTER”这一节。2:37 下单错误率冲到 34%,大客户 Northwind Retail 开始大面积失败。2:44 告警自动升级到工程经理 Priya Nair。2:47 Priya 直接 KILL 掉那条迁移连接。2:52 错误率回落到 0.05%。3:05 服务完全恢复,客户成功经理 Marcus Bell 开始给客户发通知。总时长 51 分钟,约 12,300 笔下单失败,损失约 8 万美元 GMV,没有数据丢失。次日 10:00 复盘会,blameless,定性为流程缺失,Lin 没被处罚。三条行动项全部落地,此后 22 个月无 P1。现在是 2026 年 9 月,Lin 是 on-call 培训负责人,Priya 升为工程总监。

这条时间线的妙处在于:它既有精确到分钟的内部相对时间(2:14 / 2:26 / 2:44 / 2:47,供过去完成时取锚),又有封闭的绝对日期(2024 年 11 月 12 日),还有一条开到现在的窗(22 个月)。时和体需要的三种东西,一个事件全给了。

4.1 矩阵全表

一般(点)进行(线)完成(结果)完成进行(持续回溯)
过去Lin ran the migration at 2:14 a.m.
Lin 在凌晨 2:14 执行了那条迁移。
The migration was still running when Priya joined.
Priya 上线时迁移还在跑。
Lin had never run a migration alone.
此前 Lin 从未独立执行过迁移。
Lin had been trying to kill it for ten minutes.
他试图中止它,试了十分钟。
现在(2026)Lin trains the on-call team.
Lin 现在负责 on-call 培训。
Lin is rewriting the on-call curriculum.
Lin 正在重写 on-call 培训大纲。
Pallet has gone 22 months without a P1 incident.
Pallet 已经 22 个月没有 P1 事故了。
Lin has been running on-call training since 2025.
Lin 从 2025 年起一直在负责 on-call 培训。
将来The team will adopt gh-ost for all schema changes.
团队将为所有 schema 变更采用 gh-ost。
At 10 a.m. Priya will be opening the postmortem.
十点的时候 Priya 会正在主持复盘会开场。
By December the team will have added an abort section to the runbook.
到 12 月,团队将已经把”如何中止”这一节补进 runbook。
By next November Pallet will have been running gh-ost for a full year.
到明年 11 月,Pallet 用 gh-ost 就满一年了。

关于”将来”那一行,有句话必须说清楚:它不是从 2026 年这个原点往前看的。 那是叙事视角——我们跟着故事走到 2024 年 11 月 13 日复盘会那个位置,从那里往前看。这一点后面第 8 节会展开,叫”叙事默认档”。

4.2 逐行讲语感

第一行:过去。

这行最简单,也最容易被低估。中文翻译里,“过去”两个字能翻的东西很多,但英文的四格切得极细。

a. Lin ran the migration at 2:14 a.m.
b. The migration was still running when Priya joined.
c. Lin had never run a migration alone.
d. Lin had been trying to kill it for ten minutes.
  • a(一般过去):把整件事打包成一个点,放进叙事链。“他在 2:14 执行了迁移”——这是故事里的下一个动作,推动情节。注意 at 2:14 a.m. 是个精确到分钟的封闭状语,它把这个动作钉死在时间线上的一个坐标上,动弹不得。
  • b(过去进行):镜头推近。画面里是那条 ALTER 正在一行一行地拷数据、正在持有元数据锁、过程还没结束。它不告诉你好没好,它是个背景画面。
  • c(过去完成):闪回。时间线在”他执行迁移”这个点上,而这句话往后跳了一步,交代”他此前从没自己干过这个”。它不推动情节,它填背景——而且这一填,读者立刻明白这次为什么没有第二个人在场复核。
  • d(过去完成进行):闪回 + 过程。“试图中止”不是一次动作,是从 2:31 一直持续到锚点的状态。而且这个形态自带一种无力感:他不是在”中止”,他是在”一直试着中止”。这才是这起事故真正的痛点——runbook 里没有那一步。

你看出门道没有?a 和 b 是”摄像机在现场的两种拍法”,c 和 d 是”摄像机往回跳的两种拍法”。

再看一个关键细节:c 和 d 单独拿出来都会让人觉得”话没说完”。

c'. Lin had never run a migration alone.   (……然后呢?)

这句语法上完全合法,但读者会下意识等一句”所以呢?“或者”然后发生了什么”。因为过去完成时是一个相对时态,它必须指向上下文里另一个过去时间点。这一点第 6 节专门讲。

第二行:现在。

a. Lin trains the on-call team.
b. Lin is rewriting the on-call curriculum.
c. Pallet has gone 22 months without a P1 incident.
d. Lin has been running on-call training since 2025.
  • a(一般现在):这是在说一个当下的常态/事实,不是在说某个具体动作。他现在的职责就是这样。一般现在时的本质是”把一件事说成无时间性的属性”,所以它天然用来表达习惯、常态、事实。
  • b(现在进行):过程感。“正在重写”——不是已经写完了,是还在写。
  • c(现在完成):结果导向。“22 个月无 P1”这个状态累积到现在仍然成立。中文只能说”Pallet 已经 22 个月没有 P1 事故了”,得靠”已经”和句尾的”了”撑着。
  • d(现在完成进行):既强调”从 2025 年一路持续到现在”,又强调”还在干”。跟 c 的区别在于:c 关心”累积到什么程度”,d 关心”持续了多久、还在不在继续”。

顺手点一句这里的人设反转:那个 2024 年凌晨两点半不知所措的工程师,现在是教别人怎么值班的人。这个反转本身就是完成体最好的素材——“经历""变化""持续到现在”三个意思,一个事件全给了。

第三行:将来。

a. The team will adopt gh-ost for all schema changes.
b. At 10 a.m. Priya will be opening the postmortem.
c. By December the team will have added an abort section to the runbook.
d. By next November Pallet will have been running gh-ost for a full year.
  • a:宣告。这是复盘文档、对外通报的口吻。
  • b:想象画面。把摄像机放到”11 月 13 日上午十点”,看见 Priya 正在开场的那副样子。将来时的进行体特别有”穿越过去看一眼”的效果。
  • c:站在 12 月往回看,runbook 补写这件事届时将已完成。
  • d:站在明年 11 月往回看,用 gh-ost 这件事届时已经持续了整整一年。

4.3 一格之差,意思就变:三组最小对立对

读完矩阵你可能觉得”都懂了”。那做三个判断题,看看是不是真懂。

规矩:每组看完例子,先自己说出差别,再看下面的分析。别顺着往下扫——扫过去你会觉得三组的分析你都”早就知道”。

第一组:一般 vs 进行

a. The migration locked the orders table.        (迁移锁住了 orders 表。)
b. The migration was locking the orders table.   (迁移当时正在锁 orders 表。)

a 是完整的事件:“锁住”这个动作落地了,成了事实。b 是过程画面的一个切片:**没说锁完没锁完。**你在 Grafana 上看着连接数一点点涨、慢查询一点点堆的那个瞬间,就是 b。

这就是为什么写事故报告、写复盘、写时间线主线,都用 a;写现场描述、写背景铺垫、写”当时的系统在干什么”,用 b。

第二组:完成 vs 完成进行

a. Priya had killed the connection by 2:47.                        (到 2:47,Priya 已经 kill 掉了那条连接。)
b. *Priya had been killing the connection for ten minutes.         (?)

b 句很怪。为什么?因为 kill 是个瞬间性动作(有界/telic),一条连接 kill 掉就 kill 掉了,没法”持续 kill 十分钟”。完成进行体要求动词有持续性。换成持续动词就顺了:

c. Lin had been trying to kill it for ten minutes.                 (对)

注意 c 里的动词是 try,不是 kill。try 是能拉长的——他一遍遍地试,试了十分钟。而且这一改,味道全变了:b 想说的是”kill 这个动作持续了十分钟”(不合逻辑),c 说的是”中止这件事他折腾了十分钟,一直没成”。后者才是那 51 分钟里最值钱的信息。

**有界(telic)和持续(durative)这对概念第二面会专门讲。**这里先记一句:完成进行体挑动词,它只要”能拉长”的动作。

第三组:现在完成 vs 现在完成进行

a. Pallet has adopted gh-ost.                    (Pallet 已经采用了 gh-ost。)
b. *Pallet has been adopting gh-ost.             (?)

同样的问题。但换个说法 b 就能成立:

c. Pallet has been running every schema change through gh-ost for 22 months.  (对)

因为 “run … through” 是能拉长的——“用 gh-ost 跑”是一个可以持续的状态,不是一次性的切换。有意思的是这两句在真实语境里常常连着出现:先说 We have adopted gh-ost.(结果:装上了、流程改了),再说 We have been running it for 22 months.(持续:跑了这么久,没出事)。**一句话给结论,一句话给证据。**这是复盘汇报里最常见的组合拳。

回扣三道题。第二组和第三组是同一道题:两句看起来对称的句子,为什么一句成立一句不成立?你如果只答”因为 adopt / kill 是瞬间动词”,那你只记住了一个词表;真正的原因是完成进行体这个形态自带一个语义要求——它要一段能拉长的东西。它一碰到瞬间动词就报错,跟你把 for ten minutes 塞给 die 是一模一样的错误类型:

a. *He has died for ten years.        (错)
b. He died ten years ago.             (对)
c. He has been dead for ten years.    (对,换成状态形容词就能拉长)

c 句那手”把动词换成状态”的改法,在工程语境里的对应物是 The service has been down for ten minutes.——down 是状态,能拉长。记”动词表”不如记这个改法,因为改法是可生成的,词表是背不完的。

4.4 你可能会想:十二格我背得下来吗

背不下来,也不用背。

真正要背的只有两件事:

  1. 两条轴各自解决什么问题(时 = 钉在哪,体 = 镜头怎么摆)。
  2. 其中只有一格是中国人的系统性盲区:现在完成 vs 一般过去。

其他十一格,中文多少都有对应的词(“正在""已经""当时”),你照着搬就行。唯独现在完成和一般过去这一对,中文完全没有形态上的区分手段,全靠上下文猜。

所以下一节,是这一章最重的一节,也是全书最重要的一节之一。


5. 重头戏:一般过去 vs 现在完成

这一节我会写得比较长,因为它是中国人学英语最大的一个坎。不是之一,是最大。

它难,不是因为规则复杂,恰恰是因为规则被讲错了几十年。

所以这一节我不打算一上来就给规则。我打算先让你发现一件事:你手上那把尺子,是坏的。

5.1 卡点 D:三组句子,先判对错

下面三组句子,请你逐句判”对”还是”错”。先别往下看,一句一句在心里答一遍,最好出声答一遍。

第一组

a. I saw her yesterday.
b. I have seen her yesterday.

第二组(提示:说话人的爷爷三年前去世了)

My grandfather has traveled to thirty countries.

第三组

a. Dinosaurs died out 66 million years ago.
b. Dinosaurs have died out.

想完了?我们一条一条对。

第一组:a 对,b 错。这题你多半答对了,但别急着高兴——你答对它是因为你背过:“现在完成不能跟具体过去时间连用”。背下来的东西不算本事,我们看第二组。

**第二组:错。**而且这一组是三道里最阴的一题,因为——

它语法上百分之百正确。

每个单词都合法,has 跟 My grandfather 的人称数一致,traveled 是 travel 的标准过去分词,to thirty countries 是正常的介词短语。你把它丢进任何一款语法检查器,它不会报一个错。

它错在语义撞车:完成体在说”他的人生这扇窗从过去一直开到现在”,而”他三年前去世了”这件事说”这扇窗已经关上了”。两个意思当场打架,句子死掉。正确的说法是 My grandfather traveled to thirty countries.

这就像 const x = 1; x = 2;——编译器不关心你觉得它对不对,类型冲突就是类型冲突。它不是”不地道”,它是坏句。

第三组:a 对,b 错。

这一组才是真正的杀手。

恐龙灭绝对现在的影响大到不能再大了——今天地球上没有恐龙,哺乳动物能站起来全是拜这件事所赐,你我现在能坐在这儿讨论英语,往上追六千六百万年都追得到这一笔账。那你告诉我,为什么 b 句是错的?


回扣卡点。

你刚才判这三组的时候,脑子里跑的是哪条规则?

八成是这一条——“现在完成时表示过去发生的动作对现在造成的影响”。你大概是在拿”有没有影响”当尺子去量的:第一组”昨天看见她”对现在没啥影响,所以不能用完成体;第三组恐龙灭绝……等等,这一条明明影响巨大,为什么不能用完成体?

你的尺子在这里卡住了。你翻来覆去地想”影响”两个字,越想越糊涂——因为这把尺子本身就量不了东西。

这就是本节的起点:先让你发现自己手上的工具是坏的,然后再给你一把好的。

5.2 先拆一个流传最广的伪规则

再回头看那把坏尺子,它其实还有一处更深的病灶。

你一定听过这句话:

“现在完成时表示过去发生的动作对现在造成的影响。”

这句话错吗?不错。但它是一个描述,不是一个判据。

问题出在”影响”这两个字上。什么叫影响?影响多大算影响?谁来判定?

恐龙那个例子已经把它击穿了一次。再来一个更贴身的,用母案例:

a. Lin ran the migration on November 12, 2024.
   2024 年 11 月 12 日,Lin 执行了那条迁移。
b. *Lin has run the migration on November 12, 2024.
   2024 年 11 月 12 日,Lin 执行了那条迁移。(?)

那次事故对现在的影响也大到不能再大——Pallet 把所有 schema 变更都搬到了 gh-ost 上,runbook 多了一节”如何中止迁移”,所有生产迁移必须双人 review,Lin 本人的职业生涯都因此转了向,从”第一次独立值班的工程师”变成了”on-call 培训负责人”。**影响巨大,而且是那种看得见摸得着的影响。**但 b 句是错的,任何一个英语母语者都会立刻把它改掉。

所以”影响论”救不了你。它告诉你一个事后能观察到的现象,却没给你开口之前做判断的方法。

同样坑人的还有一句:“现在完成表示动作发生在不明确的过去。”

不明确?多不明确算不明确?November 12, 2024 够明确了吧——那为什么下面这句是对的?

Lin has run production migrations before.
Lin 以前执行过生产环境的迁移。

你看,“before” 也没说清楚是哪年哪月,还是不明确。

**两条传统规则,一条没法判定,一条没法证伪。**难怪你学不会。

5.3 真正的判据:时间窗口是关着的,还是开着的

换一个判据,一个你在开口前就能跑的判据:

看你说的时间区间,到说话这一刻为止,是已经关上了(closed),还是还开着(open)。

  • 封闭区间:这个时间段的终点在说话之前。它已经结束了,成了一个有明确边界的盒子。-> 一般过去时
  • 开放区间:这个时间段从过去一直延伸到说话这一刻,甚至还可能继续往后。-> 现在完成时

就这一条。它操作性极强,因为你只需要做一件事:找时间状语,或者问自己”这个时间段结束了吗”。

先看母案例的三句:

a. Lin ran the migration on November 12, 2024.           (对)
b. *Lin has run the migration on November 12, 2024.      (错)
c. Lin has run production migrations before.             (对)

**a 为什么对?**因为 on November 12, 2024 是一个封闭区间。那一天早就过去了,现在是 2026 年 9 月。事件被装进”2024 年 11 月 12 日”这个盒子里,盒子盖上,封条贴好。盒子里的东西只能用一般过去时往外拿。

**b 为什么炸?**这句话在英语母语者耳朵里的效果是矛盾的:**完成体在说”这扇窗从过去一直开到现在”,而 on November 12, 2024 在说”这个盒子已经关上了”。**两句话打架,句子当场死掉。

不是”不地道”,是语义冲突。就像你写的 const x = 1; x = 2;——不是风格问题,是类型错误。

c 为什么对?before 指向的是”他到目前为止的职业生涯”这个区间。他 2026 年还在 Pallet 上班,所以这个区间现在还开着。窗还开着,于是你可以站在现在往回看,数一数窗里发生过什么。

而且注意 c 句的语感重量:

Lin has run production migrations before.

这句话不是在陈述一个历史事实,它是在给这个人当下的状态下定论。放在复盘会上说出来,潜台词是:“他不是没干过这个,他有经验——所以这不是新手疏忽,是我们的流程让他一个人扛了高风险操作。“你体会一下,这句话是站在 Lin 这边的。blameless 的精神,一半藏在这一个形态里。

同样的味道,换一个主语就更明显:

Pallet has had outages like this before.
Pallet 以前也出过这种故障。

这就不是站在谁那边了,这是在给这家公司贴标签:流程一直有洞,这次不是第一次。同一套形态,换个主语,立场的刀口就转了个方向。

中文怎么翻?只能翻成”他以前执行过生产迁移”,或者加个”过”——**但中文的”过”是可选的,英文的 has run 是强制的。**而且中文那句”以前执行过”,你读出”所以这不是他的错”这层意思了吗?大概率没有。这就是信息的损耗。

5.4 那个必须讲的例子:北京十年

现在上经典的。这一组你肯定见过一百遍了,但我要你用刚才那把新尺子重新量一遍。

a. I have lived in Beijing for ten years.
b. I lived in Beijing for ten years.

先别往下看。这两句是什么意思?说这话的人现在住在哪儿?想三秒,出声答一遍。

中文翻译:

a. 我在北京住了十年。
b. 我在北京住了十年。

**一模一样。**一个字都不差。可意思完全相反:

  • a:我还住在北京。(十年这段时间是开着的,从十年前一直开到现在)
  • b:我搬走了。(十年这段时间已经关上了,成了一个完整的盒子)

**回扣卡点。**你刚才答的时候,如果有一瞬间犹豫过,那你犹豫的那个点就是中文留下的坑:中文那句”我在北京住了十年”,本身不回答”你现在住哪儿”——它只给了你一段时长,没给这段时长的右沿在哪儿。你的犹豫,是中文的信息缺口造成的,不是你英语不好。

而英文那边没有这个缺口:have lived 把右沿钉在现在,lived 把右沿钉在过去某个点。你开口的时候,这个信息是强制声明的,你没法不说。

中文怎么办?只能靠上下文。听的人得追问:“那你现在还住那儿吗?”

**这就是核心卖点现场版:中文翻译几乎一样,但英文思维完全不同。**英文把”你还在不在北京”这个信息焊进了动词形态里,中文把它扔给了上下文。

你可能会反驳:中文也可以说”我在北京住了十年了”啊,那个”了”不就表示还在住?

没错,中文确实有补救手段。但请注意三点:

  1. 那个”了”是可选的。你不加,句子也成立,只是有歧义。
  2. 那个”了”要靠语感用,没有硬性规则,母语者自己也会用错。
  3. 最关键:中文的补救是词汇层的,你想加就加,不想加就不加;英文的区分是形态层的,你躲不掉,你说 I lived 就是在承诺”我已经不住了”。

再补一组,把味道做足:

a. I have worked at this company for five years.   (我还在这儿干)
b. I worked at this company for five years.        (我早就不干了)

如果 b 后面接一句 “Now I’m at another company.”,那顺理成章。如果 b 后面接 “Now I’m the team lead here.”——矛盾,你自己都觉得别扭。

再给一个更狠的:

a. My father has smoked for forty years.    (我爸抽了四十年烟。—— 他还活着,还在抽)
b. My father smoked for forty years.        (我爸抽了四十年烟。—— 多半已经戒烟了,或者人已经不在了)

b 句那种微妙的”往事已矣”感,中文只能靠语气和上下文撑,英文一个形态就交代完了。

5.5 新增弹药:22 个月,开窗还是关窗

再来一组,这组是母案例量身定做的,杀伤力比”北京十年”还大,因为它是一个你真会在汇报里说的话。

a. Pallet has gone 22 months without a P1 incident.
b. Pallet went 22 months without a P1 incident.

中文翻译:

a. Pallet 22 个月没有 P1 事故。
b. Pallet 22 个月没有 P1 事故。

一字不差。意思相反。

  • a(现在完成):这 22 个月是开着的,从那次事故之后一直开到现在,纪录还在保持。这是你在季度复盘、融资材料、客户续约会上说的话。它后面天然接的是”而且我们打算继续保持”。
  • b(一般过去):这 22 个月已经关上了,它成了一段有头有尾的纪录。既然你特意把它当成一个完整的盒子讲出来,言下之意就是——然后又出事了。这句话后面最自然的下文是 “Then, on Thursday, the checkout queue backed up again.”

是不是感觉到了?同样的七个字,一个是庆功,一个是讣告。英文靠一个 has 就把这两者分开了,中文得靠你后面接什么话。

再往下推一层,这一组还能玩出第三种:

c. Pallet had gone 22 months without a P1 incident when the audit began.
   审计开始时,Pallet 已经连续 22 个月没有 P1 事故了。

窗的右沿挪到了 the audit began 这个过去锚点上——这是第 6 节的活,先放这儿,等会儿你会回来认领它。

最后给一个工程味更足的对子,专治”我到底该写 has 还是不写”:

a. The runbook has had an abort section since November 2024.  (现在有,而且从那时起一直有)
b. The runbook had an abort section in 2025.                  (2025 年那版有 —— 现在还有没有,我不保证)

b 句那种”我不保证”的味道,在事故复盘里是要命的。你想说的是”我们现在有这一节,所以值班的人知道怎么中止”,你就必须写 a。写成 b,读者会以为你在讲某个历史版本的往事,甚至可能在想”所以后来是不是又被删了”。

卫星案例:老同学失联十年(社交领域)

这一条规则的杀伤力,跟技术、跟工程、跟电商 SaaS 一点关系都没有。

2026 年春节前,你在一个初中同学群里被人 @ 了出来。对方叫陈舟,你俩初二同桌,初三他转学去了外地,此后失联。你们约了腊月二十八晚上在五道口一家火锅店见面。见面之前,你在群里跟别人介绍这件事:

a. We haven't seen each other for ten years.
b. We didn't see each other for ten years.

中文两句都是”我们十年没见了”,一字不差。英文那边:

  • a(现在完成):十年这段”没见”的状态到现在还开着。这是你在推开包厢门之前说的话——失联状态此刻仍然成立,马上就要被打破。它天然接的下文是 “So this is going to be weird.”(所以一会儿见面肯定挺怪的。)
  • b(一般过去):那十年已经关上了,成了一个有头有尾的盒子。这是你们见完面、加回微信、三个月之后,你跟别人转述往事时说的话。它天然接的下文是 “Then he messaged me on WeChat last spring.”

中文怎么办?只能靠:“我们十年没见了(还没见着呢)“和”我们那时候十年没见(后来又联系上了)“——你得自己加括号。

再加一句,看持续感:

c. We have been trying to find each other for ten years.
   我们找了对方十年。

这句是你们见面之后、喝到第三瓶啤酒时说的。完成进行体在这里同时干了两件事:“找了十年”是过程,“现在终于找着了”是结果。中文那句”找了十年”,你读得出”找着了”这三个字吗?读不出来,得看上下文。

卫星案例:戒烟(医疗 / 健康领域)

再换一个领域,这次是体检报告上的老问题。你三十四岁,抽了十二年烟,2026 年 3 月公司体检,医生在报告上画了两条红线。

a. I have tried to quit four times.
b. I tried to quit four times.

中文都是”我戒过四次”。英文那边,这两句讲的是两种完全不同的人生现状:

  • a(现在完成):四次失败的戒烟经历,全都落在我到现在为止的人生这扇窗里。窗还开着——**言下之意是:我还在抽。**这句话后面接的是 “The longest I made it was eleven days.”
  • b(一般过去):那四次已经封进盒子里了。这句话最自然的下文是 “and the fifth one stuck”(第五次成了)——你现在是不抽烟的人。

医生问你 Have you ever tried to quit?,他不是在问你的历史,他是在给你现在的处方做判断:既往失败过,说明光靠意志力不行,得换方案。**窗里有什么,决定了现在该开什么药。**这就是完成体在医疗问询里高频出现的原因——它天然就是”到现在为止的累积病历”。

你看,从 Pallet 的生产库,到老同学的火锅店,到体检报告上的两条红线——**同一条规则,三个领域,一模一样。**它不是”工程英语”的规则,它是英语的规则。

5.6 为什么:一扇窗和一个盒子

规则记不住,是因为没画面。给你两个画面。

一般过去 = 一个已经关上的盒子。

[  == 2024-11-12 ==  ]                        # now (2026-09)
   ^ 事件在盒子里

盒子有明确的左边界和右边界,右边界在”现在”左边。事件被封在里面。你要谈盒子里的东西,你就必须站在盒子外面回头看——这就是一般过去时。

现在完成 = 一扇从过去一直开到现在的窗。

[  ===============================# now (2026-09)
   ^ 窗从这里打开,一直开到现在

窗的左沿在过去某个点,右沿贴着现在。你站在窗前往里看,看到的是”从开窗到现在”这段时间里累积的东西。

**完成体的本质,就是”一扇右沿贴着现在的窗”。**这就解释了一切:

第一,它为什么不能跟封闭时间状语连用。 因为封闭状语会说”窗已经关了”,跟”窗开着”直接冲突。

a. *I have seen her yesterday.     (错,yesterday 说窗关了)
b. I saw her yesterday.            (对)
c. I have seen her this week.      (对,this week 还没过完,窗开着)
d. *I have seen her last week.     (错,last week 关了)

注意 c:this week 是开着的(这周还没结束),所以能用完成体。但如果今天是周日晚上,这周事实上已经过完了,母语者会改说 I saw her this week.——**因为窗口关了。**看到没有,判据不是死记”this week 用完成体”,而是问”这段区间现在还开着吗”。

第二,它为什么天然带”到现在为止”的意思。 因为窗的右沿就在现在。I have read three reports so far. = 截至此刻,三份。Lin has run production migrations before. = 截至此刻,他的职业记录里有这么一笔。

第三,它为什么能表达”经历”。 窗开着,你就能往里数东西。Have you ever been paged at 3 a.m.?(你这辈子有没有在凌晨三点被呼叫过)——问的是你的人生这扇窗里有没有这个东西。这句在我们这行几乎是社交暗号,而它的时态是硬性要求:只要你还在这个行业里,这扇窗就开着,你只能用现在完成时问。

第四,它为什么不能用在已经死了的人身上。

a. *Einstein has visited Princeton.      (错)
b. Einstein visited Princeton.           (对)

因为爱因斯坦的”人生之窗”已经关上了。你能说 My grandfather has traveled to thirty countries. 只要他还活着;他一走,你只能说 My grandfather traveled to thirty countries.

这条在工程圈里有个活生生的变体:你不能说某个已经下线的服务”至今如何如何”。

a. *The v1 checkout service has handled 4 million orders.   (它已经下线了,窗关了)
b. The v1 checkout service handled 4 million orders.        (对)

第五,为什么”刚发生的事”用完成体。

a. Marcus has just emailed Northwind.       (Marcus 刚给 Northwind 发了邮件。)
b. Marcus emailed Northwind a minute ago.   (Marcus 一分钟前给 Northwind 发了邮件。)

a 里那个 just 把事件的右沿贴到此刻,所以它属于”开着的窗”。b 里 a minute ago 把事件封进”一分钟前”那个小盒子,窗关了。

(顺便说一句:美式英语在这件事上比英式宽松得多。美国人完全会说 Did you eat yet? 和 I just ate.,英国人会觉得应该 Have you eaten yet? 和 I've just eaten.。美式的逻辑是:just / yet / already 已经把”距现在很近”这层意思表达清楚了,形态上就不必再重复一遍。这是语言在演化,不是谁错了。但考试和正式写作按英式走,你心里有数就行。)

5.7 现在完成的”四种用法”其实是同一件事

教材喜欢把现在完成拆成四种用法让你背:

  1. 表示结果(I’ve lost my keys. 钥匙丢了,现在没钥匙)
  2. 表示经历(I’ve been to Japan. 去过日本)
  3. 表示持续(I’ve known her for years. 认识她好多年了)
  4. 表示刚刚发生(He has just left. 他刚走)

别背这四个。它们是同一个机制在不同语境下的四种外观:

窗从过去开到现在,你站在窗前往里看 —— 你看到的可能是”留下的状态”(结果),可能是”窗里有没有这个东西”(经历),可能是”这个东西在窗里延续了多长”(持续),可能是”它刚进窗”(刚刚)。

窗还是那扇窗。变的只是你看的位置。

用母案例各来一句:

a. Pallet has moved every schema change onto gh-ost.        (结果:现在的流程已经变了)
b. Lin has run production migrations before.                 (经历:他的职业记录里有这么一笔)
c. Pallet has gone 22 months without a P1 incident.          (持续:从那之后一直如此)
d. Lin has just finished rewriting the on-call runbook.      (刚刚:窗沿上的新东西)

四句中文翻译:“Pallet 已把所有 schema 变更搬到 gh-ost 上""Lin 以前执行过生产迁移""Pallet 已经 22 个月没有 P1 事故""Lin 刚写完 on-call runbook 的重写”。

中文靠”已""过""已经""刚”这四个不同的词来区分,英文靠同一套 has + 过去分词,靠语境决定你看到的是哪一种。

再用两个别的领域的例子验一遍,因为”四种用法”这种说法最容易被背成”四种情况”。

卫星案例:体检报告(医疗领域)

公司体检出结果那天,你在食堂跟同事聊:

a. My LDL has been high for three years.     (结果 + 持续:这三年一直高,现在还高)
b. My LDL was high in 2023.                  (一般过去:2023 年那次高,现在怎么样我不说)
c. The doctor has flagged two items this year.(刚刚:报告刚出,两条红线在那儿)
d. My LDL was climbing before I started running.(背景/持续回溯:开始跑步之前它在往上走)

四句中文:“我低密度脂蛋白这三年一直高""我 2023 年那次低密度脂蛋白高""医生今年标了两项""我开始跑步之前它一直在往上走”。

注意 b 那种”我不说现在”的味道在体检这种场合特别微妙——**你说 b,同事会以为你在暗示现在不高了。**如果你想说的是”现在还是高”,你只能说 a。一个 has,把”我需要你现在就重视这件事”这层意思说完了。

卫星案例:快递显示已签收(生活领域)

周一你在网上下单了一箱书,物流信息周三就变成”已签收”,但家门口什么都没有。周五你打客服电话:

a. The tracking has said "delivered" since Wednesday, but nothing has arrived.
   物流信息从周三起就显示"已签收",但东西到现在也没到。
b. I have been waiting for this parcel for four days.
   这个包裹我等了四天了。
c. I waited four days and then filed a complaint.
   我等了四天,然后投诉了。
  • a 里两个现在完成并排:has said 是”从周三一直开到现在”的状态,has arrived 加否定是”到现在为止窗里没有这个东西”。中文那句”东西到现在也没到”,那个”到现在”是你自己加的——英文是 has arrived 里自带的。
  • b 是完成进行体,它比 a 多了一层情绪:**“我等了四天,而且还在等,我很不高兴。“**客服听到这句,反应跟听到 a 是不一样的。
  • c 换成一般过去,整件事立刻变成”已经处理完的一桩往事”——窗关了,箱子里装着”等了四天”和”投诉了”两件东西。你还在等件儿的时候,绝不能说 c。

顺便留意一下 b 和 c 的中文:“我等了四天了” vs “我等了四天”。差别全在末尾那个”了”上,而这个”了”是可加可不加的。

有意思的是方向反过来了:在”现在完成 vs 一般过去”这一对上,中文模糊、英文精确;在”四种用法”这一组上,中文精确(有专门的词)、英文模糊(共用一套形态)。**没有哪种语言整体更精确,只有分工不同。**这一点值得你停下来想十秒。

想明白这一点,你就不会再去背”现在完成四用法”那张表了。你会改问一个问题:**我这扇窗,现在是开着的吗?**问完,形态自己就出来了。

5.8 回母案例:一整段里时态是怎么选的

看一段完整的叙事,把这一节的东西用起来。假设这是 2026 年一篇内部回顾文章的开头:

At 2:14 a.m. on 12 November 2024, Lin Wei ran a database migration
against Pallet's orders table. He was eight months into the job and
had never run one alone. He did not use gh-ost. By the time he woke
up at 2:26, the error rate had already hit 34%. Priya Nair killed
the migration connection at 2:47, and the service recovered at 3:05.
Fifty-one minutes, 12,300 failed orders, no data loss.

Pallet has since moved every schema change onto gh-ost. The team has
added an abort section to the runbook. Pallet has gone 22 months
without a P1 incident. Lin now runs on-call training.

中文:

2024 年 11 月 12 日凌晨 2:14,Lin Wei 对 Pallet 的 orders 表执行了一次
数据库迁移。他当时入职八个月,此前从未独立执行过迁移。他没有使用
gh-ost。等他 2:26 醒来时,错误率已经冲到 34%。Priya Nair 在 2:47
kill 掉了那条迁移连接,服务于 3:05 完全恢复。51 分钟,12,300 笔
下单失败,没有数据丢失。

此后,Pallet 已把所有 schema 变更搬到 gh-ost 上,团队给 runbook 补了
一节"如何中止",Pallet 已经有 22 个月没有 P1 事故。Lin 现在负责
on-call 培训。

数一数这段话里的时态选择:

  • ran —— 一般过去。封闭时间状语 At 2:14 a.m. on 12 November 2024 直接把后面整个叙事段落锁进盒子里。
  • was —— 过去进行。“入职八个月”是一个持续的背景状态,不是推动情节的动作。
  • had never run —— 过去完成。往回跳,交代”此前没独立干过”这个在主要事件之前的状态。
  • did not use —— 一般过去。叙事主线上的一个点,而且它是整段话里信息量最大的一个点。
  • had already hit —— 过去完成。锚点是 he woke up,往回跳。
  • killed / recovered —— 一般过去。叙事主线,两个连续动作。
  • has moved / has added / has gone —— 现在完成。注意这里发生了什么:叙事视角从 2024 年那个盒子跳回了 2026 年的现在,重新打开一扇窗,讲”从那以后到现在”的情况。
  • runs —— 一般现在。当下的常态事实(他现在的职责)。

最后四句最重要。since 这个词(“此后”)在中文里是个可有可无的副词,在英文里它直接决定了前三句必须用现在完成——因为 since 的意思就是”从过去某点一直到现在”,这是最典型不过的开放区间。

你把 since 拿掉,换成 In December 2024, Pallet moved every schema change onto gh-ost.,时态立刻得改成一般过去。中文那边,“此后”和”2024 年 12 月”的差别,你需要读者自己去品;英文这边,动词形态替你把话说死了。

还有一处值得单独拎出来:Fifty-one minutes, 12,300 failed orders, no data loss. 这三个名词短语里一个动词都没有。中文也是一样好懂。这说明什么?说明时间坐标这个维度,是靠动词形态承载的;一旦你不用动词,这层信息就整块消失了。名词化是第七面的主题,这里先埋个雷:你想把”谁干的”抹掉的时候,名词化是最好用的一把刀——而 blameless 复盘恰恰经常需要这把刀。

5.9 一个能立刻用的检查清单

写到英文句子,拿不准用一般过去还是现在完成,按这个顺序问:

  1. 句中有没有明确的过去时间状语?(yesterday、in 2024、last week、when I was a kid、at 2:47 a.m.、on 12 November)-> 有,就一般过去。没得商量。
  2. 有没有开放区间的信号词?(ever、never、so far、since、for、yet、already、just、up to now、in my life、this week/month 尚未结束、for 22 months)-> 有,就现在完成。
  3. 都没有?问自己:我说的这件事,它所属的时间段现在结束了吗?
    • 结束了(比如谈一个已故的人、谈一份已经离职的工作、谈一段已经翻篇的时期、谈一个已经下线的服务)-> 一般过去
    • 没结束(谈你到现在为止的人生、谈还没结束的项目/星期/年份、谈一个还在跑的服务)-> 现在完成

三条跑完,百分之九十五的场合都能定。

剩下那百分之五,是英美差异、是语体差异、是说话人想不想”拉近”这段经历。那些是语感问题,得靠读得多了才有,不急。

现在回头再看一眼那个流传最广的规则——“现在完成强调对现在的影响”。

它错了吗?没错。只是它描述的是结果,不是原因。真正的原因是:**窗还开着。**而窗开着的时候,窗里的东西自然就跟你当下的处境有关,于是看起来就像”对现在有影响”。

把”影响”换成”窗口”,你就从”靠感觉猜”变成了”按流程判”。


6. 过去完成时:不是”过去的过去”,是”叙事倒带”

卡点 E:这句话语法有问题吗?

就一句话,别多想:

The migration had locked the orders table.

先别往下看,想三秒,回答两个问题:

  1. 这句话语法有没有问题?
  2. 如果没问题,那你读着别扭吗?别扭在哪?

答完了?我猜你的答案是这样的:

“语法没问题。had + 过去分词,标准的过去完成时,主谓一致也对,locked 是 lock 的规则过去分词。读着……好像是有点别扭,但说不上来别扭在哪。”

恭喜,你掉进去了。而且这个坑是教材亲手挖的。

先回答第一个问题:**语法确实没问题。**这句话的每一个部件都合法,你把它丢进语法检查器,一个错都不会报。

第二个问题才是真问题:你为什么读着别扭?

八成有人会这么解释:“因为过去完成时表示’过去的过去’,这句话里没有’过去’可以参照,所以别扭。”

对,但那只答了一半。而且这一半是最没有操作价值的那一半——它只告诉你”缺东西”,没告诉你缺的东西长什么样、该怎么补。

真正的原因是:

过去完成时是一个”相对形态”。它不自己设原点,它必须指向上下文里已经存在的另一个过去时间点。孤立地给出,它就悬在半空。

你刚才觉得”话没说完”,是因为你的语感在等一句话——**“这句是相对于哪个时间点往回跳的?“**没有答案,句子就落不了地。

语法书会告诉你:had locked 是”过去的过去”,表示”在过去某个时间点之前发生的事”。

这话对不对?对。有没有用?几乎没用。

因为它描述的是”这个形态标记的时间关系”,却没告诉你这个形态真正的用法条件。而如果你不知道那个条件,你就会造出这种句子——而且这种句子在很多词汇书、词典、乃至语法书的例句里,天天出现:

(孤立地给出,前文不搭后文)
The migration had locked the orders table.

你读到这句什么感觉?你会觉得话没说完,会下意识等一句”然后呢?“或者”所以呢?”。

你的感觉是对的。这句单独拿出来就是别扭的——不是你水平不够,是例句本身缺了零件。

6.1 呼应本书的缘起

本书为什么要设计”一个事件、十个切面”这种结构,为什么母案例必须是一个有头有尾、有时间线、有上下文的完整事件——答案就在这一节。

因为英语的很多形态不是句子级的,是语篇级的。它们不能在一句话里独立成立,必须指向上下文里的某个东西。过去完成时就是最典型的一个。

你在词汇书里看到的那些孤立例句,语法上百分之百合法,但语感上百分之百别扭。原因不是你水平不够,是例句本身缺了零件。

缺什么?缺一个锚点(anchor)。

母案例这次又帮了大忙,因为它自带一串精确到分钟的锚点:2:14、2:17、2:19、2:26、2:31、2:37、2:44、2:47、2:52、3:05。过去完成时这种”必须找锚”的形态,在这条时间线上几乎是想怎么用就怎么用——你随手抓一个时刻当 HEAD,剩下的全都能当倒带的目标。

6.2 过去完成时的真身:一扇右沿贴着过去的窗

还记得上一节那个画面吗?

  • 现在完成 = 一扇从过去开到现在的窗
  • 过去完成 = 一扇从过去开到过去某个锚点的窗

就这点区别。

现在完成:  [=====================# now ]
过去完成:  [=============# anchor ]            now 在更右边
                          ^ 窗的右沿贴在这里

所以过去完成时根本不是”过去的过去”这种朴素说法。它是完成体在过去方向上的一次应用:把窗的右沿,从”现在”挪到”叙事中的某一个过去时刻”。

它真正的功能不是标时间,而是发信号:

注意,我现在要离开当前时间线,往回跳了。下面这句是背景,不是主线。

它是一个闪回标记(flashback marker),是叙事的倒带键。

6.3 母案例:加一个锚点,句子立刻活

a. (孤立,别扭)The migration had locked the orders table.
b. (有锚,自然)When Lin woke up at 2:26, the migration had already locked the orders table.

b 句的锚点是 Lin woke up。had locked 这扇窗的右沿,贴的就是”他醒来”这个时刻。

再给几组,体会一下锚点是怎么起作用的:

a. When Priya joined at 2:44, Lin had been trying to kill the
   migration for ten minutes.
   Priya 2:44 上线的时候,Lin 试图中止迁移已经试了十分钟。

b. By the time Priya killed the connection at 2:47, 12,300 orders
   had already failed.
   Priya 在 2:47 kill 掉那条连接时,已经有一万两千三百笔下单失败了。

c. The migration had been running for three minutes before the
   first alert fired.
   第一条告警触发之前,那条迁移已经跑了三分钟。

d. Lin had read the runbook twice, and neither time had it mentioned
   how to abort a migration.
   Lin 把 runbook 读了两遍,两次都没提到怎么中止迁移。

注意 b 句里的 already。这个词在过去完成的句子里出现频率极高,不是巧合——**already 在说”到那个锚点为止,这件事已经完成了”,跟”窗的右沿贴着锚点”是同一个意思的两种说法。**它们是天然搭档。

再看 d 句,它藏了一个更细的东西:had read 是倒带,但倒带之后句子没回来,而是在倒带的状态里又往前走了两步(读了两遍,两遍都没有)。这就是过去完成时的典型用法:**进去一小段,讲完背景,立刻回到主线。**你不能一直待在倒带里。

卫星案例:手机落出租车(生活领域)

换一个跟机房毫无关系的场景,验一遍”锚点”这件事。

2026 年 4 月的一个雨夜,你从国贸打车回双井。下车七分钟之后你摸口袋——手机没了。

a. I was paying when the taxi pulled away.
   我正在付钱的时候,车开走了。

b. By the time I called my own number, the driver had already
   handed the phone in to the lost-property office.
   我拨自己号码的时候,司机已经把手机交到失物招领处了。

c. I had left it on the back seat.
   我把它落在后座上了。(孤立,别扭)
  • a 是”进行体搭台、一般体唱戏”的标准配置:was paying 是一条进行中的线(背景画面),pulled away 是一个点(打断那条线的事件)。这个组合是英文叙事里出现频率最高的句型,没有之一。
  • b 有锚点(I called my own number),had handed 往回跳,交代”在我打电话之前,事情已经发展到这一步了”。自然。
  • c 孤立拿出来,跟卡点 E 里那句一样别扭。你得给它接上锚点——I had left it on the back seat, and by the time I called, the driver had already handed it in.

有意思的是中文。这三句中文”我正在付钱的时候车开走了""我拨自己号码的时候司机已经把手机交了""我把它落在后座上了”——全靠”正在……的时候""已经”这几个词,而且你去掉它们句子依然成立,只是读者得多猜一下。英文那边,去掉 was、去掉 had,句子直接变成另一件事。

**这条规则不是”过去完成时是工程文档的专利”。**它是一条叙事规则,你在讲任何一件有前因后果的事时都在用——丢手机、丢钥匙、丢行李,全都一样。

6.4 一个反直觉的事实:过去完成时经常是”可以不用”的

这一条很多教材不讲,但它能救命。

先看这句:

After the migration locked the orders table, checkout requests began to fail.
迁移锁住 orders 表之后,下单请求开始失败。

这里 locked 用的是一般过去,不是 had locked。为什么可以?

因为 after 已经把时间顺序交代清楚了。既然顺序清楚,倒带标记就是冗余的。

对比:

a. The migration had locked the orders table. Then checkout requests began to fail.
b. The migration locked the orders table. Then checkout requests began to fail.

两句都成立。a 句更”书面”、更像事故报告,因为它显式地打了倒带标记;b 句更”顺”,像口头讲事情经过。

这说明什么?说明过去完成时是英语里少见的、“语义上可有可无”的形态。

你想,ran 能不能换成 run?不能,时态错了。was running 能不能换成 ran?能,但意思变了。而 had locked 换成 locked,意思几乎不变,只是少了一个”我要倒带了”的信号。

这个事实很重要:凡是”意思不变但可选”的语法手段,它的功能一定在语篇层面,不在命题层面。过去完成时不是用来告诉你”事情发生在更早”(那是 after/before 的活),它是用来帮你管理读者的注意力的。

用程序员的话说:它不是数据本身,是光标位置。

6.5 git 类比

这个类比对 Go 后端应该特别有效。

把叙事想象成一次 git 提交历史:

commit 8f3a1  (HEAD)  ->  Priya killed the connection at 2:47.
commit 2b7c4          ->  Lin was trying to kill the migration.
commit 91e05          ->  Lin woke up at 2:26.
commit 4d9f2          ->  Lin ran the migration at 2:14.

讲故事的默认状态是:HEAD 就停在当前正在讲的那个 commit 上,你按顺序往回或者往前走。

git log 顺着时间线读,就是一般过去时——每个 commit 都是一个点,你一个一个念过去。

现在你想插入一段背景:

$ git checkout 4d9f2        # 离开 HEAD,回到更早的 commit

你离开了当前位置,往回跳。这就是过去完成时。它不是”更早的提交”,它是”你现在离开 HEAD 去看的提交”。

所以为什么会别扭?因为孤立句里没有 HEAD。你连当前在哪儿都不知道,我怎么知道你”往回跳”?

The migration had locked the orders table.     # 没有 HEAD,checkout 失败

而一旦给了锚点:

When Lin woke up at 2:26, the migration had already locked the orders table.
# HEAD = 他醒来的那一刻,checkout 成功

HEAD 有了,checkout 成功,句子立刻通顺。

再补一句:git checkout 之后你处在 “detached HEAD” 状态——你不在主线上了。过去完成时也是这样:它标记的内容是离线的背景,不是叙事主线。你讲完背景,还得 git checkout - 回到主线继续讲。

这就是为什么一段叙事里过去完成时永远是”插入一小段然后回来”,不会连着用十句。连着用十句,读者就晕了:我到底在哪条时间线上?

顺手说个工程上的对照:事故时间线(timeline)那种文档,恰恰是最需要”主线 + 偶尔倒带”的文体。你写 02:47 Priya killed the connection.,这是主线;你想补一句 Lin had already tried three different approaches by then.,这是倒带。一篇好的事故报告,倒带句永远紧贴它的锚点,绝不隔三段再倒一次。

6.6 三个容易踩的坑

坑一:把过去完成时当成”更早”的默认选项。

a. Lin had started the migration, had locked the table, had read
   the runbook, and had paged Priya.     (错,极不自然)
b. Lin started the migration, locked the table, read the runbook,
   and paged Priya.                      (对)

四个动作按时间顺序发生,主线推进,不需要倒带。全用过去完成,读者以为你在每个动作之间反复倒带,累死。

坑二:把 now 当成锚点。

a. *I had finished the report.    (说完就等着,没有上下文)
b. I have finished the report.    (对,我现在做完了)

如果你的锚点其实就是”现在”,那应该用现在完成时。

坑三:以为”过去完成 = 过去 + 现在完成”。

不对。看这组:

a. I have lived there for ten years.      (现在还住着)
b. I had lived there for ten years when it burned down.
   (那房子烧毁的时候,我在那儿已经住了十年)

b 的窗右沿贴的是”房子烧毁”那一刻,不是现在。所以 “住了十年”这个状态到房子烧毁时为止,之后住不住,句子不管。

母案例版同样成立:

c. Pallet has gone 22 months without a P1 incident.        (到现在为止,纪录还在)
d. Pallet had gone 22 months without a P1 incident when
   the Northwind audit began.
   (Northwind 那次审计开始时,Pallet 已经连续 22 个月没有 P1 事故了。)

d 承诺的是”到审计那一刻为止是 22 个月”,审计之后又出了什么事,这句不保证。

中文怎么翻?“那房子烧毁的时候,我已经在那儿住了十年了。” / “审计开始的时候,Pallet 已经 22 个月没有 P1 事故了。“——还是得靠”已经”和上下文。同样的模糊,同样的问题。

卫星案例:差一分没考上(学习领域)

坑三还有一个变体,它专坑”差一点”这种语境。

你表弟 2024 年考研,分数线 365,他考了 364。2026 年他第三次备考,过年的时候你在饭桌上问他:

a. I missed it by one point in 2024.
   我 2024 年差一分没考上。

b. I have missed it by one point twice.
   我差一分落榜两次了。

c. I had missed it by one point once before I changed my major.
   我换专业之前,已经有过一次差一分落榜了。
  • a(一般过去):in 2024 是封闭区间,那一次被封进盒子里。这是历史陈述,后面接”然后我换了专业”。
  • b(现在完成):窗开着,窗里躺着两次”差一分”。**这句话的力量在于它不是在讲历史,它是在描述他现在的状态——一个被一分卡住两次的人。**后面天然接的是 “So this time I’m not taking any chances.”
  • c(过去完成):锚点是 I changed my major,往回跳。

中文三句:“我 2024 年差一分没考上""我差一分落榜两次了""我换专业之前已经有过一次差一分了”。第三句那个”已经”和”之前”,是你自己加的;英文里它们焊在 had 和 before 里。

注意 b 和 c 里那个”两次/一次”的差别:**现在是第几次备考,决定了窗里躺着几次。**中文的”两次”是数出来的,英文的 have missed ... twice 是”站在窗前往里数”——这两件事在英文里是同一个动作。


6.7 卡点 B:明天下午三点的评审会,你怎么说?

我们把镜头从过去挪到将来,先卡一下。

下面这句中文,请你翻成英文。就一句,很简单:

明天下午三点的评审会。

不对,太省了。给全一点:

明天下午三点有个评审会,我参加。

先别往下看,真的在心里翻一遍,最好出声翻一遍。


翻完了?我猜你翻出来的是这几种之一:

a. I will attend the review meeting at 3 p.m. tomorrow.
b. I'm going to attend the review meeting at 3 p.m. tomorrow.
c. I'm attending the review meeting at 3 p.m. tomorrow.
d. I attend the review meeting at 3 p.m. tomorrow.

四种你都会翻,四种都没语法错误。问题来了:你怎么知道该用哪个?

我猜你翻的时候,脑子里跑的程序是这样的:“将来 -> 用将来时 -> will。“然后如果你多想了一秒,你会补一句:“或者 be going to,它跟 will 差不多吧。”

这就是问题所在:你把将来当成了一个格子,而英语在那个位置上摆了四个。

而且更要命的是:这四句在中文里只能翻成一种说法。“明天下午三点我要参加评审会”——你说完这一句,听的人不会追问你是哪种将来。中文根本不标记这个。

所以你从小到大做的一千道”用将来时翻译”的练习题,其实都在骗你:它们给你一个格子,让你填一个答案,而真实的英语在那个位置上是有四个选项的,而且四个都对——取决于你想说什么。

差别在哪?

  • a(will):宣告 / 告知。你在群里同步行程,客观陈述”我会去”。最冷、最中性。
  • b(be going to):意图已定。你早就决定要去了,现在说出来,或者你觉得”这事已经板上钉钉”。
  • c(现在进行时):流程已启动。日历邀请发出去了,你接受了,材料都准备好了。它暗示的是”我明天这个时间段已经被占掉了”。
  • d(一般现在时):时刻表。这是排期表上的一行字,跟”火车九点开”一个性质。在日常对话里最不自然,但在”我的日程/值班表/课程安排”这类语境里恰恰最地道。

回扣卡点:你刚才翻不动,不是因为你不会将来时,是因为中文那句话里根本没写”我想调用四种里的哪一种”。你在翻译的时候凭空丢掉了一个英文必须声明的信息。这是翻译缺口型卡点的典型形态——中文不说,英文必须说;你不知道该说什么,于是你随便挑了一个最眼熟的。

下一节我们把这四种放在真实叙事里演一遍,并且告诉你它们的差别是有来历的,不是约定俗成。


7. 将来时的四种说法:用母案例演一遍

第 3 节讲过”化石”,这一节把它们放进真实叙事里,再补一条硬规则。

假设我们跟着故事走到 2024 年 11 月 13 日早上:服务已经恢复,复盘会定在十点,三条行动项的草稿已经在文档里了。

7.1 第一种:will —— 预测与宣告

The team will adopt gh-ost for all schema changes.
团队将为所有 schema 变更采用 gh-ost。

这里的 will 是宣告。说话人(写复盘文档的人、通报给客户的 CSM)在陈述一个将要发生的事实,不带个人意志,不带当下迹象,就是”照决定走,会这样”。

它也可以带意志:

I'll write the runbook section myself.      (我来亲自写那一节 runbook。)

这句是 Priya 在会上当场拍板说的。你能感觉到那股”这事我扛了”的劲儿——这就是 will 里”意志”的残渣。换成 I'm going to write... 就变成了”我早就打算自己写了,现在通知你们一声”,味道差很远。

注意一个有意思的现象:will 用在正式文件、事故通报、工程规范里频率特别高。为什么?因为那些文体的立场就是”客观宣告”,正好是 will 打磨得最干净的那层意思。你去看任何一份公开的 incident report,“We will do X” 出现的频率远高于 “We’re going to do X”。不是巧合。

7.2 第二种:be going to —— 有迹象,或意图已定

We're going to add a runbook section on aborting migrations.
我们要给 runbook 补一节"如何中止迁移"。

跟 We'll add a runbook section... 中文一模一样,英文差在哪?

  • are going to:**事情已经在推进了。**复盘文档里已经列了这条行动项,负责人已经填上了名字,工单号都生成了。说话人是基于这些迹象推断的。
  • will:可以是纯宣告(“团队将补上这一节”),也可以是说话人此刻的预测或承诺。

再看一个更有画面感的:

Look at the postmortem doc — they're going to require two-person review
for every production migration.
看这份复盘文档——他们要对所有生产迁移强制双人 review 了。

“看这份文档”就是当下迹象。你把 they're going to 换成 they will,那股”我指着证据跟你说话”的劲儿就没了。

7.3 第三种:一般现在时 —— 时刻表

这条最反直觉,因为它压根没用任何将来标记。

The postmortem starts at 10 a.m.
复盘会上午十点开始。

The rotation flips on Monday.
值班轮换周一交接。

The next audit is in March.
下次审计在三月。

为什么”现在时”能说将来的事?

回到第 2 节那个判断:一般现在时的本质,是把一件事说成”无时间性的属性”。

火车九点开——这不是一个”事件”,这是时刻表上的一行字。时刻表是写死的、不受时间影响的。所以英语用一般现在时:不是说”它将来会开”,是说”这趟车的属性就是九点开”。

这就是为什么能用一般现在时表将来的,都是写死的东西:班次表、日程表、会议邀请、节假日、课程表、值班轮换表。

你不能说 *I start a new job when I feel like it. 因为那不是写死的。但你可以说 The rotation flips on Monday. 因为那是排班表写死的。这条在我们这行特别好使——值班轮换、发布窗口、冻结期、审计日期,全都是”写死的一行字”。

7.4 第四种:现在进行时 —— 已经排进日程

Marcus is meeting Northwind at 11.
Marcus 十一点跟 Northwind 开会。(邀请已经发出去了)

这句的重点不是”十一点”,是”这件事已经启动、已经安排妥当”。跟 Marcus will meet Northwind at 11. 比,后者只是陈述一个安排,前者强调流程跑起来了:日历邀请发出去了,对方接受了,材料都在准备。

再补一个特别典型的:

Priya is running the postmortem at 10.
Priya 十点主持复盘会。

这就是第 3.3 节那块化石本尊——“正在进行”意味着”已经启动、不可撤销”。

7.5 四句并排,中文全一样

a. The team will adopt gh-ost in Q1.
b. The team is going to adopt gh-ost in Q1.
c. The team adopts gh-ost in Q1.
d. The team is adopting gh-ost in Q1.

中文:

a. 团队第一季度采用 gh-ost。
b. 团队第一季度采用 gh-ost。
c. 团队第一季度采用 gh-ost。
d. 团队第一季度采用 gh-ost。

十一个字,四句话,一字不差。**英文那边是四块不同地质层的化石在打架。**你要选的不是一个”将来时”,是一个”视角”。

  • a:这是复盘文档里的正式决定,说话人在宣告。
  • b:工单都建好了,说话人指着证据说这事已经在路上。
  • c:季度路线图上的一行字,跟火车时刻表一个性质。
  • d:有人在推了,每周站会同步进度,不可撤销。

卫星案例:项目延期(工作领域)

换一个完全不涉及数据库迁移的场景——一个会员小程序的改版项目。

你们团队给华东一家连锁便利店做会员积分小程序,原定 6 月 30 日上线。6 月 10 日,技术负责人张侃在周会上发现:十六个接口只联调完九个,测试团队还没进场。新日期定在 7 月 30 日。

同一件事,四个场合,四个说法:

a. We will ship on July 30.
b. We're going to ship on July 30.
c. We're shipping on July 30.
d. The new date is July 30.

中文全是”我们 7 月 30 日上线”。英文那边:

  • a(will):这是写给客户的正式延期函里的句子。客观、冷静、不带情绪,说话人跟这件事保持距离——“照目前的决定,上线日期是 7 月 30 日”。你去看任何一封对客的延期通知,“will” 出现的频率都远高于其他三种,不是巧合,是因为正式文书的立场就是”客观宣告”。
  • b(be going to):这是张侃在周会上看着燃尽图说的话。他手上有当下的证据:还剩七个接口,测试没进场,按这个速度——7 月 30 日。这句里有”我指着进度表跟你推算”的劲儿。
  • c(现在进行时):这是新的排期表发出去之后的说法。测试窗口约好了,灰度计划排上了,客户方的验收人也确认了时间——流程跑起来了,不好再改。
  • d(一般现在时):这是项目看板上那一行字。最冷,最”写死”,跟”火车九点开”一个性质。

有意思的是这四种说法在同一个项目里会按时间顺序依次出现:

第一周,你看着燃尽图说 b(我估计得推到七月底);第二周,跟客户谈完、新排期表发出去,你说 c(我们就定七月三十了);第三周,延期函盖章发出,写的是 a;最后,看板上那行字改成 d。

**同一个事实,四个阶段,四块化石。**中文全程只说一句”七月三十上线”。

顺带戳一个高频错误:

*We're going to ship on July 30 if the client approves the new design.

条件句里塞 be going to,别扭。因为 be going to 要的是”当下的迹象”或”已定的意图”,而 if 构造的是一个还没发生的假设世界——你在那个世界里找不到迹象可看。改成 We'll ship on July 30 if the client approves the new design. 就顺了。这一条 7.6 之后会再回来。

7.6 硬规则:时间状语从句里,不用 will

这条规则值得单独讲,因为它出错率极高,而且它有道理。

a. When the postmortem begins, Priya will open with the timeline.        (对)
b. *When the postmortem will begin, Priya will open with the timeline.   (错)

为什么 b 错?

很多教材只说”记住就行”。但这件事是有原因的。

因为从句的时间已经被主句锚定了,不需要再标一次。

主句 will open 已经把整句话钉在将来。从句 when the postmortem begins 的作用是给出参照点,不是再设一个原点。既然主句已经说了”将来”,从句再说一次就是冗余。

用第 2 节的坐标系语言讲:**一个句子里,主句负责设原点,从句只负责相对这个原点定位。**所以从句退化成现在时——它标记的不是”现在”,是”相对于主句原点”。

生活类比:一份合同里,日期只在抬头写一次。 正文里的每个条款不会各自再写一个日期,因为抬头的日期已经管着全篇了。主句是抬头,从句是条款。

这套规则覆盖所有时间/条件从句的引导词:

when       /  when the next audit begins, ...
as soon as /  as soon as gh-ost lands, ...
before     /  before the migration freeze ends, ...
after      /  after the runbook is updated, ...
until      /  until the second reviewer signs off, ...
if         /  if the lock lasts more than five minutes, ...
unless     /  unless someone reviews the plan, ...

母案例来两句:

a. When the runbook is updated, every on-call engineer will know
   how to abort a migration.
   runbook 更新之后,每个值班工程师都会知道怎么中止迁移。

b. If a migration locks the orders table again, the on-call engineer
   will kill the connection immediately.
   如果再有迁移锁住 orders 表,值班工程师会立刻 kill 掉连接。

注意 a 句:When the runbook is updated —— 现在时(而且是被动,那是第三面的活);will know —— will。各司其职。

7.7 一个漂亮的例外,顺便检验你懂没懂

看这两句:

a. I don't know when the postmortem will begin.     (对,用了 will!)
b. When the postmortem begins, I'll be there.       (对,没用 will)

先别往下看,想三秒:两句话里都有 when,为什么一个能用 will,一个不能?

(如果你脑子里冒出来的答案是”因为 a 句是否定句”——那是个巧合,不是原因。再想。)

为什么 a 句能用 will begin?刚才不是说从句不能用吗?

因为 a 句的 when the postmortem will begin 不是时间状语从句,是名词性从句(它是 know 的宾语,等于一个”wh- 疑问句”的内嵌版本)。

  • a 句:I don't know [when the postmortem will begin]. —— 我不知道 [复盘会定在什么时候]。中括号里是一个独立的命题,有它自己的时间坐标,所以它自己设原点,用 will。
  • b 句:[When the postmortem begins], I'll be there. —— 中括号里是状语,是给主句做参照的,所以它不设原点,用现在时。

判断方法:把 when 换成”什么时候”能说通,就是名词性从句(可以用 will);换成”当……的时候”才通,就是状语从句(不能用 will)。

  • a:我不知道 [复盘会定在什么时候]。-> 通,用 will,正确。
  • b:[当复盘会开始的时候],我会在场。-> 通,不用 will,正确。

这个例外不是例外,它恰恰证明了规则:谁设原点,谁用将来标记;谁做参照,谁退化成现在时。

7.8 卡点 F:数一数,这段里几个动词”变了时态”?

最后一节之前,再卡你一次。这次换一个跟 Pallet 毫无关系的场景——小区停电。

2026 年 7 月的一个周四,北京,晚上七点四十。你正在厨房炒青菜,整栋楼忽然黑了。物业三天前在电梯里贴过通知,说要紧急更换变压器,晚上八点到凌晨两点停电——你扫了一眼就忘了。

下面这段是你在业主群里发的消息。先别急着看下面的分析,先数一数:这段里一共有多少个动词?其中有几个”变了时态”?

It was 7:40 on a Thursday evening. I was stir-frying greens when the
lights went out. The whole building went dark at once. The property
office had posted a notice three days earlier — emergency transformer
work, 8 p.m. to 2 a.m. — but I had skimmed it and forgotten. By 10 p.m.
the lifts were still down. It has been out for six hours now, and the
notice says the power will come back at 2 a.m.

先别往下看,真的数一遍。


数完了?我猜你数出来的数字偏大。

大部分人会这么数:“每个动词都在变时态啊——was、was stir-frying、went、went、had posted、had skimmed、were、has been、says、will come back,十个动词,十个都在标时态。”

这个答案暴露了一个普遍的误解:你把”每个动词都带时态标记”当成了”每个动词都在变时态”。

这两件事完全不同。前半句是对的——英文里每一个限定动词都必须带时态标记,一个都跑不掉,这就是第 1 节说的”编译期类型标注”。但后半句是错的。

真正的答案是:这段里有十个限定动词,只有五处偏离了默认档,另外五处什么都不做,直接继承。

逐句拆:

动词形态是默认还是覆盖
was(7:40)一般过去默认(第一句设的原点)
was stir-frying过去进行覆盖:推近镜头
went out一般过去默认(回到主线)
went dark一般过去默认
had posted过去完成覆盖:倒带
had skimmed过去完成覆盖:倒带
were(still down)一般过去默认
has been(out)现在完成改默认档:整个视角从那晚搬回现在
says一般现在新默认档下的常态
will come back将来新默认档下的将来

十个动词,五次显式操作,五次坐享其成。

回扣卡点:你刚才数多了,是因为你在数”有几个动词带时态标记”(答案:全部十个),而真正该数的是”有几个动词偏离了上一句的设定”(答案:五个)。前者是英文的强制性,后者才是你写英文时真正要做决策的地方。

**你的判断成本不是 O(动词数),是 O(偏离次数)。**这个差别,就是你写一段英文时”每句都要想”和”大部分句子不用想”的差别。

下一节就把这件事讲透。


8. 时间的”默认档”

这一节是给程序员准备的,也是我认为整个时态系统里最”工程化”的一个洞察。

8.1 讲故事的时候,你其实只在开头设了一次时态

回忆一下你读过的英文小说、事故报告、新闻报道。你会发现一个现象:

时态不是每句话都重新声明的。开头设一次,后面全部继承。

看母案例的开头(第 5 节出现过):

At 2:14 a.m. on 12 November 2024, Lin Wei ran a database migration
against Pallet's orders table. He was eight months into the job and
had never run one alone. He did not use gh-ost. By the time he woke
up at 2:26, the error rate had already hit 34%. Priya Nair killed
the migration connection at 2:47, and the service recovered at 3:05.

第一句 ran + At 2:14 a.m. on 12 November 2024:设了一次原点。原点 = 过去,镜头 = 一般体。

后面几句全部继承这个设置:

  • was —— 覆盖了”体”(-> 进行),没动”时”
  • had never run —— 覆盖了”时”(往回跳)和”体”(-> 完成)
  • did not use —— 回到默认
  • had already hit —— 覆盖了”时”(往回跳)和”体”(-> 完成)
  • killed —— 回到默认
  • recovered —— 默认

看见没有?六句话里只有三句是”显式覆盖”,三句是”什么都不写,继承默认”。

这就是为什么你写英文叙事会觉得”大部分句子不用想”。你只在三个地方动了手,其他地方都坐享默认值。

8.2 程序员版本:默认值 + 显式覆盖

这个模型你应该一眼就认出来了:

type Narrative struct {
    Tense  string `default:"past"`
    Aspect string `default:"simple"`
}

或者更贴近实际的:

# 段落级默认值
defaults:
  tense: past
  aspect: simple
 
# 只在需要偏离时才显式声明
overrides:
  - at: "他入职八个月"
    aspect: progressive
  - at: "他此前从未独立跑过迁移"
    tense: past_before_anchor
    aspect: perfect
  - at: "错误率已经冲到 34%"
    tense: past_before_anchor
    aspect: perfect

你写故事的时候,不是在每一句话里”选时态”。你是先设一个默认档,然后在少数几个地方打补丁。

这解释了一个很常见的困惑:为什么英文小说里”时态不一致”看起来那么随意?

不是随意。是默认值 + 三处显式覆盖:

覆盖类型形态作用类比
默认档一般过去主线推进,一个点接一个点顺序执行
覆盖:倒带过去完成往回跳,填背景git checkout <earlier>
覆盖:推近过去进行进入事件内部,看过程打断点,单步
覆盖:跳回现在现在时 / 现在完成从故事里抬头,对读者说话从函数里 return,回到调用方

只有这三种情况需要你显式动手。其余一律默认。

这个模型的实用价值在于:它把”我该用什么时态”这个每句一问的问题,变成了”我这一句有没有偏离默认”这个默认不答的问题。

你的判断成本从 O(n) 降到 O(覆盖次数)。

再补一个工程上特别贴切的对照:这跟日志级别是一回事。你不会在每一行日志里重复写 service=order-api env=prod,那些是 logger 上设好的默认字段;你只在需要强调的地方显式加一个 trace_id=xxx。英文叙事里的时态字段,就是这么工作的。

8.3 什么时候”改默认档”

默认值不是永远不改的。改默认档的标志是视角整体搬家。

母案例那篇文章的后半段:

Pallet has since moved every schema change onto gh-ost. The team has
added an abort section to the runbook. Pallet has gone 22 months
without a P1 incident. Lin now runs on-call training.

since 一出现,默认档从”past / simple”整体切到了”present / perfect”。视角从 2024 年那个盒子,搬回了 2026 年的现在。

这是段落级的状态切换,不是句子级的覆盖。切换之后,后面几句又全部继承新默认。

注意最后那句 Lin now runs on-call training.——now 出现之后,默认档又从”present / perfect”微调成了”present / simple”(当下的常态事实)。默认档是可以切两次的,切一次回现在,再切一次进常态。

用代码说:

// 第一段:进入故事时间线
withTimeline(nov122024, func() {
    narrate("Lin ran the migration")             // past/simple(继承)
    flashback("He had never run one alone")      // 显式覆盖
    narrate("Priya killed the connection")       // 回到默认
})
 
// 第二段:切回现在
withTimeline(now2026, func() {
    narrate("Pallet has moved to gh-ost")        // present/perfect(新默认)
    narrate("Pallet has gone 22 months P1-free") // 继承
    narrate("Lin runs on-call training")         // present/simple(微调)
})

8.4 两个有意思的极端

极端一:历史现在时(historical present)。

英文讲故事有时会忽然全部改成现在时:

So Lin runs this ALTER at 2:14 and goes back to sleep. At 2:17 the
first alert fires. At 2:19 PagerDuty calls him — and his phone is
on mute. He doesn't wake up until 2:26.

这不是时态错乱,是把默认档整体拨到”现在”,让读者觉得事情正在眼前发生。口语讲段子、讲笑话的时候特别常见:“So I’m standing there and this guy walks up to me…”

中文口语里也有类似的(“然后我就站那儿,这哥们儿就过来跟我说……”),但中文没有形态,所以你感受不到”切换”。英文里这个切换是看得见的:动词从 ran 变成 runs,读者立刻知道”镜头拉近了,我要进现场了”。

极端二:新闻标题用一般现在时。

Pallet Checkout Down 51 Minutes After Botched Migration
一次失败的迁移导致 Pallet 下单中断 51 分钟

标题里用现在时,是因为新闻标题的默认档是”这条信息现在有效”。它处理的不是”事件在过去发生”,而是”报道现在在这里”。

这两个极端都指向同一件事:**时态标记的不是客观时间,是说话人选择的观察位置。**你选哪个位置,就用哪个形态。

再补一个我们这行的例子,它同时踩中了两个极端:告警面板上的状态永远用现在时或现在完成——Order API is degraded. 12,300 requests have failed. 因为它汇报的是”此刻”;而事故时间线永远用一般过去——02:14 Lin ran the migration. 因为它归档的是”历史”。**同一件事,两个界面,两套默认档。**你写值班文档的时候其实天天在切,只是没意识到。


9. 卫星案例:十一个跨领域场景,十一组最小对立对

母案例是工作场景,这一节全部换成别的场景:生活、社交、工作、运动、公共,五个领域轮着来。每一组你先自己判断,再看分析。

这么做的目的不是凑数。是为了回答一个你心里可能在犯嘀咕的问题:**“这些规则是不是只对技术写作有效?“**不是。它们是英语的规则。

9.1 外卖订单

你在等外卖,四十分钟了还没到。

a. The rider called me.
b. The rider has called me.

中文都能说”骑手给我打过电话了”。

  • a(一般过去):陈述一件已经结束的事。比如你第二天跟室友复盘:“昨天那单,骑手给我打了电话,我没接到。“事件被封在”昨天那单”这个盒子里。
  • b(现在完成):**指向你现在该做什么。**骑手已经打过了(所以你该下楼了 / 所以问题在你没接)。这件事跟”现在”连着。

再一组:

a. I waited forty minutes.          (等完了。可能外卖到了,可能我取消了)
b. I have been waiting forty minutes.(还在等,我很不爽)

b 句的完成进行体特别能打:**它同时告诉你”持续了四十分钟”和”现在还没结束”。**中文只能说”我等了四十分钟了”,靠末尾那个”了”撑着,而且很多人还不加。

9.2 面试

换个工作场景以外的:你去一家公司面试。

a. I interviewed at that company in 2024.
b. I have interviewed at that company before.
  • a(一般过去):封闭区间。in 2024 把那次面试封进盒子里,这是履历陈述。它天然接的下文是结果:“They didn’t call back.”
  • b(现在完成):开放区间,窗是”我到目前为止的求职经历”。它天然接的下文是当下的判断:“So I know their process is a mess.”(所以我清楚他们流程乱。)——这句是在给你现在要做的决定提供依据。

中文都翻成”我面过那家公司”。你想表达”所以你别去”,必须用 b。

再来一组,这组是完成进行体最舒服的用法:

a. I prepared for the interview for two weeks.      (准备了两个礼拜。面试已经结束)
b. I have been preparing for the interview for two weeks.  (还在准备,明天才面)

中文:“我为这个面试准备了两个礼拜。” + 你可能加也可能不加的那个”了”。英文一个形态把”面完了没有”说死了。

第三组,讲倒带:

By the time I sat down, the interviewer had already read my GitHub.
我坐下的时候,面试官已经看过我的 GitHub 了。

锚点 = sat down。had read 往回跳,交代”在他坐下之前,对方已经做过功课了”。

如果你写 The interviewer read my GitHub before I sat down.,意思一样,但少了一个”我要倒带”的信号。在讲经历这种文体里,前者的可读性明显更高——因为读者需要知道”下面这句是背景,不是我接下来要做的动作”。

9.3 租房

a. I lived in that apartment for two years.
b. I have lived in this apartment for two years.

中文:“我在那套房子住了两年” / “我在这套房子住了两年”。除了”那”和”这”,动词一模一样。

英文那边:a 你已经搬走了;b 你还住着。

注意一个好玩的细节:中文靠指示代词(那 / 这)来区分,英文靠动词形态。中文把标记放在名词上,英文把标记放在动词上。

再一组:

a. The landlord raised the rent twice.        (那段租期里涨了两次。已结束)
b. The landlord has raised the rent twice.    (我租住至今涨了两次。还住着)

中文都是”房东涨了两次房租”。你想表达”我现在快住不起了”,必须用 b。用 a 的话,听的人会以为你在讲上一段租约的往事。

9.4 错过航班

这组最能体现”完成体指向当下”。

你在机场,跑到登机口,飞机已经走了。你给同事打电话:

a. I missed my flight.        (陈述一件事)
b. I've missed my flight.     (我现在误机了,得改签,下午的会我去不了了)

中文都是”我误机了”。但英文里,b 句后面天然接”所以我下午到不了”;a 句后面更适合接”然后我改签了晚上的”。

**完成体把事件和”现在该怎么办”焊在一起。**这是它在真实对话里最常见的功能。

倒带那一下:

By the time I got to the gate, the plane had already left.
我到登机口的时候,飞机已经起飞了。

锚点 = got。窗的右沿贴在那里。

高铁版,顺便练一个完成进行体:

a. I had been standing in the ticket line for twenty minutes when
   they announced the train was delayed.
   广播通知列车晚点的时候,我已经在售票窗口排了二十分钟队。
b. I have been standing here since eight, and the screen still says
   "waiting".
   我从八点就站在这儿了,屏幕上还是"候车"。

a 的锚点是广播通知那一刻,往回跳,而且 had been standing 强调”排了二十分钟还没排到”的那种卡住的感觉。b 是现场直播,窗开到现在,后面天然接”我要改签”或者”我不走了”。

中文两句都能说成”我在这儿排/站了二十分钟了”,那个”了”加不加,全看你心情。

9.5 微信消息撤回

最后一个,纯生活场景。

a. He deleted the message.               (他删了那条消息。)
b. He has deleted the message.           (他把那条消息删了。—— 现在你看不到了)
c. He had deleted the message before I could read it.
   (我还没来得及看,他就把消息删了。)
  • a:陈述。可能是在复盘昨晚的事。
  • b:指向现在。你打开聊天窗口,发现没了——这条消息现在的样子是”已删除”。
  • c:锚点 = I could read it。倒带。

再加一个进行体的:

I was typing a reply when the message disappeared.
我正在打字回复的时候,消息没了。

was typing 是背景画面(一条线),disappeared 是打断点(一个点)。**进行体搭台,一般体唱戏。**这是英文叙事里最常见的组合,没有之一。

母案例里也有这么一句,你回头去看会觉得特别亲切:

Lin was reading the runbook when the second alert fired.
Lin 正在翻 runbook 的时候,第二条告警进来了。

反过来的一次——是你自己发错群。

2026 年 5 月,你在公司大群里吐槽新版的报销流程,两百人。发完三秒你意识到:那条消息本来是要发给你和财务两个人的小群的。

a. I sent it to the wrong group.
b. I've sent it to the wrong group — can someone delete it?
c. I had sent it to the wrong group before I realised the big group
   was in the same window.
  • a(一般过去):陈述。这是你事后跟同事复盘时说的话——事已经过去了,成了”我干过的一件蠢事”。
  • b(现在完成):**指向现在,而且指向”现在该怎么办”。**消息此刻就在两百个人的屏幕上,你需要的不是陈述,是救援。这句后面天然接的是行动请求。
  • c(过去完成):锚点是 I realised,往回跳,交代”我意识到之前,事情已经发生了”。

中文三句都能说成”我发错群了”。你想让人帮你删,你必须用 b。

9.6 钥匙锁屋里(生活)

周六上午你出门倒垃圾,风把门带上了。你穿着拖鞋,手机、钥匙、钱包全在屋里。

a. I have locked my keys inside.
b. I locked my keys inside.
c. I had locked my keys inside before I realised I had no shoes on.
  • a(现在完成):**我现在处于一个”钥匙在屋里、我在屋外”的状态。**这句后面接的是”所以我现在要干嘛”——Can I borrow your phone?
  • b(一般过去):陈述一件已经结束的事。这是你换完锁、进屋、洗完澡之后,跟朋友讲笑话时说的话。后面接的是 “Then I had to call a locksmith and pay 300 kuai.”
  • c(过去完成):锚点是 I realised,往回跳。

中文全是”我把钥匙锁屋里了”。你想表达的是”我现在进不去、需要帮助”,你只能用 a。

再补一组,这组是”结果”和”过程”:

a. I have been standing in the corridor for twenty minutes.
b. I stood in the corridor for twenty minutes.

a 是”我还在走廊里站着,已经二十分钟了,开锁师傅还没到”;b 是”我在走廊站了二十分钟”——已经进屋了,这是往事。中文:“我在走廊站了二十分钟了” vs “我在走廊站了二十分钟”。又是那个可加可不加的”了”。

9.7 被朋友放鸽子(社交)

约了晚上七点半在工体附近一家川菜馆见面。七点五十,人还没来,微信也不回。

a. I have been waiting here for forty minutes.
b. I waited forty minutes and then left.
c. He has stood me up twice this year.
d. He stood me up twice, so I stopped inviting him.
  • a(现在完成进行):**还在等,而且很不高兴。**这句的信息量在于”四十分钟”和”还没走”两件事同时成立——你之所以还在等,是因为你觉得他大概还会来。
  • b(一般过去):已经走了。整件事进了盒子,盒子里装着”等”和”走”两个动作。
  • c(现在完成):窗开着。这是你跟第三个朋友吐槽时的说法——“他今年放了我两次鸽子”,这句话是在给这个人当下的信誉打分,后面接的是 “So I’m not holding my breath.”
  • d(一般过去):窗关了。整件事已经处理完了(你不再叫他了)。后面接的是已然的结果。

c 和 d 的那组特别值得停一停:中文都是”他放了我两次鸽子”,英文一句是”我对他现在的判断”,一句是”一段已经翻篇的往事”。

再补一句倒带,讲你为什么还愿意等:

He had never stood me up before, so I assumed he was just stuck in traffic.
他以前从没放过我鸽子,所以我以为他就是堵车了。

锚点 = assumed。这句是在解释”我为什么还在等”,属于背景,不是主线。这就是过去完成时最典型的活儿。

9.8 邮件发错收件人(工作)

2026 年 3 月,你给一家供应商发报价确认函。收件人栏自动补全,你手快选错了人——发给了同名的另一家公司的采购总监。函里写了底价。

a. I emailed the quote to the wrong person.
b. I have emailed the quote to the wrong person — what do I do now?
c. By the time I hit recall, she had already opened it.
  • a(一般过去):陈述。事后复盘、写事故报告时用的。
  • b(现在完成):**指向现在。**这封邮件此刻就躺在别人的收件箱里,这是个需要立刻处理的现状。后面接的是求助或行动方案。
  • c(过去完成):锚点 = I hit recall。往回跳,交代”在我点撤回之前,事已经发生了”。already 又出现了——它跟过去完成是天然搭档。

中文三句:“我把报价发错人了""我把报价发错人了,现在怎么办""我点撤回之前她已经打开了”。第三句那个”之前""已经”,是中文自己加的词;英文里它们焊在 had 里。

有意思的是 a 和 b 的中文可以一字不差,而它们在真实对话里的功能完全不同:a 是复盘,b 是报警。

9.9 最后一秒被绝杀(运动)

你们公司足球队打业余联赛,决赛,2:1 领先,第 89 分钟。补时第 3 分钟,对方一个远射扳平,加时赛你输了。

a. We were leading for eighty-nine minutes.
b. We had been leading for eighty-nine minutes when they equalised.
c. We have lost the final twice in a row.
d. We lost the final in 2025 too.
  • a(过去进行):背景画面,一条线。“我们领先”这件事在场上持续着,它不推动情节,它是要被打破的那个背景。
  • b(过去完成进行):锚点是 they equalised,往回跳,强调”到被扳平那一刻为止,我们已经领先了八十九分钟”。这句的杀伤力全在”八十九分钟”这个数字上——你越强调这个数字,那个进球就越难受。这就是完成进行体最会的活儿:把一段持续量出来,然后把它的终点钉在一个让你心疼的位置上。
  • c(现在完成):窗开着,窗里躺着两次决赛失利。这是在给这支队伍当下的状态定性——“我们连续两年倒在决赛”,后面接的是 “Maybe we’re just not a big-game team.”
  • d(一般过去):2025 年那次是封闭区间,往事一件。

中文:“我们领先了八十九分钟""我们被扳平的时候已经领先了八十九分钟""我们连续两年输了决赛""我们 2025 年也输了决赛”。第二句那个”的时候""已经”,第四句那个”也”——全是中文自己补的词。

顺手说一句:体育解说这种文体,是完成进行体出现频率最高的地方之一。He has been chasing that ball all game. They had been defending for ninety minutes. 因为它天生适合干一件事:给一段持续计时,然后宣布它被打断。

9.10 谈薪被拒(工作)

你在一家公司干了三年,2026 年 4 月提了一次调薪,被拒;7 月又提了一次,HR 说”年底再说”。

a. I have asked twice.
b. I asked twice.
c. By the time I asked the second time, they had already frozen
   all salary bands.
  • a(现在完成):窗开着。两次请求都在我这扇窗里,这句话描述的是我现在的处境——一个提了两次还没拿到的人。后面接的是决策:“所以我在看外面的机会。”
  • b(一般过去):窗关了。这是你离职三年后跟人讲往事的说法。后面接的是结果:“They countered in the end.”
  • c(过去完成):锚点 = I asked the second time,往回跳,交代你当时不知道的背景(薪资带宽已经冻结了)。

中文:“我提过两次了” / “我提过两次” / “我第二次提的时候,他们已经把所有薪资带宽都冻结了”。

再看一组更扎心的:

a. My manager has promised me a review three times.
b. My manager promised me a review three times.

a 是”他答应了三次,一次都没兑现,我现在还在等”——这句里有怨气。b 是”他答应过三次”,窗关了,多半接的是”后来我走了”。

**完成体最厉害的地方就在这儿:它能让一句纯陈述句带上情绪。**因为它把过去的事和说话人此刻的处境焊在了一起。

9.11 地铁故障(公共)

早高峰,十号线,你在隧道里停了四十分钟。广播每隔五分钟说一次”临时停车”。

a. The train has been stopped in the tunnel for forty minutes.
b. The train was stopped in the tunnel for forty minutes.
c. The power had gone out before the train came to a stop.
  • a(现在完成进行 / 完成):**你现在还在隧道里。**这是你给领导发请假消息时的第一句。
  • b(一般过去):已经开动了,或者你已经到公司了。这是你跟同事讲”今天早上倒霉”时说的话。
  • c(过去完成):锚点 = the train came to a stop。往回跳,交代因果。

再看站台广播的两句,体会一下”时刻表”那块化石:

a. Service will resume in ten minutes.        (宣告:官方口径)
b. The next train arrives at 8:42.            (时刻表:写死的一行字)

中文:“十分钟后恢复运营” / “下一班八点四十二到”。差别很小,但英文那边一个是宣告、一个是排班表——跟第 7.3 节那条完全对上。

9.12 十一个案例的共同点

回头看这十一组,你会发现中文全都在做同一件事:加词(“了""过""当时""已经""一直”),或者干脆不加,留给上下文。

而英文在做另一件事:在动词形态里做一次必选的声明。

这就是为什么”背时态表”没用。时态表给你的是十二个形态的清单,但它没给你每一次开口时的那个判断动作:这个时间窗口,现在是开着的还是关着的?我这句要不要偏离默认档?我要不要倒带?

把这三个问题跑一遍,形态自己就出来了。


10. 一面之得

这一章密度不小,收成几条。

**第一,时和体是两条正交的轴,不是一个叫”时态”的糊涂账。**时解决”钉在时间轴的哪一侧”(绝对坐标,参照物永远是说话此刻),体解决”摄像机怎么摆”(看成点、看成线、还是看成结果)。两条轴互不干涉,自由组合。

**第二,英语的”时”只有两个形态:过去和现在。没有将来时。**这是事实,不是说法。所有”将来”的表达都是借来的:will(借自”意愿”)、be going to(借自”正在去某处”)、现在进行时(借自”正在进行”)、一般现在时(借自”写死的时刻表”)。四块化石,各自带着原义的残渣,所以不能互换。

**第三,现在完成 vs 一般过去的判据不是”对现在有没有影响”,而是”时间窗口还开不开”。**窗开着(ever、so far、since、for、this week、in his career)用现在完成;盒子盖上了(yesterday、on November 12, 2024、last week、when I was a kid)用一般过去。I have lived in Beijing for ten years. 你还在北京;I lived in Beijing for ten years. 你搬走了。中文两句一模一样——**这就是中文的模糊处、英文的精确处。**母案例里那对也一样:Pallet has gone 22 months without a P1. 是庆功,Pallet went 22 months without a P1. 是讣告。

第四,过去完成时不是”过去的过去”,是叙事的倒带键。它是一扇右沿贴着”过去某个锚点”的窗。它不能凭空出现,必须指向上下文里的一个时间点。词汇书里那些孤立的 The migration had locked the orders table. 例句语法合法但语感别扭,缺的正是锚点。而且它是可选的——顺序清楚时用 after/before + 一般过去就够了。凡是”可选”的语法手段,功能都在语篇层面:它管理的是读者的注意力,不是命题的真值。

**第五,叙事有默认档。**英文讲故事默认一般过去时,像参数的默认值,设一次后面全继承。只有三种情况需要显式覆盖:倒带(过去完成)、推近(过去进行)、跳回现在(现在时 / 现在完成)。

**第六,这套规则不是”工程英语”的专利。**这一章除了母案例,还走了七个领域:钥匙锁屋里、老同学十年后重逢、体检报告上的红线、戒烟的第四十天、最后一秒被绝杀、差一分没考上、地铁停在隧道里四十分钟。**规则一个字都没改。**窗开不开、要不要倒带、偏离没偏离默认档——这三问在火锅店里和在机房里是同一套。如果你只从 Pallet 那一个例子里学会了它们,那你学到的其实是一个案例,不是一条规则。

第七,也是全书最想让你带走的一句:

中文把时间信息外包给时间词和上下文,运行时解析;英文把它焊进动词形态,编译期声明。

所以你写英文时的那种”烦”,本质上是你被逼着在每个动词上做一次类型标注。

如果这一章只记一句话,记这个:

开口之前先问:我这扇窗,现在是开着的,还是关着的?


11. 思考题

五道,都配参考答案。建议先把答案挡住,自己写一遍再对。

题 1(辨析层)

下面两句中文翻译完全一样,请说明英文的意思差别,并各补一句能让差别更明显的上文或下文。

a. Lin has run production migrations before.
b. Lin ran the migration on November 12, 2024.

参考答案

a 用现在完成,时间窗口是”他到目前为止的职业生涯”,而这个窗口现在还开着(他 2026 年仍在 Pallet 任职)。所以这句不是在汇报一件往事,而是在给这个人当下的状态下定论:他不是没干过,他有经验。放在复盘会上说,它天然接的下文是一个归因,比如 “So this wasn’t a rookie mistake — our process put a high-risk change on one person at 2 a.m.”(所以这不是新手失误,是我们的流程在凌晨两点把高风险变更压在了一个人身上。)它站在 blameless 那一边。

b 用一般过去,因为 on November 12, 2024 是一个封闭区间——那一天早就结束了,事件被封在一个有明确边界的盒子里。这句是历史陈述,它天然接的下文是后续事实,比如 “The first alert fired three minutes later.”

很多人会问:那次事故对现在影响那么大(流程改了、runbook 补了、Lin 本人都转岗做培训了),为什么不能用现在完成?这恰恰是”影响论”失效的地方。**判据不是影响的大小,是窗口的开关。**你把 on November 12, 2024 一放进去,窗就关上了,完成体当场失效。

顺带一个验证:把 a 句的 before 换成 on November 12, 2024,句子立刻炸掉——*Lin has run the migration on November 12, 2024. 反过来,把 b 句的日期删掉、换成 before,就必须改成 has run。改的不是事实,是窗口。

再给你一个横向对照:把主语从 Lin 换成 Pallet,同样一句 Pallet has had outages like this before.——形态没变,立场的刀口却转了个方向,从”他不是没经验”变成了”这公司的流程一直有洞”。完成体只负责把窗打开,窗里照出来的是好话还是坏话,取决于你把镜头对着谁。

题 2(辨析层)

下面哪一句(或哪几句)单独作为一段话的开头是自然的?不自然的请说明缺了什么。

a. The migration had locked the orders table.
b. The migration locked the orders table.
c. Lin had been trying to kill it for ten minutes.

参考答案

自然的是 b。不自然的是 a 和 c——但不是语法错,是缺锚点。

过去完成时是一个相对时态:它标记的是”窗的右沿贴着某个锚点”。孤立地给出 a 和 c,读者会本能地等待:“这句是相对于哪个时间点往回跳的?“没有答案,句子就悬在半空。

给个锚点它们立刻活:

a'. When Lin woke up at 2:26, the migration had already locked the orders table.
c'. By the time Priya joined at 2:44, Lin had been trying to kill it for ten minutes.

而 b 是一般过去,属于”默认档”。它不需要任何外部参照——它自己就是一个叙事主线上的点,直接推动情节。这就是”默认档”这个说法的实用价值:只有偏离默认的形态才需要额外的支撑。

这条还能推出一条写作建议:在事故报告、复盘文档这类文体里,倒带句(过去完成时)一定要紧跟或紧邻它的锚点,别隔了三段才倒带。隔太远,读者已经忘了 HEAD 在哪,git checkout 就失败了。

顺手补一个更细的点:c 句的”十分钟”是从 2:31 到 2:44 左右,而锚点选在 Priya joined(2:44)还是 Priya killed it(2:47),句子都能成立,只是倒带的落点不同。选 2:44,强调的是”他孤立无援地折腾了十分钟”;选 2:47,强调的是”到 Priya 动手时,他还在折腾”。**锚点不是客观刻度,是叙事选择。**这就是第 10 节那句”时态标记的是观察位置”的具体含义。

题 3(应用层)

Pallet 的 Order API 出了事故,现在是事故当天上午十点,服务已经恢复。你要在群里发一条消息,向团队同步现状。请给下面四个空选时态,并说明理由。

1. The Order API _____ (start) failing at 2:17 a.m.
2. We _____ (kill) the migration by the time Marcus joined the call.
3. Error rate _____ (stay) below 0.1% since 2:52.
4. I _____ (write) the postmortem doc now.

参考答案

  1. started。at 2:17 a.m. 是典型的封闭区间(凌晨两点十七分那个时刻早就过去了),一般过去。这是历史记录,不是现状。
  2. had killed。锚点是 Marcus joined the call(过去时)。“kill 掉迁移”发生在他进会之前,所以要倒带。你也可以写 We killed the migration before Marcus joined the call.——意思完全一样,只是少了”倒带”的信号。在事故同步这种需要读者分清”哪些是背景、哪些是主线动作”的文体里,had killed 明显更好读。
  3. has stayed。since 2:52 是最典型的开放区间信号——从 2:52 一直开到现在(上午十点)。这句话汇报的是截至此刻的状态,用现在完成。如果你写 stayed,读者会以为”错误率保持在 0.1% 以下”这件事已经结束了(言下之意现在又不正常了),意思直接反了。这条在事故沟通里是真正会出人命的:你以为你在报平安,别人听到的却是”刚才还正常,现在又炸了”。
  4. am writing。now 指向说话此刻,进行体——“我正在写”。这里不能用现在完成(*I have written the postmortem doc now),因为 now 要求一个正在进行的过程,而完成体给的是结果。

这四句正好覆盖了本章的三件武器:封闭盒子(1)、倒带(2)、开着的窗(3),外加一个”此刻正在进行”(4)。事故同步这种文体,本质就是在这四种视角之间来回切。

题 4(应用层)

下面六句都有毛病或者别扭,请指出问题并改正。

a. *Lin has run the migration on November 12, 2024.
b. *When the postmortem will begin, Priya will open with the timeline.
c. *The migration had locked the orders table. (作为整个故事的第一句)
d. *I don't know when does the postmortem begin.
e. *Lin is running on-call training for two years.
f. *By next November, the team will go twelve months without a P1 incident.

参考答案

a -> Lin ran the migration on November 12, 2024. 完成体的窗(开到 now)跟 on November 12, 2024(封闭盒子)语义冲突。二者只能留一个:留具体日期就用一般过去;想用 has,就把时间状语换成开放的(before、since then、so far、in his career)。

b -> When the postmortem begins, Priya will open with the timeline. 时间状语从句不设原点,主句的 will 已经管着整句的时间了,从句退化成现在时。判断方法:把 when 换成”当……的时候”讲得通,就是状语从句,不能用 will。

c -> The migration locked the orders table. 缺锚点。故事第一句还没有 HEAD,had locked 这个倒带操作没有参照。或者给它一个锚点:By the time Lin woke up, the migration had already locked the orders table.

d -> I don't know when the postmortem begins. 这一句其实有两个可能的改法,取决于你想说什么。如果意思是”我不知道复盘会定在什么时候(请告诉我具体时间)“,那更自然的是 When does the postmortem begin?(直接问);内嵌成宾语从句时要用陈述语序:I don't know when the postmortem begins.。原句错在内嵌疑问句用了疑问语序(does the postmortem begin)。另外注意:这里的 when 从句是名词性从句(等于”什么时候”),所以如果强调未来,也可以说 I don't know when the postmortem will begin.——这时用 will 是对的,跟 b 的情况正好相反。

e -> Lin has been running on-call training for two years. 或 Lin has run on-call training for two years. “for two years” 表示一段从过去持续到现在的时间,而且显然还在持续,属于开放区间 + 持续体。现在进行时不能跟 for + 时间段 搭配表达”从过去持续到现在”——进行体只能覆盖”此刻正在”,够不到两年前。这条是中式英语最高频的错误之一,因为中文说”我干这个两年了”,动词不需要任何变化。

f -> By next November, the team will have gone twelve months without a P1 incident. By + 将来时间点 的意思是”站在那个将来点上往回看”,这正是将来完成时的地盘:will have gone。原句 will go 表示”团队将在明年 11 月开始连续十二个月无事故”,少了”截至那时已完成”这层回溯。中文两句大概都能说成”到明年 11 月团队连续十二个月无 P1”,英文差了整整一个视角。

题 5(拔高层)

英语没有”将来时”这个动词形态,却能用至少四种方式表达将来(will / be going to / 现在进行时 / 一般现在时),而且它们不能互换。

请回答三层:(1)这四种方式各自”借”自什么原义?(2)为什么借来的东西一定带着原义的残渣,不能彻底洗干净?(3)“语法是化石”这个说法,对你理解英语其他的语法现象有什么启发?

参考答案

(1)四块化石的原义

  • will 借自意愿、意志。古英语 willan = “想要、决意”,跟德语 wollen 同源,名词义项”遗嘱”今天还活着。所以它到今天还带着”说话人的主观立场”:预测、当场决定、承诺、正式宣告。它也解释了为什么 The door won't open. 有”门不肯开”的拟人味(同理 The deploy won't finish.),为什么条件句里默认用 will(条件句构造假设世界,压掉了说话人的意志,反而最适合纯预测)。母案例里 Priya 说 I'll write the runbook section myself.——那股”这事我扛了”的劲儿,就是从这一层来的。
  • be going to 借自空间位移(正在去某处)。从”我正在往那儿移动”抽象成”目标就在前方”,所以它要求当下的迹象或已定的意图:Look at the postmortem doc — they're going to require two-person review.
  • 现在进行时借自正在进行。它说的是”这件事已经启动、流程在跑、不可撤销”,所以它只用于有安排、有票、有预约的将来:Marcus is meeting Northwind at 11.
  • 一般现在时借自无时间性的属性。时刻表、日程、值班轮换表本质上是”写死的一行字”,不是事件,所以能用现在时说将来的事:The rotation flips on Monday.

(2)为什么洗不干净

因为语法化(grammaticalization)是渐变的,不是开关。一个新用法从旧用法里长出来,要经历几百年:先是旧义为主、新义是语用推断(“他要去了”<-“他决意去”),然后新旧义并存(两可句),最后旧义在某些语境里才彻底消失。而在任何一个时点切一刀,你看到的都是新旧叠加的中间态。英语的将来表达正处在中间态:抽象化程度足够高所以能表将来,但抽象化得不够彻底所以还带着原来的搭配限制。

这也解释了”不能互换”:它们从来就不是同一个功能的四种说法,而是四个不同来源的结构碰巧都能指向将来。功能重叠不等于功能相同。就像 Go 里 sync.Mutex 和 channel 都能做同步,但没人觉得它们可以互换——因为它们的语义来源不同。

(3)对全书方法论的启发

“语法是化石”真正的价值,是把语法从规则清单变成历史地层。

规则清单只能靠背,而且例外无穷:为什么 would 能表示委婉?因为它是 will 的过去式,而过去式天然带”距离感”,距离感又能变成”客气”。为什么 If I were you 用 were 不用 was?因为那是残存的虚拟式,它的作用是拉开跟现实的距离(这一条第二面、第六面会展开)。为什么 be supposed to 表示”应该”?因为 suppose 本义是”假定”,“被假定要做”漂移到”理应做”。为什么完成时叫 perfect?perfect 来自拉丁语 perfectus = “做完了的”。为什么 incident report 里动不动就是 Mistakes were made.?因为被动把施事抹掉了,而抹掉施事正是 blameless 想要的效果——这一条第三面会专门拆。

如果你只记规则,这些全是零散的例外,你得一条一条背。如果你知道它们是化石,你就有了一个生成规则的规则:看到一个奇怪的语法现象,先问”它原来是什么?“——答案几乎总是”它原来是个实在的词,意思更具体,只是被磨薄了”。

这套”考古学视角”是本书后面几个切面(语气与非真实、确定性与言据、语域与态度)的共同底子。语法不是从天上掉下来的公式表,它是一层层沉积下来的、还带着前人生活痕迹的岩层。你每挖一层,就会发现下面那层比上面这层更具体、更有画面感。


12. 附:本面速查表

12.1 十二格矩阵(母案例版)

格形态典型时间状语母案例例句中文
过去一般didyesterday, on 12 November 2024, last week, at 2:47 a.m.Lin ran the migration at 2:14 a.m.Lin 在凌晨 2:14 执行了那条迁移。
过去进行was/were doingat that moment, when + 一般过去, whileThe migration was still running when Priya joined.Priya 上线时迁移还在跑。
过去完成had doneby then, already, never, before + 一般过去, when + 一般过去Lin had never run a migration alone.此前 Lin 从未独立执行过迁移。
过去完成进行had been doingfor ten minutes, since + 过去点, by the timeLin had been trying to kill it for ten minutes.他试图中止它,试了十分钟。
现在一般do/doesalways, every day, usually, now, on MondaysLin trains the on-call team.Lin 现在负责 on-call 培训。
现在进行am/is/are doingnow, at the moment, these days, right nowLin is rewriting the on-call curriculum.Lin 正在重写 on-call 培训大纲。
现在完成have/has doneever, never, since, for, so far, yet, already, just, in his careerPallet has gone 22 months without a P1 incident.Pallet 已经 22 个月没有 P1 事故了。
现在完成进行have/has been doingfor + 段时间, since + 点时间, all dayLin has been running on-call training since 2025.Lin 从 2025 年起一直在负责 on-call 培训。
将来一般will dotomorrow, next quarter, in Q1, soonThe team will adopt gh-ost for all schema changes.团队将为所有 schema 变更采用 gh-ost。
将来进行will be doingat 10 a.m., this time tomorrow, when you arriveAt 10 a.m. Priya will be opening the postmortem.十点的时候 Priya 会正在主持复盘会开场。
将来完成will have doneby + 将来点, by then, by the timeBy December the team will have added an abort section to the runbook.到 12 月,团队将已经把”如何中止”这一节补进 runbook。
将来完成进行will have been doingby + 将来点, for + 段时间By next November Pallet will have been running gh-ost for a full year.到明年 11 月,Pallet 用 gh-ost 就满一年了。

12.2 时间状语:封闭 vs 开放

封闭区间(配一般过去)开放区间(配现在完成)
yesterday, last week/month/yearever, never, before
on 12 November 2024, in 2024so far, up to now, until now
at 2:47 a.m., at that momentsince November 2024, for 22 months
when I was a kid, when Lin woke upyet, already, just, recently
… ago, once, that dayin his career, this week(未结束时)
during the outage, in the 2020sthese days, over the years

12.3 母案例的三组杀手级对立对

对立对开窗(现在完成)关窗(一般过去)
北京十年I have lived in Beijing for ten years. 我还住着I lived in Beijing for ten years. 我搬走了
22 个月无 P1Pallet has gone 22 months without a P1 incident. 纪录还在保持(庆功)Pallet went 22 months without a P1 incident. 纪录已终结,然后又出事了(讣告)
有经验 / 有前科Lin has run production migrations before. 他不是没干过Lin ran the migration on November 12, 2024. 历史陈述

12.4 将来四说法

说法化石原义语感母案例
will do意愿、意志预测 / 当场决定 / 承诺 / 正式宣告The team will adopt gh-ost in Q1.
be going to do正在去某处(空间位移)有当下迹象 / 意图已定We’re going to add a runbook section.
be doing正在进行已有安排 / 流程已启动Marcus is meeting Northwind at 11.
do/does无时间性的属性时刻表 / 写死的日程The postmortem starts at 10 a.m.

12.5 三个判断问题(写每个动词前跑一遍)

  1. 时间窗口现在开着吗? 开着 -> 完成体;关着 -> 一般过去。
  2. 这一句偏离叙事默认档了吗? 倒带 -> 过去完成;推近 -> 过去进行;跳回现在 -> 现在时;都没 -> 一般过去(继承默认)。
  3. 这一句是设原点的,还是做参照的? 主句 / 名词性从句 -> 可以设原点(用 will);时间状语从句 -> 做参照(用现在时)。

12.6 本章卫星案例索引(按领域)

母案例 The Outage 之外,本章一共用了十九个独立事件。它们不是装饰,是用来证明”这条规则不是技术场景的专利”的证据。

领域案例出现在服务的知识点
技术 / 工程The Outage(母案例)全章全部
日常生活外卖等了四十分钟9.1一般过去 vs 现在完成;完成进行的”还在等”
日常生活租房两年 / 房东涨租9.3that / this 与动词形态的分工
日常生活错过航班 / 错过高铁9.4完成体指向”现在该怎么办”
日常生活钥匙锁屋里9.6现在完成 = 当下的处境
日常生活快递已签收但没收到5.7现在完成四种用法
日常生活手机落出租车6.3倒带必须有锚点;进行体搭台
社交 / 情感微信消息被撤回 / 发错群9.5陈述 vs 报警;倒带
社交 / 情感老同学失联十年后重逢5.5开窗 / 关窗对立对
社交 / 情感被朋友放鸽子9.7完成进行体的情绪;完成体给当下定性
工作 / 商业面试 / 准备面试两周9.2履历陈述 vs 当下判断;倒带
工作 / 商业项目延期到 7 月 30 日7.5将来四化石
工作 / 商业邮件发错收件人9.8复盘 vs 报警;倒带
工作 / 商业谈薪被拒9.10完成体描述当下的处境
医疗 / 健康体检指标异常5.7现在完成四种用法
医疗 / 健康戒烟反复失败5.5have tried vs tried = 两种人生现状
运动 / 比赛最后一秒被绝杀9.9完成进行体给持续计时并钉终点
学习差一分没考上6.6完成体 = 站在窗前往里数
公共 / 新闻小区停电六小时7.8默认档与显式覆盖
公共 / 新闻地铁十号线故障9.11完成进行;时刻表化石
公共 / 新闻楼下店铺关了一个月卡点 C形态定不了格,得看词性

**七个领域。技术类只占一个(母案例)。**你把这些案例里的 Pallet、orders 表、gh-ost 全部换成钥匙、火锅店、体检报告、足球赛,规则一个字都不用改——这就是它们存在的意义。

12.7 本章的十二个卡点

按类型分一下,方便你回头挑着练:

#卡点类型位置
1中文”我昨天吃饭”和”我吃饭”动词有什么区别观察型1
2was walking 和 walked 的区别二选一2
3英语到底有几个”时态”(多半答 16 或 12)判断对错卡点 A
4will 除了”将要”还在哪儿见过观察型3.1
5The noodle shop has been closed for a month. 是 12 格哪一格判断对错卡点 C
6三组最小对立对(一般/进行、完成/完成进行)判断对错4.3
7三组句子判断对错(含恐龙灭绝 + “语法全对但语义撞车”的祖父那一题)判断对错卡点 D / 5.1
8I have lived in Beijing for ten years. 这人现在住哪儿二选一5.4
9孤立的 The migration had locked... 语法有问题吗判断对错卡点 E
10”明天下午三点有个评审会”翻成英文翻译缺口卡点 B
11数一数停电那段里有几个动词”变了时态”判断对错卡点 F
12when ... will begin 为什么一处能用一处不能判断对错7.7

附赠两处练习区:§4.3 那三组最小对立对(已算入第 6 项),以及 §9 的十一组最小对立对——外卖、钥匙、放鸽子、绝杀、谈薪、地铁,每一组你都可以拿来当新的二选一练。

三种类型是轮换的:判断对错(3、5、6、7、9、11、12)、二选一(2、8,外加 §9 那十一组)、翻译缺口(10),剩下两个是”观察型”(1、4)——先让你看见一个你从没注意过的现象,再拆它。


下一面:完成性与过程 —— 为什么 The migration locked the orders table. 和 The migration was locking the orders table. 不只是”镜头推近”,而是事件本身的有界性在作祟。