This Is It
Friday, October 30th, 2009晚上和LP去电影院看了”This Is It”。老实说,我不是MJ的粉丝,于是对该电影也没什么期待,但看完之后我相信:这是一部值得珍藏的电影。
MJ 无疑是同时代艺术家中的佼佼者,天才的出现是一个时代的光明,但光芒四射下的自己终究早早的化为灰烬。值得欣慰的是,我们看见一大批沐浴在星光中的追随者始终带着坚定的信仰,在前人的鼓舞和激励下继续前进。这种精神的传承和延续是最为珍贵的,也是我们这个时代、这个国度最为缺乏的。
晚上和LP去电影院看了”This Is It”。老实说,我不是MJ的粉丝,于是对该电影也没什么期待,但看完之后我相信:这是一部值得珍藏的电影。
MJ 无疑是同时代艺术家中的佼佼者,天才的出现是一个时代的光明,但光芒四射下的自己终究早早的化为灰烬。值得欣慰的是,我们看见一大批沐浴在星光中的追随者始终带着坚定的信仰,在前人的鼓舞和激励下继续前进。这种精神的传承和延续是最为珍贵的,也是我们这个时代、这个国度最为缺乏的。
正在对着屏幕写代码的时候,忽然听到背后core说他老婆最近在看《宫心计》,并引用嫂子的说法,称其为继《金枝欲孽》后又一TVB热剧。吾顿时如遇知音,吼道:俺LP也是这么说的!然后旁边Rocky同学丢出了一句:我老婆也在看。OMG! 我来我们都”被”TVB粉了。这三个随机样本观测值可以明显支持一个结论:占领了女性市场就等于占领了男性市场,要抓住那人的心只要抓住女人的心。
不过我是不喜欢看宫廷斗争、尔虞我诈的,再昏庸的皇帝都是圣明的,在悲惨的宫女也要恪守所谓”本份“,并因为皇帝的一个不经意的眼神而幸福不已 — 不知道这是否也是”斯德哥尔摩综合症”的体现。
前一篇文章中缺乏示例,一眼看下去可能不太好理解。这次用几个简单的例子说明一下。
“Pure”总是和下面几个词联系在一起:”referentially transparent”,”no side-effect”。基本上来说,它们表达的同一个意思。直观的意思就是:给定相同输入,一定会得到相同的输出结果。更正式一点的说法就是:给定一个函数f,把所有调用f的地方换成该调用的结果不会改变程序的意义。举个例子:假如f(3) = foo,把程序总所有调用f(3)的地方换成foo不会改变程序的结果,反之亦然。
更具体一点的例子,假设有个C函数,如下:
int add(int x, int y) { return x + y; }
显然,它是个没有side-effect的函数。好了,现在多了个需求:统计”add”函数的执行次数。这在允许side-effect的语言(如,C/C++等大多数主流语言)中简直是小菜一碟,加个全局变量就行:
static int count = 0;
int add(int x, int y) { count++; return x + y; }
注意:此时add函数已经是个具有side-effect的函数了。我们无法把程序中所有出现add(1,2)的地方都替换为3!作为一个side-effect,该函数还修改了count的值。做了替换之后,将使得我们统计执行次数的努力付诸东流。
那么,在Haskell之类的纯函数式语言中,如何做到这种统计功能呢?最先的add函数可以写出如下方式:
add x y = x + y
因为不允许side-effect[1],那么最简单的方式就是引入一个额外的参数作为初始的调用次处,然后add每次都返回更新后的调用次数:
add x y cnt = (x + y, cnt + 1)
郁闷的是,这样一来函数add的输入、输出都修改了,程序中所有调用到该函数的地方都要做相应修改。不过千万不要气馁,Haskell中提供了解决之道 - Monad。
[1] 对于习惯print调试大法的程序员来说,很可能会不习惯Haskell,因为向一个pure的函数中添加print语句是不允许的。Haskell用Monad来分隔pure/impure的行为。似乎这也是一些程序员选择OCaml/Standard ML而放弃Haskell的原因之一。但Pure的系统中,编译器有更多空间去做并发方面的优化。
在函数式编程领域有所谓Pure和Impure之分。简单来说,两者之间的区别就是Impure是有side-effect的,比如:赋值、异常和continuations;而Pure则意味着对于一个函数来说相同的输入一定会产生相同的输出,函数中也没有赋值操作这些用以改变某个状态的行为。Scheme和Standard ML是Impure的,而Miranda和Haskell则选择了Pure。
Pure有一个优点就是计算不依赖于执行顺序,因而可以容易的达到较好的并发性能、以及实现惰性求值(Lazy Evaluation);而Impure则使得程序更直观、紧凑。比如,有个函数foo(),如果我们要修改它,得到整个程序中foo()的执行次数。在Impure系统中,这相当容易:添加一个变量记录foo()的执行次数即可。在Pure家族,这就不是如此简单了,我们可能需要修改foo的输入和输出:在输入中记录已经执行的次数,而输出中返回更新的次数 — 而且糟糕的是,我们需要修改所有涉及到foo()调用的地方。
有人会想,我写个程序不就是为了得到某些输出吗?如果一个语言都不能改变状态(显然,输出涉及到屏幕状态的改变),那又有何用?如果读者以为Pure实在是没啥搞头,那就言之太早了。在Haskell中,程序员喜欢用Monad来模拟以上所有Impure的行为。
Dr. Erik Meijer 在MSDN Channel9上开设了Functional Programming Fundamentals,总共13次课,目前已经完成4课视频,并有各种格式可供免费下载。想了解函数式编程的同学不妨移步一观,课程基于Haskell,内容流畅且富有洞察,一定会有所获。
Erik提到了一个有趣的观点,那就是IDE的发展在OOP语言很成熟,而FP则相对较弱 — 这和语法有很大关系。OOP的中心是object,而FP的重点则都在function。比如OOP中常有如下语法形式:
object.function(parameters)
而函数式编程中则有如下形式:
function(parameters)
IDE可以利用”.”操作符去提示一个object里都有哪些函数。这是一个历史的偶然,却改变了很多人的编程习惯(如果习惯于IDE的话)。