为什么要迭代可以用来代替尾递归? [英] Why should iteration be used instead of tail recursion?
问题描述
什么是设计的味道,实践差递归?
我看见ReSharper的提出改进建议我赶紧看了看周围的谷歌。
锯各地重新分解尾递归众多的意见,并反复提到它作为一种设计的气味。
公共静态无效DebugOutput2(例外前){
如果(前== NULL){
返回;
}
的Debug.WriteLine(ex.Message);
如果(ex.InnerException!= NULL){
DebugOutput2(ex.InnerException);
}
}
//被重构了
公共静态无效DebugOutput(例外前){
如果(前== NULL ){
的回报;
}
,而(真){
的Debug.WriteLine(ex.Message);
如果(ex.InnerException!= NULL){
前= ex.InnerException;
继续;
}
中断;
}
}
编辑:基于C#编译器处理意见。看起来现在是递归的结果
目标.NET 4.5。 C#5.0
为尾递归版本ILDASM输出:显示递归调用,而不是迭代
。方法公开hidebysig静态无效DebugOutput(类[mscorlib程序] System.Exception的前)CIL管理
{
//代码大小54(0x36数据)
.maxstack 2
.locals的init([0]布尔CS $ 4 $ 0000)
IL_0000:NOP
IL_0001:ldarg.0
IL_0002:ldnull
IL_0003:CEQ
IL_0005:LDC .i4.0
IL_0006:CEQ
IL_0008:stloc.0
IL_0009:ldloc.0
IL_000a:brtrue.s IL_000e
IL_000c:br.s IL_0035
IL_000e:ldarg.0
IL_000f:callvirt比如字符串[mscorlib程序] System.Exception的:: get_Message()
IL_0014:呼叫无效[系统] System.Diagnostics.Debug:的WriteLine(字符串)
IL_0019:NOP
IL_001a:ldarg.0
IL_001b:callvirt实例类[mscorlib程序] System.Exception的[mscorlib程序] System.Exception的:: get_InnerException()
IL_0020:ldnull
IL_0021:CEQ
IL_0023:stloc.0
IL_0024:ldloc.0
IL_0025:brtrue.s IL_0035
IL_0027:NOP
IL_0028:ldarg.0
IL_0029:callvirt实例类[mscorlib程序] System.Exception的[mscorlib程序] System.Exception的:: get_InnerException()
IL_002e:调用无效ca1.Program :: DebugOutput(类[mscorlib程序] System.Exception的)
IL_0033:NOP
IL_0034:NOP
IL_0035:RET
} //方法程序:: DebugOutput
结束
由于人误更关心微观优化比清晰可读的代码。
What is the design smell, poor practice in recursion ? once I saw resharper suggesting improvements I quickly looked around on google. Saw numerous comments around re-factoring tail recursion to iterations and referring to it as a design smell.
public static void DebugOutput2(Exception ex) {
if (ex == null) {
return;
}
Debug.WriteLine(ex.Message);
if (ex.InnerException != null) {
DebugOutput2(ex.InnerException);
}
}
// WAS REFACTORED TO
public static void DebugOutput(Exception ex) {
if (ex == null) {
return;
}
while (true) {
Debug.WriteLine(ex.Message);
if (ex.InnerException != null) {
ex = ex.InnerException;
continue;
}
break;
}
}
EDIT: BAsed on C# compiler treatment comment. Looks like it is recursive now
Target .net 4.5 . C# 5.0
ILDASM Output for tail recursion version: Shows recursive call and not iteration
.method public hidebysig static void DebugOutput(class [mscorlib]System.Exception ex) cil managed
{
// Code size 54 (0x36)
.maxstack 2
.locals init ([0] bool CS$4$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: ceq
IL_0005: ldc.i4.0
IL_0006: ceq
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brtrue.s IL_000e
IL_000c: br.s IL_0035
IL_000e: ldarg.0
IL_000f: callvirt instance string [mscorlib]System.Exception::get_Message()
IL_0014: call void [System]System.Diagnostics.Debug::WriteLine(string)
IL_0019: nop
IL_001a: ldarg.0
IL_001b: callvirt instance class [mscorlib]System.Exception [mscorlib]System.Exception::get_InnerException()
IL_0020: ldnull
IL_0021: ceq
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: brtrue.s IL_0035
IL_0027: nop
IL_0028: ldarg.0
IL_0029: callvirt instance class [mscorlib]System.Exception [mscorlib]System.Exception::get_InnerException()
IL_002e: call void ca1.Program::DebugOutput(class [mscorlib]System.Exception)
IL_0033: nop
IL_0034: nop
IL_0035: ret
} // end of method Program::DebugOutput
Because people mistakenly care more about micro-optimizations than clear and readable code.
这篇关于为什么要迭代可以用来代替尾递归?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!