SICP 对面向对象和函数式程序的模块性有过一段评述。见 3.5.5 Modularity of Functional Programs
and Modularity of Objects
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5.5
脚注 76 对面向对象什么时候适用什么时候不适用的评述值得注意。
我自己的一点看法。
现实世界的对象用面向对象的方式来描述是更加容易,但并不一定是对对象的描述越直接就越好,有时候甚至是用直观的方式很难对问题进行描述。就像数学对问题的抽象有时候并不是那么直观,但在完成这一步抽象之后却能够使得问题得到简单的解决,或者是一个方法能够适用于很多的问题。
当然,当对问题的描述方式不是那么直观时,完成这一步抽象的困难也是必须要克服的。
因此无论是面向对象还是函数式的思维方式都有其优势和不足之处,然而结合这两者优点的思维方式还没有出现。
2008/10/18 fisher <wangq...@gmail.com>:
> 个人觉得 函数式编程 不太符合人的 思维方式,比较难掌握。 有种想法:会不会有一天 可以将 用面向对象思维 编写的程序 由 某种方式 转化成 由函数式
> 表示的 代码,再利用其 良好的 原子性 和 并发性。
>
--
Best regards,
Chen Yufei
不太明白你的意思,用函数式替代了什么?
2008/10/18 Jay True <gla...@gmail.com>:
> 嗯,你提到的函数式语言的优点,其实指的是纯函数式语言的优点,比如 haskell 。除此之外,还有别的种类的函数式语言,比如大家都知道的 lisp
> ,还有 OCaml 等,在这些函数式语言中,就有对变量的赋值,以及非惰性求值。
但要惰性求值基本上一定得是纯的才行,函数式语言没有惰性求值就不那么漂亮了。
>
> 总的来说,函数式语言区别于命令式语言的最大一点其实是,将函数作为语言中的一等公民来对待,以及通过函数的组合使用来达到求解问题的目的。
>
> 至于陈宇飞所提到的将用面向对象思维所写的程序转化成函数式的代码,我觉得没有必要,更现实一些的作法是两者的结合。当然,我说更现实,是因为已经有了这样的实例,比如
这个不是我的观点,明知道我对面向对象不感冒的。我说的是结合两种思考方式优点的方式还没有出现。
> scala 以及 ocaml 。而且在我看来,这两者并不是可以相互取代的存在,而是互补的存在。
>
> 所以,对于对函数式语言感兴趣的程序员,完全可以从 scala 和 ocaml 这类语言入手,并且这种语言也许会有更好的发展前景。
前景的话 Haskell 确实不会比 scala/clojure/ocaml 好。
>
> 2008/10/18 fisher <wangq...@gmail.com>
>>
>> 如果简单的替代的话,为何 要费很大的劳神 ,用函数式?
>
>
--
Best regards,
Chen Yufei
> 如果设计一个复杂的程序,就像 C 的设计者 要考虑考虑内存模型、和多线程,带来一些思维负担(这有现成的解决方法), 而函数式编程 将要考虑如何用
> 并不直观的的思维 方式 进行建模与实现,这也许将带来更大的思维负担。反倒不利于设计。
建模不会有太大区别,用fp也很容易写出OO的代码。而到了实现的时候,我想还是imperative
style会带来更大的思维负担: 它迫使程序员考虑howto,在一个比较低的层面上思考问题,而不是whatto.
参考Backus的turing lecture <<Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs>>, 很明确的指出了imperative style对思考方式的限制。
Thanks,
Jan
>
>
>
> 2008/10/19 Wei Hu <wei...@gmail.com>
>
> > 1. 你需要考虑内存模型、和多线程,这本身就不pure了。
> > 就算你说的那个函数是pure的,你无法保证所有函数都是pure的。Haskell从语言一级就保证了这一点。
> >
> >
--
jan=callcc{|jan|jan};jan.call(jan)
人们使用一门语言的时候倾向于使用它支持的最自然的编程方式,因此习惯于一门有足够抽象能力的语言的程序员倾向于不去学习新的语言,因为他们觉得没有必要。如果有这样的倾向就意为着你的思考方式可能被语言所影响了。
我不否定其他编程方式,但是局限于一种风格限制的是自己的视野。编程风格很多,其中函数式风格值得一学。而学习函数式风格最好的办法还是学习一门函数式的语言。
所有编程语言都是图灵等价的,但是我们还是在不停的发明新的语言来解决问题,原因在于不同的语言抽象能力不同,对问题的描述方式也不同。
类似的,用 C 也可以写出面向对象或者函数式风格的代码,但我们仍然创造出专门的面向对象语言和函数式语言,原因在于不同的语言本身适合的思考方式不同。很显然
,用 C 写面向对象或者函数式的代码不会那么令人愉快。(创造出这些新语言的人的 C 语言的功力肯定不在我们之下,如果他们觉得用 C
也能方便的写出其他风格的代码也不会自找麻烦弄新的语言出来,即使弄出来了也不会有这么多人去用。)
一门语言支持那种特定的编程方式很大程度上由其语法决定,好的语法可以使得代码更简洁,可读性更好,因而维护起来更简单。我在学习 Haskell
之后自觉的在 Python 代码大量使用 map/filter/partial/compose 等函数,这些函数很多情况下比嵌套使用 for
循环更加方便而不易出错(前提是习惯以后),但是 Python 没有对 partial/compose 这样的操作在语法上进行支持使我觉得在
Python 中写函数式的代码不那么愉快,不仅要多打字,可读性也比 Haskell 的代码差。(可想而知在 C 中写这样的代码会有多痛苦。)
语言还可以防止程序员犯错,就像静态类型,就像 GC,就像 Java 限制程序员使用指针。(Java
的例子并不太好,好的程序设计语言应该在避免犯错的同时不限制程序员能够做的事情。)纯的函数式语言确实是对程序员加了不少限制,有些限制可以减少错误的发生,而在这些限制的上也得到了其他的东西,比如惰性求值。
关于语言方面更多的思考推荐你看看 Paul Graham 的不少文章,我的很多想法是受他的文章的影响。关于编程的本质推荐看
SICP。还有另外一本书,Concepts Techniques and Models of Computer
Programming,或许比 SICP 更具体更容易些,用一门支持多种编程范式的语言 Oz
为例,介绍了各种编程范式,我只看过目录,很多人也推荐这本书。
其实不止是函数式,并发模型以及支持它的语言也值得学习。The Pragmatic Programmer 中推荐程序员每年学习一门新的语言是有道理的。
如果说这些还不够的话那再推荐你看看李笑来老师的文章,比如这篇
http://www.xiaolai.net/index.php/archives/687.html
有些事情有没有好处只有做了才知道,也有些事做了是肯定有好处的。做事太考虑结果或许会错过一些很好的机会。这个扯远了。
2008/10/19 fisher <wangq...@gmail.com>:
> 抱歉,没有, 没有理解它所带来的好处之前,没有去学习它的动力。或许您可以举一些例子让我们这些还有疑问的人理解。
>
--
Best regards,
Chen Yufei
赞推荐!
Backus 发明了 Frotran,没弄错的话他后来却一直都是支持函数式编程的。
再次缅怀下大师级的人物。
>
> Thanks,
> Jan
>
>>
>>
>>
>> 2008/10/19 Wei Hu <wei...@gmail.com>
>>
>> > 1. 你需要考虑内存模型、和多线程,这本身就不pure了。
>> > 就算你说的那个函数是pure的,你无法保证所有函数都是pure的。Haskell从语言一级就保证了这一点。
>> >
>> >
>
> --
> jan=callcc{|jan|jan};jan.call(jan)
>
--
Best regards,
Chen Yufei
再次重复之前说过的,对现实世界的直观描述并不一定导致最好的解决问题的办法。换个描述方式问题或许就明朗了。
换个描述本身并不难,难的是找到能简化问题解决的描述。有些时候 OO 的描述可以简化问题,有些时候函数式可以,有些时候可能是其他的描述方式。
把现实世界用函数式的风格进行描述不是太难,只是需要花时间习惯,就像学习 OO 一样。
> 目前的比较热门的程序设计语言 并没有什么太大的差别。
我不知道什么是第二类问题。冷门的程序设计语言或许就有大的差别。
如果你看过 Project Euler 上有人用 J 写的代码的话就会感叹语言的差别实在是太大了。
http://www.math.chalmers.se/~rjmh/Papers/whyfp.html
里面用的语言是 Miranda (不知道这个名字是不是来自作者 David Turner 的某女友或者女儿)。有人哟故 Haskell 写了另外的一个版本。
看过以后如果你赞叹文中程序本身的优雅的话就学学吧,如果觉得这些例子没什么实用价值的话就算了。
个人认为代码是有优雅和丑陋之分的,要是从来没有过这种感觉只在乎是否实用的话我没什么好说的了。
2008/10/19 Jay True <gla...@gmail.com>:
> 纯粹的计算吗,了解过 pugs 这个项目吗,没有的话可以去了解一下。
呵呵,真像是你的口气。
>
> 2008/10/19 fisher <wangq...@gmail.com>
>>
>> 陈 你好:
>> 感谢推荐了几本 好书。
>> 函数式 思维方式 和 面向对象式 很不一样,对于拓展锻炼思维也许很有好处。我所质疑的是他实用性(程序员是否 容易 理解 接受 并最终应用,
>> 它是否能方便的做出有用的产品), 如果暂时不能,那仅仅是很酷的思维方式,恕我 孤陋寡闻 , 我所看到的FP 例子 和 教程 仅仅是 纯粹的计算。
不是纯粹的计算,real world haskell 里面就有很多实际的例子。
不是不能,Haskell 的话 pugs, darcs 就是例子,Linspire 的包管理器是用 Haskell 写的。ITA 内部是用
Common Lisp 的。gnumeric 扩展是用 Scheme 的。mldonkey 是用 ocaml 的。
总的来说函数式语言的项目不多,实用还不够广泛,但语言的质量高低和流行度没有绝对的联系。
我自己也觉得 Haskell 不会被很多人接受,至少得改头换面成 F# 那种样子才可能成为 popular language。而且
Haskell 作为研究型的语言要 avoid success at all cost (Simon Peyton Jones
原话),用户太多就不能方便的进行演化。好在现在的 Haskell
都是自愿选择这门语言,即使有变化大家也不会太抱怨,但其实它现在的流行程度到了已经有人开始抱怨 library 的变化导致的问题。
但即使在工作中没有直接使用 FP 语言的机会,但通过学习 FP
而开阔了视野这本身就已经值得了。你要那么在乎目的实用性自己一点时间都不投入的话就算了,多说也没用。
天天用, hehe
* fisher <wangq...@gmail.com> [2008-10-19 13:26:12 +0800]:
--
jan=callcc{|jan|jan};jan.call(jan)
fisher,我说一下:
你说:
>如果所要问题的规模不变,那么所需处理的状态不会因为 用什么语言而带来减少。总是去想what to do ,最终也要 有 howto 实现才行,回避不了的。
其实不是这样的。举个物理学中的例子,高中的时候经常会有这种题,让我们计算有好几个因素影响下的一个系统我们做了多少功之类的,如果采用F=Ma这个方式去算,可能维度很多,涉及到微积分之类的方式,可是如果用能量守恒定律的话,或许我们就可以简单的得出结果了,因为我们不再纠缠于细节,而是直接把握其实质。
或许这个例子不怎么恰当,但是我觉得它有点用。
函数式编程就是要我们不要去想如何去做,而是想规律是什么,也就是说,我们不需要给出步骤的描述,我们给出规则的描述。不给出动作,只给出关系。a = b + c在命令式语言中看做一个执行操作,一个动作,在函数式语言中看做一个规则,一个关系,一个永恒不变的东西。
* up duan <fix...@gmail.com> [2008-10-19 22:17:46 +0800]:
忍不住想说你在"诡辩":)。
或许你知道我在说什么而故意混淆,或许你由于世界观的缘故对我的看法根本看不入心,无论如何,你用动作+状态变化来概括你世界中的程序,并不能断定别人用关系和规则概括别人世界中的程序是错误的。
而你扯到不知所云的软件工程,更是拿出《人月神话》这个大棒槌来指责我,我觉得很是诡异。
我想Haskell应该是一个PureFP吧,Pugs不知道算不算是一个程序呢?
说实话:
> ……我觉得采用 (FP语言中 与指导思想相矛盾但又离不开的技术)比较本分一点。
这句话我确实没有理解:(。
Some functional languages extend their purely functional core with side effects. The programmer must make sure himself that he doesn't use impure functions in places where only pure functions are expected.
Another way of introducing side effects to a pure language is to simulate them using monads. While the language remains pure and referentially transparent, monads can provide implicit state by threading it inside them. The compiler does not even have to 'know' about the imperative features because the language itself remains pure, however usually the implementations do 'know' about them due to the efficiency reasons, for instance to provide O(1) mutable arrays.
Allowing side effects only through monads and keeping the language pure makes it possible to have lazy evaluation that does not conflict with the effects of impure code. Even though the expressions are evaluated lazily, some parts of them are forced by monads to be evaluated in a specific order and the effects are properly sequenced.
2008/10/20 up duan <fix...@gmail.com>:
--
Best regards,
Chen Yufei

* Yufei Chen <cyfd...@gmail.com> [2008-10-20 07:48:23 +0000]:
--
jan=callcc{|jan|jan};jan.call(jan)
我不知道Fisher为什么非要选择性失明。
Haskell是Pure的。而不是non Pure的。或许你觉得IO一定要用状态才能描述,可是哪只是你的世界观,Monad也可以描述的。
而Monad其实是Pure的。我想你应该先仔细看看它们怎么通过lamdba和high order模拟出你关注的state再考虑对Haskell纯与不纯做个判断吧。
看来你来兴致了。很好,加油,我看好你哦!
2008/10/20 Jay True <gla...@gmail.com>:
看来你没写过 FP 的代码但对其基石有所了解啊?原来是学院派的。愿闻其详,再解释下为啥是充满未知性的吧。
http://en.wikibooks.org/wiki/Haskell/Category_theory
>
> @fisher
>
> 你再拿 pure 不实用来说事我可跟你急哈,话说我已经跟你说过 N 多遍就算是 side effect 也可以通过 pure 的方式来实现啊。
可以看到 Haskell 的接受率肯定不会高的,好在这样它就可以不断演化了。不过还是赞你如此的努力。
2008/10/20 Jay True <gla...@gmail.com>:> 靠,鄙视我,我本来就很幽默的好不好。
嗯,是本来就很好,不过很少展示忽略掉了。
>category theory,以前看到说是群论的一个分支。你也看过下面这篇文章吧
> 话说 lambda calculaus
> 是跟图灵机等价还是跟冯氏图灵等价来着。貌似是前者,但不管怎样,这个基石很"充满未知性"吗?我怎么不知道?现代计算机的理论基石是图灵机吧,那图灵机是不是"充满未知性"的呢?
>
> 再有,这个理论基础跟 FP pure 不 pure 没什么关系吧,只要是 FP 都是建立在 lambda calculus 的基础上的吧。
>
> haskell 的另一个理论基础,我知道的就是 category 什么的了,可那也跟 pure 不 pure 没关系啊,那个是 haskell
> 类型系统的基础。
http://en.wikibooks.org/wiki/Haskell/Category_theory
>可以看到 Haskell 的接受率肯定不会高的,好在这样它就可以不断演化了。不过还是赞你如此的努力。
> @fisher
>
> 你再拿 pure 不实用来说事我可跟你急哈,话说我已经跟你说过 N 多遍就算是 side effect 也可以通过 pure 的方式来实现啊。
wikipedia 上只提到 Haskell 的类型推断系统是 Hindley-Milner
的一个版本(这个我不懂,记得你看过类型系统方面的书,应该比我清楚),但是没有提它本身的类型系统是不是基于 category theory。
2008/10/20 Jay True <gla...@gmail.com>:
那篇讲 category theory 的文章在谈 functor 和 monad 之前把 haskell 中的类型作为 category
的 object,而函数作为 morphism,而 haskell 语言级别上还有 composition 的记号,所以感觉至少
haskell 的类型"标注"方式基于 category theory。
之前我凭感觉得到的说法一直没有找到官方的说法,原来就是错的……
2008/10/20 Wei Hu <wei...@gmail.com>:
> type theory 和 category theory基本上还是正交的,我觉得后者更难理解一些。category theory主要是作为
> monad、functor之类的理论基础,和类型的关系倒不大。
>
> On Oct 20, 7:54 am, "Yufei Chen" <cyfde...@gmail.com> wrote:
>> 那篇文章也没有这么明显的说,我只能 90% 的确定,所以想问你。
>>
>> wikipedia 上只提到 Haskell 的类型推断系统是 Hindley-Milner
>> 的一个版本(这个我不懂,记得你看过类型系统方面的书,应该比我清楚),但是没有提它本身的类型系统是不是基于 category theory。
>>
>> 2008/10/20 Jay True <glac...@gmail.com>:
>>
首先它的目的是研究性的,而你的目的看来是实用巨多,虽然 Haskell 也能写出实用的东西,但它肯定不适合你。你不会喜欢 category
theory, type theory, monad, monad transformer, type inference, STM
等等一系列东西的,所以你不合适。
其次,你是要当将军的人,而我们是喜欢写优雅代码的人。大家站的层面不同,考虑问题的方式不同,谈不来的。
嗯,我们说了那么多最终被你证明是在浪费时间而已,所以算了。
2008/10/21 fisher <wangq...@gmail.com>:
--
Best regards,
Chen Yufei
根据Fisher的说法,总是让我想起以前有人说C不过还是汇编,就是加了语法糖而已,C++还是C,不过加了语法糖而已。呜呼……
根据anderson的说法,OO【单指实现啊】不过就是语法糖而已,为什么我们允许OO,而不允许lambda?【注:有人就lambda引入C#质疑anderson,说不过就是匿名委托而已云云】,提供lambda明显能让抽象【表达能力】提升一个层次,可是就是有人忽略这一点。
如果关注经济利益,就应该看到Haskell提供一个PureFP带来的表达能力能够提升我们表达现实问题的能力,可以以更高的性价比提供软件,符合人类社会发展的方向:)。
当然,未来未必是Haskell的,也未必是PureFP的,但是,我们至少应该保持心态开放不是!