gpt4 book ai didi

c# - 晦涩的编译器的 lambda 表达式翻译

转载 作者:行者123 更新时间:2023-11-30 14:10:43 27 4
gpt4 key购买 nike

我研究了 Y Combinator(使用 c# 5.0),当这个方法出现时我很惊讶:

public static  Func<T1, Func<T2, TOut>> Curry<T1, T2, TOut> ( this Func<T1, T2, TOut> f)
{
return a => b => f(a, b);
}

...被编译器翻译成这样:

public static Func<T1, Func<T2, TOut>> Curry<T1, T2, TOut>(this Func<T1, T2, TOut> f)
{
first<T1, T2, TOut> local = new first<T1, T2, TOut>();
local.function = f;
return new Func<T1, Func<T2, TOut>>(local.Curry);
}
private sealed class first<T1, T2, TOut>
{
private sealed class second
{
public first<T1, T2, TOut> ancestor;
public T1 firstParameter;
public TOut Curry(T2 secondParameter)
{
return ancestor.function(firstParameter, secondParameter);
}
}
public Func<T1, T2, TOut> function;
public Func<T2, TOut> Curry(T1 firstParameter)
{
second local = new second();
local.ancestor = this;
local.firstParameter = firstParameter;
return new Func<T2, TOut>(local.Curry);
}
}

因此,当我们使用引用 second.Curry 的委托(delegate)时,第二类是嵌套的,而第一类不可用于垃圾回收。同时,头等舱所需要的只是功能。也许我们可以将它复制(委托(delegate))到第二个类(class),然后可以收集第一个类(class)?是的,我们也应该做二等非嵌套,但似乎没问题。据我所知,委托(delegate)是“按值”复制的,所以我可以说它很慢,但同时我们复制了firstParameter?!所以,也许有人可以解释,为什么编译器会做所有这些事情?)我谈论这样的事情:

private sealed class first<T1, T2, TOut>
{
public Func<T1, T2, TOut> function;
public Func<T2, TOut> Curry(T1 firstParameter)
{
second<T1, T2, TOut> local = new second<T1, T2, TOut>();
local.function = function;
local.firstParameter = firstParameter;
return new Func<T2, TOut>(local.Curry);
}
}
public sealed class second<T1, T2, TOut>
{
public T1 firstParameter;
public Func<T1, T2, TOut> function;
public TOut Curry(T2 secondParameter)
{
return function(firstParameter, secondParameter);
}
}

最佳答案

这个问题很难理解。让我澄清一下。您的建议是编译器可以改为生成

public static Func<T1, Func<T2, TOut>> Curry<T1, T2, TOut>(this Func<T1, T2, TOut> f)
{
first<T1, T2, TOut> local = new first<T1, T2, TOut>();
local.function = f;
return new Func<T1, Func<T2, TOut>>(local.Curry);
}
private sealed class first<T1, T2, TOut>
{
private sealed class second
{
//public first<T1, T2, TOut> ancestor;
public Func<T1, T2, TOut> function;
public T1 firstParameter;
public TOut Curry(T2 secondParameter)
{
return /*ancestor.*/function(firstParameter, secondParameter);
}
}
// public Func<T1, T2, TOut> function;
public Func<T2, TOut> Curry(T1 firstParameter)
{
second local = new second();
// local.ancestor = this;
local.function = function;
local.firstParameter = firstParameter;
return new Func<T2, TOut>(local.Curry);
}
}

是吗?

您的说法是,由于这种情况,这是一种改进。

Func<int, int, int> adder = (x, y)=>x+y;
Func<int, Func<int, int>> makeAdder = adder.Curry();
Func<int, int> addFive = makeAdder(5);
  • addFivesecond
  • 实例方法的委托(delegate)
  • makeAdderfirst
  • 实例方法的委托(delegate)
  • 在原始代码生成器中,second 保留 ancestor,这是 first 的同一实例

因此如果我们说

makeAdder = null;

那么first的实例就无法被收集。该实例无法再通过 makeAdder 访问,但可以通过 addFive 访问。

在提议的 codegen 中,first 可以在这种情况下收集,因为无法通过 addFive 访问该实例。

您是正确的,在这种特定情况下优化是合法的。但是,由于 Ben Voigt 在他的回答中描述的原因,它一般是不合法的。 如果 fCurry 中发生了变化,那么 local.function 必须发生变化。 但是 local 无法访问 second 的实例 直到执行外部委托(delegate)

C# 编译器团队可以选择执行您已确定的优化,但到目前为止,为了节省一点点钱根本不值得为此费心。

我们正在考虑按照您描述的思路对 Roslyn 进行优化;也就是说,如果外部变量已知不会发生变化,那么就更积极地捕获它的值。我不知道该优化是否适用于 Roslyn。

关于c# - 晦涩的编译器的 lambda 表达式翻译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22564893/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com