我有一个很好,优雅的(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的所有,同时保持代码结构基本相同 - 使其更容易读取,更易于移植。