jjzjj

C# Linq 与柯里化(Currying)

coder 2024-05-20 原文

我正在研究函数式编程及其各种概念。所有这些东西都很有趣。我已经多次阅读有关 Currying 及其优势的文章。

但我不明白这一点。以下源代码演示了 curry 概念的使用和 linq 的解决方案。实际上,我没有看到使用柯里化(Currying)概念的任何优势。

那么,使用柯里化(Currying)有什么好处呢?

static bool IsPrime(int value)
{
    int max = (value / 2) + 1;
    for (int i = 2; i < max; i++)
    {
        if ((value % i) == 0)
        {
            return false;
        }
    }
    return true;
}

static readonly Func<IEnumerable<int>, IEnumerable<int>> GetPrimes = 
        HigherOrder.GetFilter<int>().Curry()(IsPrime);

static void Main(string[] args)
{
    int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

    Console.Write("Primes:");
    //Curry
    foreach (int n in GetPrimes(numbers))
    {
        Console.Write(" {0}", n);
    }
    Console.WriteLine();

    //Linq
    foreach (int n in numbers.Where(p => IsPrime(p)))
    {
        Console.Write(" {0}", n);
    }

    Console.ReadLine();
}

这是高阶过滤方法:

public static Func<Func<TSource, bool>, IEnumerable<TSource>, IEnumerable<TSource>> GetFilter<TSource>()
{
    return Filter<TSource>;
}

最佳答案

what is the advantage of using currying?

首先,让我们澄清一些术语。人们使用“currying”来表示两者:

  1. 将两个参数的方法重新表述为一个返回一个参数的方法的一个参数的方法
  2. 部分应用两个参数的方法生成一个参数的方法

显然,这两项任务密切相关,因此容易混淆。在正式发言时,应该将“currying”限制为指代第一个定义,但在非正式发言时,这两种用法都很常见。

所以,如果你有一个方法:

static int Add(int x, int y) { return x + y; }

你可以这样调用它:

int result = Add(2, 3); // 5

你可以 curry Add方法:

static Func<int, int> MakeAdder(int x) { return y => Add(x, y); }

现在:

Func<int, int> addTwo = MakeAdder(2);
int result = addTwo(3); // 5

部分应用有时也被非正式地称为“currying”,因为它有明显的相关性:

Func<int, int> addTwo = y=>Add(2,y);
int result = addTwo(3);

你可以制造一台机器来为你完成这个过程:

static Func<B, R> PartiallyApply<A, B, R>(Func<A, B, R> f, A a)
{
    return (B b)=>f(a, b);
}
...
Func<int, int> addTwo = PartiallyApply<int, int, int>(Add, 2);
int result = addTwo(3); // 5

那么现在我们来回答您的问题:

what is the advantage of using currying?

这两种技术的优势在于,它可以让您更灵活地处理方法。

例如,假设您正在编写路径查找算法的实现。您可能已经有了一个辅助方法,可以为您提供两点之间的大致距离:

static double ApproximateDistance(Point p1, Point p2) { ... }

但是当你实际构建算法时,你经常想知道的是当前位置和固定终点之间的距离是多少。算法需要的是Func<Point, double> -- 从该位置到固定终点的距离是多少?你拥有的是Func<Point, Point, double> .你打算如何把你所拥有的变成你所需要的?部分应用;您部分地将固定端点作为近似距离方法的第一个参数应用,并得到一个与您的路径查找算法需要消耗的内容相匹配的函数:

Func<Point, double> distanceFinder = PartiallyApply<Point, Point, double>(ApproximateDistance, givenEndPoint);

如果首先柯里化(Currying) ApproximateDistance 方法:

static Func<Point, double> MakeApproximateDistanceFinder(Point p1) { ... }

那么您就不需要自己进行部分应用;你只要调用MakeApproximateDistanceFinder有了固定的终点,你就完成了。

Func<Point, double> distanceFinder = MakeApproximateDistanceFinder(givenEndPoint);

关于C# Linq 与柯里化(Currying),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8826266/

有关C# Linq 与柯里化(Currying)的更多相关文章

  1. c# - Ruby 等效于 C# Linq 聚合方法 - 2

    什么是Linq聚合方法的ruby​​等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj

  2. C# 的 LINQ 用于在 ruby​​ 中等效的集合操作 - 2

    我是ruby​​开发的新手,我目前正在使用rails2.3.11在ruby​​1.8.7中开发一个项目,我想知道这种语言是否有与C#的linq等效的集合操作,例如where子句。谢谢。 最佳答案 Ruby中Linq的where等价于find_all检查documentationfortheEnumerableModule用于其他功能。 关于C#的LINQ用于在ruby​​中等效的集合操作,我们在StackOverflow上找到一个类似的问题: https://

  3. ruby - 在 Ruby 中使用关键字参数柯里化(Currying) proc - 2

    假设我有一个通用的Proc、Lambda或method,它带有一个可选的第二个参数:pow=->(base,exp:2){base**exp}现在我想柯里化(Currying)这个函数,给它一个3的exp。cube=pow.curry.call(exp:3)这里有一个歧义,由关键字参数和新的散列语法引起,Ruby将exp:3解释为作为第一个参数传递的散列,base.这导致函数立即被调用,当#**被发送到散列时呈现NoMethodError。为第一个参数设置默认值同样会导致函数在柯里化(Currying)时立即被调用,如果我将第一个参数标记为必需,而不提供默认值:pow=->(base:

  4. ruby - Ruby 中的简单柯里化(Currying) - 2

    我正在尝试用ruby​​进行一些柯里化(Currying):defadd(a,b)returna+bendplus=lambda{add}curry_plus=plus.curryplus_two=curry_plus[2]#Line24putsplus_two[3]我得到了错误func_test.rb:24:in`[]':wrongnumberofarguments(1for0)(ArgumentError)来自func_test.rb:24:in`'但如果我这样做plus=lambda{|a,b|a+b}这似乎有效。但是通过在用lambda赋值之后打印加号,两种方式都返回相同类型的

  5. javascript - LINQ.JS,用于 Except 的 comparerSelector - 2

    我正在尝试使用LINQ.JS(不是.NetLINQ!),但无法获得comparerSelector概念。我有两个对象数组,每个对象都包含Id、Name、Date、Passport等。我只想通过以下2个字段来区分它们:Id、Name。应忽略日期和护照上的差异。comparerSelector怎么写?以下仅适用于Id:Enumerable.From(p2).Except(p1,"$.Id}").ForEach(function(x){alert('Id=='+x.Id);});这也行:Enumerable.From(p2).Except(p1,function(x){returnx.Id;

  6. javascript - 如何使用 UnderscoreJS 进行柯里化(Currying)? - 2

    我正在尝试使用_.bind(...)。我知道如何使用绑定(bind)强制函数上下文,但还不知道如何进行柯里化(Currying)。我尝试的是:add=function(number){this.sum=this.sum+number;}add5=_.bind(add,{sum:0},5)但是,调用add5(),或者add5(5)似乎没有什么效果。任何线索如何包装参数,以便从一个调用到另一个调用保留上下文? 最佳答案 可能您想做部分应用,而不是currying/schönfinkeling。下划线有_.partial为此功能:func

  7. javascript - linq.js 按 javascript 中的对象数组分组 - 2

    我想使用linq.js按日期对以下数据进行分组。data2=[{"date":1399298400.0,"adId":1057946139383,"impressions":1000000},{"date":1399298400.0,"adId":3301784671323,"impressions":535714}......etc.];这是我的尝试:varlinq=Enumerable.From(data2);data2=linq.GroupBy(function(x){returnx.date;}).Select(function(x){return{date:x.Key(),i

  8. javascript - 取消 javascript 中 n 个参数的柯里化(Currying)函数 - 2

    如果f::a->b->c是柯里化(Currying)的,那么uncurry(f)可以定义为:uncurry::(a->b->c)->((a,b)->c)我正在尝试在javascript中实现上述功能。我的以下实现是否正确且足够通用,或者是否有更好的解决方案?constuncurry=f=>{if(typeoff!="function"||f.length==0)returnf;returnfunction(){for(leti=0;ia=>b=>f(a,b);constcurriedSum=curry((num1,num2)=>num1+num2);console.log(currie

  9. javascript - 在 React 中柯里化(Currying)事件处理程序 - 2

    我正在尝试在组件上编写一个(curried?)onChange事件处理程序,该组件将接收一个key参数,该参数将让它知道状态对象中的哪个键更新。代码无法编译,提示'key'isnotdefined。classAppextendsComponent{constructor(props){super(props);this.state={firstName:null,lastName:null}this.handleChange=this.handleChange.bind(this);}handleChange=(key)=(event)=>{console.log(key,event)

  10. javascript - 动态柯里化(Currying),以及如何在 JavaScript 变量中同时保存函数和值 - 2

    这个问题在这里已经有了答案:Variadiccurriedsumfunction(19个回答)关闭6年前。我正在学习JavaScript,我最近遇到了一个practiceproblem这要求我构建一个可以创建如下输出的函数:varthreeSum=sum(3);threeSum//3threeSum(4)//7threeSum(4)(3)//10threeSum(4)(3)(7)//17threeSum(4)(3)(7)()(2)//19threeSum-2//1threeSum+2//5我假设涉及柯里化(Currying),并且我认为我基本了解柯里化(Currying)如何以简单的形

随机推荐