函数式编程学习之路(五)

    荆棘:

刚开个头,身体就出点小毛病,这充分说明,这玩意必须吃透不可,遇到困难就放弃,那么以后可能也没办法再提高了.

零零碎碎查不少资料,泛泛看了些东西,先记下来.

首先,传统C#是没有闭包的.但有了匿名函数和Lambda后,就有了这个东东.

public class TCloser
{
    public Func<int> T1()
    {
        var n = 999;
        return () =>
        {
            Console.WriteLine(n);
            return n;
        };
    }
}

class Program
{
    static void Main()
    {
        var a = new TCloser();
        var b = a.T1();
        Console.WriteLine(b());
    }
}

C#再通过委托(直接用不方便),加泛型,定义了Func<T, TRusult> 这的东西, 间接的完成了函数传入及返回.

最后通过Lambda表达式,实现了函数式编程所需要的基本东西.

当然,C#是强类型的,所以为了达成目的又加了些东西,C#4.0加入了in(逆变), out(协变),当然了字面意思,文档,教科书等都把这种简单思想搞太复杂.好在本人懂面向对象啊.也懂点什么叫强类型.具不想用弱类型,又想实现类型推导.

 

逆变允许方法具有与接口的泛型形参所指定的实参类型相比,派生程度更小的实参类型。 

协变允许方法具有与接口的泛型类型参数所定义的返回类型相比,派生程度更大的返回类型。

说穿了,就是为了隐式转换,作为参数,我们假想下,底层编译成IL时,根据定义,去查找定义的类型,in一般作为参数修饰 找最顶层的,比如object, 这样什么参都可以传入, out找最底层的.这样返回的变量,很容易匹配 ,比如object = out TResult

还是那句老话,简单的东西,搞这么复杂,MS的这些人,过犹不及, 在这种地方不用弱类型,目的无非是在VS编辑器里可以. 出来.让用户更傻瓜化,花更多的钱去买,然后使用更人工复杂化的东西.天下没有免费的午餐,不迷信权威,是提高的不二途径.

Y组合子:

static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f)
{
return x => f(Fix(f))(x);
}

static Func<T1, T2, TResult> Fix<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> f)
{
return (x, y) => f(Fix(f))(x, y);
}

有了泛型,Func, in, out, Y组合子也有了.看上去C#函数式编程问题不大了(可能不够直观,但起码可用)

再来点简单直观的

Func<int, int> fun = (int x) => x * x;

算是有个fun的变量(或函数符号)了,因为函数式编程,是没有变量,没有副作用的.

通过这里我们可以看到,fun是个函数,或一个算法,本身是个概念,或者一个规则,这里的规则,就是完成乘这个概念.

最后,当我们把大量的东西概念化(函数化)后,我们得到了大量不可变的概念,规则.这就是所谓的"声明式编程".

Func<int, int, int> addition = (int x, int y) => x + y;
Func<int, int, int> subtraction = (int x, int y) => x - y;
Func<int, int, int> multiplication = (int x, int y) => x * y;
//计算 x = 1 + 2 * (3 - 1)
int result = addition(1, multiplication(2, subtraction(3, 1)));

看上去还不错,但这个玩意和传统函数调用没两样,还需要具体深入.

看着就不象函数式编程.

posted @ 2013-04-18 23:27  人工智能-群513704292  阅读(464)  评论(0编辑  收藏  举报