[C#3.0系列分享]Lambda表达式的前世今生

 

Lambda的前世

 

     假如您大学时代的 离散数学或者 编译原理 还没完全还给老师,那不妨看下下面的一段话:

 

    λ(Lambda演)算是一套用于研究函数定义、函数应用和递归的形式系统。它由 Alonzo Church 和 Stephen Cole Kleene 在 20 世纪三十年代引入,Church 运用 lambda 演算在 1936 年给出判定性问题 (Entscheidungsproblem) 的一个否定的答案。这种演算可以用来清晰地定义什么是一个可计算函数。关于两个 lambda 演算表达式是否等价的命题无法通过一个通用的算法来解决,这是不可判定性能够证明的头一个问题,甚至还在停机问题之先。Lambda 演算对函数式编程有巨大的影响,特别是Lisp 语言。

 

   Lambda 演算可以被称为最小的通用程序设计语言。它包括一条变换规则 (变量替换) 和一条函数定义方式,Lambda 演算之通用在于,任何一个可计算函数都能用这种形式来表达和求值。因而,它是等价于图灵机的。尽管如此,Lambda 演算强调的是变换规则的运用,而非实现它们的具体机器。可以认为这是一种更接近软件而非硬件的方式。

 

 

   看不懂 没关系,因为根本没必要看懂,就像饭馆的食客没必要会做菜一样,我们依旧可以把Lambda 吃得津津有味。

 

   匿名方法

 

C# 2.0推出了匿名方法,而Lambda表达式则是对匿名方法一个更简化的书写,同时也是匿名方法的一个超集。让我们先来复习匿名方法

 

(详细内容参见 )

 

 List<string> stringList = new List<string> { "Burke", "Connor", "Frank", "Everett" };

            stringList.ForEach(delegate(string item)

            {

                this.richTextBoxShow.AppendText(item+""n");

            });

 

在匿名方法中直接以一个 delegate申明一个委托,string item申明其接受一个string类型的参数,并可以在匿名方法代码块中使用。

 

Lambda表达式

 

再来看下Lambda表达式的用法

 

 List<string> stringList = new List<string> { "Burke", "Connor", "Frank", "Everett" };

            stringList.ForEach(item => this.richTextBoxShow.AppendText(item + ""n"));

其中 item => this.richTextBoxShow.AppendText(item + ""n")就是一个Lambda表达式,item是隐式申明的入参item的类型由编译器推断出, =>右侧就是一个表达式,也可以是一个代码块{     this.richTextBoxShow.AppendText(item + ""n");    }

 

 下面就来看看Lambda表达式的一种书写形式

 

   参数部分可以是隐式申明的,也可以是显示申明的

 

 (x) => int y = x + 1     //隐式申明

 (int x) => int y = x + 1      //显示申明

   当参数是一个是,()可以省略

 

 x => return y = x + 1 

 (x, y) => return z = x + y

代码块部分,当只有一句语句时,使用纯粹的表达时 就可以了,而超过两句,则需用代码块的形式

 

m => int z = m+2     //表达式

m => { int z = m +2; int y = z*z };   //代码块

 Lambda表达式是匿名方法的一个超集,相比匿名方法提供了更多的功能

 

 Lambda表达式允许参数类型被删除和推断,而匿名函数需要参数类型的显式声明。

 Lambda表达式的主体可以是一个表达式或者是一个声明块,而匿名函数的主体只能是声明块。

 Lambda表达式的主体可以是一个表达式或者是一个声明块,而匿名函数的主体只能是声明块。

Lambda的高阶用法

 

      Lambda最为匿名方法的超集,匿名方法所具有的内联参数等都是继承了的,那它的灵活性又怎么样呢?网上的资料似乎也只是把它当作写代码块的形式,那能不能玩出点花样呢?本着RD探索的精神,尝试了递归和嵌套的写法

 

   递归

 

   我尝试用Lambda表达式来完成一个分解质因数的算法

 

    LambdaDelegateVoidLong delegateVoidLong = null;

            delegateVoidLong = (m) =>

            {

                for (long i = 2; i <= m; i++)

                {//遍历 比自身的 小的数

                    if (m == i)

                    {

                        this.richTextBoxShow.AppendText(m.ToString() +""n");            //如果比对到自己,说明已经无法再 分解,则输出质因数

                    }

                    else //如果尚未比对到自己,则测试是否是自身的因数

                    {

                        long lest = m % i;

                        if (lest == 0)//如果是因数,则递归分解质因数

                        {

                            delegateVoidLong(m / i);

                            delegateVoidLong(i);

                            break;

                        }

                    }

                }

            };

            this.richTextBoxShow.AppendText("分解质因数" + MAX.ToString() + ""n");

            delegateVoidLong(MAX.Value);

在这段代码中,为了能自己调用自己,必须首先申明委托对象

 

LambdaDelegateVoidLong delegateVoidLong = null;

而不是象如下这样,在声明的 同时定义代码块,因为这样在代码块中调用自身的委托对象delegateVoidLong会报编译器错误 ,事先声明一下就OK了。由理由相信这是VS 2008 bate2版存在的编译器bug。

 

 LambdaDelegateVoidLong delegateVoidLong = (m) =>   { }

        

嵌套

 

 在Lambda表达式的数学含义就是定义函数的形式表达,Lambda 算子计算规则有alpha和beta。Alpha规则又叫转换(conversion)规则,而beta规则又叫简化(reduction)规则。

 

在 Lambda表达式中,变量的名字是不重要的,一次可以无限次转换和简化。冲着Lambda灵活的数学表达意义,原以为C#3.0Lambda表达式也能带来无限灵活的表达意义,但事实总是让人失望,至少目前的尝试是这样。

 

 LambdaDelegateIntIntInt delegateIntIntInt = (m, n) => {

                int z = (m + n);

                LambdaDelegateIntInt delegateIntInt = (f) => { return f + 1; };

                return delegateIntInt(z);

            };

            delegateIntIntInt(2, 3);

 在上面这段代码中,试图在一段Lambda表达式delegateIntIntInt中,套用另一个Lambda表达式delegateIntInt。因为参数只能是变量,而不能是表达式,因此如数学概念中的 (m, n)=>(m+n, m-n)=>{ m+n/m-n };的表达式至少目前是无法写出的。

转载于:https://www.cnblogs.com/OliveSky/archive/2008/08/16/1269277.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值