程序员对于编程语言的争论,是一场永远都不会停止的战争。但社会在进步,科技在进步,那么就让大家继续吵下去吧 :)

这是一本讲述七种不同类型编程语言:Ruby,Io,Prolog,Scala,Erlang Clorjure 和 Haskell 代表的现代编程语言的重要特性和编程范式的书。这里面的语言多多少少被大家听过或者用过。他们分别作为某个领域的代表而汇集到一本书里。

Ruby

这门语言是我目前工作中的主语言,包括对应的生态。语法简单但又灵活,超强的 DSL 能力和丰富的社区资源给我的工作提供了巨大的便捷和效率。 Ruby 或者 Ruby on Rails 是一种在开发过程当中,程序员能够按照自然语言的思维并且很容易写出符合预期逻辑的程序。这让项目的迭代速度不会打折扣。

当数据量变大之后,它的内存管理和执行效率的劣势就慢慢展露出来。随之而来的还有” 过于灵活 “的语法特性导致了一旦 Code Review 没有做到位并且代码风格与团队成员差异巨大的情况出现时,维护项目阅读代码就变得很糟糕。我们曾经常出现服务器内存不足的报警消息,也偶尔因为难以维护部分旧有的糟糕代码而不得不进行重构。可以说 —— 动态语言一时爽,重构现场火葬场(逃

Io

这一门原型语言。什么是原型语言? 在传统的面向对象语言中,比如 Java、Ruby、C++、Python,我们通常需要定义一个称为 class 的东西,然后再基于这个 class 创建对象。而 Io 这门语言是只操作对象的,简单说就是 Io 有一个叫做根对象 Object 的东西,我们需要定义一个对象直接 Car := Object clone 即可。在 Io 这本语言的上下文中,一切都是由对象和消息组成。这一点很像 Ruby 中的元编程,甚至我个人会认为元编程学习了 Io。同样,这门基于消息的编程语言在实现 actor 作为并发模型就变得轻而易举。我们会在 Scala、Erlang 和 Haskell 以及今后众多流行编程语言中再见到 actor。Io 的语法很简单,几乎没有可以被叫做语法糖的东西,甚至关键字也少的可怜。这门语言让我想到了当今国内算是火热的 Go 语言,简单高效却给人强大的印象。

Prolog

这是一门逻辑编程语言。和 SQL 一样,Prolog 基 于数据库,但是其数据由逻辑规则和关系组成; 和 SQL 一样,Prolog 包含两个部分: 一部分用于 描述数据,而另一部分则用于查询数据。在 Prolog 中,数据以逻辑规则的形式存在。这个是很有意思的一件事情,如果读者看过 伊曼努尔 · 康德 所著的《纯粹理性批判》会更加体会到这门语言的编程哲学。比如说,在 Prolog 中,数据的标准存放格式如下:

「事实 」关于真实世界的基本断言(对没错,就是你测试代码中的 assert)—— Babe 是一头猪,猪喜欢玩泥巴

「规则」真实世界的推论(if then)—— 如果你是一头猪,那么你喜欢玩泥巴

「查询」向真实世界寻求一个问题(布尔表达式)—— Babe 喜欢玩泥巴吗?

按照大多数语言通常的 Coding Pattern,应该是这样

收集和整理逻辑

用程序表达逻辑

找出所有可能的解决方法

通过程序验证这些可能的解决方法

这是标准的做法,给大家清晰的脉络,并且也容易维护。

然而,Prolog 会给人一种神乎其技的感觉。对的,大多数语言写代码都是 how 需要我们自主阐述逻辑,然而 Prolog 是一种 what,当我们人为定义好问题之后,让计算机来解决。书中的「地图着色问题」、「数独问题」有详细解释。

曾几何时,基于规则的 AI 和 NLP 领域让这门语言大放异彩。随着后来深度学习,基于统计算法的兴起,以前这种,呵呵。。

Scala

是一把名贵的瑞士军刀,因为它什么都有。运行在宇宙最强虚拟机 JVM 上,融合了面向对象和函数式编程。语法给我的感觉是吸收了 Java/Ruby/Haskell。最近刚好在写 Scala 还有学 Akka,后期会专门补充。

Erlang

回到一个原始的原则,在技术选型上我始终认为工程师需要考虑所用技术的三个指标:开发效率,执行效率和可维护性。在 Erlang 中,以下的特质都给予了 Erlang 不错的上述指标

pattern matching 比如说有两个 kv 数据结构,如何最方便比较结构是否一致。很大程度上避免大量的 if-else

函数 通过 export 方式让函数给外部模块调用,加上 pattern matching 可以非常方便写测试代码

消息传递 不同的 erlang 进程可以通过消息传递的方式共享变量

热更新 修改了代码可以不重启服务器生效

parse_transform 通过发送和接受 AST 来使用模块

spawn 一个 erlang 进程只是在 erlang 虚拟机中的进程并且只占用极少的操作系统资源,高并发的情况下表现优异。

如今在天朝南部沿海某城市,很多基于 OTP 框架的游戏公司依然是 Erlang 的忠实用户。

Clorjure

如果有看过 SICP 那本书,就一定知道 Lisp 的威力,当然有不少大 V 都写过赞誉它的文章比如:阮一峰博客中的译文「为什么 Lisp 语言如此先进?」

http://www.ruanyifeng.com/blog/2010/10/why_lisp_is_superior.html

还有陈皓的「Lisp 的永恒之道」https://coolshell.cn/articles/7526.html 都非常认可 Lisp 的很多理念以及这门语言带给现代编程界的影响。

所以,当这门语言跑到了 JVM 上之后,又会产生什么样的效果呢?

工程化的环境。由于 JVM 平台的的推力,clorjure 朝着一种工业化的通用的方向发展并且简化了 Lisp 中的括号写法。在 Java 中常常会有设计接口来做工程化的抽象,clorjure 中有「协议」的概念。如果需要调用 Java 自带的方法,比如 Object.toString(),可以直接这样

Object
(toString [this] (str “[“ (your object) “]”))
就可以直接调用了。这相当于扩展了 Java(附带了 Lisp 的函数式和宏),也可以认为扩展了 Lisp(结合了面向对象)。所以我决定学 Scala,😂

clorjure 中还有原子和代理来保证并发安全,原子和大多数语言的 atom 类似,代理是说当某个对象被代理之后,使用者可以异步修改代理对象的值,更新发生在另外的线程,并且每次只有一个函数可以修改代理的状态。

Haskell

我认为 Haskell 一定是高纯度的函数式语言。

模式匹配拒绝大量的 if-else,尾递归优化让递归更高效,元组则让函数写得更加简洁且富有表达力 🕶️。一个列表被定义为 head 和 tail 两个部分,那么列表的定义就是 head 和 tail 的模式匹配,特别是列表推导编程,严谨而且聪明。惰性求值,高阶函数,monad(一个自函子范畴上的幺半群),柯里化… Haskell 在作者的观点里是本书中最难学的语言,但也是最引人深思和启发的语言。在笔者与 Scala 前辈的交流中听到里许多关于 Haskell 的赞誉。

回到一个偏哲学意义的问题:如果编程是在给输入的问题找到一个解,那么,是否存在任何情况下只要我们输入出问题的定义,就能让计算机返回解的场景?

希望你也喜欢这本书。😊