不确定如何描述此问题,因此标题可能有误。
我正在阅读一些代码示例,并对以下返回函数感到困惑:
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时,这个函数返回循环,但我不明白Loop(c,f)(f(n))如何计算 - 它们是否都被传递回Loop ?我已经尝试在Linqpad中运行转储,我只是不知道那个位是如何运行的。
任何帮助都会受到赞赏,明白这可能是一个愚蠢的问题!
答案 0 :(得分:4)
尝试理解它的一种方法是从小开始:基本循环1-10,增量为+1。
Func<int,int> basicLoop = null;
basicLoop = n => n < 10 ? basicLoop(n+1) : n;
非常简单 - basicLoop
是基于参数n
的函数返回n
(对于n&gt; = 10)或使用递增参数调用自身。所以basicLoop(8)
计算为:
basicLoop(8)
8&lt; 10,所以请basicLoop(8+1)
来获取结果basicLoop(9)
9&lt; 10,所以请basicLoop(9+1)
来获取结果basicLoop(10)
10 == 10,所以返回n
即10。basicLoop(9)
得到结果10(来自basicLoop(10)
)并将其返回basicLoop(8)
得到结果10(来自basicLoop(9)
)并将其返回现在我们要将条件作为参数传递给循环。这意味着我们的循环&#34; 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&lt; 5是真的 - 调用具有相同条件的condLoop
并增加n - condLoop(x => x < 5)(4 + 1)
以获得结果condLoop(x => x < 5)(5)
- 条件为x => x < 5
,n = 5,因此当调用condition(5)
时x = 5,5 <&lt; 1} 5是假的 - 返回n
即5 condLoop(x => x < 5)(4)
- 因condLoop(x => x < 5)(5)
使用类似的逻辑添加函数增加值 - 在每次迭代时,您需要在原始帖子中传递condition
和increment
函数(c
和f
)。< / p>
答案 1 :(得分:1)
C#的匿名委托声明语法导致混淆,所以我将用F#的函数类型语法重写它。
(int -> bool) -> (int -> int) -> (int -> int)
所以这是一个函数,它接受两个函数并返回一个函数。它接受的第一个函数是谓词,第二个函数可能是一个映射,最后它返回一个接受int的函数来返回一个int。
Loop = (c , f ) => n => c(n) ? Loop(c , f ) ( f (n)): n;
执行上述签名。正如预期的那样,它需要两个参数作为c和f。我们希望它返回一个函数,这里是:
n => c(n) ? Loop(c,f) (f (n)) : n;
我可以想象Loop(c,f)(f(n))部分最让你失望。调用Loop的结果是一个接受整数并返回整数的函数。 n是整数,f是取整数并返回整数的函数。在w
的条件中,它将该整数递增2.因此,给定n为2,如第一个示例中所示,您将f(n),2 + 2的结果作为新n传递。只要c(n)解析为真,你就会继续迭代,每次n增加2,直到大于或等于10。
答案 2 :(得分:1)
&#34;我知道当c(n)求值为true时,此函数返回循环,但我不明白循环(c,f)(f(n))如何评估&#34; - 该功能不返回Loop
。函数是 Loop
,它返回Func<int, int>
。
因此,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
将返回一个函数,如果将来n
,Loop(c, f)(f(n))
c(n)
true
和n
时会返回false
它是w
;
Loop
是n => n < 10
的返回函数,当参数为n => n + 2
&amp; 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;
}
:
Column A (Error.Type) |
(Or any other text) | Column B (Message)
> 1 | #REF! |
> 1 | #REF! | total for error 1 is 2
> 2 | #DIV/0! |
> 2 | "Hello World" | total for error 2 is 2
> 3 | "Foobar" |
> 3 | "Something" |
> 3 | "Else" | total for error 3 is 3
现在可以重写为:
2 + 2 + 3 = 7
希望这种进展很容易看出来。