编程语言是平台的创作工具

Hacker News Top 新闻

摘要

一篇反思性文章,论证编程语言是平台的创作工具,通过IBM和Microsoft等历史实例,阐述语言如何塑造生态系统和开发者社区。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/07/28 09:24

# 编程语言是平台的创作工具 来源: https://www.makonea.com/en-US/blog/programming-languages-are-authoring-tools-for-platforms ## 引言…… 在规划新项目并决定使用哪种语言时,人们常常陷入两种幻觉。他们要么推崇某种"学术血统",比如函数式范式或类型系统的纯粹性;要么盲目追随"社区热点",被GitHub星星数和程序员圈子的喧嚣所裹挟。认为优雅的数学证明或时髦的语法就能保证产品的生存,这是一种天真的假设——尽管在某种程度上也可以理解。人们希望自己倾注职业生涯去学习的语言及其世界观/范式,能够经得起时间的考验。老实说,如果明天C#和TypeScript开始失去市场份额,我会在每一个编程论坛上大肆宣扬它们有多么优越。 无论如何,每个程序的执行最终都归结为由机器执行的指令和状态转换。当解释器逐步读取源代码或字节码时,原始程序可能永远不会被完全翻译成机器码。即便如此,如果我们只关心可计算性,高级语言并非严格必需。同样的计算完全可以只用机器码或汇编来表达。 然而,真实的历史正如我们所知那样展开。人们并没有只用汇编和C来编写每一个程序。大量高级语言和运行时环境的涌现,是为了解决不同的问题和应对不同的**平台**。 每当新硬件出现,操作系统兴起,浏览器和智能手机普及,用于这些"表面"的语言和工具也随之而来。这是因为更昂贵的问题从"机器*能否*计算某物"转变为"人们能在该机器之上*构建*多少程序"。 IBM将PC平台领导权拱手让给微软,也可以用同样的视角来解读。IBM创造了被称为PC的硬件标准,但在此之上构建的应用软件和开发者生态系统,却与MS-DOS和Windows API绑定在了一起,而非IBM的机器。随着兼容PC的普及,硬件变成了商品,而微软——控制着开发者编写程序接口的公司——成为了该平台的真正所有者。¹ (https://www.makonea.com/en-US/blog/programming-languages-are-authoring-tools-for-platforms#fn-fn-x46m75) **一个空平台还不是产品。只有当游戏、生产力应用和内容在其上累积,它才成为用户驻留的世界。语言就是创作那个世界的工具。** 而程序员拿起那个工具,将逻辑和规则施加于空白的空间时,他们便不再仅仅是机器操作员。 > 然而,计算机程序员是一个宇宙的创造者,而他本人就是唯一的立法者。 这是ELIZA的创造者约瑟夫·维森鲍姆在《计算机力量与人类理性》中留下的一句话。 然而,程序员能用语言构建世界这一事实本身,并不能解释该语言的成功。一种极具表现力的语言可能局限于一个小型研究社区,而一种广受批评的语言却可能遇到一个巨大的运行时环境,并成为行业标准。 关于编程语言的讨论通常始于学术分类,如类型系统、语义、范式和实现策略。这些分类很重要,但我认为仅凭它们无法解释语言的实际历史。我的观点是,从就业市场的角度能更好地回答人们为什么要学习一门编程语言。正是这种通过就业市场和更广泛市场视角的思考,促使我写了这篇文章。 追溯编程学术血统的文章并不少见,所以我再添几笔也难有竞争优势。相反,我想提供一个不同的视角。 在我看来,阅读语言史需要区分至少三个问题。 它为什么被创造?开发者为什么采用它?它为什么能长期占据主导地位?我认为这是最根本的问题。一种为研究而构建的语言,可以通过遇到一个巨大的工业平台而获得成功;而为特定平台构建的语言,则可以突破该平台的边界。仅从语言最初的动机出发来解释所有后续历史,很快就会遇到麻烦。 ## 平台与互补品 操作系统、浏览器、游戏主机或智能手机的价值,会随着其上运行的程序而增长。用户每天接触的不是系统的内核或其设计优雅性,而是最终产品:生产力应用和游戏。一台没有游戏可玩的游戏主机,不过是一件昂贵的客厅家具。 在经济学中,组合使用时价值最大化的商品被称为**互补品**。平台和应用程序恰好具有这种互补关系。 如果基础设施是一个巨大的空旷舞台,那么应用程序和内容就是填补它的演员和剧本。无论一个剧院的音响和灯光系统多么先进,如果舞台上没有可表演的内容,观众是不会来的。换句话说,一个平台真正的商业价值和市场主导地位,并非由其自身的计算能力决定,而是完全且依赖性地由其生态系统内持续产生的**互补品**(杀手级应用)的总量决定。 从概念上讲,可以总结如下。 对于平台运营者来说,开发工具类似于工厂设备。销售编译器是否为核心收入来源并不重要。当开发者能够更廉价、更快速地构建程序时,平台上互补品的数量就会增加,平台本身也变得更值钱。Joel Spolsky 描述的"使你的互补品商品化"策略同样适用于语言和 SDK。² (https://www.makonea.com/en-US/blog/programming-languages-are-authoring-tools-for-platforms#fn-fn-0taowy) 因此,关于"高级语言是为销售编译器而创造"的问题,我认为是一个有些片面的框架。企业收入更多地来自计算机、操作系统、运行时、浏览器和智能手机。语言是让人们有理由持续使用这些产品的东西。 ## 语言降低的成本 语言降低的成本远不止于减少敲键盘的数量。 说"你可以用汇编来实现"是关于图灵完备性的一种回答,即关于计算表达力。但它是否能在公司时间表内完成,是否能在多年后由不同的团队进行修改,以及是否能移植到下一台机器,这些都是完全不同的问题——涉及**开发成本**和**实际效用**。 原则上,图灵完备的语言可以表达相同的计算,但问题是,编写、验证和维护这些计算的成本在不同语言间并不相同。那么,我们应该如何看待语言设计中的差异呢?通常,这些差异更多地体现在计算成本与责任如何在人类、编译器和运行时之间分配,而非能计算什么。 在现实世界中,最常被反复问到的问题是什么?是某件事在财务上是否可行。这就是为什么从计算的可能性到其成本分配这一转变如此重要。 从这个角度看,编程语言的历史可以被解读为对每个时代系统中最昂贵资源的一系列响应。当硬件稀缺且昂贵时,执行效率是主要的约束。但随着软件规模扩大和开发组织扩张,编写、验证和维护代码的人力成本也变得同样重要。 高级语言将曾经由人类记忆力和注意力承担的部分工作转移给了编译器、类型系统、垃圾回收器和库。在这个意义上,编程语言既是一种向机器发出指令的**符号系统**,也是一个向个人分配认知成本、向组织分配开发成本的**界面**。 (可以把这看作是编程领域的萨丕尔-沃尔夫假说。) ## 如果C能做到,为什么要用Python? 艾伦·佩利斯在1982年的《编程箴言》中写下了第十九条箴言。³ (https://www.makonea.com/en-US/blog/programming-languages-are-authoring-tools-for-platforms#fn-fn-pi2dud) > "一种不影响你思考编程方式的语言,不值得学习。" 这也可以理解为一种改变你价值观的语言,其含义依然成立。不过,这里的"价值观"较少指代政治信念,更多是指你感知程序的习惯:你视为什么是单个值,你给什么操作起名字,你把状态和失败放在哪里,你能简洁地表达什么组合。语言决定了这一切。其核心,语言是一组权衡和集合的集合。(这里,**子集**指的是语言设计者从机器拥有的无限自由中,有意切割出的**'约束的允许空间'**。) 换句话说,你选择关注什么领域、设定做什么目标,都深受你选择的语言影响。 将其应用于Python会引出一个自然的问题。CPython是用C实现的,性能关键的扩展模块也常用C或C++编写。如果底层执行还是C在处理,那为什么不从一开始就全部用C写呢? 仅从底层材料看,这个论点似乎合理,但每个作者所操作的世界完全不同。直接从C调用库的人必须处理指针、缓冲区长度、所有权、错误码、类型转换和链接。而一个Python扩展模块则将这项工作转化为可以通过`import`访问的函数和对象。即使是官方的C扩展API,也被描述为一个边界,用于创建新的对象类型或暴露C库和系统调用,供Python使用。⁴ (https://www.makonea.com/en-US/blog/programming-languages-are-authoring-tools-for-platforms#fn-fn-6nhshz) 例如,即使数值计算的内部循环由C、C++、Fortran和BLAS处理,用户仍将数组作为单个值传递,组合函数,并直接在笔记本中检查结果。遍历内存地址的实现世界与操作矩阵、数据框和模型的创作世界,在同一个程序中并存。Python与其说是C的替代品,不如说是一种以不同粒度处理已有原生代码的方式。 语言世界观(范式)的概念可以总结如下。 | 语言决定的内容 | 更接近C的表面 | 更接近Python的表面 | | :--- | :--- | :--- | | 基本工作单元 | 地址、缓冲区、结构体、函数调用 | 对象、可迭代对象、模块、可调用对象 | | 资源与生命周期 | 显式分配/释放、所有权约定 | 对象生命周期、上下文管理器 | | 失败传播 | 返回值、`errno`、临时约定 | 异常与回溯 | | 组合模型 | 头文件、ABI、链接、函数指针 | `import`、协议、高阶函数 | | 探索风格 | 构建-然后-运行、调试器 | REPL、内省、笔记本 | 在大多数编程社区中,C 之所以被尊崇为"真正的"编程,正是因为它更古老、更接近机器。但程序员拥有有限的认知资源,他们必须始终就如何分配这些资源做出选择。(这样表述可能听起来像硅谷式的泰勒主义,但在这一点上,我发现自己同意泰勒主义的立场。) 如果你投资于数值计算,将注意力集中在底层控制、直接向机器发出指令是合理的。另一方面,如果你的认知能量需要用于建模数据流和业务领域规则,那么你应该愿意将内存管理和线程同步的机械细节委托给垃圾回收器和运行时这些黑箱。 没有人能面面俱到。选择编程语言,本质上就是在自身认知资源的限制下,选择如何变得高效。 即便在同一个系统内,内层应贴近机器,而外层应易于人们频繁修改。C 处理计算成本和内存布局,Python 处理实验序列和组装,这种分工之所以能长久存在,正是因为这个原因。C 位于 Python 之下,与其说是 Python 多余,不如说它揭示了这两种语言如何处理不同的变更速率。 当然,大家都知道边界上存在成本。对象转换和内存拷贝、ABI 和打包、GIL、将 C 中引发的错误转换为 Python 异常,以及当你只有一个 Python 回溯时追踪原生崩溃的难度——这些成本依然存在。抽象并没有消除实现成本;相反,它将成本集中在一小部分扩展模块作者身上,从而解放了更庞大的用户群体,让他们能够用自己问题领域的词汇来编写代码。 从这个角度看,学习一门新语言并不仅仅是替换语法符号。LISP 教会我们将代码视为数据;Prolog 将关系和搜索置于过程之前;Rust 将所有权和借用引入了类型检查系统。Python 也将可迭代对象、协议、动态组合和交互式探索提升为日常的工作单元。如果一门新语言只是把分号改改就能表达与旧语言相同的想法,那么按佩利斯的准则,你就没理由费心去学它。反过来说,即使底层实现仍然运行在相同的 C 和机器码上,只要作者感知到的问题和可用于表达问题的语句发生了变化,那它就已经是一种不同的**创作工具**了。 这就是为什么语言的选择应该由你想做什么来驱动,当你选择一种语言时,你就在进入该语言的世界观。 ## 通过平台经济学重读语言史 这里我以 Fortran 作为起点。在此之前有重要的先驱——Plankalkül、Short Code、A-0、Autocode——所以这并非一场争夺"第一门高级语言"桂冠的竞赛。

相似文章

人工智能时代编程语言的演变

Hacker News Top

本文探讨了在人工智能时代,编程语言及其社区可能如何演变,重点关注编码代理对语言设计、工具和生态系统动态的影响。

我们应当能够改变我们的语言

Hacker News Top

本文批判了对改变或定制编程语言的抵触情绪,讨论了围绕宏的历史辩论,并倡导在语言设计中增加更大的灵活性。

为什么要关心编程语言

Lobsters Hottest

在AI辅助编程的时代,作者认为深入理解编程语言概念对工程仍然至关重要,并列出来自不同语言的关键思想,这些思想扩展了解决问题的思维模型。

七大编程原语言(2022)

Hacker News Top

一篇文章探讨了七种构成大多数现代编程语言基础的编程语言原型(原语言),认为学习植根于这些原型的基础知识比选择特定语言更重要。

我们应当能够修改自己的语言

Lobsters Hottest

Jimmy Miller 主张编程语言应能按代码库进行定制,并反驳了长期以来针对宏和语言修改工具的批评——例如 Raymond Chen 对流程控制宏的猛烈抨击——认为这些论点在现代软件开发中已不再成立。