Visual Studio 2008正式发布了,我们。NET开发者也走进了新的。NET 3.5时代。相对于。NET 3.0中的Foundations,3.5的改进更注重编码体验了。新的Linq系列语法和Linq to Sql、Linq to Xml大大改变了我们访问数据的方式。但是纵观Linq系列语法,影响最大的要数Lambda表达式。虽然从渊源来讲Lambda表达式就是匿名函数的简化表示方法,但谁也想不到这一小小的语法给我们带来了整个Linq与众不同的查询式语法。
Linq这种类似于SQL的语言,含有很多通常我们传统语言所不具备的要素。比如我们可以用一条语句将规则作用于整个集合之上,而规则则是通过表达式来传递的。也就是说我们编写这样的语句时,查询中的表达式并不立即执行,而是之后对整个集合的每个元素进行分别调用。这里面一个重要的思想就是我们将运算规则传递给了查询语句,而不是表达式的值或结果。这种思想在函数式语言中尤为重要,我们通过函数为媒介,用组合与递归的方式将运算规则逐渐抽象为一个完整的应用程序。
当然,整个函数式编程范式与我们所熟悉的命令式语言都是不同的,这里我们仅讨论函数式编程的一些思想,希望能够启发思考,或作为命令式编程的一种补充来使用。其实我们在编写Linq代码中已经用到了函数式编程的思想:
int[] a; a.Where(i => i > 0).Select(i => i * 2); |
这里,Where函数将我们用Lambda表达式传递的运算规则作用于a[]的每一个元素上,然后返回满足条件的所有元素。这就是一种筛选操作。而Select函数则将规则作用于集合的每一个元素后返回新值组成的集合。这是一种映射操作。C#简短的Lambda语法为我们编写类似的逻辑提供了很大的方便。不过呢,从下面开始,我将使用Visual Basic 2008的Lambda表达式继续讨论。有人可能奇怪为什么不继续使用C#了呢,下面我就会介绍VB2008编写函数式编程的独特之处。即使您用C#,我仍建议您往下看完,您会看到有些程序用VB来写更容易想清楚;而C#的对应做法下面也会有小小的挑战等着您。
首先我们熟悉一下VB2008的Lambda表达式语法。它由两个部分组成:
Function(参数列表)表达式
Function(a) a + 1 '等于C#的 a => a + 1 Function(a As Integer) a + 1 '显式指定类型 Function(a, b) a + b '两个或多个参数 |
如您所见,和普通的函数声明相比,它只是没有函数的名字,以及不需要使用Return语句而已。注意VB的Lambda表达式只能使用单行表达式作为函数体,而且必须有返回值,C#的Lambda表达式是没有这些限制的。接下来就是重头戏,VB2008的Lambda表达式拥有一些C#3.0所不具备的突出特性,使得它成为我们学习函数式编程的首选:
1.匿名委托特性
VB2008支持一种称作匿名委托的特性。请不要和匿名函数的概念弄混,有些人喜欢把C#的匿名方法教成匿名委托,实际上两者并不相同。VB2008可以根据Lambda表达式的签名,自动生成委托的定义。也就是说在VB中使用Lambda表达式,不用事先声明接受它的委托类型。这使得VB的Lambda表达式更像变量,而不是函数。
| Dim f = Function(i) i + 1 '无需声明f的类型,它自动从Lambda表达式推导 f(2) '调用,结果为3 |
而C#则需要显式定义委托的类型,是不能用var f = (int i) => i + 1;的形式来定义Lambda表达式变量的。后面我们会看到Lambda表达式的类型令人惊奇地复杂,以至于要显式声明有时会过于困难。而且匿名委托带来的好处绝不仅仅只有这一点……。

