Scala Language
オプションクラス
サーチ…
構文
class Some [+ T](value:T)はOption [T]を拡張します。
オブジェクトなし拡張オプション[何もありません]
オプション[T](値:T)
指定された値に応じて
Some(value)
またはNone
を作成するコンストラクタ。
コレクションとしてのオプション
Option
Sが容易に0個または1個のアイテムをコレクションとしてオプションを表示することによって理解することができるいくつかの有用な高次の機能を持っている-ここでNone
空のコレクションのように動作せず、 Some(x)
、単一のアイテム、のコレクションのように振る舞うx
。
val option: Option[String] = ???
option.map(_.trim) // None if option is None, Some(s.trim) if Some(s)
option.foreach(println) // prints the string if it exists, does nothing otherwise
option.forall(_.length > 4) // true if None or if Some(s) and s.length > 4
option.exists(_.length > 4) // true if Some(s) and s.length > 4
option.toList // returns an actual list
Nullの代わりにOptionを使う
Java(および他の言語)では、 null
を使用することは、参照変数に値が添付されていないことを示す一般的な方法です。 Scalaでは、 Option
を使用する方がnull
を使用するよりも優先されnull
。 Option
は 、 null
可能性のある値をラップしnull
。
None
はnull参照をラップするOption
サブクラスです。 Some
は、null以外の参照をラップするOption
サブクラスです。
参照の折り返しは簡単です。
val nothing = Option(null) // None
val something = Option("Aren't options cool?") // Some("Aren't options cool?")
これは、null参照を返す可能性のあるJavaライブラリを呼び出すときの典型的なコードです。
val resource = Option(JavaLib.getResource())
// if null, then resource = None
// else resource = Some(resource)
getResource()
がnull
値を返した場合、 resource
はNone
オブジェクトになります。それ以外の場合は、 Some(resource)
オブジェクトになります。 Option
を処理するための好ましい方法は、 Option
タイプ内で使用可能な高次関数を使用することです。たとえば、値がNone
でないかどうかをチェックする場合( value == null
場合と同様)、 isDefined
関数を使用します。
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isDefined) { // resource is `Some(_)` type
val r: Resource = resource.get
r.connect()
}
同様に、 null
参照をチェックするには、次のようにしnull
。
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isEmpty) { // resource is `None` type.
System.out.println("Resource is empty! Cannot connect.")
}
Option
をモナドとして扱い、 foreach
を使ってOption
ラップされた値に対する条件付き実行を扱うことが望ましい( '例外的な' Option.get
メソッドを使用せずに)。
val resource: Option[Resource] = Option(JavaLib.getResource())
resource foreach (r => r.connect())
// if r is defined, then r.connect() is run
// if r is empty, then it does nothing
Resource
インスタンスが必要な場合( Option[Resource]
インスタンスに対して)、 Option
を使用してnull値から保護することはできます。ここでgetOrElse
メソッドはデフォルト値を提供します:
lazy val defaultResource = new Resource()
val resource: Resource = Option(JavaLib.getResource()).getOrElse(defaultResource)
JavaコードはScalaのOption
容易に扱うことができないので、値をJavaコードに渡すときは、 Option
をアンラップして、適切な場合にはnull
または適切なデフォルトを渡してください。
val resource: Option[Resource] = ???
JavaLib.sendResource(resource.orNull)
JavaLib.sendResource(resource.getOrElse(defaultResource)) //
基本
Option
は、単一の値を含むか、まったく値を持たないデータ構造です。 Option
は、0または1要素のコレクションと考えることができます。
Optionは2つの子を持つ抽象クラスです: Some
とNone
。
Some
は単一の値を含み、 None
は値を含みません。
Option
は、具体的な値の欠如を表すためにnull
を使用する式で便利です。これは、 NullPointerException
FlatMap
、 Map
、 FlatMap
などのコンビネータを使用して値を返さない多くの式の合成を可能にします。
マップの例
val countries = Map(
"USA" -> "Washington",
"UK" -> "London",
"Germany" -> "Berlin",
"Netherlands" -> "Amsterdam",
"Japan" -> "Tokyo"
)
println(countries.get("USA")) // Some(Washington)
println(countries.get("France")) // None
println(countries.get("USA").get) // Washington
println(countries.get("France").get) // Error: NoSuchElementException
println(countries.get("USA").getOrElse("Nope")) // Washington
println(countries.get("France").getOrElse("Nope")) // Nope
Option[A]
は封印されているため拡張できません。したがって、セマンティクスは安定しており、依存することができます。
内包のためのオプション
Option
は、 flatMap
メソッドがあります。これは、それらが理解のために使用できることを意味します。このようにして、再定義することなく、 Option
に取り組むために通常の関数を呼び出すことができます。
val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = Option(2)
val myResult = for {
firstValue <- firstOption
secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = Some(3)
値の1つがNone
の場合、計算の終了結果はNone
になります。
val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = None
val myResult = for {
firstValue <- firstOption
secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = None
注:このパターンはMonad
と呼ばれる概念のためにより一般的に拡張されています。 (より多くの情報は、理解とMonad
に関するページで利用できるはずです)
一般に、異なるモナドを混同して理解することは不可能です。しかし、 Option
は簡単にIterable
に変換できるので、 .toIterable
メソッドを呼び出すことで、 Option
とIterable
簡単に組み合わせることができます。
val option: Option[Int] = Option(1)
val iterable: Iterable[Int] = Iterable(2, 3, 4, 5)
// does NOT compile since we cannot mix Monads in a for comprehension
// val myResult = for {
// optionValue <- option
// iterableValue <- iterable
//} yield optionValue + iterableValue
// It does compile when adding a .toIterable on the option
val myResult = for {
optionValue <- option.toIterable
iterableValue <- iterable
} yield optionValue + iterableValue
// myResult: Iterable[Int] = List(2, 3, 4, 5)
小さな注記:われわれが理解のために定義したならば、私たちの選択肢は暗黙的に変換されるので、理解のためのもう一つの方法はコンパイルされるだろう。そのため、この.toIterable
(または使用しているコレクションに応じて対応する関数)を常に一貫性のために追加すると便利です。