【问题标题】:Lambda returning another lambdaLambda 返回另一个 lambda
【发布时间】:2010-05-15 14:21:48
【问题描述】:

有什么方法可以递归地从另一个 lambda 返回 lambda?

我想做的只是有限状态机,实现为 lambda,它返回实现另一个状态(或 null)的 lambda。

嵌套函数无法按我的意愿工作。

C#、.NET 3.5

例子:

机器、3 种状态、伪语言

private Lambda State1()
{  
    if (SomeConditionIsMet)
        return State2;
    else
        return State1;
}

private Lambda State2()
{  
    while (SomeConditionIsMet)
        return State2;
    else
        return State3;
}

private Lambda State3()
{  
    LogEnd();
    return NULL;
}

public void FSM()
{
    Lambda _currentState = State1;

    while(_currentState != NULL)
    {
        _currentState = _currentState();
    }
}

我知道,例如,我可以使用 enum+switch 解决此问题,但我只是好奇是否可以这样做。

【问题讨论】:

  • 我对这个问题的“递归”属性感到困惑;你能举一个这种行为的例子吗? lambda 实际上应该返回 自身 吗?
  • 目前还不清楚您希望它如何工作。能否给个伪代码示例,或者详细解释一下?
  • 我对更新感到困惑。此代码中的任何地方都没有 lambda 表达式。 “lambda”这个词到底是什么意思?我的意思是一个 lambda 表达式
  • 我想通了。当您说“lambda”时,您的意思是“代表”。我已经更新了我的答案。
  • 这是个好主意,但最好使用函数式语言。

标签: c# lambda


【解决方案1】:

当然,你可以从另一个 lambda 中返回一个 lambda:

Func<int, Func<int, int>> makeAdder = x => y => x + y;
Func<int, int> addTen = makeAdder(10);
Console.WriteLine(addTen(20)); // 30

您在语法的哪个方面遇到了问题?我很想知道人们是如何犯这种错误的,因为这有助于我们下次更好地设计语言和文档。

更新:

好吧,但是你不能返回 lambda 返回 lambda

当然可以。

Func<int, Func<int, int>> GetAdderMaker()
{
    return x => y => x + y;
}

这里我们返回一个返回 lambda 的 lambda。为什么你认为这是不可能的?

更新:

啊哈,我明白了。您认为“lambda”一词的意思是“代表”。它不是。 lambda 是一种可转换为委托的表达式。

如果你想要一个返回一个委托的委托,那么只需声明它。这是完全合法的。例如,这里有一个称为“组合器”的委托——组合器是一个接受自身并返回自身的委托:

delegate D D(D d);

这是一个名为 D 的委托,它接受一个 D 并返回一个 D。

您可以制作一个与此委托类型兼容的lambda 表达式。例如:

D I = x=>x;

是身份组合子。或者

D M = x=>x(x);

是 Raymond Smullyan 异想天开的组合器描述中的 Mockingbird 组合器。

正如您正确指出的那样,没有办法制作出这种组合子的通用 Func。我早在 2006 年就写过一篇关于这个事实的文章:

http://blogs.msdn.com/ericlippert/archive/2006/06/23/standard-generic-delegate-types-part-two.aspx

【讨论】:

  • 好吧,但你不能返回 lambda 返回 lambda ...(-> 查看我的编辑)
  • 我发现很多人混淆了“lambda”和“delegate”。当我们实际返回/传递由 lambda 表达式构造的委托时,常见用法会加剧这种情况:“所以我们返回这个 lambda...”或“传递一个像这样的 lambda”。
【解决方案2】:

我相信你可以声明一个委托类型:public delegate Lambda Lambda(),它返回一个自己类型的委托。无论如何,它确实可以编译。

【讨论】:

  • 我的问题可能有点令人困惑,但这正好解决了我的问题,谢谢。 :-)
【解决方案3】:

您的问题已经得到解答,但阅读本文的人可能有兴趣注意到您可以使用此技术将 Lambda 演算嵌入到 C# 中。

首先从:

    public delegate Lambda Lambda(Lambda x);

使用在http://en.wikipedia.org/wiki/Lambda_calculus 找到的各种函数定义,我定义了各种原语如下:

    public static Lambda Id         = x => x;
    public static Lambda Zero       = f => x => x;
    public static Lambda True       = x => y => x;
    public static Lambda False      = x => y => y;
    public static Lambda One        = f => x => f(x);
    public static Lambda Two        = f => x => f(f(x));
    public static Lambda Succ       = n => f => x => f(n(f)(x));
    public static Lambda Three      = Succ(Two);
    public static Lambda Pred       = n => f => x => n(g => h => h(g(f)))(u => x)(Id);
    public static Lambda Plus       = m => n => f => x => m(f)(n(f)(x));
    public static Lambda Sub        = m => n => n (Pred) (m);
    public static Lambda And        = p => q => p(q)(p);
    public static Lambda Or         = p => q => p(p)(q);
    public static Lambda Not        = p => a => b => p(b)(a);
    public static Lambda IfThenElse = p => a => b => p(a)(b);
    public static Lambda IsZero     = n => n(x => False)(True);
    public static Lambda IsLtEqOne  = n => IsZero(Pred(n));
    public static Lambda Pair       = x => y => f => f(x)(y);
    public static Lambda First      = pair => pair(True);
    public static Lambda Second     = pair => pair(False);
    public static Lambda Nil        = x => True;
    public static Lambda Null       = p => p(x => y => False);
    public static Lambda LtEq       = x => y => IsZero(Sub(x)(y));
    public static Lambda Gt         = x => y => LtEq(y)(x);
    public static Lambda Eq         = x => y => And(LtEq(x)(y))(LtEq(y)(x));
    public static Lambda M          = x => x(x);

各种测试和完整代码见:http://code.google.com/p/jigsaw-library/source/browse/trunk/Theory/EmbeddedLambdaCalculus.cs

【讨论】:

    【解决方案4】:

    你可以有一个方法来构建并返回一个expression tree

    public Expression GetExpression()
    {
    
    }
    

    还在.NET 4.0 has been greatly enhanced中构建表达式树。

    【讨论】:

      猜你喜欢
      • 2013-02-11
      • 2015-01-08
      • 1970-01-01
      • 2012-09-20
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多