我不理解为何人们会对面向对象编程和函数式编程作无休无止的争论。就好象这类问题已经超越了人类智力极限,因此你能够几个世纪的这样讨论下去。通过这些年对编程语言的研究,我已经清楚的看到了问题的答案,因此,我常常的发现,人们对这些问题作的都是一些抓不住要领、无心义的争论。程序员
简言之,不管是面向对象编程仍是函数式编程,若是你走了极端,那都是错误的。面向对象编程的极端是一切都是对象(纯面向对象)。函数式编程的极端是纯函数式编程语言。编程
面向对象的问题在于它对“对象”的定义,它试图将全部事情就归入到这个概念里。这种作法极端化后,你就得出来一个一切皆为对象思想。但这种思想是错误的,由于设计模式
有些东西不是对象。函数就不是对象。安全
也许你会反驳,在Python和Scala语言里,函数也是对象。在Python中,全部的含有一个叫作__call__的方法的对象其实都是函数。相似的,在Scala语言里,函数是拥有一个叫作apply方法的对象。可是,通过认真的思考后,你会发现,它混淆了源祖和衍生物的概念。函数是源祖,包含函数的对象实际是衍生物。__call__
和apply
它们自身首先就是要定义的所谓“函数对象”。Python和Scala其实是绑架了函数,把它们监禁在“对象”里,而后打上“__call__” 和 “apply” 标签,把它们称做“方法”。固然,若是你把一个函数封装到对象里,你能够像使用一个函数那样使用对象,但这并不意味着你能够说”函数也是对象“。数据结构
大多数的面向对象语言里都缺少正确的实现一等(first-class)函数的机制。Java语言是一个极致,它彻底不容许将函数看成数据来传递。你能够将所有的函数都封装进对象,而后称它们为“方法”,但就像我说的,这是绑架。缺少一等函数是为何Java里须要这么多“设计模式”的主要缘由。一旦有了一等函数,你将再也不须要大部分的这些设计模式。app
类似的,函数式编程走向极端、成为一种纯函数式编程语言后,也是有问题的。为了讨论这个问题,咱们最好先理解一下什么是纯函数式编程语言。出于这个目的,你可能须要阅读一下Amr Sabry先生(他是个人博士导师)的What is a Purely Functional Language。概述一下就是,纯函数式编程语言是错误的,由于编程语言
有些东西不是纯的。反作用是真实存在的。wordpress
所谓纯函数,基本上就是忽略了物质基础(硅片、晶体等)表现的特性。纯函数式的编程语言试图经过函数——在函数中传入传出整个宇宙——来从新实现整个宇宙。但物理的和模拟的是有区别的。“反作用”是物理的。它们真实的存在于天然界中,对计算机的效用的实现起着不可或缺的做用。利用纯函数来模拟它们是注定低效的、复杂的、甚至是丑陋的。你是否发现,在C语言里实现一个环形数据结构或随机数发生器是多么的简单?但使用Haskell语言就不是这样了。函数式编程
还有,纯函数编程语言会带来巨大的认知成本。若是你深刻观察它们,你会看到monads
使程序变得复杂,难于编写,并且monad的变体都是拙劣的修改。monads跟Java的“设计模式”具备相同的精神本质。使用monad来表现反作用就像是visitor模式来写解释器。你是否发现,在不少其它语言里很简单的事情,放到Haskell语言就变成了一个课题来研究如何实现?你是否常常会看到一些有着诸如“用Monadic的方式解决一个已经解决的问题”这样标题的论文?有趣的是,Amr Sabry先生一块儿合著了这样一篇论文。他试图用Haskell语言从新实现Dan Friedman的miniKanren,但他不知道如何构造这些monads
。他向Oleg Kiselyov——公认的世界上对Haskell类型系统知识最渊博的人——求教。并且你可能不知道,Amr Sabry先生应该是世界上对纯函数编程语言知识最渊博的人了。他们在 Oleg 的帮助下解决了疑难后一块儿合著了这篇论文。讽刺的是,Dan Friedman——这个程序的原做者——在使用Scheme语言开发时却没有遇到任何问题。我在Dan的代码基础上从新实现了miniKanren,增长了一个复杂的负操做。为了实现这个,我须要使用约束式逻辑编程和其它一些高级的技巧。鉴于用Haskell语言重写基本的miniKanren将两位世界级程序员都难倒了的事实,我不敢想象若是用Haskell的monads
如何能实现这些。函数
有些人认为monads
的价值在于,它们“圈定”了反作用的范围。但若是monads
不能真正的使程序变得易于分析或更安全,这种“圈定”有什么用呢?事实上就是没用处。自己就跟反作用同样难于分析理解。没有一种东西能够说monads
能使其简单而静态分析办不到的。全部的静态分析研究者都知道这点。静态分析利用了monads
的本质,但却去除了程序员编写monads
代码的负担——而不是增长负担。固然,过分的反作用会使程序很难分析,但你也可使用C语言写出纯函数,例如:
int f(int x) { int y = 0; int z = 0; y = 2 * x; z = y + 1; return z / 3; }
你用汇编语言也能作到这些。纯函数并不专属于纯函数式编程语言。你能够用任何语言写出纯函数,但重要的是,你必须也应该容许反作用的存在。
回首历史,你会发现,数学上的理想主义是纯函数编程语言的背后推进力。数学函数简单漂亮,但不幸的是,它们只是在你构建原始纯粹的模型时才好用。否者它们会变得很丑陋。不要被“范畴论”等标语吓倒。我对范畴论了解不少。即便是范畴理论学家本身也称其为“抽象无心义”,由于它们基本上就是用一种怪诞的方式告诉你一些你已经知道的事情!若是你读过Gottlob Frege的文章Function and concept,你会吃惊的发现,在他的这篇论文前的大多数数学家都错误的理解了函数,而这仅仅是刚刚100多年前的事。事实上,数学语言上的不少事情都是有问题的。特别是微积分方面。编程语言的设计者们没有理由要盲目的学习数学界。
不管任何事情,当走向极端时都是有害的。极端化时,面向对象编程和函数式编程都试图把整个世界装入它们的特有模型中,但这个世界是在彻底不依赖咱们的大脑思考的状况下运转的。若是觉得你有一个锤子,就把全部东西都当成钉子,这明显是不对的。只有经过认清咱们的真实世界,才能摆脱信仰对咱们的束缚。
不要让世界适应你的模型。让你的模型适应世界。