为什么要迭代可以用来代替尾递归? [英] Why should iteration be used instead of tail recursion?

查看:376
本文介绍了为什么要迭代可以用来代替尾递归?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是设计的味道,实践差递归?
我看见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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆