ScalaのOption.mapとKotlinのletの話

先日、Scala初心者向けの勉強会 を開催してそこで「OptionのforeachはKotlinのletみたいな使い方をするものですか?」という質問をうけたのですが、そのときKotlinのletをきちんと思い出せないままズレた回答をしてしまったので、とりいそぎブログを書くことにしました。(すみません・・・) 勢いで書いているので語弊がある部分があればご指摘いただけると幸いです。

が、foreachは戻り値がUnit型なので比較するならmapかな?と思いますので、map関数の方で似たようなコードを書いてみました。(Kotlinのletは最後の評価値が戻り値となるので。)

下は、ScalaのOption[String]にmap関数で中の値に文字列を連結、そのあと値をOptionから取り出している例です。

val name: Option[String] = Some("きの子")
val greetOpt = name.map(n => s"${n}さんこんにちは")  // greet: Option[String] = Some(きの子さんこんにちは)
val greet = greetOpt.getOrElse("なまえがないよ")  // Optionから値をとりだした。 res1: String = きの子さんこんにちは

次は、KotlinのNullableのStringに、値がある場合はlet関数で文字列を連結している例になります。

val name: String? = "きの子"
val greet = name?.let { n -> "${n}さんこんにちは" }  // nameに値が入っている場合にlet関数を適用している

やっていることは似たような処理ですが、Scalaの方は name.map(n => s"${n}さんこんにちは") の結果はOption型の値となります。 値をOption型でラップした状態のまま処理をチェインしていって、最後に値を getOrElse で取り出すという書き方をよくします。

一方Kotlinは ?. を利用することでnameに値が入っている場合のみ、その値に let 関数を適用している形になっています。 let は全オブジェクトに生えている標準の拡張関数です。なのでここで呼び出すことができています。

上記のように、KoltinのletはNullableな値に ?. と組み合わせて、nullではない場合のみ処理を適用という使い方をよくしますし、そういう意味ではScalaのOption.mapと確かににたような使い方をしますが、

  • ScalaのOption型は値を包んでいるイメージ。値があるときはSomeで値をラップ。nullのときはNone。中の値を使用するときはSomeから値を取り出す必要がある。Option型にはコレクション同様の mapforeach といったメソッドがある。
  • KotlinのNullableは値がnullである可能性があることを示す型。 ?. で値がnullではない場合のみ後ろの処理を適用することができる。let は全オブジェクトに生えている標準の拡張関数。Nullable特有の機能というわけではない。

要は用途は似ているけど、結構違うよということでした。