再帰でsumを実装してみる

配列に対しての処理パターン増やしたかったのと、 再帰で詰まって放置したことがあったので克服のため、 再帰処理で合計を出すsumを実装してみる

参考資料

「case x::xs =>」でなぜリストがマッチできるのか(infix-operation-patterns)

  • head tailのパターンマッチについてのわかりやすい資料

目的

  • 配列に対して再帰するときのhead tailのパターンマッチについて覚えたい
  • 再帰の書き方を覚えたい
  • 再帰の考え方を学びたい

再帰って?

めっちゃざっくりいうと内部で自分自身を呼ぶメソッド - ルールさえわかれば簡潔に書ける

やってみる

やりたいこととしては、配列を渡してその合計を計算するメソッドの実装
イメージは
List[Int] => Intのメソッドを実装
 1 配列を渡す
 2 head / tailに分解
 3 tail を自分自身のメソッドに渡す (再帰)
 4 2 - 3 を配列が空になるまで再帰
 5 空の状態から再帰を巻き戻して計算していく

実装

object RecursiveSample{
    def run:Unit  = {
        println(recSum(List(1,2,3)))
    }
    def recSum(list:List[Int]):Int = {
        list match {
            case x::xs => x + recSum(xs) 
            case Nil => {
                println(s"Nil")
                0
            }
        }
    }
}

説明

  • case x::xs => これはListが空じゃない場合マッチする、x=head / xs = tailで分割
  • ちなみにList(1)の場合、x = 1 / xs = List() になる、Listに何かしら入ってればマッチする

考え方

headを取り出して、tailを自分自身の関数に渡す => 空になるまで繰り返し、空の初期値から巻き戻して計算するっていうイメージが個人的にしっくりくる

上でいうと下記の考え方 ()内の数値は、再帰処理に渡す値になる

1 / (2,3)に分割、tailを再帰
 => 2 / (3) に分割、tailを再帰
  => 3 / (0) に分割、tailを再帰
   => Nilなので0を返す、巻き戻し、結果の0を1階層上に返す
  => 3 / () = 0 で計算、結果の3を1階層上に返す
 => 2 / (3) = 3 で計算、結果の5を1階層上に返す
=> 1 / (2,3) = 5 で計算、結果の6が返る

うーんなんかわかりづらいけど スタックして巻き戻ってくるイメージが自分的にはわかりやすい メンテしてもっとわかりやすい説明できるようになりたい

今日の学び

  • list match の case x :: xs はhead / tailが存在する場合にあてはまる
  • 値が一つでもあれば当てはまる
  • headを取り出して、tailを処理にかけたい!というときに使える
  • 再帰は、headを取り出してtailを処理にかける => 空になるまで繰り返し => 空の状態から巻き戻すイメージ