语言简史

语言简史

原文:https://medium.com/hackernoon/brief-history-of-languages-a2fda2ab053

为什么每 6 个月就要学一门新语言

“嘿,你知道,长生不老药是一种神奇的函数式语言。我真的很喜欢它”,一个热情的我展示了我对科技世界正在发生的事情的了解。

他:“好吧。我确信它是。但是,你不是红宝石迷吗?您想用使用 Ruby 创建的 DSL 重写我们复杂的代码库。你也展示了一个工作原型。这似乎令人印象深刻!为什么是新语言?我不明白为什么一种新的语言年复一年地出现。我们还不够吗?C++、Java、Python、Ruby、Scala 什么的。”

我:“是啊,确实是这样。但是所有这些语言都针对不同的受众、问题空间,有时还建立在不同的理念之上。开发者的世界是碎片化的。人们如何看待软件开发中的复杂性和挑战的概念是不同的。所以人们选择自己喜欢的语言来解决他们那部分的问题。"

他:“这个我懂一部分。我可以理解,如果你在嵌入式系统上工作,你需要一个不同的 beast,而当你在更高级的应用上工作,你可能需要不同种类的电源。但是,我看到的是在同一个空间里有这么多种语言。”

我:“对,你说得对。有时有太多的语言针对同一个空间。其中一些是因为时间的需要,很多时候是因为公司之间的主导权之争。每个大公司都在努力推行他们的语言版本,以确保他们不会被逼入绝境。有时,所有者的官僚作风使得语言的发展更加困难,人们倾向于创造自己的解决方案。有时人们只是喜欢这个想法,并在社区的支持下去实现它。

他:“我没拿到。你能不能说得更具体一点。”

我:“我们各退一步。我们用 C++编程已经很多年了。在 C++中,我们有一个巨大的遗留代码库。为什么你认为,我们正在走向 Java。”

失信和指责游戏

他:“Java 好像更有生产力。你在一个环境中写代码(读操作系统),你可以在另一个环境中运行,不用担心可移植性问题。IDE 支持非常出色。没有指针混乱,也不用再担心内存问题。你能想到的几乎所有东西都有图书馆。如果需要日志记录,可以使用 log4j,如果需要注入,可以使用 spring。你可以从惊人的人才库中找到人,因为几乎每个人都懂 Java。寻找优秀的 Java 人才是如此容易。”

我:“是的,它真正抓住了 Java 的精髓。我们用 Java 重写了一个应用程序,对吧?但是我听说演出不太好。看起来 C++有 30k 行代码,Java 有 130k 行代码。它只有 15%的能力,而 SLA 提高了 1.2 倍。现在,新开发人员不得不通过一堆初学者工具包来开始查看代码,因为代码从 xml 开始,你不知道代码是如何到达 xml 的,因为我们用于 spring 的库将细节隐藏在一些深奥的 jar 中,而你应该从这些 jar 中抽象出来。”

他:“但那是个坏例子。这不能怪 Java。这只是一个糟糕的工程实践造成的混乱。有人认为一切都应该是可配置的,他们编写了巨大的 xml 文件,即使你想添加一个条件。任务、组、beans、数据管道、暂存区等等。这是一个糟糕的设计。他们对大型数据集进行深度拷贝,导致垃圾收集速度过快,20%的时间都花在了垃圾收集上”

我:“等等!你不是说过,在 Java 里我们不用再去搞乱指针和内存了吗?你不是说过,Java 提供了一个惊人的天才工程师库,你可以从中雇用,而且你有很好的 IDE 支持吗?”

他看起来不顾一切地捍卫自己的立场:“是的,这是事实,但如果我认为对我们来说,scala 会是一个更好的选择。它是功能性的、表达性的、高度可测试的和可组合的,最好的部分是它运行在 JVM 上,所以我们可以使用现有的 Java 库。它有着令人惊叹的社区,人们使用 Scala 在短时间内构建了令人惊叹的高性能应用程序。它有一个令人惊叹的基于 actor 模型的框架,叫做 Akka,有了它,你可以真正地构建几乎无状态的、纯粹功能性的、孤立的组件,这些组件仅仅使用消息就可以相互交流。一个组件中不再有 NPE 导致其他组件出现故障。他们只是通过信息交流。如果你崩溃了,那只是你崩溃了。因为消息传递合同非常清楚,所以您不需要担心其他组件。”

我:“嗯。所以你认为 Scala 可能是一个不错的选择,因为它的函数范式?”

他:“是的,我想是的。”

我:“有意思。看起来我们已经偏离了我们最初关于这么多语言的讨论太多了。我们现在就来谈谈这个吧。”

他:“是的,非常真实。所以我的问题是为什么我们需要这么多的语言。我仍然读到几乎每 6 个月就有一种新语言出现。”

复杂性不同,感知也不同

我:“对,你说得对。正如你刚才解释的为什么我们从 c++迁移到 Java,为什么我们应该迁移到 Scala,这实际上说明了应用程序的复杂性,以及我们认为哪一部分是挑战。”

他毫无头绪,试图理解:“我不明白。”

我:“看,你已经谈到了像面向对象和函数式这样的编程范例。所以这是因素之一。让我们谈谈其他一些因素。你认为我们大多数 c++开发人员把时间浪费在什么上面了?”

他:“没有第二个想法,这是神秘的编译和链接错误。我有时真可怜他们。现在是 2016 年,他们仍在试图弄清楚第 200 行中发现的意外标记的含义,这就像缺少逗号一样简单。”

我:“好。在我们回到最初的讨论之前,让我们再谈一个问题。”

他:“当然”

我:“给定一个巨大的日志文件,如果你必须快速找到不同错误类型的频率,你会选择什么工具。”

他:“对于这样简单的任务,AWK 会做得很好。”

我:“好的,如果给你一个几百个用户的列表,你必须从 ldap 中找到他们经理的名字,你会怎么做?"

他:“这也很简单。我以前做过这个。我就简单用 Python 吧。Python 已经有了惊人的库来处理 ldap。”

“我也很确定,你一定在为这个问题考虑 Ruby”,他大笑着说。

“是的,当然。“Ruby 是我最近使用的脚本语言”,我回答道。

寻找更好的抽象

我:“所以,我希望你明白,为什么我带来了这个讨论。”

“语言建立在不同的哲学基础上,考虑不同类型的人。你可以这样想:

人们认为汇编太低级了,所以他们编写了 c 语言,它仍然接近于机器,但是提供了更多人类可以理解的结构。for 和 while 比 go to 和 move 更容易阅读。后来,项目开始变大,管理代码库变得困难起来。数以千计的方法分布在多个文件中,没有重载。方法名开始反映个人个性,填充与填充,复制与赋值,添加,相加,求和,求和等开始变得普遍。找到一种方法做想要的事情变得非常困难。我们缺少一些东西来把相似的东西组合在一起。名称空间是一种方法,但这仍然不够。我们在寻找更强的凝聚力,看起来更自然地将这些方法结合在一起。概念不断发展,我们提出了面向对象的编程,其中数据及其操作被绑定在一起。受自然的启发,面向对象的概念似乎是抽象复杂性的一个好方法,因为它更接近普通人的日常生活。看到一辆汽车和本田牌汽车,我们可以很好地把一个类和一个对象的含义联系起来。随之而来的是 C++、Java 等语言。"

他满面自信,仿佛这就是他想听的:“是的,这是真的。OO 范式似乎仍然是最流行的一种。这也是我热爱 Java 的原因。一切都是类,不像 c++有一些全局方法概念。”

我:“是的,它确实开始改善场景。人们现在能够编写更大的代码库。但是当人们开始努力设计类时,这种兴奋很快就结束了。渐渐地,问题空间本身转移到更高层次的应用。我们不再为机器编写自动化程序,而是讨论如何通过互联网汇款。如何定义付款、退款、授权和退款的类别,事情开始变得与动物和猴子、汽车、本田和 CRV 的玩具例子大相径庭。”

他,略显失望:“是的,我同意,名词和动词分类不太管用。人们开始创新,开始写动词的名词形式来代表阶级。我们有像分析器、验证器等类,但搞清楚蓝图和实现是模糊的。”

开发人员的工作效率占据了中心位置

我:“OO 也有缺点,但它帮了大忙。过了一段时间,问题空间又变了。机器也变得更强大,内存更便宜。这样,我们可以留下一些未优化的内存使用,少量的额外字节不会以更高的生产率为代价。它带来了两个有趣的变化:在应用程序开发过程中,处理内存似乎是最适得其反的,因此这一整套语言诞生了,它从程序员那里抽象出了内存管理部分,托管语言如 Java、C#。走吧,拉斯特等人只是顺着小路走。垃圾收集成为一个热门话题,现在仍然如此。

互联网带来了另一系列变化。我们希望代码可以在一个地方编写,但可以在任何地方运行,因此出现了编译/解释成中间语言并在虚拟机上运行的语言。C#,Java 跟着套件。"

有机会再次证明自己的优势,他说:“看,我告诉过你,这就是我喜欢 Java 的原因,你提到的一切都表明我们应该使用 Java。”

我:“在这一切发生的同时,有人认为我们花在编译和链接上的时间最多。为什么要浪费时间去弄清楚是用 int 还是 long 还是 float,为什么我的语言不能自动弄清楚。为什么给一个我还没有调用的方法一个错误。为什么要编写自己的堆栈、散列、数组实现来存储数据,而我知道没有它们我就写不出任何有用的程序。有了这些东西,我们概念化的动态类型,鸭类型,更高层次的数据结构和其他构造。进入基于解释器的语言时代,承诺我们想要的生产力的一切。

Perl,Python,Ruby 紧随其后。

Pythons 的哲学是基于可读性,这是唯一的标准做事方式,而 Ruby 相信给予用户权力。你可以用这种神奇的力量来生成代码,隐藏抽象,实际上创造一种新的语言。"

他:“我知道。这些语言在短时间内是高效的。但我听说这些速度要慢得多,最糟糕的是,我们直接把错误丢给客户。”

以后再用,先用

我:“对,你说得对。它通常比较慢,而且在编译过程中您确实错过了一个重要的错误检查步骤。但是你有没有想过,一个试图构建一些工作原型的初创公司,他们更愿意花时间在哪里,炫耀他们可以提供的所有功能,或者努力决定是使用 long 还是 double,使用哪些库来解析 JSON。当你必须向投资者演示时,你的应用程序在未来的运行速度有多快、可扩展性有多强并不重要。”

处理复杂性

在所有这些冒险进行的同时,还有另一项关于函数式编程的努力。这个想法很简单。程序只不过是对数据的操纵,还有什么比数学函数更好的操纵数据的方式呢?纯粹的方法、不可变的数据、无副作用的编程成为这些家伙的主题。Lisp,Haskell,Erlang 跟着组曲。这些语言认为程序员做的最具反作用的事情是处理不可追踪的、非预期的状态变化,然后调试代码以找到变量被更新的地方。erlang 更进一步,确保两个进程(Erlang 进程)能够对话的唯一方式是通过消息传递,以确保系统的一部分不会破坏另一部分。人们用 erlang 构建了具有 9 个 9 可用性的应用程序(是的,是 9 个 9,99.9999999)

“其中一些语言提供了修改底层 AST 和语言结构的方法,以从同一种语言构建一个完全不同的 beast。Lisp 的宏,Ruby 的元编程就属于这几类。”

摩尔定律的终结

“21 世纪初,该行业发生了一些重大变化。摩尔定律不再适用。在过去的二十年里,芯片的处理能力没有以同样的速度增长。我们开始通过添加更多内核来水平扩展,而不是更强大的内核。互联网给应用带来了规模,这在以前只是电信领域的问题。有了网络规模的目标,事情必须改变。”

“并行、分布式、并发性似乎成了事实上的时髦词汇。所以新的语言必须进化才能记住这些东西。去吧,拉斯特,尼姆跟在随员后面。”

这不是一个零和游戏,让我们合作来赢得胜利

“随着时间的推移,人们意识到一种或另一种哲学可能不会获胜,我们可能需要支持多种范式。人们也意识到我们不能摆脱遗留代码。大量的投资都投入到这些遗留代码中,我们不能简单地让它过去并从零开始。所以新语言开始瞄准可移植性和多范例。

Scala,例如目标 JVM,带有函数式和面向对象范例的选项。Clojure 用类似 lisp 的宏和函数式方法瞄准 JVM。Elixir 以 Erlang VM 为目标,采用类似 Ruby 的语法、参与者模型和函数式方法。

Crystal 的目标是用 Ruby 语法实现类似 c 的性能。Nim 的目标是提供更强大的宏、并发和并行支持,以及与 c 和其他编程语言的互操作性。"

“另一种有趣的语言是 Lua,它旨在成为嵌入另一种语言的脚本语言。这为现有应用程序提供了惊人的高性能定制选项。您可以使用 Lua 对现有的 c/C++应用程序进行定制,如 HAProxy、NGINX、redis 等。这有助于您专注于自己的定制,而不是自己构建整个堆栈。”我继续说道。

他被逗乐了,但看起来绝望地喘口气:“有意思。如果有这么多的选择,为什么我们还在发展中吮吸?”

光有选择是没有帮助的

我:“讽刺的选择通常是我们选择了错误的选择。我们不看眼前的问题,而是先看解决方案,然后变得过于依赖它。围绕语言的沙文主义也不会让它变得更好。选择 C++进行 web 开发就像选择 Java 进行网络编程一样没什么帮助。他们两个实际上都可以做任何一件事,但当问题不是钉子时,为什么要选择锤子呢?”

他,恍然大悟:“咦,你根本没提 JavaScript?”

前端不同的野兽

我:“是的,我们没有谈论 JavaScript 和那个领域的很多语言。”

他,这次更吃惊了:“什么!!我们在那么小的空间里也有很多语言?”

我:“是的,出于选择或可能,由于向后兼容性,我们在前端一直使用 JavaScript。人们厌倦了 JavaScript,于是他们创造了可以生成 JavaScript 的语言。你可能听说过 s Coffescript,typescript 等。这里的想法是减少 JavaScript 造成的开发/调试/错误处理限制。有些给了它功能性的接触,有些给了它静态/动态的类型。Elm 更进一步,不仅针对 JavaScript,还针对 html、CSS 和 JavaScript 的整个 echo 系统。”

“我们也没有谈论其他一些特定平台的流行选择。如果你使用 Windows stack,如果你有一些很棒的语言可以使用。C#是令人惊奇的,当你来自 c++时,你会有宾至如归的感觉,所有的问题都是精心挑选和解决的,例如属性(像函数一样工作,用作变量),引用输入输出,委托,linq,最好的部分是围绕它的工具。Visual studio 是我们见过的最好的 IDE。F#函数也是如此。

苹果 echosystem objective c 也是如此,swift 对它的功能感到惊叹。

他:“有这么多选择,我们如何挑选一个正确的?”

做出一个好的选择需要一些努力

我:“事情很复杂,但没有你想的那么复杂。看你的要求。你的问题空间是什么?嵌入式或 web 或后端。你的目标规模是多少?有多少人会从事这项工作?你的内存有限吗(请记住,我们的资源可能更便宜,但既不是免费的,也不是无限的)。是针对 windows、Linux 还是 iOS/Mac?什么样的用户会使用它:普通终端用户、程序员还是产品经理?您期望的吞吐量是多少?它将在几个盒子(例如工具)上运行还是在许多盒子上运行?您有动力利用多核吗?你已经接触过一些可能适合你的语言了吗?您是否有想要重用的遗留代码库?您的 echosystem(日志记录、监控、数据挖掘、服务发现、缓存等)是否支持不同的语言,或者构建它们需要多长时间

他:“嗯。这么多方面去找。我没意识到选择一种语言如此复杂。其中你最喜欢的是什么?”

需求决定选择,而不是沙文主义

我:“有意思!c++是我大部分职业生涯所做的,所以如果它符合要求,我会选择它。我也学过一些 Java,所以如果我们要和一个更大的团队,更高层次的应用程序或者不那么低级的东西一起工作,这将是下一步。对于工具和内部项目,Ruby 是我的首选,因为在这里写代码会让你感觉更快乐。你可以建立的 DSL 看起来如此神奇,你每天都会爱上它。对于现有复杂应用程序的小定制,Lua 是我的首选。编写 L4/l7 定制路由器或定制代理服务器需要如此多的努力,我更喜欢使用现有的成熟技术,如 NGINX,并使用 lua 进行定制,这样我们可以获得相同的性能,但可以定制行为。当我不得不提取机器的所有能量并建立容错系统时,我会选择长生不老药。无状态数据操作、轻量级进程、平滑并发支持、基于角色模型的消息传递、内置的容错结构、分布式系统、热代码交换、内存中的键值存储和经过实战测试的 Erlang vm 让您的生活如鱼得水。

对于前端,我尝试了一段时间 JavaScript,但我厌倦了它不好的部分(显然它也有好的部分),所以想尝试一下 Elm,这似乎很有希望。核心功能,同时针对 HTML,JavaScript 和 CSS,惊人的编译时消息和时间调试器,它使前端编程有趣,好玩,像后端编程一样接近

他:“说了这么多,为什么没有图?”

我:“因为我懒的去做!!

黑客中午是黑客如何开始他们的下午。我们是 @AMI 家庭的一员。我们现在接受投稿,并乐意讨论广告&赞助机会。

要了解更多信息,请阅读我们的“关于”页面在脸书上点赞/给我们发消息,或者简单地说, tweet/DM @HackerNoon。

如果你喜欢这个故事,我们推荐你阅读我们的最新科技故事趋势科技故事。直到下一次,不要把世界的现实想当然!


本站为非盈利网站,作品由网友提供上传,如无意中有侵犯您的版权,请联系删除