2016-06-30 6 views
4

Scalaのimplicitlyの呼び出しが実行時にnullを返すと、私は最近驚いていました。暗黙的なスコープで暗黙的なインスタンスが利用できない場合、コードをコンパイルしてはならないと考えると、そうは考えられませんでした。暗黙のうちにnullを返すことはいつ可能ですか?これはコンパイラの制限ですか、これが予期される動作ですか?Scalaが暗黙的にnullを返すことはいつですか?

ここにいくつかの文脈が役立ちます。私は、任意のネストされたケースクラスを永続化するための型クラスインスタンスを導出するために無形を使用しています。ネストされたケースクラスが暗黙のうちに使用されると、ネストされたケースクラスが大きいかどうかを調べ始める場所が不明確になる可能性があるので、型クラスインスタンスが導出できるかどうかを確認すると便利です。

ので、例えば、私が持続しようとしていた場合:

case class Bar(i: Int, q: Qux) 
object Bar { 
    implicit val formatter = implicitly[MyFormatter[Bar]] 
} 

case class Foo(bar: Bar, baz: Baz) 

をコンパイラが私のフォーマッタMyFormatter[Foo]のインスタンスを導き出すことができませんでした、私は次のようなものを始めました

コンパイラがMyFormatter[Bar]という暗黙的なインスタンスを見つけることができないことをコンパイラに知らせることを期待しています。

代わりに、これはひどい考えであり、私のコードはコンパイルされていてはいけません(Quxのtypeclassインスタンスが派生できないため)、実行時にBar.formatterがnullでした。

+0

「MyFormatter」に関連するコードに問題があります。 _Something_はそれを暗黙的にしていますが、見ていないものを言うことは不可能です。 Scalaコンパイラは、それ自身で 'null 'のものを魔法のように作成することはありません。 –

+0

私はあなたが言っていることを聞いていますが、暗黙的なval oyVey:MyFormatter [Bar] = null(これはできないと約束しています)のような定義が不十分です。 –

+3

コードを見ずにわかりません。暗黙のうちに魔法を与えない。 'println(scala.reflect.runtime.universe.reify(暗黙的に[MyFormatter [Foo]]))'を実行して、どこから解決されているかを調べることができます。 –

答えて

8

暗黙の定義は再帰的です。

scala> class C ; object C { implicit val cs: List[C] = implicitly[List[C]] } 
defined class C 
defined object C 

scala> C.cs 
res0: List[C] = null 

範囲がcsだけでなく、オブジェクトCはリスト[C]の暗黙のスコープにあります。

また、インプリシットのタイプを指定することが推奨されます。時には推論が働くことが必要です。いつかそれが必要になるでしょう。

+0

直接チケットhttps://issues.scala-lang.org/browse/SI-9109。 –

関連する問題