函数编程(FP)

面对越来越复杂的软体开发需求,我们需要更高的抽象层。过去二十多年,我们将物件导向(Object-Oriented Programming,OOP)和元件(Components)的观念注入大多数的主流imperative编程语言(例如BASIC丶C丶 Pascal),采用这些技术可以降低软体开发的复杂度(Complexity),增加再用性(Reusability),於是我们着实过了好一阵子安稳的生活。

但软体的复杂度就像细菌的抗药性一样,依然在持续增加。当万古霉素开始压制不住金黄色葡萄球菌,物件导向渐渐让软体开发力不从心,我们要如何是好?

越来越复杂的专业领域知识丶越来越多元的异质平台丶越来越普遍的网路环境和多核心电脑…这些都会提升软体开发的复杂度,我们再度陷入困境。忽然发现,古老的函数编程(Functional Programming,FP)可以解决这个阶段的许多问题,原来FP是现代编程问题的一帖良方。这使得最近函数编程忽然又被炒热,成为许多语言设计者的最爱。

相较於OOP是往真实世界的方向进行抽象,FP却是往数学的方向进行抽象。FP的理论基础是来自Lambda Calculus,而Lambda Calculus同时赋予FP简单性和威力。当然除了Lambda Calculus之外,方便的List处理丶自动记忆体管理丶Meta-Programming也都是函数式编程语言常见的特性。

提到函数编程,就不能不提1958年被创造出来的LISP,因为它是函数编程的始祖。畅销书《骇客与画家》(Hackers and Painters)的作者Paul Graham提到,LISP是许多公司成功的秘诀,因为透过LISP,他们可以用精简的人力,在很短的时间内,开发出威力强大的系统。Paul Graham本来很担心,他这麽一鼓吹LISP,要是别人都因此改用LISP,自己就占不到便宜了。不过作者最後的结论是,大多数的人不会这麽聪明,所以应该可以不必担心。他说的没错,在《骇客与画家》与《Practical Common Lisp》出版约五年後的今天,LISP语言在Tiobe的语言需求排行榜却不升反降,眼看就要被挤出前20名了,我直呼大师预言神准。

虽然Paul Graham称赞的对象是LISP,但等於间接称赞到FP。尽管一般程式开发人员对於FP的重视程度依然不高,但是语言设计者却对FP兴致高昂。既有的主流语言(例如C#丶VB)开始在新版本中加入FP的特色;新兴的语言(例如Scala丶JavaFX)同时结合FP和OOP,就连古老的FP语言(例如 ML)也有了新的面貌(例如F#)。

C#为了支援LINQ,以进行更高程度的资料查询抽象,开始加入FP的特色。目前LINQ已经利用FP进行meta-programming,未来LINQ还会利用FP进行concurrent programming,以充分利用现代多核心的运算环境。

F#是衍生自ML家族的OCaml,融合了一些C#和Haskell的概念。许多时候,F#和OCaml的程式是可以交互编译的,也就是说,两个语言的相容性很高。由於F#是目前.NET平台最重要的FP语言(也是微软官方提供的语言),因此未来随着FP渐渐受到重视,F#也会占有一席之地。

但我认为这「一席之地」恐怕坪数不大,却公设很多。.NET环境下,函数式编程的语言选择,我的建议是:如果你是基於科学丶工程的目的而写程式,那麽F# 会比较适合,如果你要写的是「世俗化的系统」(例如Web丶资料库丶RIA),那麽还是使用C#吧。因为既有主流语言的使用者,可以渐进地学习函数编程。过去的经验告诉我们,C++会流行丶Java会流行,某一部份的因素是因为它们是从既有的语言去做加强(C++是C的强化版丶Java是C/C++的改良版)。

但是我认为使用C#中语言的人,或许会因为使用LINQ之类的技术,而「间接」用到函数编程,但是很少有人在规划软体时会直接使用到函数编程的重要特色。「使用函数编程语言」不等於「进行函数编程」,你可以用函数编程语言写出不合乎函数编程理念的程式,正如同你可以用物件导向语言写出不合乎物件导向理念的程式。

更何况C#因为加入太多语言特色,变得过度复杂,开始有C++化的趋势,而「复杂」是和FP的「简单」背道而驰的。因此对於初学FP的人,或许F#等「新瓶旧酒」语言会更适合用来学习FP的观念,培养相对单纯的FP体验。

真的想学好函数编程的观念,可能还是得从传统的FP语言着手,会比较彻底。函数编程只是一个观念,各个语言的作法和语法差异可能不小,例如LISP家族丶 ML家族(F#属於这个家族)丶Erlang这三者都是相当重要的函数编程语言,但是这三种语言的差异相当大。如果你是.NET使用者,就学 F#;Java使用者就学JavaFX或Scala;其他使用者就学Common Lisp或Erlang。

Paradigm-Shift总是痛苦的,但这是生存之道。从OOP的Paradigm转移到FP,一开始可能会有不适应的地方,但熟悉之後,你会很高兴你学会了一个新的技能丶新的思维,可以面对新的环境丶新的挑战。

我知道函数编程当然也不会是软体开发一劳永逸的解决之道,未来还有更多的挑战会出现。或许,下次编程挑战的救星,会是逻辑编程(Logic Programming)也说不定。

posted on 2009-02-13 15:13  highmayor  阅读(1199)  评论(1编辑  收藏  举报

导航