【问题标题】:Is there a use for a delegate type that returns a delegate of the same type as itself?是否有使用返回与自身相同类型的委托的委托类型?
【发布时间】:2013-08-19 12:50:53
【问题描述】:

我在 Visual Studio 中摆弄,我发现

delegate RecursiveDelegate RecursiveDelegate();

是一个有效的委托定义。

我没有大量的函数式编程经验,但我想知道这种模式在函数式编程中是否真的有用,或者它只是对语义的好奇。我想从两个方面问这个问题:

  1. 在有副作用的情况下。我可以看到这实际上是用函数式语言对迭代学习算法进行建模的一种不错的方式,其中算法的实际任务是作为副作用执行的,而新版本的函数是返回值。完成了吗?
  2. 在没有副作用的情况下。我认为这原则上没用,但如果我错了,我会非常好奇。如果我们假设 RecursiveDelegate() 的实现没有副作用,这会有用吗?

【问题讨论】:

  • 在 CLR 中,委托是具有 Invoke 方法的对象(带有一些额外的元数据,但这是它的核心)。如果你这样想,它的工作原理就没有什么奇怪的了。没有什么比在方法中返回自身的对象更奇怪了。
  • @zneak - 我认为问题不在于它为什么起作用(有点合理,因为函数可以返回它想要的任何类型),而是它如何/是否对函数式编程有用.
  • 当然。这就是为什么我没有发布答案。我正在解决最初表达的惊讶。

标签: c# delegates functional-programming


【解决方案1】:

我有一些类似代码的示例,它不完全是递归委托,但它很接近。 “Y-Combinator”接近了 - 坦率地说,我不知道它在实践中是如何工作的,但它用于定义递归函数。

这是您需要定义的时髦代码:

public delegate T S<T>(S<T> s);

public static T U<T>(S<T> s)
{
    return s(s);
}

public static Func<A, Z> Y<A, Z>(Func<Func<A, Z>, Func<A, Z>> f)
{
    return U<Func<A, Z>>(r => a => f(U(r))(a));
}

现在您可以在一行中定义递归函数。

阶乘:

var fact = Y<int, int>(_ => x => x == 0 ? 1 : x * _(x - 1));
var fact5 = fact(5); // == 120
var fact6 = fact(6); // == 720
var fact7 = fact(7); // == 5040

斐波那契:

var fibo = Y<int, int>(_ => x => x <= 1 ? 1 : _(x - 1) + _(x - 2));
var fibo5 = fibo(5); // == 8
var fibo6 = fibo(6); // == 13
var fibo7 = fibo(7); // == 21

我最喜欢的代码行是调用s(s)。说真的,如果有人能在头脑中理顺这一点,那他们就是天才!更不用说整个U&lt;Func&lt;A, Z&gt;&gt;(r =&gt; a =&gt; f(U(r))(a))了。

【讨论】:

    【解决方案2】:

    这对于状态机来说是一种潜在有用的模式:

    delegate State State();
    
    State state = MainMenu;
    
    while (state != null) // or have a 'pump' call each update
    {
       state = state();
    }
    
    State MainMenu()
    {
       if (playPressed) return StartLevelOne();
       return MainMenu;
    }
    
    State StartLevelOne()
    {
       //set up level
       return LevelOne;   // or LevelOne() if you want an immediate update
    }
    
    State LevelOne()
    {
        //check for level one ending
        return LevelOne;
    }
    

    【讨论】:

      猜你喜欢
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-28
      • 2010-10-29
      • 2021-02-22
      • 1970-01-01
      • 2011-04-09
      相关资源
      最近更新 更多