函数式编程的正确使用方式

在我年纪尚轻、刚开始学习计算机编程的时候,曾经一度非常沉迷函数式编程,笃信它必将取代指令式编程成为未来的编程方式。但时光荏苒,十多年过去了,函数式编程语言却从来没有成为过主流:根据GitHub的编程语言排行榜所示,排名前10甚至前20的语言,没有一个是(单纯的)函数式的;直到排名21~30这个区间里面,函数式编程语言的身影才开始出现,然而尴尬的是,跟排名前10、前20的指令式编程语言相比,使用函数式编程语言编写的代码数量少得几乎可以忽略不计。

那么为什么会这样呢——在编程上具有多种高级技术的函数式编程语言,为何在近年来未能取得成功?我想究其原因,说到底就是使用函数式编程语言的人还是太少了。我不知道有多少人是否发现了,在现代编程中,编程语言的使用者数量实际上是一个非常关键的因素,其重要性远远超过编程语言本身,更不要说编程语言提供的某个或某些高级特性了。

著名投资人、Lisp黑客保罗·格雷厄姆曾经写过一篇名为《Beating the Averages》的文章,阐述他们在创业期间如何通过使用抽象层次更高的Lisp语言及其带来的动态编程和快速迭代优势,打败其他使用C和Perl等抽象层次较低的编程语言的竞争对手(这篇文章也因此被Lisp和函数式编程爱好者广为引用)。但是与保罗·格雷厄姆创业时所处的1995年相比,现代的编程活动已经发生了翻天覆地的变化:现在的程序员不必单打独斗,他们可以通过GitHub等代码共享库又或者编程语言的包管理器,瞬间获得成百上千万行可工作的代码,然后站在巨人的肩膀上进行开发。

但是通过复用其他程序员的代码来实现高效开发的前提是——你使用的必须是热门的编程语言,比如对于Python、Java和JavaScript等语言来说,各种包几乎是无穷无尽的;反之,如果你使用的是少有人问津的编程语言,比如Lisp,那么你找到的共享包通常只会有寥寥几个,而且它们可能已经年久失修,又或者未能提供齐全的功能。这时你唯一能做的就是自己动手开发所需的包,而这样做的效率要远远低于直接复用别人的代码,单纯依靠编程语言提供的几个高级特性根本无法填平这一巨大的鸿沟:你也许是一个勇敢无畏的堂吉诃德,但你面对的却是由数百万开发者组成的大军——在他们面前,你根本毫无胜算。

不过并不是说函数式编程语言使用的人少它就一无是处,事实上,函数式编程语言的各项特性和概念早已融入在现代编程语言的设计中,即使你使用的不是函数式编程语言,也一样能享受到它们带来的好处:

  • 比如说,对于JavaScript,它的很多功能就是在函数式编程范式下实现的,而Rust等新锐语言则通过借鉴函数式编程语言的不可变等特性来实现安全编程。

  • 又比如说,Python的迭代器和列表处理方式对于熟悉函数式编程的程序员来说就非常易懂,并且Python还有JavaScript等大量语言的并发编程都是基于函数为单位实现的,而一等函数性质在这其中扮演了至关重要的角色。

  • 更进一步,即使是Java和C++这样传统的语言,近年来也在积极加入匿名函数等函数式编程特性,以便支持更高效的开发。

因此,从实用主义的角度出发,大家有时间的话还是可以去学习一下函数式编程:尽管你不太可能直接转向这种编程方式,但它对于开阔眼界、了解编程语言中借用的函数式编程特性来说,具有非常大的好处。另一方面,如果你确实想要使用这种小众的方式进行编程,那么最好能够找出一个非它不可的理由。

黄健宏
2024.9.19