Download presentation

Presentation is loading. Please wait.

Published byRafael Dudgeon Modified about 1 year ago

1
Recursion in Scala

2
2 Definitions 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

3
3 Recursive functions...er, methods The mathematical definition of factorial is: We can define this in Scala as: 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 1, if n <= 1 n * factorial(n-1) otherwise factorial(n) is

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

5
5 The four rules Do the base cases first Recur only with simpler cases Don't modify and use non-local variables 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

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

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

8
8 Infinite recursion The following is the recursive equivalent of an infinite loop: def toInfinityAndBeyond (x: Int): Int = toInfinityAndBeyond(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 def collatz(n: Int): Int = if (n == 1) 1 else if (n % 2 == 0) collatz(n / 2) else collatz(3 * n - 1)

9
Why recursion? As long as we are dealing with linear data structures (sequences), there isn’t much need for recursion Although it can be very handy for lists Next semester we will be working with many recursively-defined data structures Example: A binary tree is a data structure consisting of 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

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

11
Merging sorted lists scala> def merge(list1: List[Int], list2: List[Int]): List[Int] = { | if (list1 isEmpty) list2 | else if (list2 isEmpty) list1 | else if (list1.head merge(List(1, 4, 5, 7, 11), List(2, 3, 5, 10, 20)) res1: List[Int] = List(1, 2, 3, 4, 5, 5, 7, 10, 11, 20) 11

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

13
The End 13

Similar presentations

© 2016 SlidePlayer.com Inc.

All rights reserved.

Ads by Google