再帰でsumを実装してみる
配列に対しての処理パターン増やしたかったのと、 再帰で詰まって放置したことがあったので克服のため、 再帰処理で合計を出すsumを実装してみる
参考資料
「case x::xs =>」でなぜリストがマッチできるのか(infix-operation-patterns)
- 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を処理にかける => 空になるまで繰り返し => 空の状態から巻き戻すイメージ