Recursion in Scala Definitions n n n A

  • Slides: 13
Download presentation
Recursion in Scala

Recursion in Scala

Definitions n n n A recursive method is a method that calls itself A

Definitions n n n A recursive method is a method that calls itself A method is indirectly recursive if it calls a method that calls a method. . . that calls the original method Mutually recursive methods are methods that call each other 2

Recursive functions. . . er, methods n The mathematical definition of factorial is: factorial(n)

Recursive functions. . . er, methods n The mathematical definition of factorial is: factorial(n) is n We can define this in Scala as: n n n 1, if n <= 1 n * factorial(n-1) otherwise def factorial(n: Long) = { if (n <= 1) 1 else n * factorial(n – 1); } This is a recursive function because it calls itself Recursive functions are legal in almost all languages 3

Anatomy of a recursion Base case: does some work without making a recursive call

Anatomy of a recursion Base case: does some work without making a recursive call def factorial(n: Long) = { if (n <= 1) 1 else n * factorial(n – 1) } Extra work to convert the result of the recursive call into the result of this call Recursive case: recurs with a simpler parameter 4

The four rules n n n Do the base cases first Recur only with

The four rules n n n Do the base cases first Recur only with simpler cases Don't modify and use non-local variables n n n You can modify them or use them, just not both Remember, parameters count as local variables, but if a parameter is a reference to an object, only the reference is local—not the referenced object Don't look down 5

Another simple example n The following counts the number of elements in a list

Another simple example n The following counts the number of elements in a list n n n scala> def count(list: List[Any]): Int = { | if (list. is. Empty) 0 | else 1 + count(list. tail) |} count: (list: List[Any])Int scala> count(List("ace", "deuce", "trey")) res 2: Int = 3 Note: For a recursive method, you must specify the return type 6

Parts of the simple example def count(list: List[Any]): Int = { | if (list.

Parts of the simple example def count(list: List[Any]): Int = { | if (list. is. Empty) 0 | else 1 + count(list. tail) |} Extra work to convert the result of the recursive call into the result of this call Base case: does some work without making a recursive call Recursive case: recurs with a simpler parameter 7

Infinite recursion n The following is the recursive equivalent of an infinite loop: n

Infinite recursion n The following is the recursive equivalent of an infinite loop: n n n def to. Infinity. And. Beyond (x: Int): Int = to. Infinity. And. Beyond(x) This happened because we recurred with the same case! While this is obviously foolish, infinite recursions can happen by accident in more complex methods n def collatz(n: Int): Int = if (n == 1) 1 else if (n % 2 == 0) collatz(n / 2) else collatz(3 * n - 1) 8

Why recursion? n As long as we are dealing with linear data structures (sequences),

Why recursion? n As long as we are dealing with linear data structures (sequences), there isn’t much need for recursion n n Although it can be very handy for lists Next semester we will be working with many recursively-defined data structures n Example: A binary tree is a data structure consisting of n n A value An optional left binary tree, and An optional right binary tree The best way to work with recursively-defined data structures is with recursive functions 9

Binary trees n scala> class Binary. Tree(value: Any, left: Option[Binary. Tree], right: Option[Binary. Tree])

Binary trees n scala> class Binary. Tree(value: Any, left: Option[Binary. Tree], right: Option[Binary. Tree]) { | override def to. String = s"($value $left $right)" | } defined class Binary. Tree scala> val l = new Binary. Tree("I'm left", None) l: Binary. Tree = (I'm left None) scala> val r = new Binary. Tree("I'm right", None) r: Binary. Tree = (I'm right None) scala> val root = new Binary. Tree("I'm the root!", Some(l), Some(r)) root: Binary. Tree = (I'm the root! Some((I'm left None)) Some((I'm right None))) 10

Merging sorted lists n scala> def merge(list 1: List[Int], list 2: List[Int]): List[Int] =

Merging sorted lists n scala> def merge(list 1: List[Int], list 2: List[Int]): List[Int] = { | if (list 1 is. Empty) list 2 | else if (list 2 is. Empty) list 1 | else if (list 1. head < list 2. head) list 1. head : : merge(list 1. tail, list 2) | else list 2. head : : merge(list 1, list 2. tail) | } warning: there were 2 feature warning(s); re-run with -feature for details merge: (list 1: List[Int], list 2: List[Int])List[Int] scala> merge(List(1, 4, 5, 7, 11), List(2, 3, 5, 10, 20)) res 1: List[Int] = List(1, 2, 3, 4, 5, 5, 7, 10, 11, 20) 11

Reprise n n Do the base cases first Recur only with a simpler case

Reprise n n Do the base cases first Recur only with a simpler case Don't modify and use nonlocal variables Don't look down 12

The End 13

The End 13