摆脱递归生成器方法(通过转换为状态机)中的"屈服"的最简单方法?



我有一个很好,优雅的(IMO)代码,我想将其移植到其他语言,例如C ,Java等。

我面临的问题是双重的:

  • 代码使用yield
  • 代码高度递归

手工摆脱 yield可能的,但是非常乏味 - 该过程非常机械,显然是自动的。
同时,C#编译器将其转换为非常丑陋的状态机 - 实际上是无法使用的。(我尝试将其分解;它只是不可读的。)

我想知道,除了花几天的时间以手动摆脱yield外,我还有其他选择吗?
还是可以将yield块转换为(可读)状态机的某种工具,然后我可以像普通代码一样移植?


如果您很好奇我的含义"高度递归" - 下面的代码基本上是代码的结构(实际的东西只有〜66行;这不是一个非常长的功能):

static IEnumerable<ReturnType> MyRecursiveYielder(args)
{
    if (blah1) yield return foo;
    else if (blah2)
        foreach (var foo1 in foo2.Blah())
            foreach (var item in MyRecursiveYielder(moreArgs))
                yield return item;
    else
    {
        var state = new State();
        foreach (var item in blah)
            foreach (var item2 in MyRecursiveYielder(otherArgs))
                foreach (var item3 in blah3)
                {
                    foreach (var result in MyRecursiveYielder(yetMoreArgs)))
                        yield return result;
                    foobar1();
                }
        while (condition)
            foreach (var foo in blah)
                foreach (var result in MyRecursiveYielder(argh)))
                {
                    if (condition2)
                        foreach (var result in MyRecursiveYielder(almostThere)))
                            yield return result;
                    foobar2();
                }
    }
}

收益率成就的成就接近共同调查。您应该能够移植一种支持这些语言的语言。不幸的是,很少有语言。我相信Ada拥有它们。

下一步是纤维。Win32 API暴露了纤维,因此对于C ,这可能是一种选择。我认为不是爪哇。

因此,简短答案:调查目标平台的共同路线或纤维的可用性。

我想我找到了一个解决方案:我可以在大多数情况下使用linq。这样,在前几种情况下,我不需要yield,因为这些情况并不陈述。

状态收益率(即最后一个产量)是问题所在 - 但是在睡觉后,我意识到我的"状态" yield代码基本上只是树搜索(确切地说是广度优先搜索)。基本上喜欢此代码。

因此,我可以简单地做自己的IEnumerable<T>类,以执行广度优先搜索 - 即给定传输功能(T parenet) => (IEnumerable<T> children),它将一对一输出孩子,并继续搜索直到剩下。

如果有效,那将摆脱 yield s的所有,同时保持代码结构基本相同 - 使其更容易读取,更易于移植。

最新更新