Smoke Art Cubes to Smoke — MattysFlicks — (CC BY 2.0)

请注意:这是JavaScript ES6+学习函数式编程和组合软件技术的“组合软件”系列的第1部分。接下来的部分更精彩,敬请期待!

在我大约六岁时,我的大部分光阴是在与我最好的朋友玩电脑游戏中度过的。他家中有一个装满了电脑的房间,对我来说,它们像魔力一样无法抗拒。我花了很多时间探索所有的游戏。有一天,我问朋友“我们怎样能做出一个游戏呢?”

他不知道,所以我们就去问他的父亲,他的父亲在一个高架子上拿下来一本关于用Basic写游戏的书。我的编程之旅从此开始。当公立学校开始讲授代数时,我已经很了解了,因为编程基本上就是代数,代数在程序中无处不在。

组合软件的崛起

在计算机技术发展的初始阶段,计算机还不能实现大多数计算前,有两位伟大的计算机科学家,阿隆佐·邱奇  (Alonzo Church)和阿兰·图灵 (Alan Turing)。他们发明了两种不同的,但是等效的通用计算模型。这两种模型都可以计算可计算的任何东西(因此被称为“通用”)。

阿隆佐·邱奇发明了λ演算。λ演算是基于函数组合的通用计算模型。阿兰·图灵则以图灵机而闻名。图灵机是一种通用计算模型,它定义了一种可以处理条带上符号的理论装置。

他们共同证明了λ演算和图灵机在功能上是等价的。

λ演算是关于函数组合的。函数组合是一种极富有表现力的组合软件的方法。本文将讨论函数组合在软件设计中的重要性。

以下三点使得λ演算与众不同,

  1. 允许匿名函数:add(x, y) => x + y可以表示为(x, y) => x + y。
  2. λ演算中的函数只接受单个输入,它是一元的。如果需要多个参数,该函数将接受一个输入,并返回一个接收下一个参数的新函数,依此类推。N元函数 (x, y) => x + y 可以表示为这样的一元函数 x => y => x + y。从N元函数到1元函数的这种变换被称为柯里化(currying)。
  3. 函数是一级的,意味着函数可以作为其他函数的输入和返回值。

这些特征共同形成了一个简单的、表达性的词汇,用于编写使用函数作为主要构件块的软件。换句话说,使用函数组合来构建软件。

经典的函数组合是将一个函数的输出作为另一个函数的输入,例如,组合f . g可以写为compose2 = f => g => x => f(g(x))

以下是使用方法,

double = n => n * 2
inc = n => n + 1

compose2(double)(inc)(3)

compose2函数将double函数作为第一个参数,inc函数作为第二个,然后将这两个函数的组合应用到参数3上。再来看一下compose2(),f 是 double(), g是inc(), x 是 3.函数调用compose2(double)(inc)(3)实际是三个不同的函数调用,

  1. 第一个通过double,返回一个新函数。
  2. 返回的函数使用inc,返回另一个新函数。
  3. 另一个新函数使用3,计算f(g(x)),即double(inc(3))。
  4. x 的值是3,传递给inc()。
  5. inc(3)得到4。
  6. double(4) 得到8。
  7. 8就是整个函数的返回值。

当组合软件时,可以用一个组合图来表示,以下表达式可以直观的表示为:

阿里云-推广AD

append = s1 => s2 => s1 + s2
append(‘Hello, ‘)(‘world!’)

2

λ演算对软件设计有巨大的影响,在1980之前,很多非常有影响力的计算机科学品牌使用函数组合来构建软件。表处理语言(Lisp)创建于1958,它深受λ演算的影响。现在,Lisp是依然在广泛使用的历史第二悠久的语言了。

I was introduced to it through AutoLISP: the scripting language used in the most popular Computer Aided Design (CAD) software: AutoCAD. AutoCAD is so popular, virtually every other CAD application supports AutoLISP so that they can be compatible. Lisp is also a popular teaching language in computer science curriculum for three reasons:

  1. Its simplicity makes it easy to learn the basic syntax and semantics of Lisp in about a day.
  2. Lisp is all about function composition, and function composition is an elegant way to structure applications.
  3. The best computer science text book I know of uses Lisp:Structure and Interpretation of Computer Programs.

我通过AutoLISP了解了LISP, AutoLISP是在最流行的计算机辅助软件(CAD)AutoCAD中使用的脚本语言。AutoCAD很受欢迎,几乎每一个其他CAD应用为了能够与之兼容也使用了AutoLISP. Lisp也是计算机科学课程中的一种流行的教学语言,原因有三:

  1. 它的简单性使得大约一天就可以学会Lisp的基本语法和语义。
  2. Lisp是关于函数组合的,而函数组合是构建应用程序最好的方法。
  3. 我知道最好的计算机科学教科书是使用Lisp的:计算机程序的结构与解释

函数式编程的没落

1970到1980年间,软件的构建方法偏离了简单的组合,成为了供计算机遵循的一系列线性指令。然后出现了面向对象编程——一个关于组件封装和消息传递的伟大想法,却被流行的编程语言曲解为一个关于继承层次结构的糟糕想法。

函数式编程被边缘化,沦落到了学术界:1990到2010年间,酷爱编程的极客们,常春藤名校中的教授们,和一些幸运的学生躲过了Java填鸭式的痴迷。

对我们大多数人来说,在这30年中,软件开发简直是噩梦。 黑暗时代。

函数式编程的崛起

2010年左右,一些伟大的事情开始发生:JavaScript爆发了。在2006年之前,JS被广泛的认为是用来编写浏览器中小动画的玩具语言,但它隐藏了一些强大的功能,即λ演算。人们开始悄悄讨论这个被称为“函数式编程”的新事物。

到了2015年,用函数组合来构建软件的想法再次流行起来。为了使它更简单,JS规范做了十年来的第一次大版本升级,并添加了箭头函数,这使得创建和阅读函数、克里化、λ演算更容易。

箭头函数就像火箭燃料,使得JS中的函数式编程异常火爆。今天很少见到一个不使用大量函数式编程技术的大型应用程序。

组合是一种简洁,优雅,清晰的描述软件行为的方法。组合小的、确定性的功能以创建一个大的软件组件和功能的流程,产生了易于组织、理解、调试、扩展、测试、维护的软件。

当你阅读以下文章时,请将实例一一实践。请记住在学习时,要像孩子一样,找出问题、探索、边玩边学。重新发现儿时发现的乐趣。让我们来创造一些奇迹吧。