18

このコードがコンパイルに失敗するのに、指定された行のコメントを外すと正常にコンパイルされるのはなぜですか? (私は毎晩 Scala 2.8 を使用しています)。明示的に呼び出すとstring2Wrapper、その時点から暗黙的に使用できるようになります。

class A {
  import Implicits.string2Wrapper
  def foo() {
     //string2Wrapper("A") ==> "B" // <-- uncomment
  } 
  def bar() {
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  }
  object Implicits {
    implicit def string2Wrapper(s: String) = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }
}

編集:Martin Oderskyのコメントへのポインタを含む、これまでの回答に感謝します。

「明示的な結果の型のない暗黙の変換は、独自の定義に続くテキストでのみ表示されます。そのようにして、循環参照エラーを回避します。」

1) 「循環参照エラー」の危険性とは何か、および 2) 明示的な呼び出しが違いを生むのはなぜですか?

4

3 に答える 3

21

string2Wrapper の戻り値の型を明示的に指定すると、問題が解決します。

class A {
  import Implicits._

  def bar() {    
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  }
  object Implicits {
    implicit def string2Wrapper(s: String): Wrapper = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }
}

Implicits前に定義するbarこともできます:

class A {
  object Implicits {
    implicit def string2Wrapper(s: String) = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }

  import Implicits._

  def bar() {    
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  } 
}

現在のスコープ内で以下に定義されている暗黙的な変換に依存する必要がある場合は、その戻り値の型に注釈を付けてください。これは以前にメーリング リストで取り上げられたことがあるはずであり、バグではなく予想される動作である可能性があります。しかし、私は現時点でそれを見つけることができません。fooの明示的な呼び出しは、 の戻り値の型の型推論をトリガーすると思います。barこれは、 の内容を入力するときに有効になりますbar

アップデート

循環参照エラーの危険性は何ですか?

暗黙的なメソッドの本体は、暗黙的な変換を必要とするメソッドを呼び出す場合があります。これらの両方に推論された戻り値の型がある場合は、行き詰まりです。これはあなたの例には当てはまりませんが、コンパイラはこれを検出しようとしません。

明示的な呼び出しが違いを生むのはなぜですか?

以前の明示的な呼び出しは、暗黙的なメソッドの戻り値の型の型推論をトリガーします。ここにロジックがありますImplicits.isValid

sym.isInitialized ||
      sym.sourceFile == null ||
      (sym.sourceFile ne context.unit.source.file) || 
      hasExplicitResultType(sym) ||
      comesBefore(sym, context.owner)

更新 2

この最近のバグは関連しているようです: https://lampsvn.epfl.ch/trac/scala/ticket/3373

于 2010-04-28T16:19:23.893 に答える
12

毎晩 1 回だけだったら、代わりに昨日追加したエラー メッセージが表示されたはずです。

<console>:11: error: value ==> is not a member of java.lang.String
 Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
           "A" ==> "B"
           ^
<console>:12: error: value ==> is not a member of java.lang.String
 Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
           "B" ==> "C"
           ^
<console>:13: error: value ==> is not a member of java.lang.String
 Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
           "C" ==> "D"
           ^
于 2010-04-28T18:32:04.430 に答える
3

あなたがobject Implicits最初に置くなら、それはうまくいきます。これは、複数のコンパイラ パスを作成するためのロジックのバグのように見えます。string2Wrapperいつコンパイルするかを本当に知らなくても逃げることができると想定していますbar。私の推測では、それを使用すると、string2Wrapper が実際に何であるかを知らずに逃げることができないことがわかり、実際にコンパイルされImplicits、それ==>が String で暗黙的に定義されていることがわかります。

編集: Retronym が投稿した内容に基づいて、バグではなく「機能」である可能性があります。まだ私には厄介なようです!

于 2010-04-28T16:22:08.513 に答える