OOP和FP错在哪里?
面向对象和面向函数一直在争论,实际上纯粹的OOP和纯粹的FP都是极端的,对于OOP来讲:存在的并一定都是对象,函数就不是对象;对于FP来说:存在的并不总是纯粹的,副作用总是真实存在。
What’s Wrong with OOP and FP提出了以上观点。
首先,OOP错在哪里?
对于OOP来讲:存在的并一定都是对象,函数就不是对象。
OOP是错误的,因为其定义“对象”企图适应一切。当到了极致时便是“一切都是对象”。但这种观念是错误的。
你可能会认为,在Python或Scala 函数也是对象。在Python中,每一个对象的方法的__call__是一个函数。同样,在Scala中,对象的方法命名也适用函数。但经过一番深思熟虑,你会看到,这是混淆了传递和根本基础两个概念,函数才是根本基础,而传递的是包装它们的对象。Python和Scala只是绑架了函数,把它们打入了牢狱“对象” ,然后给他们一个标签是__call__或apply,然后再调用这些对象的方法。
当你包装成函数成为一个对象时,你可以使用像一个对象去使用函数,但是这并不意味着你就可以说“函数也是对象” 。
大多数面向对象的语言也缺乏正确实现first-class的函数。一个极端是Java,不允许函数作为数据传递。您可以随时用对象包装函数,称他们为“方法” ,但正如我所说,这是绑架。first-class的缺乏是主要原因,为什么在Java有这么多的“设计模式” 。一旦你有first-class函数,您将不需要任何设计模式。
其次,FP错在哪里?
FP是错误的,当你走到极端,变成一个纯粹的函数性语言,也是错误的,见Amr Sabry :What is a Purely Functional Language
对于FP来说:存在的并不总是纯粹的,副作用总是真实存在。
纯粹函数语言试图重新实现宇宙,通过将宇宙一切输入输出。但是真实世界和模拟之间有一个相差,副作用是真实世界的,它真实存在物理世界,当我们进行模拟计算是也是必不可缺少的,纯函数模拟它们注定是低效的,复杂的,甚至是丑陋的。 Haskell的同样是不正确的。
纯粹的函数性语言造成了巨大的认知成本。如果你看看他们的深入,monads单子使程序复杂,很难写,monad单子变压器只是丑陋的黑客而已,monads同样于设计模式,用单子代表副作用很类似用访问者模式去写解释器一样。
当你使用Haskell做事时,你有没有注意到其他语言实现起来多么容易吗?
Amr Sabry可能是世界上最纯粹的函数式编程语言知识最渊博的人,他通过一个小故事告诉我们:他们使事情不必要地复杂化。
有人说单子的价值是他们“划去了”的副作用,但是单子不能使你的程序更容易分析或安全,这种划去有什么意义呢?
当然过度使用的副作用会让程序更加难以分析,但你也可以在C语言中写纯函数:
int f(int x) {
int y = 0;
int z = 0;
y = 2 * x;
z = y + 1;
return z / 3;
}
你也可以使用汇编写,纯函数不只是属于纯函数语言,你可以在任何语言中编写纯函数,前提是,你得允许也能使用副作用。
回顾历史,数学的理想主义是纯粹的函数性语言的原动力。数学函数是简单而美丽的,但不幸的是,只有当你的模型是纯粹的,它们才工作得很好。否则,它变成难看。
不要害怕“范畴论”等流行语。我知道有相当数量的范畴论。即使类别理论家自己称之为“抽象的废话” ,因为它基本上是一个怪诞的方式表达你已经知道的东西!如果你读了Gottlob Frege弗雷格文章的函数和概念,你会惊奇地发现,大多数数学家在他写作之前就得到了错误的函数,这大概已经追溯到一百年以前。事实上,数学家用其语言已经做了这么多错误的事情,特别是微积分之类的东西。没有理由今天编程语言的设计者应该盲目地学习数学。
[该贴被banq于2013-11-13 14:14修改过]