本来是这篇帖子里孟岩老大的评论。因为在评论里不好加链接和格式,就贴在这里了。
不错,语言设计不光是提供一堆功能。设计语言的时候我们得仔细细考必须舍弃什么功能,以便用户们轻易地理解语言的设计思路。一门语言不仅帮助用户解决问题,也引导用户沿着某种统一的思路或风格来运用这门语言。从这个角度来说,孟岩老大担心“面对同一个问题的可能方案越来越多,彼此差异越来越大。。。共同价值观消失”是非常有道理的。不过我们到底该欢迎还是拒绝closure这个功能呢?至少从我个人的角度,closure这个功能给程序员带来的好处远远超过随之而至的开销。关键是,closure为程序员提供了新的(相对于Java)抽象机制:我们可以自然地抽象出行为。想想我们有多少和行为相关的模式?如果我们能用更加简洁,更加直观的方式解决我们的问题,何乐而不为呢?Java的Closure并不是一个用来补充现有的功能(比如匿名类)的小改进,而是一个全新的功能,用来弥补Java语义的残缺(强烈推荐那篇“名词的王国”),用来替代先天不足的匿名类。不然的话,我们都不能写出简洁的map和reduce这些非常好用的函数。举个例子,我们可以用Java试试实现 (1..5).map{|i| i * i}。再举个和map/reduce无关的:用Java实现一下用牛顿迭代找平方根。下面是JavaScript的解法。
function sqrt(x){
function sqrt_iter(guess){
if (good_enough(guess)){
return guess;
}
return sqrt_iter(improve(guess));
}
function improve(guess){
return average(guess, x / guess);
}
function average(x, y){
return (x + y) / 2 ;
}
function good_enough(guess){
return Math.abs(guess * guess - x) < 0.001 ;
}
return sqrt_iter( 1.0 );
}
关于closure的强大功能,John Hughs的论文是很好的注解。这里有中文版。
最后说一下C#3.0里加的新功能。孟老大也许不了解,微软并不是出于对动态语言的热爱而加入那么多动态语言的特性。微软为了简化对数据的操作,提出了LINQ(有兴趣的可以到这里看看。有了LINQ,(1..5).map{|i| i * i}可以写成:
var result = from n in [1, 2, 3, 4, 5] select n * n
要实现LINQ这些功能,closure就必不可少了。比如说,那些查询操作符(比如from 和 where)都是普通的函数。那我们怎么传给它们不同的条件呢?当然是匿名函数了,也就是我们的closure。