C#中的Lambda/Linq表达式的高级功能混淆[英] High Level Function Confusion with Lambda/LINQ expressions in C#

本文是小编为大家收集整理的关于C#中的Lambda/Linq表达式的高级功能混淆的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

不确定如何描述这个问题,因此标题可能是错误的.

正在阅读一些代码示例,并对以下返回函数感到困惑:

Func<Func<int , bool>, Func<int , int>, Func<int , int>> Loop = null ;
Loop = (c , f ) => n => c(n) ? Loop(c , f ) ( f (n)): n;
Func<int , int> w = Loop(n => n < 10 , n => n + 2); 
var r = w(2); 
var s = w(3);
Console . WriteLine ("{0} {1}" , r , s );

我知道,当C(n)评估为true时,此功能正在返回循环,但我不明白循环(c,f)(f(n))如何评估循环 - 它们是否都被回到循环中?我尝试在linqpad中运行转储,但我只是不明白该位如何运行.

任何帮助都将不胜感激,理解这可能是一个愚蠢的问题!

推荐答案

尝试理解它的一种方法很小:具有+1增量的基本循环1-10.

 Func<int,int> basicLoop = null;
 basicLoop = n => n < 10 ? basicLoop(n+1) : n;

这很简单 - basicLoop是基于参数n返回n(对于n> = 10)或以增量参数调用自己的函数.因此,basicLoop(8)计算为:

  • basicLoop(8) 8 <10,所以打电话basicLoop(8+1)获得结果
  • basicLoop(9) 9 <10,所以打电话basicLoop(9+1)获得结果
  • basicLoop(10) 10 == 10,所以返回n是10.
  • basicLoop(9)获得结果10(来自basicLoop(10))并返回
  • basicLoop(8)获得结果10(来自basicLoop(9))并返回

现在,我们想将条件作为参数传递到循环.这意味着我们的"循环" Func需要在每次迭代中传递该条件:

该条件的类型显然是(类似于n<10) - Func<int, bool>.因此,现在我们有一些将Func<int,bool>作为参数的东西,并返回与原始basicLoop相同的值.因此,它将是一个参数的Func,一个结果是:

Func<Func<int, bool>, Func<int,int>> condLoop = null;

condLoop是一个参数的函数 - 因此,当定义时,我们将参数:condLoop = (condition) => ....

我们需要在原始basicLoop中替换条件:n => n < 10 ? ...变为n => condition(n) ? ....

最后一部分是替换basicLoop(n+1) - 我们具有condLoop函数,当您传递条件时返回basicLoop等效.幸运的是,我们的病情不会在迭代之间发生变化,并且我们已经拥有 - condLoop(condition)相当于basicLoop.将这一切聚在一起:

condLoop = (condition) =>
   n => condition(n) ? 
      condLoop(condition) (n + 1) :
      n; 

通过电话跟踪condLoop(x => x < 5)(4)

  • condLoop(x => x < 5)(4) - 条件为x => x < 5,n = 4,因此当condition(4)称为x = 4,4 <5是正确的 - 呼叫condLoop,情况相同,n- condLoop(x => x < 5)(4 + 1)增加了结果
  • condLoop(x => x < 5)(5) - 条件是x => x < 5,n = 5,因此当condition(5)称为x = 5,5 <5是false -return n,是5
  • 回到condLoop(x => x < 5)(4) - condLoop(x => x < 5)(5)
  • 的结果返回5

具有相似的逻辑添加函数,可以增量值 - 在每个迭代中,您都需要通过condition和increment函数(c和f在原始帖子中).

其他推荐答案

c#的匿名代表声明语法会导致混乱,因此我将在f#的函数类型语法中重写它.

(int -> bool) -> (int -> int) -> (int -> int)

因此,这是一个函数,该函数具有两个函数并返回一个函数.它接受的第一个功能是谓词,第二个可能是映射,最后它返回一个接受int返回int的函数

Loop = (c , f ) => n => c(n) ? Loop(c , f ) ( f (n)): n;

实施上述签名.如预期的那样,它需要两个参数.我们希望它能返回一个函数,这里是:

n => c(n) ? Loop(c,f) (f (n)) : n;

我可以想象循环(c,f)(f(n))部分给你扔你最多.调用循环的结果是一个接受整数并返回整数的函数. n是一个整数,f是采用整数并返回整数的函数.在w的术语中,它将整数增加2.因此,给定n的n,如第一个示例,您将通过f(n),2 + 2的结果作为新n.只要C(n)解决真实,您将继续迭代,每次n增加2个直到大于或等于10.

.

其他推荐答案

"我知道当C(n)评估为true时,此功能正在返回循环,但我不明白循环(c,f)(f(f(n))如何评估" - 函数t返回Loop.函数 IS Loop,它返回a Func<int, int>.

so,Loop是一个函数,它将两个函数作为输入并返回第三个函数.它具有签名Func<Func<int , bool>, Func<int , int>, Func<int , int>>显示了这一点.

现在,Loop = null在第一行中,以便在第二行上实际定义了Loop,它可以递归地调用自身.

然后,Loop基本上是返回函数n => c(n) ? Loop(c, f)(f(n)) : n的函数.也就是说,Loop将返回一个函数,即将来给定的Loop(c, f)(f(n)) c(n)是c(n)是Loop(c, f)(f(n)) Loop(c, f)(f(n)) true and n当它为false; c62>;

时.

w是Loop的返回函数,当时使用参数n => n < 10&n => n + 2.

所以,将其替换为Loop您可以定义w这样:

Func<int, int> w = null;
w = n => n < 10 ? w(n + 2) : n;

现在可以像这样重新编写:

int w(int n)
{
    while (n < 10)
    {
        n += 2;
    }
    return n;
}

希望进步很容易看到.

本文地址:https://www.itbaoku.cn/post/1556865.html

问题描述

Unsure how to describe this question so the title might be wrong.

Am reading over some code examples and am confused over the following return function:

Func<Func<int , bool>, Func<int , int>, Func<int , int>> Loop = null ;
Loop = (c , f ) => n => c(n) ? Loop(c , f ) ( f (n)): n;
Func<int , int> w = Loop(n => n < 10 , n => n + 2); 
var r = w(2); 
var s = w(3);
Console . WriteLine ("{0} {1}" , r , s );

I understand that this function is returning the Loop when c(n) evaluates to true, but I don't understand how Loop(c,f) (f(n)) evaluates - are they both being passed back into Loop? I have tried running dumps in Linqpad and I just don't get how that bit is running.

Any help would be appreciated, understand this is probably a dumb question!

推荐答案

One way to try to understand it is start small: have basic loop 1-10 with +1 increment.

 Func<int,int> basicLoop = null;
 basicLoop = n => n < 10 ? basicLoop(n+1) : n;

That's pretty simple - basicLoop is function that based on parameter n returns n (for n >= 10) or calls itself with incremented parameter. So basicLoop(8) is computed as:

  • basicLoop(8) 8 < 10, so calls basicLoop(8+1) to get result
  • basicLoop(9) 9 < 10, so calls basicLoop(9+1) to get result
  • basicLoop(10) 10 == 10, so returns n which is 10.
  • basicLoop(9) got result 10 (from basicLoop(10)) and returns it
  • basicLoop(8) got result 10 (from basicLoop(9))and returns it

Now we want to pass condition as parameter to the loop. That means our "loop" Func will need to pass that condition around on every iteration:

Type of that condition is clearly (similar to n<10) - Func<int, bool>. So now we have something that takes Func<int,bool> as argument and returns same value as our original basicLoop. Hence it will be Func of one argument and one result:

Func<Func<int, bool>, Func<int,int>> condLoop = null;

condLoop is function of one argument - so when defining we take argument: condLoop = (condition) => ....

We need to replace condition in our original basicLoop: n => n < 10 ? ... becomes n => condition(n) ? ....

The last part is replacing basicLoop(n+1) - we have condLoop function that returns equivalent of basicLoop when you pass condition to it. Fortunately our condition does not change between iterations and we already have it - condLoop(condition) is equivalent of basicLoop. Getting it all together:

condLoop = (condition) =>
   n => condition(n) ? 
      condLoop(condition) (n + 1) :
      n; 

Tracing through calls condLoop(x => x < 5)(4)

  • condLoop(x => x < 5)(4) - condition is x => x < 5, n = 4 so when condition(4) is called x = 4, 4 < 5 is true - calling condLoop with same condition and increased n - condLoop(x => x < 5)(4 + 1) to get result
  • condLoop(x => x < 5)(5) - condition is x => x < 5, n = 5 so when condition(5) is called x = 5, 5 < 5 is false - returning n which is 5
  • back to condLoop(x => x < 5)(4) - returning 5 as result of condLoop(x => x < 5)(5)

With similar logic adding function that increments value - on every iteration now you need to pass condition and increment function (c and f in original post).

其他推荐答案

C#'s anonymous delegate declaration syntax leads to confusion, so I'm going to rewrite it in F#'s function type syntax.

(int -> bool) -> (int -> int) -> (int -> int)

So this is a function that takes two functions and returns a function. The first function it accepts is a predicate, the second is likely a map, and finally it returns a function that accepts an int to return an int.

Loop = (c , f ) => n => c(n) ? Loop(c , f ) ( f (n)): n;

The implementation of the above signature. It takes two parameters, as expected, as c and f. We expect it to return a function, and here it is:

n => c(n) ? Loop(c,f) (f (n)) : n;

I can imagine the Loop(c,f) (f (n)) part is throwing you the most. The result of calling Loop is a function that accepts an integer and returns an integer. n is an integer, and f is a function that takes an integer and returns an integer. In the terms of w it increments that integer by 2. So, given an n of 2, as in the first example, you would pass the result of f(n), 2 + 2, as a new n. So long as c(n) resolves true, you will continue to iterate, with n increasing by 2 each time until greater than or equal to 10.

其他推荐答案

"I understand that this function is returning the Loop when c(n) evaluates to true, but I don't understand how Loop(c,f) (f(n)) evaluates" - the function doesn't return Loop. The function is Loop and it returns a Func<int, int>.

So, Loop is a function that takes two functions as input and returns a third function. It has the signature Func<Func<int , bool>, Func<int , int>, Func<int , int>> which show this.

Now, Loop = null in the first line so that the when Loop is actually defined on the second line it can recursively call itself.

Then, Loop is basically a function that returns the function n => c(n) ? Loop(c, f)(f(n)) : n. That is Loop will return a function that, given an n in the future, will return Loop(c, f)(f(n)) when c(n) is true and n when it is false;

w is then the return function from Loop when with the parameters n => n < 10 & n => n + 2.

So, substituting those in to Loop you could define w like this:

Func<int, int> w = null;
w = n => n < 10 ? w(n + 2) : n;

Now that can be re-written as this:

int w(int n)
{
    while (n < 10)
    {
        n += 2;
    }
    return n;
}

And hopefully that progression is easy to see.