返回介绍

数学基础

统计学习

深度学习

工具

Scala

四、递归函数

发布于 2023-07-17 23:38:23 字数 2865 浏览 0 评论 0 收藏 0

  1. 通常一个不断更新 varwhile 循环可以修改为递归函数。

    
    
    xxxxxxxxxx
    //************ while 版本 *****************// def func(init_guess: Double) : Double = { var guess = init_guess while(!=is_ok(guess)) // 不满足条件,继续迭代 guess = improve(guess) guess // 返回结果 } ​ //************ 递归函数 版本 *****************// def func(guess : Double) : Double = { if (is_ok(guess)) guess // 满足条件,返回 else func(impove(guess)) // 不满足条件,继续递归 }
    • 从代码简洁性来讲,递归函数的版本更好。但是从执行效率上讲,通常 while 版本更好。

    • 如果递归函数是尾递归的,则这两个版本的执行效率一样高。尾递归tail recursive:递归函数的递归发生在函数的最后一步。

      因为 Scala 编译器会执行尾递归优化。当Scala 检测到尾递归时,编译器将其替换为跳到函数的最开始,并且在跳转之前将参数更新为新的值。这样尾递归并不会在每次调用时都构建一个新的栈帧,所有的调用都会在同一个栈帧中执行。

      这在调试尾递归函数时可能会是不利影响。如果你对调试信息感到困惑,可以将尾递归优化关闭,方法是 scala 命令或者 scalac 编译器添加参数 -g:notailcalls。 一旦调试结果,可以继续打开尾递归优化。

  2. Scala 中使用尾递归比较受限,因为Scala 只能对那些在函数末尾直接调用自己的函数做优化。如果递归调用是间接的,则无法使用尾递归优化。

    • 最后一个表达式是递归调用之后再做了其它操作:无法使用尾递归优化。

      
      
      xxxxxxxxxx
      def func(x: Int) : Int = { if (x==0) 0 else func(x-1) + 1 // 无法使用尾递归优化,因为最后一个表达式是 func 的间接调用:调用之后再加 1 }
    • 相互递归调用:无法使用尾递归优化。

      
      
      xxxxxxxxxx
      def isEven(x: Int): Boolean = if (x==0) true else isOdd(x-1) def isOdd(x: Int): Boolean = if (x==0) false else isEven(x-1)
    • 最后一步调用的是一个值函数(而不是发起调用的那个函数自己):无法使用尾递归优化。

      
      
      xxxxxxxxxx
      var funValue = (x :Int) => x+1 def func(x: Int) : Int = { if(x!=0) {println(x); funValue(x-1)} else 0 } funValue = func _ // 现在 funValue 指向一个打包了 func 函数的值函数对象

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文