0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

自从20世纪80年代以来就存在的未来编程语言的预见失误

Linux爱好者 来源:未知 作者:胡薇 2018-04-11 10:46 次阅读

我的上一篇博文《与 C 语言长别离》引来了我的老朋友,一位 C++ 专家的评论。在评论里,他推荐把 C++ 作为 C 的替代品。这是不可能发生的,如果 C++ 代替 C 是趋势的话,那么 Go 和 Rust 也就不会出现了。


但是我不能只给我的读者一个光秃秃的看法(LCTT 译注:此处是双关语)。所以,在这篇文章中,我来讲述一下为什么我不再碰 C++ 的故事。这是关于计算机语言设计经济学专题文章的起始点。这篇文章会讨论为什么一些真心不好的决策会被做出来,然后进入语言的基础设计之中,以及我们该如何修正这些问题。

在这篇文章中,我会一点一点的指出人们(当然也包括我)自从 20 世纪 80 年代以来就存在的关于未来的编程语言的预见失误。直到最近,我们才找到了证明我们错了的证据。

我记得我第一次学习 C++ 是因为我需要使用 GNU eqn 输出 MathXML,而 eqn 是使用 C++ 写的。那个项目不错。在那之后,21 世纪初,我在韦诺之战Battle For Wesnoth那边当了多年的资深开发人生,并且与 C++ 相处甚欢。

在那之后啊,有一天我们发现一个不小心被我们授予提交权限的人已经把游戏的 AI 核心搞崩掉了。显然,在团队中只有我是不那么害怕查看代码的。最终,我把一切都恢复正常了 —— 我折腾了整整两周。再那之后,我就发誓我再也不靠近 C++ 了。

在那次经历过后,我发现这个语言的问题就是它在尝试使得本来就复杂的东西更加复杂,来粗陋补上因为基础概念的缺失造成的漏洞。对于裸指针这样东西,它说“别这样做”,这没有问题。对于小规模的个人项目(比如我的魔改版 eqn),遵守这些规定没有问题。

但是对于大型项目,或者开发者水平参差不齐的多人项目(这是我经常要处理的情况)就不能这样。随着时间的推移以及代码行数的增加,有的人就会捅篓子。当别人指出有 BUG 时,因为诸如 STL 之类的东西给你增加了一层复杂度,你处理这种问题所需要的精力就比处理同等规模的 C 语言的问题就要难上很多。我在韦诺之战时,我就知道了,处理这种问题真的相当棘手。

我给 Stell Heller(我的老朋友,C++ 的支持者)写代码时不会发生的问题在我与非 Heller 们合作时就被放大了,我和他们合作的结局可能就是我得给他们擦屁股。所以我就不用 C++ ,我觉得不值得为了其花时间。 C 是有缺陷的,但是 C 有 C++ 没有的优点 —— 如果你能在脑内模拟硬件,那么你就能很简单的看出程序是怎么运行的。如果 C++ 真的能解决 C 的问题(也就是说,C++ 是类型安全以及内存安全的),那么失去其透明性也是值得的。但是,C++ 并没有这样。

我们判断 C++ 做的还不够的方法之一是想象一个 C++ 已经搞得不错的世界。在那个世界里,老旧的 C 语言项目会被迁移到 C++ 上来。主流的操作系统内核会是 C++ 写就,而现存的内核实现,比如 Linux 会渐渐升级成那样。在现实世界,这些都没有发生。C++ 不仅没有打消语言设计者设想像 D、Go 以及 Rust 那样的新语言的想法,它甚至都没有取代它的前辈。不改变 C++ 的核心思想,它就没有未来,也因此,C++ 的抽象泄露leaky abstraction也不会消失。

既然我刚刚提到了 D 语言,那我就说说为什么我不把 D 视为一个够格的 C 语言竞争者的原因吧。尽管它比 Rust 早出现了八年(和 Rust 相比是九年)Walter Bright 早在那时就有了构建那样一个语言的想法。但是在 2001 年,以 Python 和 Perl 为首的语言的出现已经确定了,专有语言能和开源语言抗衡的时代已经过去。官方 D 语言库/运行时和 Tangle 的无谓纷争也打击了其发展。它从未修正这些错误。

然后就是 Go 语言(我本来想说“以及 Rust”。但是如前文所述,我认为 Rust 还需要几年时间才能有竞争力)。它的确是类型安全以及内存安全的(好吧,是在大多数时候是这样,但是如果你要使用接口的话就不是如此了,但是自找麻烦可不是正常人的做法)。我的一位好友,Mark Atwood,曾指出过 Go 语言是脾气暴躁的老头子因为愤怒而创造出的语言,主要是C 语言的作者之一(Ken Thompson) 因为 C++ 的混乱臃肿造成的愤怒,我深以为然。

我能理解 Ken 恼火的原因。这几十年来我就一直认为 C++ 搞错了需要解决的问题。C 语言的后继者有两条路可走。其一就是 C++ 那样,接受 C 的抽象泄漏、裸指针等等,以保证兼容性。然后以此为基础,构建一个最先进的语言。还有一条道路,就是从根源上解决问题 ——修正C语言的抽象泄露。这一来就会破环其兼容性,但是也会杜绝 C/C++ 现有的问题。

对于第二条道路,第一次严谨的尝试就是 1995 年出现的 Java。Java 搞得不错,但是在语言解释器上构建这门语言使其不适合系统编程。这就在系统编程那留下一个巨大的洞,在 Go 以及 Rust 出现之前的 15 年里,都没有语言来填补这个空白。这也就是我的 GPSD 和 NTPsec 等软件在 2017 年仍然主要用 C 写成的原因,尽管 C 的问题也很多。

在许多方面这都是很糟糕的情况。尽管由于缺少足够多样化的选择,我们很难认识到 C/C++ 做的不够好的地方。我们都认为在软件里面出现缺陷以及基于安全方面考虑的妥协是理所当然的,而不是想想这其中多少是真的由于语言的设计问题导致的,就像缓存区溢出漏洞一样。

所以,为什么我们花了这么长时间才开始解决这个问题?从 C 1972 年面世到 Go 2009 年出现,这其中隔了 37 年;Rust 也是在其仅仅一年之前出现。我想根本原因还是经济。

从最早的计算机语言开始,人们就已经知道,每种语言的设计都体现了程序员时间与机器资源的相对价值的权衡。在机器这端,就是汇编语言,以及之后的 C 语言,这些语言以牺牲开发人员的时间为代价来提高性能。 另一方面,像 Lisp 和(之后的)Python 这样的语言则试图自动处理尽可能多的细节,但这是以牺牲机器性能为代价的。

广义地说,这两端的语言的最重要的区别就是有没有自动内存管理。这与经验一致,内存管理缺陷是以机器为中心的语言中最常见的一类缺陷,程序员需要手动管理资源。

当相对价值断言与软件开发在某个特定领域的实际成本动因相匹配时,这个语言就是在经济上可行的。语言设计者通过设计一个适合处理现在或者不远的将来出现的情况的语言,而不是使用现有的语言来解决他们遇到的问题。

随着时间的推移,时兴的编程语言已经渐渐从需要手动管理内存的语言变为带有自动内存管理以及垃圾回收(GC)机制的语言。这种变化对应了摩尔定律导致的计算机硬件成本的降低,使得程序员的时间与之前相比更加的宝贵。但是,除了程序员的时间以及机器效率的变化之外,至少还有两个维度与这种变化相关。

其一就是距离底层硬件的距离。底层软件(内核与服务代码)的低效率会被成倍地扩大。因此我们可以发现,以机器为中心的语言向底层推进,而以程序员为中心的语言向着高级发展。因为大多数情况下面向用户的语言仅仅需要以人类的反应速度(0.1 秒)做出回应即可。

另一个维度就是项目的规模。由于程序员抽象发生的问题的漏洞以及自身的疏忽,任何语言都会有可预期的每千行代码的出错率。这个比率在以机器为中心的语言上很高,而在程序员为中心的带有 GC 的语言里就大大降低。随着项目规模的增大,带有 GC 的语言作为一个防止出错率不堪入目的策略就显得愈发重要起来。

当我们使用这三种维度来看当今的编程语言的形势 —— C 语言在底层,蓬勃发展的带有 GC 的语言在上层,我们会发现这基本上很合理。但是还有一些看似不合理的是 —— C 语言的应用不合理地广泛。

我为什么这么说?想想那些经典的 Unix 命令行工具吧。那些小程序通常都可以使用带有完整的 POSIX 支持的脚本语言快速实现出来。重新编码那些程序将使得它们调试、维护和拓展起来都会更加简单。

但是为什么还是使用 C (或者某些像 eqn 的项目,使用 C++)?因为有转换成本。就算是把相当小、相当简单的程序使用新的语言重写并且确认你已经忠实地保留了所有非错误行为都是相当困难的。笼统地说,在任何一个领域的应用编程或者系统编程在一种语言的权衡过时之后,仍然坚持使用它。

这就是我和其他预测者犯的大错。 我们认为,降低机器资源成本(增加程序员时间的相对成本)本身就足以取代 C 语言(以及没有 GC 的语言)。 在这个过程中,我们有一部分或者甚至一大部分都是错误的 —— 自 20 世纪 90 年代初以来,脚本语言、Java 以及像 Node.js 这样的东西的兴起显然都是这样兴起的。

但是,竞争系统编程语言的新浪潮并非如此。 Rust 和 Go 都明确地回应了增加项目规模这一需求。 脚本语言是先是作为编写小程序的有效途径,并逐渐扩大规模,而 Rust 和 Go 从一开始就定位为减少大型项目中的缺陷率。 比如 Google 的搜索服务和 Facebook 的实时聊天复用。

我认为这就是对 “为什么不再早点儿” 这个问题的回答。Rust 和 Go 实际上并不算晚,它们相对迅速地回应了一个直到最近才被发现低估的成本动因问题。

好,说了这么多理论上的问题。按照这些理论我们能预言什么?它告诉我们在 C 之后会出现什么?

推动 GC 语言发展的趋势还没有扭转,也不要期待其扭转。这是大势所趋。因此:最终我们将拥有具有足够低延迟的 GC 技术,可用于内核和底层固件,这些技术将以语言实现方式被提供。 这些才是真正结束 C 长期统治的语言应有的特性。

我们能从 Go 语言开发团队的工作文件中发现端倪,他们正朝着这个方向前进 —— 可参见关于并发 GC 的学术研究 —— 从未停止研究。 如果 Go 语言自己没有选择这么做,其他的语言设计师也会这样。 但我认为他们会这么做 —— 谷歌推动他们的项目的能力是显而易见的(我们从 “Android 的发展”就能看出来)。

在我们拥有那么理想的 GC 之前,我把能替换 C 语言的赌注押在 Go 语言上。因为其 GC 的开销是可以接受的 —— 也就是说不只是应用,甚至是大部分内核外的服务都可以使用。原因很简单: C 的出错率无药可医,转化成本还很高。

上周我尝试将 C 语言项目转化到 Go 语言上,我发现了两件事。其一就是这活很简单, C 的语言和 Go 对应的很好。还有就是写出的代码相当简单。由于 GC 的存在以及把集合视为首要的数据结构,人们会预期代码减少,但是我意识到我写的代码比我最初期望的减少的更多,比例约为 2:1 —— 和 C 转 Python 类似。

抱歉呐,Rust 粉们。你们在内核以及底层固件上有着美好的未来,但是你们在别的 C 领域被 Go 压的很惨。没有 GC ,再加上难以从 C 语言转化过来,还有就是 API 的标准部分还是不够完善。(我的select(2)又哪去了啊?)。

对你们来说,唯一的安慰就是,C++ 粉比你们更糟糕 —— 如果这算是安慰的话。至少 Rust 还可以在 Go 顾及不到的 C 领域内大展宏图。C++ 可不能。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 计算机
    +关注

    关注

    19

    文章

    7428

    浏览量

    87728
  • C语言
    +关注

    关注

    180

    文章

    7601

    浏览量

    136235
  • C++
    C++
    +关注

    关注

    22

    文章

    2104

    浏览量

    73501

原文标题:计算机语言的巨变

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    功率半导体各品类及下游应用市场空间分析

    20世纪80年代后期,沟槽型功率MOSFET和IGBT逐步面世,半导体功率器件正式进入电子应用时代。20
    的头像 发表于 09-27 08:04 413次阅读
    功率半导体各品类及下游应用市场空间分析

    【每天学点AI】五个阶段带你了解人工智能大模型发展史!

    20世纪50年代NLP的早期研究主要基于规则的方法,依赖于语言学专家手工编写的规则和词典。这些规则通常是关于语法、语义和句法结构的人工规则。例如一个简单的陈述句通常遵循“主语+谓语+宾
    的头像 发表于 09-25 16:51 414次阅读
    【每天学点AI】五个阶段带你了解人工智能大模型发展史!

    光学识别技术的工作原理是什么?

    。 一、OCR技术的发展历史 OCR技术起源于20世纪50年代,当时主要用于邮政编码的自动识别。随着计算机技术的发展,OCR技术逐渐成熟,并广泛应用于各种场景。20
    的头像 发表于 09-10 15:46 540次阅读

    国产工控机的发展与未来

    市场中占据一席之地。本文将探讨国产工控机的发展历程、市场现状、技术优势及未来趋势。一、发展历程初期阶段国产工控机的起步可以追溯到20世纪80年代
    的头像 发表于 08-12 17:56 826次阅读
    国产工控机的发展与<b class='flag-5'>未来</b>

    同步DRAM(SDRAM)介绍

    DRAM从20世纪70年代初到90年代初生产,接口都是异步的,其中输入控制信号直接影响内部功能。
    的头像 发表于 07-29 09:55 584次阅读
    同步DRAM(SDRAM)介绍

    自然语言处理技术的核心是什么

    ,广泛应用于机器翻译、情感分析、语音识别、智能问答、文本摘要等众多领域。 自然语言处理技术的发展可以追溯到20世纪50年代。1950,图灵
    的头像 发表于 07-03 14:20 599次阅读

    电力二极管的定义 电力二极管动态过程的波形介绍

    电力二极管(Power Diode)在20世纪50年代初期就获得应用,当时也被称为半导体整流器;
    的头像 发表于 03-26 15:26 1299次阅读
    电力二极管的定义 电力二极管动态过程的波形介绍

    无人机科技:颠覆未来的空中变革之力

    20世纪90年代以来,无人机科技的蓬勃发展引起了全球瞩目。伴随着科技创新的脚步,无人机已逐渐跻身人们的日常生活,成为一项至关重要的科技产业。 本文将探讨无人机的历史沿革和发展趋势,并
    的头像 发表于 03-01 20:10 1649次阅读
    无人机科技:颠覆<b class='flag-5'>未来</b>的空中变革之力

    四种编程语言之间的区别和联系

    、背景和发展 Python:Python由Guido van Rossum于上世纪90年代初开发,以其简洁、易读的语法和丰富的第三方库而受到广泛欢迎。它是一种高级编程语言,尤其擅长数据
    的头像 发表于 02-05 14:16 1452次阅读

    pcb是什么化学物质 pcb是什么滤芯

    、电容器、润滑油等工业领域。然而,随着人们对环境和健康的关注不断增强,PCB被发现对人体和环境有极高的毒性和持久性,因此从20世纪70年代初至80
    的头像 发表于 02-04 10:53 3825次阅读

    使用48V电源对汽车制造商的好处和挑战

    20世纪50年代以来,12V电源一直是汽车行业的标准,因而成为汽车设计和部件的默认配置。即使汽车功能和电气化不断发展,但该标准使得汽车制造商仍然能够维持简单的电气架构和保持低成本。
    的头像 发表于 01-25 09:42 686次阅读

    几纳米指什么尺寸?了解芯片节点命名的多次更改

    20世纪70年代80年代和90年代的大部分时间里,最近的金属线半节距和栅极长度半节距的尺寸基
    的头像 发表于 01-02 11:18 1405次阅读
    几纳米指什么尺寸?了解芯片节点命名的多次更改

    人工智能对工业软件的影响

    人工智能这个词的含义非常广泛。它代表了算法和信息处理策略的集合。其中许多概念已经存在了很长一段时间,有些可以追溯到20世纪40年代。由巨大的处理能力支持的新应用策略组合创造了我们现在正
    发表于 12-21 10:06 448次阅读
    人工智能对工业软件的影响

    硬件电路设计之锁相环电路设计

    法国工程师De Bellescize 在20世纪30年代初实现。然而,直到20世纪60年代中期,
    的头像 发表于 11-30 15:01 2389次阅读
    硬件电路设计之锁相环电路设计

    自动驾驶技术从SLAM+DL到BEV+Transfomrer的进化历程

    自动驾驶技术在20世纪初的概念和实验主要集中在车辆自动化和遥控方面。到了20世纪80年代和90
    发表于 11-29 10:50 683次阅读
    自动驾驶技术从SLAM+DL到BEV+Transfomrer的进化历程