当前位置:  开发笔记 > 编程语言 > 正文

C#lambda - 咖喱用例

如何解决《C#lambda-咖喱用例》经验,为你挑选了2个好方法。

我读了这篇文章,我发现它很有趣.

总结那些不想阅读整篇文章的人.作者实现了一个名为Curry的高阶函数(由我重构而没有他的内部类):

 public static Func> 
             Curry(this Func fn)
 {
     Func, Func>> curry = 
     f => x => y => f(x, y);
     return curry(fn);
 }

这使我们能够采用像F(x,y)这样的表达式.

Func add = (x, y) => x + y;

并以F.Curry()(x)(y)方式调用它;

这部分我理解,我觉得它很酷,以一种令人讨厌的方式.我无法解决的问题是这种方法的实际用途.何时何地需要这种技术以及可以从中获得什么?

提前致谢.

编辑:在最初的3个响应之后,我理解增益将是在某些情况下,当我们从curried创建一个新函数时,一些参数不会被重新评估.我在C#中进行了这个小测试(请记住,我只对C#实现感兴趣,而不是一般的咖喱理论):

public static void Main(string[] args)
{
    Func concat = (a, b) => a.ToString() + b.ToString();
    Func> concatCurry = concat.Curry();
    Func curryConcatWith100 = (a) => concatCurry(100)(a);

    Console.WriteLine(curryConcatWith100(509));
    Console.WriteLine(curryConcatWith100(609));
}

    public struct Int
    {
        public int Value {get; set;}

        public override string ToString()
        {
             return Value.ToString();
        }

        public static implicit operator Int(int value)
        {
            return new Int { Value = value };
        }
    }

在连续2次调用curryConcatWith100时,对值100的ToString()求值被调用两次(每次调用一次),所以我在这里看不到任何评估增益.我错过了什么吗?



1> Cameron MacF..:

Currying用于将具有x参数的函数转换为具有y参数的函数,因此可以将其传递给需要具有y参数的函数的另一个函数.

例如,Enumerable.Select(this IEnumerable source, Func selector)使用带有1个参数的函数.Math.Round(double, int)是一个有2个参数的函数.

您可以使用currying将Round函数"存储" 为数据,然后将该curried函数传递给Select类似的函数

Func roundFunc = (n, p) => Math.Round(n, p);
Func roundToTwoPlaces = roundFunc.Curry()(2);
var roundedResults = numberList.Select(roundToTwoPlaces);

这里的问题是,还有匿名委托,这使得currying多余.事实上,匿名代表一种讨论形式.

Func roundToTwoPlaces = n => Math.Round(n, 2);
var roundedResults = numberList.Select(roundToTwoPlaces);

甚至只是

var roundedResults = numberList.Select(n => Math.Round(n, 2));

考虑到某些函数语言的语法,Currying是解决特定问题的一种方法.使用匿名委托和lambda运算符,.NET中的语法更简单.



2> AnthonyWJone..:

更容易首先考虑fn(x,y,z).这可以通过使用fn(x,y)进行计算,给出一个只接受一个参数z的函数.无论单独使用x和y需要做什么,都可以通过返回函数所持有的闭包来完成和存储.

现在,您使用z的各种值多次调用返回的函数,而不必重新计算所需的x和y部分.

编辑:

咖喱有两个理由.


参数减少

正如Cameron所说,将一个带有2个参数的函数转换为仅占用1的函数.使用参数调用此curried函数的结果与使用2个参数调用原始函数相同.

由于Lambda存在于C#中,因此它们的价值有限,因为它们无论如何都能提供这种效果.虽然你使用的是C#2,但你问题中的Curry函数有更大的价值.

分段计算

咖喱的另一个原因就像我之前所说的那样.当最终参数被提供给curried函数时,允许复杂/昂贵的操作被分阶段并重复使用几次.

这种类型的currying在C#中是不可能实现的,它确实需要一种功能性语言,可以原生地模拟它的任何功能来实现.


结论

通过你提到的Curry参数减少在C#2中是有用的,但由于Lambdas在C#3中被大幅度减值.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有