函数式编程functional programming的特点

以Erlang为代表的面向功能语言functional programming(FP)越来越热门,虽然本身有比较难学等缺点,
Where functional programming fits in一文总结总结了FP适合哪些场合?

Java平台的Scala,.NET的F都是FP语言,而Ruby因为包含一些FP特点受到欢迎。
FP特点:
1.FP代码没有边界影响“side effects.”(目的明确,是一就是一,不会因为捣蛋鬼调用导致其他功能实现)
2.没有literal值, 简单的功能只是返回相同值。
3.许多FP语言有“lazy evaluation,”(类似懒加载机制),功能并不真正运行,直到他们被调用,比如你定义x = y +5,只有当x被使用时,才真正计算y+5,这个带来更好的性能boon和curse (有时不确定值),(注:这个和我们之前讨论的异步Domain Events好像类似,模型的值只有即时使用才访问数据库获得,我们也是为了获得更好地性能,见Domain Events异步应用)

FP语言的这些特性代表了思想的根本转变,但是使用FP语言,必须考虑是不是存在过度工程或overthinking的问题,因为这代码的其他维护者需要学习一个新的语言。

作者认为FP语言使用在算法应用领域比较好,在Xbox Live排名系统中,用F替代C重写,只用了10% 的代码量,节约了近90%的代码。

如果你使用现代主流的胶水库library glue code之类应用,如果你的代码是由一个个类组成的结构,而算法只是被融合在这些类之中,就没有必要使用FP语言。

[该贴被admin于2009-12-09 14:24修改过]

functional programming -> 函数式编程,其根源是数学中的lambda演算
side effect -> 副作用,OO中接近的概念是不改变对象状态的方法调用
lazy evaluation -> f(x + y),如果f内部根本未用到这个参数,x+y不会被计算,您举的例子也是对的
[该贴被weidagang2046于2009-12-09 13:14修改过]

2009年12月09日 13:12 "weidagang2046"的内容
functional programming -> 函数式编程,其根源是数学中的lambda演算
side effect -> 副作用,OO中接近的概念是不改变对象状态的方法调用

多谢,看来应该翻译成面向函数式编程,side effect翻译成副作用更贴切。

推荐一篇FP的文章,里面对FP的优势做了很好的介绍。在OO语言中也可以借鉴一些FP的风格改进设计。http://www.cnblogs.com/erain/archive/2008/12/14/1354810.html

2009年12月09日 15:04 "weidagang2046"的内容
推荐一篇FP的文章,里面对FP的优势做了很好的介绍。在OO语言中也可以借鉴一些FP的风格改进设计。http://www.cnblogs.com/erain/archive/2008/12/14/1354810.html

彻底受教了,不过对这篇文章有不敢苟同之处:
之前一段试图将数学哲学化很让我反感,这是典型的泛数学主义思想,数学之外还有一个艺术,不是所有事物都可以量化数学化,如果可以,如今就不存在那么多未知领域和疑惑,也不能认为混沌结构思维毫无用处,中国人靠中医活下来了,活得不差。这是灌水,不多说。

用currying说明设计模式就不需要使用,这也只是一厢情愿(GoF设计模式三作者15年后再谈模式),算法数学占据主要地位大概只有特定算法科学领域,现实的胶水模块领域,还必须注重架构和模式,在DDD中有一段对算法观点:

1.算法或计算非常复杂,导致设计受到了冲击,模型中的概念变成了用“怎么做”来解释,而不是用“是什么”表达。(主次颠倒)

2. 算法本身存在内聚性(因为它能用公式表达,公式就是算法具有内内聚性的特征),使用策略模式等框架把这些内聚计算分离出来,用一个明确接口来说明这个框架的功能,将怎么做复杂细节交给框架(主要管算法的API)去完成。

3.我们计算方法不可能把所有功能都包含进来,我们需要的也不是一种万能计算机制。(批评那种算法万能观点,没有一个算法能够把万事万物功能算进来,如果是,就成了周易算命了)。

在DDD中将副作用也就是边界影响归纳为柔性设计,所谓柔性实际就是艺术性的事情,这是架构的目标,DDD认为柔性设计为:
1.明显意图的接口:面向接口编程,做什么目的在接口中清晰表达,而无需翻看具体代码。

2.边界影响: 消除边界影响,不要搞一机多能。

3.粒度适当界定 粒度不能太大,造成重复和冗余,很多概念混在一起;当然粒度也不能太细,以至于太碎,不能完整表达一个领域概念。高聚合、低关联。

4.消灭依赖 每复杂的依赖关系无疑提高了系统的复杂性,每个依赖都是值得怀疑的。

5.操作封闭 服务行为操作的是同一个类型,不要一次性处理多个模型。

6.声明性设计,尽量使用成熟框架,保证质量。 如DSL

可是这些这篇文章中用轻飘飘一句:“因为 lambda 演算不是被设计为在物理局限下工作的。因此,象面向对象的编程一样,函数式编程是一系列理念,而不是严格的教条,”这其实就是柔性艺术性的特征,由于作者背景知识原因没有认识到罢了。

所以,函数式编程和OO不矛盾,而且是在OO世界中属于一个“怎么做”的问题,而OO方法论如DDD是解决把“是什么”和“怎么做”如何分开。

说得详细一点:“是什么”就是需求是什么,先要把需求说清楚,功能要求说清楚;“怎么做”是如何实现问题,通过软件技术架构或算法等等科学来实现。

btw:由于我们都是在学“怎么做”中长大的,忘记“是什么”这个主要目标,就容易造成井底观蛙,舍本求末,南辕北辙,这实际是为什么当前科学总是不能转化为生产力的原因之一。

以上只是个人想法。
[该贴被banq于2009-12-09 16:29修改过]

首先,我认同您关于“做什么”重于“怎么做”。但您认为FP注重的是“怎么做”那就是恰好说反了。举个例子:
x = x + 1;
这个java代码不正是“怎么做”吗?对于未学过程序设计的人它是很难理解的,因为起码这句话已经有了内存空间的概念。FP中没有内存空间的概念,类似上面这样的代码根本不存在。DSL是关注的“做什么”,我们很难看到OO语言直接写出DSL代码来,而这在FP中是天然的。

所以,就FP到底是关注“做什么”还是“怎么做”建议您先不急于下结论。

OO与FP不矛盾也是对的,它们是两种正交的程序设计范式(paradigm)。语言间最大的差别在于范式:C,Pascal是命令式,所以它们很像;Java,C是对象式,所以它们很像;Lisp和Haskell是函数式,所以它们也很像。目前主流的程序设计语言都是以一种范式为主,其它范式为辅,比如:C++以对象式为主,以命令式,泛型式等为辅。

个人认为虽然纯FP语言很难成为主流,但是在现在主流语言和设计中不断融入FP风格是大的趋势。

呵呵,我同意不要急于对FP是属于“做什么”和“怎么做”下定义。

关键可能还是大家对OO定义有些不一样,OO定义分理论和实现,Java自称是OO语言,只是以前OO理论的实现,现在OO理论发展了,比如DDD,上面提到的柔性设计等,Java就也需要发展,而FP对柔性设计比Java到位。

我前面帖子主要讨论了一下算法和设计关系,如果FP专门用来做算法,那么应该也属于这种范围,如果FP用来做DSL,那么就属于是什么了,Scala好像比Erlang更适合做“是什么”。

所以,这样一讨论,大家应该明白,软件设计思想发展的一脉相承。这也是我写这么多的意思,软件当然少不了算法发展,但是不只是算法发展,还有很多方法论的发展,这是我想侧重的。

至于谁是未来主流,这个就很难说,不否认结合FP和DSL的Scala可能是主流,但是我个人倡导是什么和怎么做分家,不分家,Java还是不错的。


[该贴被banq于2009-12-09 18:02修改过]

good

当今主流的编程语言中对FP特性支持最好的莫过于c,从引入lambda后FP就成为C的一个不可分割的特性了,现在发现有的时候用lambda真的是非常优雅.
.NET有个东东叫LINQ -- 语言集成查询,可以用C语句查询数组对象(LINQ 2 OBJECT),查询XML(LINQ 2 XML),查询SQL(LINQ 2 SQL OR DLINQ)而不需要了解xpath,SQL等专业领域的查询语言.这方面感觉C走的很快,在生产中也确实解决了不少问题.java我不熟悉,不知道java是否支持闭包,如果java支持闭包的话,应该也会实现(或者即将实现或者已经实现了我不知道)这种功能吧.
感觉混合范式编程也是一种趋势.
[该贴被xiaoqianglinsen于2009-12-10 12:05修改过]

等scala的工具成熟些,就可以用scala了。

banq:你有几点让我奇怪.
1)辩论时候非常强势,好以专家口吻。
2)对新鲜事物保持强烈的关注。
3)能和各样技术背景的人交流,包括学生。
4)能够承认别人的优点,但总是要加上自己的“独特”见解。

1 不喜欢。
2,3 我比较钦佩。
4 部分认同。

i like scala