Scala のオプションを理解する

Suraj P 2023年1月30日
  1. Scala の Option
  2. Scala で Option の値を取得する
  3. Scala のコンテナとしての Option
Scala のオプションを理解する

この記事では、Scala でオプションのデータ要素を操作する方法を学びます。Scala の Option は、堅牢なコードを書くのに役立ちます。

Scala の Option

Scala の Option[T] は、指定されたタイプの 0 個または 1 個の値を格納する container です。Scala の Option を使用してオプションの値を管理することで、次の 2つのことを保証できます。

  1. タイプセーフティ:オプションの値をパラメータ化できます。
  2. 機能認識:Option タイプは、プログラムで作成されるバグを少なくするための多くの機能機能を提供します。

Scala では、Option[T]Some[T] または None[T] オブジェクトのいずれかで表されます。ここで、scala.Option は抽象的で拡張された基本クラスであり、Scala の Option をコンテナーのように動作させます。

Option クラスとそのサブクラスには具象型が必要であることに注意してください。これらは、明示的にすることも、次の構文のように推測することもできます。

例:

val obj1: Option[Int] = None
val obj2 = Some(100)

ここで、obj1obj2Option[Int] のオブジェクトです。よくある質問の 1つは、Option一部なしかを確認する方法です。

この問題を解決するために、以下の機能があります。

  1. isEmpty:オブジェクトが None の場合、このメソッドは true を返します。
  2. nonEmpty:オブジェクトが Some の場合、このメソッドは true を返します。
  3. isDefined:オブジェクトが Some の場合、このメソッドは true を返します。

Scala で Option の値を取得する

get メソッドを使用して、Options 値を取得できます。get メソッドが None のオブジェクトで呼び出されると、NoSuchElementException がスローされます。これは成功バイアスとも呼ばれます。

サンプルコード:

val obj1: Option[Int]= ...

val v1 = if (obj1.isDefined)
{
  obj1.get
}
else
{
  0
}

上記のコードは、パターンマッチングを使用して記述することもできます。

サンプルコード:

val obj1: Option[Int]= ...

val v1 = obj1 match {
  case Some(temp) =>
    temp
  case None =>
    0
}

値を取得するための getOrElseorElse などの他のメソッドもあります。

  1. getOrElse:このメソッドは、オブジェクトが Some の場合に値を取得します。それ以外の場合は、デフォルト値を返します。
  2. orElse:このメソッドは、オブジェクトが Some の場合に値を取得します。それ以外の場合は、alternate オプションを返します。

オプションの値が設定されていない場合、デフォルト値を返すことができるため、getOrElse メソッドは非常に便利です。

構文:

val v1 = obj1.getOrElse(0)

Scala のコンテナとしての Option

Scala では、Option が別の値を格納するコンテナであることを見てきました。ちょうど List をトラバースするように、Option をトラバースすることができます。

このコンテナのいくつかのメソッドを見てみましょう。Scala の Option.map メソッドの構文:

final def map[Y](f: (X) => Y): Option[Y]

サンプルコード:

val obj1: Option[Int] = Some(100)
assert(obj1.map(_.toString).contains("100"))
assert(obj1.map(_ * 2.0).contains(200))

val obj2: Option[Int] = None
assert(obj2.map(_.toString).isEmpty)

上記の例では、Option.map メソッドを使用して、含まれている値を別のタイプに変換しました。Option.map メソッドを使用して、プログラムのフロー制御に影響を与えることもできます。

サンプルコード:

val obj1: Option[Int] = Some(10)
val obj2: Option[Int] = None

def mul(n: Int): Int = n * 2

assert(obj1.map(mul).contains(20))
assert(obj2.map(mul).isEmpty)

ここでは、Option[Int] の 2つのオブジェクトを作成しました。最初のオブジェクトの値は 10 で、2 番目のオブジェクトは空です。次に、入力に 2 を掛けるメソッド mul を定義しました。

最後に、mul メソッドを使用して obj1obj2 をマップします。obj1 をマッピングすると Some(20) が得られ、obj2 をマッピングすると None が得られます。

ここで注意すべきことの 1つは、2 番目の呼び出し obj2.map(mul) では、mul メソッドがまったく呼び出されないことです。フィルタリングによるフロー制御も可能です。

これを行うには多くの方法があります。

  1. filter:このメソッドは、Options 値が Some であり、提供された関数が true を返す場合、Option を返します。
  2. existsOption が設定され、提供された関数が true を返す場合、このメソッドは true を返します。
  3. forallexists メソッドと同じように動作します。

これらの関数を使用すると、コードを非常に簡潔に記述できます。

最高得点のチームを見つける例を見てみましょう。

サンプルコード:

 def highScoringTeam(playerA: Player, playerB: Player, tournament: Tournament): Option[(Player, Int)] =
 { getTopScore(playerA, tournament).foldRight(getTopScore(playerB, tournament)) {
      case (playerAInfo, playerBInfo) => playerBInfo.filter {
        case (_, scoreB) => scoreB > playerAInfo._2
      }.orElse(Some(playerAInfo))
    }
  }

上記のコードでは、Option をコレクションとして使用できることを利用しています。唯一の違いは、オプションは最大で 1つの値を持つことができるということです。

著者: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub