为什么AI不擅长这些编程语言
并非所有编程语言都是生而平等的。
梯形图转SCL | AI模型价格对比 | AI工具导航 | ONNX模型库 | Vibe Coding教程 | PLC在线仿真器 | Tripo 3D | Meshy AI | ElevenLabs | KlingAI | ArtSpace | Phot.AI | InVideo
并非所有编程语言都是生而平等的。有些语言隐藏了上下文、所有权、状态、顺序和语义规则的层级,这些都必须同时保持正确。
或者用简单的话说: 即使一行简单代码也能携带的不同上下文,使得这个神话完全错误,而开发者的参与比以往任何时候都更加必要……取决于编程语言。一旦你看到它,你会确切地知道自己属于哪个群体。
1、案例分析:C++的克星
AI能写C++并不意味着它能构建可靠的C++项目。
它可以生成模板、编写RAII、产生概念、迭代器、lambda、移动构造函数、转发包装器、分配器和并发代码,看起来惊人地熟练。很好。
是的,我们在这里同意那些危言耸听的人。大部分可见的代码生产已经在自动化了。
但别急着开AI香槟。
因为C++有一个像Go这样的语言暴露得不那么强烈的讨厌特性:一行代码的意义可能依赖于多个交互的语义上下文,而这些上下文在代码行本身中是不可见的。
一段C++代码可以干净地编译、通过表面测试,但仍然是错误的,因为正确性依赖于几个语义层之外的东西:名称查找、ADL、模板依赖、重载解析、概念、值类别、对象生命周期、所有权、并发,等等。
而这正是AI可能搞砸你整个项目的地方。
问题不是它不能产生语法。问题是C++可能需要更接近于:
(代码,嵌套上下文) → 意义
而不仅仅是:
代码 → 意义。
现在你知道当前AI最糟糕的地方:嵌套上下文,无论是在C++中还是在任何其他严重依赖它们的编程语言中。
如果你以前读过我的文章,这是另一个确凿的证据,说明为什么我们需要一种完全不同类型的AI,建立在与当今不同的数学基础上。
所以重点很简单:
代码行只是可见的表面。真正的语义生活在下面。而这正是当前AI糟糕的地方。
2、为什么AI无法理解普通开发者轻松完成的事情
这是对任何感到被自动化威胁的开发者真正重要的问题,不仅仅是C++开发者。
一个普通开发者,更不用说高级开发者,看到一行代码就能立即恢复围绕它的大部分上下文。
那么,对你来说几乎是例行公事的事情,对AI来说为什么如此困难?
下面的动画对你来说会像C++的ABC一样熟悉,但同样的想法适用于任何在单行代码后面隐藏多个嵌套上下文的语言。
这个简单的事实扼杀了任何AI编码器。这不是或多或少人工监督的问题。问题是AI对许多这些嵌套上下文视而不见,正如你将在接下来的例子中看到的。
而有效使用AI进行编程的关键是在它们炸毁你整个项目之前,确切地知道这些上下文雷区隐藏在哪里。
再看看上面动画中这行无害的代码:process(x)。
一个称职的C++开发者几乎可以立即看到它背后是什么,因为他们已经知道周围的代码。在特定上下文中,该表达式可以存在于五个不同的语义层中:词法作用域、类型、ADL、隐藏朋友和重载解析。
而这只是一个语义宇宙中的一行代码——我用语义宇宙作为那些嵌套上下文获得其含义的更大环境的简称——
现在把完全相同的行放在另一个语义宇宙中,具有不同的类型、不同的查找规则、不同的ADL路径、不同的隐藏朋友和不同的重载集。
突然间,我们的AI不再只处理一个头痛。它正在处理完全不同语义宇宙中的嵌套上下文。
那时,头痛正在变成更糟糕的事情。
一旦那些嵌套上下文属于不同的语义宇宙,AI不仅要保留层本身,还要保留每个层属于哪个宇宙。
那时,我们现代的AI开始看起来像一艘试图在热带风暴中保持干燥的玩具纸船。
如你所见,AI编码器作为一台生成机器,开始在各种故障中溺水:
命名空间相互模糊,类型失去了重要的区分,ADL路径消失,隐藏朋友不再可见,重载集扁平化成从前面看欺骗性相似的东西。
而在模型面前剩下的东西仍然可以看起来像同一行无害的代码:
process(x);
而它背后的真实语义世界完全不同。这就是噩梦:相同的可见代码,不同的隐藏宇宙,不同的意义。
现在回到任何AI编码器问题的核心。
我们在开头看到的五个语义层是我们软件工程中称之为程序隐藏结构的一部分,它们可能是正确的C++代码和微妙或明显错误的C++代码之间的区别。
但当然,C++只是AI编码器道路上的一块石头。如果你现在问AI是否也在其他编程语言上表现糟糕,答案是响亮的是的。
下面的列表显示了五种对AI打击最大的编程语言,正是因为它们充满了这些雷区:埋藏在语法和语义中的嵌套上下文。
规则很简单:一种语言越依赖于上下文、顺序、所有权、生命周期或非局部语义,对AI来说工作就越困难。
这也不仅仅是理论。实验工作不断发现相同的模式:一旦正确性依赖于多个同时交互的上下文,当前的LLM变得不那么可靠。
3、Haskell:我们万亿美元超级AI的氪石
以Haskell作为一个典型例子——runST用与C++不同类型的上下文问题打击同一个AI:这次是嵌套类型上下文。
用在JavaScript中不会造成麻烦的相同类型的提示愚弄AI是微不足道的:要求它在ST计算中创建一个可变引用,然后天真地尝试返回它。
每一行代码看起来都没问题。每个本地操作甚至可以单独有效。
但该引用属于由runST创建的私有类型级上下文s。Haskell的类型系统不会允许绑定到该s的引用在计算外部返回。
**而这正是当前AI可能出错的那种事情:**所有本地操作看起来都很熟悉,但由于在生成行之上几个步骤的上下文强加的隐藏类型级边界,整个程序是非法的。
如果你从未处理过不可变函数上下文中的可变状态,请看下面的图表。你会立即明白要点。
这可能会让JavaScript程序员感到惊讶,因为闭包似乎做了几乎相反的事情。JavaScript闭包可以在保持对其原始作用域中创建的变量的访问的同时返回。runST故意禁止其私有可变引用的这种行为。
你可以返回在runST内执行的计算结果,但你不能返回可变引用本身。
底层规则非常简单:你可以携带信息,但不能携带产生它的私有可变状态。
所以用简单的话说,我们万亿美元的AI可以理解每个本地操作,但仍然错过当上下文决定正确代码时,由封闭类型上下文强加的边界。
底线:这个嵌套上下文问题的一个根源是,今天的LLM围绕下一个令牌预测构建。而下一个令牌预测本身并不正式执行将一个语义上下文与另一个语义上下文分开的规则。
所以,总结一下:当前的AI可以从示例中学习这些规则,并且它可以经常遵循它们。但它不能保证它们的每个组合都保持正确。
Haskell的类型系统残酷地暴露了这一点,其他明确执行类似作用域和类型约束的强类型函数语言也是如此。它们揭示了AI最大的弱点之一:同时保持多个嵌套语义上下文正确。
4、Rust:所有权上下文对AI来说难以消化
Rust暴露了第三种破坏派对的上下文:所有权、借用和生命周期关系。
Haskell用类型级上下文困住AI。Rust用谁拥有什么、谁在借用它,以及这种关系被允许保持有效多长时间来困住它。
看看看起来完全合理的东西:
fn first_then_push(v: &mut Vec<i32>) -> &i32 {
let first = &v[0];
v.push(42);
first
}
这段代码的问题在哪里?每一行对AI编码器来说看起来都几乎微不足道:
let first = &v[0];
v.push(42);
first
从局部来看,每个操作看起来都完全有效。这正是陷阱所在。
问题只在这些行在同一个语义上下文中组合时出现。当v.push(42)尝试修改v时,first仍然指向v。Rust不允许这种组合,因为修改可能使活动引用无效。
所以再次,失败不在于单个令牌或行。而在于它们之间的关系。
而这正是当前AI可能丢失上下文并遇到困难的地方:它可以正确生成每个本地操作,同时未能保留使整个组合非法的周围所有权和借用上下文。
5、现在反过来看:最适合AI的编程语言
如果嵌套上下文是AI遇到麻烦的地方,那么相反的情况也应该成立。
有些语言只是给模型一个更干净的工作。
它们的含义更接近你实际能看到的代码。需要重建的隐藏语义层更少,查找陷阱更少,生命周期机制更少,类型级间接更少。也更少出现一行无害的代码突然因为代码中三个语义上下文深处发生的事情而改变意义的情况。
这正是为什么,在本文开发的结构标准上,Python、JavaScript、Go、Lua和Java等语言更适合当前的AI。
记住一点:这不是基准排名。它是根据我们所说的隐藏语义结构负载进行的排名。
用简单的英语说:
在一行看起来正确的代码实际上正确之前,AI必须跟踪多少不可见的语义机制?
看看表格中的模式。对于这些语言中的传统代码,语义路径通常短得多:
可见代码 → 局部上下文 → 意义
与我们之前看到的C++结构相比,其中嵌套上下文成为我们AI真正的头痛:
意义[类型[查找[候选[约束[值类别[生命周期]]]]]]
不是来自C++标准的字面层次结构。只是一个视觉简写,表示一个语义层如何约束或重新解释下一个。
这是你在决定希望AI自动化多少代码时应该关心的区别。它在很大程度上取决于你使用哪种语言。
是的,我已经能听到抱怨了:但Python或JavaScript也可能变得很丑陋。
当然它们可以。
Python有元类、装饰器、描述符、猴子补丁和动态分派。
JavaScript有原型、强制转换、闭包和异步状态。
Lua有元表。
Java仍然有继承、重载、反射和泛型。
但在大多数传统代码中,这些语言通常迫使AI同时保持更少的隐藏语义层同步。
而当上下文依赖确实出现时,这些上下文通常比C++或Haskell等语言更浅,交互也不那么激烈。
这很重要,因为更浅的上下文结构原则上更容易让LLM从示例中统计学习,而不是更深的上下文,其中几个语义层都必须同时保持正确。
而这就是对你来说非常实用的地方。
AI不会以同样的方式来到每个程序员身边。如果你的大部分工作生活在意义就在模型面前的代码中,AI的工作相当容易。
但如果你的代码依赖于所有权、生命周期、查找、约束、隐藏状态或生活在几个层级之外的上下文,那么你正在玩一个完全不同的游戏。
当然,让机器写样板代码。让它生成测试、清理本地代码、翻译API、解释模块,并在几秒钟内拼凑出第一份草稿。
这正是你应该使用它的地方。
但当项目的真正正确性存在于隐藏的语义结构中时,仍然有人需要知道哪个上下文重要,它来自哪里,以及什么绝对不能被破坏。
那个人仍然是你。
原文链接:Why AI Sucks at These Programming Languages
汇智网翻译整理,转载请标明出处