如果 AI 已经能够写出大部分代码,编程语言还有什么价值?

一种直接的回答是:人仍然需要检查 AI 写出的程序,所以仍然要学会编程。这个回答当然没有错,但它只是在为旧有的软件开发流程寻找延续。真正值得追问的是,当亲手实现程序不再是人的主要工作,编程语言是否还有一种更基础的价值?

我认为有。编程语言不只是命令计算机的工具,也可以成为人向 AI 表达思想的工具。

代码变便宜了,意图没有

AI Coding 降低的主要是实现成本。只要目标足够清楚,模型已经可以生成函数、页面、接口、测试,甚至连续修改一个完整项目。

但「目标足够清楚」恰恰是最难满足的条件。

人的想法并不是一份天然完整的需求文档。它可能只是一个画面、一种不满、一条还说不清的直觉,或者几个彼此冲突的愿望。我们把它说给 AI 时,往往只表达了其中很小一部分,其余内容则被当作无需说明的常识留在脑中。

AI 无法直接读取这些没有说出口的部分。它只能根据已经得到的文字和训练中见过的模式,把空白补成一种看起来合理的结果。正如我在《LLM 与信息熵》中讨论的那样,模型能够从少量信息补全出庞大结果,但补全并不是还原人的真实意图。

于是,AI 越会写代码,人的工作越可能向上游移动:不再是亲手敲出每一行实现,而是先回答自己究竟想创造什么、其中有哪些对象、规则、边界和例外。

自然语言擅长交流,却不总擅长约束

自然语言是人最熟悉的表达方式。它能承载情绪、语境、隐喻和大量没有完全说死的空间。很多思想也只有在这种模糊中才有机会慢慢成形。

但当我们需要表达精确关系时,这种开放性也会变成歧义。

比如,「把重要结论记录下来」听起来已经很清楚,实际却留下了许多问题:什么算重要?结论和推测如何区分?结论是否需要来源?后来被推翻时应该覆盖,还是保留历史?没有证据的判断能不能进入系统?

这些问题当然可以继续用自然语言解释,但每补充一段,又可能引入新的指代和例外。读者必须同时记住前文,并推断这些句子之间究竟是什么关系。

编程语言则会迫使一部分关系显式出现。例如,可以先把一条判断写成这样的结构:

from dataclasses import dataclass
from typing import Literal


@dataclass
class Claim:
    text: str
    kind: Literal["fact", "inference", "preference"]
    source: str | None
    confidence: float

这几行代码并没有解决「什么是真实」这样的哲学问题,也没有保证所有数据都正确。但它一次性固定了几件事:一条判断需要正文;事实、推断和偏好具有不同地位;来源可能缺失;置信度需要被单独表达。

更重要的是,这个结构可以运行。我们可以构造例子、加入反例、写下断言,让思想不只停留在听起来合理的句子中,而是接受具体输入的检验。

编程语言的高密度,来自同时排除许多解释

编程语言不一定比自然语言更短。一个类型定义可能比一句口头描述长得多。它的信息密度也不应简单理解为字符更少,而在于一段定义可以同时约束许多后续解释。

函数签名说明输入和输出,类型说明对象如何组合,状态机说明什么可以发生,测试说明哪些具体行为必须成立。写下一条约束,往往意味着同时排除了许多不符合它的可能世界。

这正是编程语言适合与 AI 沟通的地方。AI 不必从一段散文中反复猜测「这里大概是什么意思」,而可以沿着已经显式存在的结构继续推演。即使它仍然可能理解错误,错误也更容易被定位:是类型定义错了,是状态遗漏了,是例子不完整,还是实现违反了约束。

代码因此不只是最终产物,也可以是意图的中间表示。自然语言负责保留动机、语境和仍未成形的部分;编程语言负责固定已经能够说清的结构;运行结果再反过来检验这套结构是否真的符合最初想法。

类型系统也可以成为人的外部记忆

类型通常被解释为防止程序出错的工具。但当代码被用来思考时,它还有另一个作用:帮助人记住自己之前定义过什么。

人的工作记忆十分有限。写到后面时,我们可能已经忘记前面某个概念允许哪些状态、一个函数承诺返回什么、某个字段究竟能否为空。类型、自动补全和跳转定义把这些关系保留在编辑器里,让人不必一直把整个模型装在脑中。

因此,类型不只是机器对代码的检查,也是一种认知脚手架。它可以把暂时不需要关注的细节放到外部,在需要时再重新展开。

当然,约束出现得太早也会打断思考。一个想法刚刚萌芽时,人可能还不知道它应该有哪些类型;如果此时急于让所有分支完整、所有命名稳定,编程语言就会从表达工具变成格式审查员。

更合适的过程或许是渐进的:先允许思想以较松散的形式出现,再把逐渐稳定的概念变成类型、函数、状态和测试。形式化不是思想的起点,也不是所有思想的终点,而是其中一部分开始需要被准确传递和反复验证时才采用的手段。

编程语言不是唯一的形式语言

如果目的只是把思想更准确地传递给 AI,那么没有理由把编程语言变成新的教条。

数学家表达关系时,数学公式通常比 Python 或 TypeScript 更直接,而公式常常使用 LaTeX 书写。状态转换可能更适合状态图,多个条件之间的组合可能更适合决策表,数据边界可能更适合 schema,具体行为则可能直接交给示例和测试表达。

不同媒介各自压缩了不同类型的思想:

  • 自然语言适合动机、语境、价值和仍然开放的问题;
  • 编程语言适合过程、状态、数据关系和可执行行为;
  • 数学公式适合数量、变换和形式关系;
  • 图表适合空间、顺序和整体结构;
  • 示例与测试适合说明抽象在具体情况下究竟意味着什么。

真正重要的不是坚持使用哪一种语言,而是判断当前思想的哪一部分最容易在传递中丢失,再选择能把这一部分说清楚的表达方式。

形式化也会损失思想

编程语言降低了歧义,却不会自动保留人的全部意图。

当我们把一段感受写成字段,把一个价值判断写成布尔值,把连续变化的现实压成几个枚举状态时,也可能为了让结构整齐而删掉无法形式化的部分。程序能够运行,只能证明这套模型内部可以运行,不能证明它忠实地代表了现实。

所以,编程语言不是比自然语言更高级的表达方式。它只是牺牲了一部分开放性,换来一部分明确性。好的表达不应把所有内容都强行写成代码,而应该让自然语言、形式结构和具体例子互相校正,并且始终保留回到原始问题的路径。

这和 AI Coding 本身很相似。模型可以生成一套逻辑完整的实现,但如果最初的问题定义错了,代码越完整,只会让错误的想法执行得越可靠。

AI Coding 时代更需要学会表达结构

过去学习编程,常常从语法、标准库、框架和工程实践开始,因为人必须亲手把思想翻译成机器可以执行的细节。未来,这部分翻译会越来越多地由 AI 完成。

但这不意味着编程语言会失去价值。它的价值会从「我能否亲手写出所有实现」,部分转移到「我能否把自己的思想表达成 AI 不必大量猜测的结构」。

人不一定需要记住每个库函数,也不一定需要比 AI 更快地写出样板代码。但他仍然需要知道:哪些概念必须区分,哪些状态不能出现,什么结果算成功,什么代价不能接受,以及现实反馈如何推翻原来的模型。

AI 可以替人生成代码,却不能替人拥有最初的意图。它也可以帮助澄清意图,但最终仍然需要人判断,生成出来的结构是否真的是自己想表达的世界。

因此,在 AI Coding 时代,编程语言依然重要。它不再只是人与计算机之间的命令,也可以成为人与 AI 之间的精确媒介。

目的从来不是写代码本身,而是让内心尚且模糊的东西,在传递给另一个智能体时少丢失一点。编程语言、数学公式、图表、测试以及未来可能出现的新表达方式,都是为这个目的服务的工具。

当实现越来越便宜,真正稀缺的仍然是形成思想,并把它说清楚的能力。