写点什么

编程会有“历史终结”的一天吗?

  • 2021 年 4 月 30 日
  • 本文字数:3353 字

    阅读完需:约 11 分钟

编程会有“历史终结”的一天吗?

本文作者对编程历史的终结作了一番畅想,这是作者的一家之言,我们无法准确判断未来编程将会转向何处,但是我们可以根据其发展轨迹,就像本文作者一样,做出大概的判断(未必准确)。


本文最初发表于作者个人博客,经原作者 Gabriel Gonzalez 授权,InfoQ 中文站翻译并分享。


我花了不少时间思考这个问题:编程历史的终结可能是什么样子的。我所说的“历史的终结”,就是编程范式不再有重大发展的时候。


对于编程的“命运”我很关心,因为我更愿意参与那些让我们接近终极编程模式的开源项目。从我的经验来看,这类工作寿命更长,影响更大,有助于推动整个编程领域的发展。


那么,对于编程而言,历史的终结会是怎样的呢?是不是:


  • 已经到来了?


一些人将编程视为已经解决的问题,并将所有新的语言和范式视为旧语言或范式的翻版。在他们看来,剩下的工作就是慢慢地优化事物,排除错误,或者解决非技术性的问题(比如人事管理或者资金),从而完善我们的工艺。


这一观点我个人并不认同,因为我相信,至少,函数式编程范式将逐渐取代面向对象和命令式编程范式(虽然函数式编程未必就是终极编程范式)。


  • 人工智能?


或许机器可以将我们的自然语言指令翻译成代码,从而减轻了我们准确表达意图的负担。或许一些足够智能的、人工智能驱动的 IDE 可以为我们自动地完成大多数程序。


同样,我也不相信这一观点,而且我认为 Dijkstra 在他的文章《论“自然语言程序设计”的愚蠢性》(On the foolishness of "natural language programming*"*)中很好地推翻了这一观点。


老实说,我不能肯定什么是正确答案,但是我会给出我自己关于编程的历史终结的猜测。

数学 DSL

我的观点是,编程的下一个逻辑步骤是分成两个没有重叠的编程领域:


  • 运行时构建

  • 数学编程语言


具体地说,我预期编程语言在本质上将发展成为更具数学特性的语言,让用户编写的程序像纯粹的数学表达式一样表达其意图。


举例来说,考虑下列布尔逻辑“和”运算符和函数合成运算符的数学规范:


True  && x     = xx     && True  = xFalse && False = False(f . g)(x) = f(g(x))
复制代码


这些数学规范也是可执行的 Haskell 代码(尽管使用了额外的括号来与主流函数语法相似)。Haskell 是编程语言的一个例子,它的代码希望类似于纯数学表达式和定义。


由于现实世界是混乱的,因此任何呈现这种理想化数学界面的语言都需要在幕后引入大量的复杂性,在这里,运行时构建可以用来掩盖这些“丑陋”的细节。


换言之,我预言编程的历史终结将是连接纯数学表达式和现实世界的接口。

过去和现在

请允许我举几个例子,说明这种将用户空间(userland)代码数学化的趋势已经开始显现:


  • 内存管理


手动内存管理曾经是大多数编程语言的“用户空间”问题,但新语言的总体趋势是自动内存管理(Rust 除外)。以前,内存管理是程序员必须关心的一个明显的副作用,现在,把内存管理下推到运行时(通过垃圾收集或其他方式),使编程语言更加纯粹,使它们更接近于理想化的数学表达式。


事实上,Rust 是证明这一规则的例外,因为人们普遍认为 Rust 更适合于构建运行时,而非用于意图的高级规范。


  • 函数式编程(尤其是纯函数式编程)


函数式编程是向更倾向于数学化的编程方向迈进的一个重要步骤:


  • 以表达式代替语句;

  • 以纯函数代替副作用;

  • 以代数数据类型代替非对象;

  • 以递归代替循环。


关于这一点,我在《为什么我更喜欢函数式编程》(Why I prefer functional programming)一文中详细讨论过。


但是,函数式编程并非自由的胜利。有效地支持高阶函数和闭包并非易事(特别是对于编译语言来说),这就是为什么那些较不复杂的语言实现通常更倾向于命令式而非函数式。


  • 评估顺序(特别是懒惰)


对于 Haskell 的评估模型,我一直认为“懒惰评估”并不适合推广其优点。但我更倾向于认为,Haskell 拥有“自动评估管理”(注:这一解释与实际情况相差不大,因为 Haskell 标准只规定了一个非严格的评估策略。GHC 是懒惰的,但是 Haskell 这一预言标准并没有要求懒惰实现。详情请参阅《懒惰与不严格》(Lazy vs. non-strict︎)。换句话说,程序员将表达式指定为依赖于计算的图,而运行时则找出最有效的顺序来减少图。


这里还有一个例子,我们把过去用户空间问题(评估顺序)推进到了运行时。忽略评估顺序可以让我们用更数学的方法来指定事物,因为评估顺序在数学上同样是不相关的。

现在与未来

在研究上述趋势时,出现了一种常见的模式:


  • 下面是把用户空间问题推送到运行时问题:

  • 使程序更接近纯数学表达式,并且:

  • 显著地增加了运行时的复杂性。


你可能会想:在不远的将来,还有哪些用户空间问题可能会被推送到运行时问题上呢?我能想到的例子如下:


  • 包管理


这次是如此的接近未来,以至于它已经发生了(见:Nix 和 Dhall)。这两种语言都为获取代码提供了内置支持,而没有使用独立的包管理工具来处理带外包。这一语言级别的支持允许程序嵌入外部代码,就好像它是一个纯粹的子表达式,更接近于数学化的理想。


  • 错误处理


这个问题需要更多的解释:我认为,类型系统是一个逻辑结论,它把错误处理推入“运行时”(实际上是推到了类型检查器而非运行时)。在 Dhall 语言中,这种想法得到了充分的体现:Dhall 不能用来引发或捕捉错误的用户空间支持,因为所有的错误都是类型错误。(注:这有点过于简化,因为 Dhall 支持 Optional 值,你可以使用 unions 在 Dhall 中模拟错误,但是它们不常以这种方式出现,而且通常 Dhall 代码使用类型检查器捕获错误。Dhall 是一种完全函数式编程语言,它做了很多工作来防止运行时出错,例如,禁止比较文本是否相等。另外,该语言在技术上依赖于类型,并且支持在类型检查时测试任意代码,以便静态地捕捉错误。)


依赖类型完全函数式编程语言的发展使我们与把错误处理推到运行时的目标更加接近。


  • 日志


事实上,我感到惊讶的是,尚未完成对大量日志记录的语言支持(或者,也许发生了,但是我没有注意到)。在语言中,这似乎是一件可以实现的很普通的事情,特别是在性能不敏感的应用领域中。


很多语言已经支持分析了,如果用户愿意为日志花费性能预算,那么将分析支持转变为日志支持看起来并不是一个什么大的飞跃。


日志是典型的副作用之一,它是一种“丑陋”的细节,“破坏”了本来是纯粹的、数学的代码。


  • 服务


面向服务的架构是另一种倾向,它会阻碍纯无副作用代码的编写。


我并不清楚面向服务的语言运行时是什么样子,但是我认为,目前的“无服务器”解决方案并不是我心中所想的那样。诸如 AWS Lambda 之类的东西还是太低级了,无法提升本质上是数学化的代码。举例来说,如果编程过程中有任何部分需要使用独立的工具来部署或管理无服务器的代码,那么这与编写纯数学表达式大相径庭。必须有与“无服务器代码的 Nix 或 Dhall”类似的东西。

结语

你可以批评我的预言,说它是不可证伪的。看起来我可以将编程中的新进展解释为属于运行时构建或数学表达式范畴。


正因为如此,我想强调预言中的一个关键支柱:运行时和数学表达式的划分会随着时间而变得更明显。它是预言的实际内容,我们可以从语言中推断出一些证据。


当前,许多主流编程范式和工程组织混淆了这两种职责,因此,你最终会发现,人们编写的软件项目是操作逻辑(运行时问题)和“业务逻辑”(数学意图)的混合体。


在我的预言中,工程领域将会对拥有编程语言理论或编程语言工程经验的人产生强烈的需求。这些人将负责构建专用语言和运行时,将尽可能多的操作问题抽象出来,以支持各自企业的纯数学领域特定语言。这些语言将会被另一组人所使用,其目的是将人们的意图转化为数学表达式。


这个预言的一个结果就是,在不远的将来,你会看到编程语言的“寒武纪大爆发”。当语言工程师把更多的操作问题推到运行时中时,当然,他们需要根据特定的目标或组织需求对运行时进行定制,而非尝试编写一种通用语言。换言之,随着每种新语言适应其各自的利基市场,在语言运行时(和类型检查器)中会出现明显的碎片化现象。


虽然存在一些运行时碎片,但你在用户空间代码中看到与此相反的趋势:用这些不同的语言编写的程序将开始更接近于彼此,因为他们本质上变得更数学化了。数学表达式在某种意义上将成为用户空间代码的可移植“通用语言”,尤其是当非数学问题被推到相应语言的运行时。


这种预言更容易被证伪。


原文链接:


https://www.haskellforall.com/2021/04/the-end-of-history-for-programming.html

2021 年 4 月 30 日 15:213215
用户头像
刘燕 InfoQ记者

发布了 793 篇内容, 共 261.9 次阅读, 收获喜欢 1502 次。

关注

评论 1 条评论

发布
用户头像
整天写这些没有意义的文章
2021 年 05 月 06 日 09:46
回复
没有更多了
发现更多内容

自从看了百度强推的“Spring源码笔记”我从渣渣成功逆袭成为钢铁侠!

比伯

Java 架构 程序人生 计算机 spring源码

一周信创舆情观察(12.7~12.13)

统小信uos

我不喜欢挫折教育

熊斌

成长 自我思考 自我独白 个体成长

极客大学架构师训练营 - 同城快递业务架构设计

好吃不贵

极客大学架构师训练营

请回答2020:芯片巨头并购潮究竟意味着什么?

脑极体

JVM垃圾回收性能分析

积极&丧

朱嘉明:产业周期、科技周期与金融周期的失衡

CECBC

金融 科技

原创 | 使用JPA实现DDD持久化-O/R映射元数据-关联属性映射

编程道与术

Java hibernate 编程 mybatis jpa

阿里Java研发第2面,都会问什么?斩获阿里P6+的“他”告诉你答案

Java架构之路

Java 程序员 架构 面试 编程语言

终于有人把性能优化讲清楚了!阿里架构师推荐的Java性能权威指南可太强了

Java架构之路

Java 程序员 架构 面试 编程语言

架构师训练营 1 期 -- 第十三周作业

曾彪彪

极客大学架构师训练营

原创 | 使用JPA实现DDD持久化-O/R映射元数据-值和关联的比较+继承映射

编程道与术

Java hibernate 编程 mybatis jpa

Java程序员还没有掌握SpringBoot?这一份文档你真应该好好学学!

Java架构之路

Java 程序员 架构 面试 编程语言

原创 | 使用JPA实现DDD持久化-通过Spring Data JPA访问数据

编程道与术

Java hibernate 编程 mybatis jpa

架构师训练营第 1 期 -week13

习习

架构2期第八周作业(1)

浮生一梦

极客大学架构师训练营 2组 第八周作业

点燃“云+AI”的烽火,照亮网络安全的月之暗面

脑极体

第九周作业

Griffenliu

原创 | 使用JPA实现DDD持久化-启动JPA程序+通过JPA原生API访问数据

编程道与术

Java hibernate 编程 mybatis jpa

基于区块链的政务平台设计探索

华为云开发者社区

区块链 架构 安全

工作多年还是只会用wait和notify?30分钟用案例告诉你有更好得选择

小Q

Java 学习 编程 架构 面试

第九周学习总结

Griffenliu

阿里Java岗面试必备JVM指南:内存分配+垃圾回收+调优+类加载器等

Java架构之路

Java 程序员 架构 面试 编程语言

架构师训练营第四周命题作业

Geek_xq

盘点 2020 | 感悟总结

idonkeyliu

盘点2020

沪上首座“区块链生态谷”揭开面纱!

CECBC

大数据 生态产业

滴滴开源Super-jacoco:java代码覆盖率收集平台

滴滴技术

Java 开源 滴滴开源 Super-Jacoco

读《全球创新投资:经济大变局中的财富新机遇》

邓瑞恒Ryan

创业 读书笔记 企业 企业管理 产业竞争

去 DeepMind 面试是怎样一种体验?

故胤道长

人工智能 面试 谷歌Google 硅谷 移动开发

“九章”问世,量子计算将如何影响区块链技术?

CECBC

量子计算机

90分钟10个手写案例,从源码底层给你讲解7种线程池创建方式

小Q

学习 源码 架构 面试 多线程

编程会有“历史终结”的一天吗?_编程语言_Gabriel Gonzalez_InfoQ精选文章