Amethyst Studio
3458 words
17 minutes
AI编程的挑战

毋庸置疑,以大模型为代表的AI技术正在深刻地改变着编程的格局。市场涌现了不少AI辅助编程的工具。然而,除了模型本身的能力之外,我们还必须正视一个关键问题:在现有的众多编程语言中,真正适合AI编程的语言似乎并不多。

回顾过去几十年,编程语言领域涌现了无数的创新。从工业界广泛应用的C/C++、Python、Java、JavaScript,到学术界备受推崇的Haskell、OCaml等,各有千秋。但一个不争的事实是,前者在流行程度上远超后者。即便这些主流语言在设计理念上存在各种各样的不足,甚至某些语言(如JavaScript)一直以来都面临着不少争议,但它们依然占据着编程世界的主导地位。

一个引人深思的问题是,为什么一个仅仅花费十天设计的JavaScript,其流行度竟然远远超过了经过十几年精心打磨和严谨论证的Haskell?诚然,时代背景和技术风口是重要的驱动因素——JavaScript抓住了浏览器普及的浪潮,Python则搭上了机器学习和大数据快速发展的列车。但从语言设计本身的角度来看,这些流行语言都具有一个非常显著的共同点,那就是它们提供了许多为了方便人类程序员编写代码而设计的特性,例如动态类型、隐式类型转换、函数重载、多态以及宏等等。相比之下,像Haskell、OCaml这类更加注重严谨性和逻辑性的语言,则往往缺乏这些对人类非常友好的特性。再比如Rust,虽然拥趸众多,但也有不少开发者对其复杂性望而却步,这很大程度上也是因为Rust对程序员的心智负担相对较重。

然而,我们必须认识到,那些对人类友好的语言特性,对于AI而言,可能恰恰是潜在的障碍。

人类编程与AI编程的巨大差异#

要理解这一点,我们需要区分人类编程和AI编程之间的一个根本差异。对于人类来说,无论使用何种编程语言,验证程序正确性的最常见方法通常是先运行程序,如果得到了预期的结果,那么就认为程序是正确的;反之,则说明程序存在错误。在这种模式下,编译型语言和解释型语言之间的区别对人类程序员而言,并没有那么本质。

但是,对于AI而言,情况则大不相同。AI在很大程度上依赖于对代码的静态分析和理解。虽然AI也可以像人类一样执行程序,但这对于它来说并非总是便捷高效的。首先,运行程序可能会消耗大量的上下文窗口资源。其次,如果程序涉及到图形渲染或者音视频处理等领域,我们是否需要等待大模型具备极其庞大的上下文容量和强大的多模态能力,使其既能“看懂”图像、“听懂”声音,甚至“理解”视频内容之后,才能进行AI编程呢?

显然,我们可能无法等待如此漫长的时间。一个更直接有效的方案或许是,我们直接设计出更适合AI进行编程的语言。

对人类友好,对AI则是潜在障碍的特性#

动态类型#

在过去的十年左右,动态类型语言如JavaScript和Python异常火爆。动态类型语言的学习曲线相对平缓,入门简单,初学者不需要预先掌握大量的复杂概念。一个新手往往只需要花费几天的时间学习Python,就能编写出一些实用的脚本和小工具。易学性带来了一个显著的优势,那就是市场拥有大量掌握这类语言的开发者,从而降低了劳动力市场的成本。尽管动态类型语言通常存在运行效率相对较低的缺点,但过去的普遍观点是硬件成本远低于人力成本,程序员的时间比机器的时间宝贵得多。因此,牺牲一定的机器运行时间来换取开发效率的大幅提升,在当时看来是相当划算的。

然而,对于AI来说,动态类型却可能成为一个“噩梦”。首先,在动态类型语言中,一旦发生类型错误,报错的位置往往与错误实际发生的地方相距甚远。当错误发生时,AI可能需要沿着调用栈进行更深入的分析,这无疑需要更长的调试步骤和更大的上下文支持。其次,由于动态类型语言中变量的类型可以在运行时动态改变,AI在阅读代码时无法进行“跳跃式”的理解。如果AI跳过了一段代码,它将无法确定变量的类型是否仍然符合其之前的推断,这导致AI需要构建更长的推理链才能理解动态类型语言的代码。

正是由于动态类型语言的这些特性,使得Python和JavaScript不太适合用于构建大型的AI驱动的程序。或许作为脚本语言,AI可以利用它们编写一些简单的代码片段,但指望AI使用Python或JavaScript来构建复杂的、具有高度可靠性的AI系统,目前来看基本是不太现实的。

隐式类型转换#

在进行赋值操作(包括函数调用时将实参传递给形参)时,如果左右两边的值的类型不一致,编译器可能会自动进行隐式类型转换,将右值的类型强制转换为左值的类型,然后再进行赋值。在一些基础场景下,这种隐式类型转换往往符合人类的直觉,一个简单的例子就是C语言中的float x = 1,这里的1int类型,编译器会自动执行一个整数到浮点数的转换,这在大多数情况下不会引起问题。

然而,令人遗憾的是,多年来的实践表明,隐式类型转换带来了大量的Bug。因为类型系统远不止floatint这么简单。在C++等更复杂的语言中,左值引用、右值引用、const限定符等都被纳入到类型系统之中。不加区分地进行隐式类型转换可能会导致一些原本存在类型错误的代码顺利通过编译,从而使得一些潜在的问题无法在编译期被及时发现,最终只能在运行时暴露出来。这种运行时错误对于依赖静态分析的AI编程来说,无疑是一个巨大的障碍。

宏和模板#

宏和模板技术可以有效地减少代码中的重复逻辑,使得人类程序员能够用更少的代码完成更多的工作。对于人类程序员来说,宏和模板是非常强大的工具,能够提高开发效率和代码的复用性。但是对于AI来说,宏和模板的存在使得代码的逻辑变得不那么直观。宏展开和模板实例化会生成大量的代码,这增加了AI理解代码结构的难度。更重要的是,如果被宏或模板包裹的代码中存在错误,调试将会变得非常困难。即使对于经验丰富的人类程序员来说,调试宏和模板相关的错误也是一项具有挑战性的任务,对于AI来说,其难度可想而知。

函数重载#

对于人类程序员来说,函数重载能够在一定程度上降低心智负担,因为不同的功能实现可以使用相同的函数名称,从而提高代码的可读性和易用性。如果人类程序员不确定某个函数调用是否是预期的版本,可以通过运行时的调试操作来确认。然而,对于AI来说,函数重载可能会造成混淆,导致AI难以准确判断当前调用的是哪个具体的函数实现。如果编程语言本身还具有动态类型或隐式类型转换等特性,那么AI被误导的可能性将大大增加。一旦AI在分析过程中出现了偏差,错误地理解了实际调用的函数,那么它后续基于错误理解生成的代码几乎可以肯定会无法正常工作。

全局变量#

人类在编写小型程序时可能会觉得全局变量很方便,可以直接访问和修改,省去了参数传递的麻烦。但是对于AI来说,尤其是在处理并发或者大型程序时,全局变量会引入复杂的状态依赖和副作用,使得程序的行为难以预测和分析。AI需要追踪这些全局状态的变化,这会显著增加其理解和调试的难度。函数式编程范式中强调的不可变性和纯函数,在这方面对AI可能更友好,因为它们减少了状态的共享和修改,使得程序的行为更加可预测。

隐式的控制流#

异常处理机制允许程序在遇到问题时跳转到特定的处理代码块,这对于提高程序的健壮性很有帮助。然而,对于AI来说,这种非局部的控制流转移可能会比较难以理解和预测。当异常发生时,程序的执行流程会突然跳转到另一个地方,这使得AI难以跟踪代码的执行路径和理解程序的整体逻辑。AI可能需要更明确的错误处理方式,例如返回错误码或者使用特定的Result类型来显式地表示操作的结果,这样可以使得错误处理的逻辑更加清晰和可控。


什么样的语言更适合AI编程#

如果我们根据前面的讨论来“对号入座”,那么Java,Python、JavaScript、C和C++这些流行语言,由于它们包含较多上述对AI不友好的特性,可能在AI深度参与的大型软件工程中面临较大的挑战。这里面的Java相对而言会稍微好一些,其强类型系统和相对较少的“魔法”特性对静态分析更友好,但其纯面向对象的范式有时也显得较为臃肿和刻板,并且Java隐式控制流的问题也很突出。

在当前的流行语言中,反而是以“难学”著称的Rust,展现出了一些更适合AI编程的潜力。尽管Rust也有宏系统(过程宏),但其核心优势在于:

  • 强类型系统:几乎没有隐式类型转换,类型错误在编译期就能被严格检查出来。

  • 所有权与借用检查器:这是Rust的“杀手锏”。它在编译期强制执行内存安全和线程安全规则,能消除一大类困扰C/C++程序员的运行时bug(如悬垂指针、数据竞争)。这意味着编译器本身就能承担大量的静态验证工作,减轻了AI在理解和生成安全、正确代码方面的负担。

一个强大的、能在编译阶段捕获大量非业务逻辑错误的编译器,对于AI来说是一个极其宝贵的“伙伴”。因此,在AI编程的时代,像Rust这样重视编译期检查和静态分析能力的语言,其未来的表现非常值得我们期待。

专门为AI编程设计语言#

尽管如此,Rust仍然有宏系统这种不太适合AI的特性,这也很正常,因为Rust是在2008年左右开始设计,那个时候的Rust创始人未必会预料到今天的AI时代。但是考虑到AI时代已经来临,专门为AI编程设计语言可能是一条更可行的路,但要注意的是适合于AI编程的语言可能会抛弃掉一些对人类友好的特性,甚至可能增加一些在人类眼中看起来很麻烦的特性,这样的语言,应该会更加强调:

  • 简洁明确的语义:减少歧义,让AI更容易理解代码的精确含义。

  • 更强的静态保证:不仅仅是类型安全,可能还包括资源管理、并发模型等方面的静态验证。

  • 更优的代码分析工具和代码总结工具:快速提供给AI所需要的信息。

  • 更强大的项目组织工具。

总而言之,编程语言的设计一直是在开发效率、运行性能、安全性、表达能力等多个维度之间进行权衡。随着AI越来越多地参与到软件开发过程中,“对AI友好” (AI-friendliness)可能会成为语言设计需要考量的一个新的重要维度

AI编程的挑战
https://ziyue.cafe/posts/thought-about-ai-coding/
Author
Kaida Amethyst
Published at
2025-03-18