4

我在 Visual Studio 中摆弄,我发现

delegate RecursiveDelegate RecursiveDelegate();

是一个有效的委托定义。

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

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

2 回答 2

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

我最喜欢的代码行是 call s(s)。说真的,如果有人能在头脑中理顺这一点,那他们就是天才!更别说整体了U<Func<A, Z>>(r => a => f(U(r))(a))

于 2013-08-17T06:22:17.417 回答
1

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

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-01-11T13:31:09.690 回答