写点什么

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

2021 年 4 月 30 日

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

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


本文最初发表于作者个人博客,经原作者 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:213128
用户头像
刘燕 InfoQ记者

发布了 638 篇内容, 共 200.1 次阅读, 收获喜欢 1226 次。

关注

评论 1 条评论

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

新手村:MySQL 学习经验、资源的分享

多选参数

MySQL MySQL 高可用 MySQL优化

性能测试和并发压力的关系

王锟

英特尔唐炯:把最好、最合适的产品带给最需要的消费者

最新动态

数据湖应用解析:Spark on Elasticsearch一致性问题

华为云开发者社区

大数据 spark elasticsearch 数据湖 华为云

计算机网络基础(八)---网络层-路由概述

书旅

计算机网络 网络协议 计算机基础 AS

挑战10的1,143,913次方种算法组合:这都不是事儿!

华为云开发者社区

华为 算法 进化 华为云

MinIO 分布式集群搭建

耳东

Minio cluster Minio 集群

第七周学习总结

王锟

来了,来了,你们要的Nginx教程来了

Java旅途

nginx

BIGO | Likee深度推荐模型的特征工程优化

InfoQ_3597a20b53cc

人工智能

百度人脸算法“飞速迭代”,多模态活体检测V3.1获银行卡检测中心增强级认证

百度大脑

人工智能 人脸识别 百度大脑

MinIO 参数解析与限制

耳东

配置 Minio

企业架构框架之FEA

Winfield

企业架构

WebRTC框架下的实时视频关键路径

fumingwang

面试官拿System.out.println()考了我半个小时?我傻了

Java小咖秀

Java 面试

秒懂云通信:选云通信到底哪家强?

阿里云Edge Plus

云通信 通信云

技术​选型的艺术

YourBatman

技术选型 湖北

手写实现Promise

GKNick

性能测试与优化 和 操作系统与文件系统

满山李子

极客大学架构师训练营

http请求压测工具

潜默闻雨

【一起学系列】之命令模式:封装一个简单Jedis

Kerwin

设计模式 命令模式 Jedis

英特尔唐炯:竞争推动PC行业良性发展,促使英特尔前行

最新动态

第7周-作业1

seng man

程序设计理念-CentOs7实践Nginx-带来安装服务的通用法则

图南日晟

Nginx PHP-FPM 架构设计 环境安装

47 张图带你 MySQL 进阶!!!

cxuan

MySQL 后端

架构师第七周作业

傻傻的帅

web压力性能测试

周冬辉

压力测试

JVM系列之:String,数组和集合类的内存占用大小

程序那些事

Java JVM GC JOL

直播中那几秒延时到底来自哪?

阿里云Edge Plus

CDN 云直播 直播 直播带货

架构训练营第七周作业

张锐

【小白学YOLO】YOLOv3网络结构细致解析

华为云开发者社区

人工智能 网络 物体检测 华为云 网络层

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

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