気になります:
_scala> Some(null) == None
res10: Boolean = false
_
Some(null)
がNone
に変換されないのはなぜですか?
Option(null)
を使用して目的の効果を達成し、None
を返す必要があります。
Some(null)
は定義された値(したがってOption
)で新しいSome
を作成するだけで、実際にはnull
であり、作成する正当な理由はほとんどありません。実際のコードではこのように。
残念ながら、null
は、任意のAnyRef
タイプに対して有効な値です。これは、ScalaとJavaの相互運用性の結果です。したがって、タイプA
のオブジェクトを受け取り、それを内部的にOption
内に格納するメソッドは、そのオプション内にnull
を格納する必要があるかもしれません。
たとえば、リストの先頭を取得し、その先頭がストア内のキーに対応しているかどうかを確認し、対応している場合はtrueを返すメソッドがあるとします。このように実装するかもしれません:
def isFirstAcceptable(list: List[String], keys: Set[String]): Boolean =
list.headOption map keys getOrElse false
だから、これが...list
とkeys
の内部がいくつかのJava APIから来ている場合、両方にnull
が含まれている可能性があります!Some(null)
が不可能な場合は、isFirstAcceptable(List[String](null), Set[String](null))
は、false
の代わりにtrue
を返します。
スレッドの他のメンバーは、Some(null)
が存在する理由を説明するのに良い仕事をしていると思いますが、たまたまどこかでSome(null)
を取得していて、それをNone
にすばやく変換したい場合、私は以前にこれを行いました:
scala> val x: Option[String] = Some(null)
x: Option[String] = Some(null)
scala> x.flatMap(Option(_))
res8: Option[String] = None
そして、開始Option
が正当なnull以外の値である場合、おそらく期待どおりに機能します。
scala> val y: Option[String] = Some("asdf")
y: Option[String] = Some(asdf)
scala> y.flatMap(Option(_))
res9: Option[String] = Some(asdf)
ScalaのWTFの多くは、Javaとの互換性の必要性に起因する可能性があります。 null
は、Javaで値として使用されることが多く、おそらく値がないことを示します。たとえば、hashMap.get(key)
はnull
を返します。キーが一致しない場合。
これを念頭に置いて、nullを返すメソッドをOption
でラップすることで考えられる次の値を検討してください。
_if (b) Some(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked;
Some(value) // the method was invoked and a value returned; or
Some(null) // the method was invoked and null was returned.
_
この場合、Some(null)
はNone
とは十分に異なるようであり、言語で許可する必要があります。
もちろん、これがあなたのケースで望ましくない場合は、単に以下を使用してください。
_if (b) Option(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked or the mapped value was null; or
Some(value) // the method was invoked and a value returned
_
オプションはファンクターと見なされ、ファンクターであるということは次のことを意味します。
unit
関数があります(Scalaではapply
または単にOption("blah")
)T=>B
_から変換するmap
関数がありますが、コンテキストはありませんこのトピックの主要部分は#2-Option(1).map(t=>null)
はコンテキストを変換できません。 Some
はそのままにしておく必要があります。そうでなければ、それは結合法則にブレーキをかけます!
次の法律の例を考えてみてください。
_def identity[T](v: T) = v
def f1(v: String) = v.toUpperCase
def f2(v: String) = v + v
def fNull(v: String): String = null
val opt = Option("hello")
//identity law
opt.map(identity) == opt //Some(hello) == Some(hello)
//associative law
opt.map(f1 _ andThen f2) == opt.map(f1).map(f2) //Some(HELLOHELLO) == Some(HELLOHELLO)
opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) == Some(nullnull)
_
しかし、Option("hello").map(t=>null)
がNone
を生成した場合はどうなるでしょうか。結合法則は破られます:
_opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) != None
_
それは私の考えです、間違っているかもしれません
簡単な思考実験として、長さ5と長さ20の2つの文字列リストを考えてみましょう。
JVMで実行しているため、これらのリストの1つに有効な要素としてnull
を挿入することができます。したがって、それを要素#10として長いリストに入れます。
では、次の2つの式から返される値の違いは何でしょうか。
EDIT:get
をlift
に交換しました、私は地図を考えていました...
shortList.lift(10) //this element doesn't exist
longList.lift(10) //this element exists, and contains null