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 (または使用しているコレクションに応じて対応する関数)を常に一貫性のために追加すると便利です。