- Learn Scala Programming
- Slava Schmidt
- 239字
- 2021-06-10 19:35:50
Recursion
Recursion is used to implement recurring logic without relying on loops and the internal states associated with them. The recursive behavior is defined by two properties:
- Base case: The simplest terminating case, in which no recursive calls are needed anymore
- Recursive case: The set of rules describing how to reduce any other state to the base case
One of the possible examples for recursive implementation can be reversing a string. The two recursive properties would be:
- The base case is an empty or single-char string. In this case, the reversed string is just the same string as given.
- The recursive case for the string of length N can be reduced to the case of a string of length N-1 by taking the first char of the string and appending it to the reversed tail of the given string.
This is how we implement this logic in Scala:
def reverse(s: String): String = {
if (s.length < 2) s
else reverse(s.tail) + s.head
}
So, this is easier implemented than explained, right?
One important aspect of our implementation in a recursive case is that it first makes the recursive call and then adds the rest of the string to the result. Such functions are head-recursive (but usually just called recursive) in the sense that the recursive call stays in the head of the computation. This works in a similar way to the depth-first algorithm, with the implementation first going down to the terminal case and then building up the result from the bottom up:
scala> println(reverse("Recursive function call"))
llac noitcnuf evisruceR
The nested function calls are naturally kept in the stack during runtime. Because of this, functions that work fine for inputs of smaller size might blow up the stack for bigger inputs, crashing the whole application:
scala> println(reverse("ABC" * 100000))
java.lang.StackOverflowError
at scala.collection.StringOps$.slice$extension(StringOps.scala:548)
at scala.collection.StringOps$.tail$extension(StringOps.scala:1026)
at ch03.Recursion$.reverse(Recursion.scala:7)
at ch03.Recursion$.reverse(Recursion.scala:7)
at ch03.Recursion$.reverse(Recursion.scala:7)
...
It is possible to increase the size of memory reserved for a stack in JVM, but often there is a better solution—tail recursion.
- Advanced Quantitative Finance with C++
- Three.js開發指南:基于WebGL和HTML5在網頁上渲染3D圖形和動畫(原書第3版)
- JavaScript+jQuery開發實戰
- Android 7編程入門經典:使用Android Studio 2(第4版)
- HTML5+CSS3 Web前端開發技術(第2版)
- 微服務架構深度解析:原理、實踐與進階
- Instant PHP Web Scraping
- Hands-On GUI Programming with C++ and Qt5
- Unity Character Animation with Mecanim
- 微信小程序開發實戰:設計·運營·變現(圖解案例版)
- 百萬在線:大型游戲服務端開發
- ArcPy and ArcGIS(Second Edition)
- Ubuntu Server Cookbook
- 大話C語言
- 現代JavaScript編程:經典范例與實踐技巧