Scala newbie:递归和stackoverflow错误
作为
Scala新手,我正在阅读书籍文档,并尝试解决
http://aperiodic.net/phil/scala/s-99/发现的问题.似乎正确的Scala代码基于不可变值(val)和递归而不是循环和变量,以使并行性更安全并避免使用锁.
例如,运动P22(http://aperiodic.net/phil/scala/s-99/p22.scala)的一个可能的解决方案是: // Recursive. def rangeRecursive(start: Int,end: Int): List[Int] = if (end < start) Nil else start :: rangeRecursive(start + 1,end) 当然,这个代码很紧凑,看起来很聪明,但是当然,如??果递归次数很高,那么你会遇到一个StackOverflow错误(例如,没有JVM调优的rangeRecusrsive(1,10000)).如果您查看内置List.range的源码(https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/immutable/List.scala#L1),您会看到使用循环和变量. 我的问题是如何管理Scala学习内容的影响,促进vals和递归知道这样的代码可以由于递归的次数而中断? 解决方法
Scala的好处是,你可以轻松地进入它.从开始,您可以编写循环,并且随着语言越来越舒服,就可以进行更多的递归操作.您不能使用更纯粹的功能语言(如Clojure或Haskell)来执行此操作.换句话说,你可以很好地享受不变性和价值,随后再递交.
当您开始递归时,您应该查找尾部调用递归.如果递归调用是函数中的最后一个调用,则Scala编译器会将其优化为字节码循环.这样,你不会得到StackOverflowErrors.此外,如果将@tailrec注释添加到递归函数中,则编译器会警告您,如果您的函数不是尾调用递归. 例如,您的问题中的函数不是尾调用递归.看起来像rangeRecursive的调用是函数中的最后一个,但是当这个调用返回时,它仍然需要将start添加到调用的结果.因此,它不能是尾调用递归:当调用返回时,它仍然需要工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |