for-comprehensionの中でnullsと型の注釈を扱うときに、奇妙な動作のように思えるものを理解しようとしています。一例として、型の注釈での理解のためのスカラーの例外
:期待で
def f(): String = null
for {
a <- Option("hello")
b = f()
} yield (a, b)
結果:
//> res0: Option[(String, String)] = Some((hello,null))
しかし、私はb
def f(): String = null
for {
a <- Option("hello")
b: String = f()
} yield (a, b)
の型に型注釈を追加した場合、私は取得実行時例外:
//> scala.MatchError: (hello,null) (of class scala.Tuple2)
どうしてですか?最初の例でb
暗黙のうちにタイプString
ではありませんか? 2番目の例の明示的な型アノテーションは何を変更しますか?
(注意、例はScalaの2.11.4で行った)
あなたはREPLで 'reify'使用して見ることができるように、第2の例では、試合にコンパイル:'インポートscala.reflect.runtime.universeを._; reify {for {...}} '。私はなぜあなたに言ってもらえません。 AIUIの 'null'は、' b'が 'String'のコンパイル時の型を持っていても、マッチングが実行時の型(または値)に作用するので一致しません。これはある意味では型システムの穴であり、スカラーコードは一般的にヌルの使用を避けるべきです。 – lmm
私はnullsのファンではない、私を信じて!私がこれを見つけた実際のコードでは、私はいくつかのレガシーJavaコードと統合するために 'Try'sを使っていました。しかし、nullは私にとっては偶然であるように思えます。私が気づいているのは、タイプ特異性を増やすと(直感的ではない)実行時例外が発生するということです。 –
'for' /' yield'に型を入れることは、パターンマッチをもたらすという奇妙なことです。式の "普通の"型では問題はありません。私が言うことは残念ですが、おそらくこの段階で変更することはできません。私はこの理由でfor/yieldの左側にタイプを与えることを避ける傾向があります:/ – lmm