getOrElseについて。
scala> val a = Some("hoge") a: Some[String] = Some(hoge) scala> a.getOrElse(Some("fuga")) res3: java.io.Serializable = hoge scala> a.getOrElse("fuga") res4: String = hoge
で、結果の型がStringではなくSerializableになるのがよくわからんかったので、Gitterに質問してみました。
scala> a.getOrElse(Some("fuga"))
res3: java.io.Serializable = hoge
よしださんからの回答。
def getOrElse(default: => A): A じゃなく def getOrElse[B >: A](default: => B): B と定義されてるからですね https://github.com/scala/scala/blob/v2.11.7/src/library/scala/Option.scala#L120 どちらで定義するべきかはトレードオフなのでなんとも言えないですが、scalazの場合はその上記のSerializableになるミス(?)を避けるため、違う定義になってます https://github.com/scalaz/scalaz/blob/v7.1.4/core/src/main/scala/scalaz/Maybe.scala#L31
がくぞさんからの回答。
String と Option[String] の共通の型が Serializable だからじゃないでしょうか 必用なのは getOrElse じゃなくて orElse なのでは? https://github.com/scala/scala/blob/v2.11.7/src/library/scala/Option.scala#L288
ということで、
- def getOrElseB >: A: B なので、defaultの型はB(Aの継承元)
- StringとOption[String]の継承元はSerializable
むろん、getOrElseで使われるOptionの中の値は何でもよくて、還元するとこうなる。
scala> class A;class B extends A;class C extends A; Option(new B).getOrElse(new C) defined class A defined class B defined class C res0: A = B@5474c6c
よしださん、がくぞさん、いつもありがとうございます。
(Gitterの発言ってブログに埋め込めないのかな)
追記
Scalaのソースコードを読むってところでいうと、やっぱり上限境界、下限境界などの知識が必要で、昔の勉強会でちょっと話があったことを思い出しました。