函数式编程的兴衰(Composing Software 1)

1,388 阅读6分钟

最近都在紧张的准备期末,然后为即将开始的19届实习春招在panic,觉得自己好慌,找不到实习怎么办)

不过发现了之前翻译过文章,这个是一个系列的文章,也算是我函数式编程的入坑之作吧

只是翻译了第一篇,第二篇第三篇都在progress中,大家有兴趣的话我就就陆续放出来吧

没有就接着坑了。。。

我六岁的时候很喜欢和我的朋友玩电脑游戏。他家有一个专门的房间放满电脑。对于我来说,他们家就像一片魔法天地吸引着我。在花了很多时间玩过很多游戏后,我问我的朋友,”我们该怎么做一款出来呢?“

他也不知道,所以我们去问了他爸爸,他爸爸从书架高处拿下一本用Basic写游戏的书。所以我开始了我的编程之旅。在学校开始教代数的时候,我早就学过了,因为编程就是代数。

组合式程序(Composing Software)的兴起

在计算机科学初期,在很多计算机科学理论在电脑上实践在电脑上之前,有两个伟大的计算机科学家:Alonzo Church和 Alan Turing。他们发明了两种不同但是都被广泛使用的计算模型。两个模型都可以将任何可计算的模型计算。

Alonzo Church 发明了λ演算。λ演算是一个基于函数应用的普遍模型。Alan Turing以图灵机著称,图灵机是一个在一卷胶带定义了设备和操作符的普遍模型。

在这两组模型的合作中展示了,其实两种模型在功能上是殊途同归的。

λ演算主要是关于函数组合。从函数组合的角度来思考问题,是非常直观的,而且对于组合程序非常有效的。在接下来,我们将讨论函数组合在程序设计中的重要性。

说λ演算很特别一下有三个理由:

  1. 函数通常是匿名的。在JavaScript里面, const sum = (x, y) => x + y 的右操作数是一个匿名函数表达式。
  2. 在λ演算中函数只接受单一输入,是一元的。如果你需要更多的参数,那么函数会接受一个输入后返回一个新的函数,来接受新的参数。多元函数(x, y) => x + y 可以表示为x => y => x + y 这样的一元函数。这样的变化被称为编程的柯里化(currying)
  3. 函数是第一级的,这意味着函数可以用来作为其他函数的输出,函数可以返回函数。

这些特性就赋予了组合式程序,使用函数作为基础构建模块的能力。在JavaScript里面,匿名函数和柯里函数都是可用的特性。鉴于JavaScript有着这些λ演算的特性,所以就可以恰当的使用λ演算模型。

经典的函数组合会从一个函数的输出提取输入进另外一个函数,举个例子,这样的组合:

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() 的签名, fdouble(), ginc(), 然后 x3。最后采用了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 最终被函数返回。

当程序被组成化后,他可以形象的用图像表示函数组合过程。举个例子:

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

可以被这样表示:

img

λ演算对程序设计产生了巨大的影响,直到1980年,有许多基于组合函数的计算机科学研究成果。Lisp诞生于1958年,就受到了λ演算很大的影响。如今使用的语言中,Lisp依然是一门第二老的语言。

我是通过AutoLISP了解的Lisp。AutoLISP是一个用于CAD语言。AutoCAD广受欢迎当然支持AutoLISP,但是基本上CAD的主要软件都支持AutoLISP。Lisp在如今还是一门很热门的语言有三个原因:

  1. 学习Lisp的符号和语法差不多一天就够了。
  2. Lisp都是函数组合,是一种优雅的结构化编程方式。
  3. 我知道最棒的CS课本: Structure and Interpretation of Computer Programs使用着Lisp

组合式程序(Composing Software)的衰落

在二十世纪七十年代,创建程序的模式于简单的组合检票渐远,成为了工业流水线式的生产。之后又有了面向对象编程,一个关于组件封装和信息传递的好主意。不过由于一些热门的语言扭曲,变成了继承和类关系的噩梦。

函数是编程在学术和应用上都失去了地位,仅仅残存在一些有执念的极客,常青藤高塔中的教授,还有一些没有因Java风潮而着迷的学生那里。

对于大部分的人来说,这都是一个黑暗的时代。

组合式程序(Composing Software)的再次兴起

到了2010年左右,发生了一件好事:JavaScript大爆发。在2006年以前。JavaScript被认为是一个做网页动画的玩具语言,但是其实有很多强大的特性隐匿其中,即λ演算的特性。人们开始口耳相传的一个“新的概念”:“函数式编程”。

到了2015年,组合式程序的概念又开始兴起。为了让他更普遍,JavaScript也升级了新的特性,加入了箭头函数,使函数,柯里化,以及λ表达式更加直观可读。

箭头函数就像是函数式爆发的火箭燃料,以至如今已经很难见到不怎么使用函数式编程的JavaScript程序了。

组合让软件模型和行为都更加简单,优雅,直观。使用一些轻量而重要函数来构建大一些的程序组件,函数式的编写程序更加易于测试,理解,组织,引入。

原文:The Rise and Fall and Rise of Functional Programming (Composing Software)

作者:Eric Elliott

翻译:Dominic Ming