方法:“letrec”在 C# 中(在其定义内调用 lambda 表达式)

发布于 2024-10-30 18:33:09 字数 815 浏览 0 评论 0原文

将方法体中定义的阶乘函数视为 lambda 表达式并分配给变量:

Func<int, int> factfail = n =>
{
    if (n == 0)
        return 1;
    else
        return n * factfail(n-1);
};

这会失败,因为 factfail 尚未受局部变量绑定。

有没有办法通过抽象函数本身来添加某种固定点?

Func<Func<int, int>, int, int> fact_ = (fact, n) => 
{  
    if (n == 0) 
        return 1;
    else 
        return n * fact(n-1); 
};

fact_(??);

长话短说: 我需要编写一个递归函数,它具有更改某些外部状态的副作用。 因此,我尝试将该方法编写为捕获外部状态的 lambda 表达式。

我仍在尝试不同的风格如何编写它 - 除了所有递归调用都需要相同的字典之外 - 我希望尽可能纯粹的函数式和惰性。

所以我正在使用 LINQ,因为它可以帮助我减少相互数据。 它还有助于理解代码的哪些部分可以用函数式风格表达。

简而言之,在 LINQ 语句中能够在前面定义一些辅助函数是很有帮助的,我通过将 lambda 表达式绑定到变量来做到这一点。

通过 lamda 表达式,我还可以捕获我的字典,而无需显式地将其引用传递给该方法,这非常好。

但不确定我是否走在正确的轨道上......

Consider the factorial function defined within a method body as a lambda expression and assigned to a variable:

Func<int, int> factfail = n =>
{
    if (n == 0)
        return 1;
    else
        return n * factfail(n-1);
};

This fails, since factfail isn't bound by the the local variable yet.

Is there a way to add a sort of fixpoint - by abstracting over the function itself?!

Func<Func<int, int>, int, int> fact_ = (fact, n) => 
{  
    if (n == 0) 
        return 1;
    else 
        return n * fact(n-1); 
};

fact_(??);

long story:
I need to write a recursive function that has the side effect of changing some outer state.
Therefore i am trying to write that method as a lambda expression that captures that outer state.

I am still experimenting with different styles how to write that and - besides of that one dictionary that needs to be the same for all recursive calls - i want to be as purely functional and lazy as possible.

So i was playing with LINQ, since it helps me reducing mutual data.
It also helps with understanding which parts of the code can be expressed in a functional style.

To be brief in the LINQ statement it is helpful to be able to define some helper functions in front of and i did that by binding lambda expressions to variables.

And with lamda expression i also can capture my dictionary without the need to pass its reference to the method explicitely, which is quite nice.

not sure if i am on the right track though...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↘人皮目录ツ 2024-11-06 18:33:09

您可以在 这篇博文,作者:Mads Torgersen。他展示了如何定义通常的定点组合器。他使用阶乘函数作为示例,因此您可以在那里找到确切的样本:-)。

然而,在实践中,您可以只定义一个本地 Func<..> 变量,然后对其进行变异。如果你想给委托一个名字,那么它就可以正常工作(它有点脏,但很简单):

Func<int, int> fact = null;
fact = (n) => (n == 0) ? 1 : n * fact(n-1);

这是有效的,因为闭包捕获了对 fact 变量的引用,所以当你实际上调用它(在递归调用期间),该值不再是 null ,而是引用委托。

You can find more information about recursive lambda expressions in this blog post by Mads Torgersen. He shows how to define the usual fixed point combinator. He uses factorial function as an example, so you can find your exact sample there :-).

However, in practice, you can just define a local Func<..> variable and then mutate it. If you want to give a name to the delegate, then it works just fine (it is a bit dirty, but simple):

Func<int, int> fact = null;
fact = (n) => (n == 0) ? 1 : n * fact(n-1);

This works, because the closure captures reference to the fact variable, so when you actually call it (during the recursive call), the value is not null anymore, but references the delegate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文