【Scala】再帰的定義

Scalaで再帰プログラミング】を読みながらまとめる


再帰的定義ってなに

関数の定義の中にその関数自身が現れる定義のこと。
例えば階乗 n! を求める関数 fact を作るとき

scala> def fact(n: Int):BigInt = if (n==0) 1 else n * fact(n-1)
fact: (n: Int)BigInt

scala> fact(5)  
res: BigInt = 120



factという関数の定義中にfactという関数を使用している。これが再帰的定義
あと、再帰的定義をするときは返り値を設定すること。

scala> def fact(n: Int) = if (n==0) 1 else n * fact(n-1)
<console>:8: error: recursive method fact needs result type
       def fact(n: Int) = if (n==0) 1 else n * fact(n-1)
//error



再帰的定義を使って色々な関数を作るよ

フィボナッチ数を計算する関数 fib を作る

scala> def fib(n:BigInt):Int = if(n<2) 1 else fib(n-1) + fib(n-2)
fib: (n: BigInt)Int

scala> fib(6)
res: Int = 13



リストでも再帰的定義。
リストの総和を求める関数 sum を作る

scala> list
res: List[Int] = List(1, 2, 3, 4)

scala> def sum(xs:List[Int]):Int = if (xs.isEmpty) 0 else xs.head + sum(xs.tail)
sum: (xs: List[Int])Int

scala> sum(list)
res: Int = 10



xs.head は最終的に空リストを参照してしまうため、、空リストだったときのパターンを作らないとerror吐かれる。

scala> def sum(xs:List[Int]):Int = xs.head + sum(xs.tail)
sum: (xs: List[Int])Int

scala> sum(list)
java.util.NoSuchElementException: head of empty list



リストの要素をインクリメントさせる関数 mapInc

scala> def mapInc(xs:List[Int]):List[Int]  = if(xs.isEmpty) Nil else xs.head +  1 :: mapInc(xs.tail)
mapInc: (xs: List[Int])List[Int]

scala> mapInc(list)
res: List[Int] = List(2, 3, 4, 5)





リストで再帰的定義を使うタイミングなんてあまりない気がする