2010-04-28 44 views
14

爲什麼此代碼無法編譯,但是當我取消註釋指定的行時,編譯成功? (我每晚都使用Scala 2.8)。看起來,明確呼籲string2Wrapper允許它從這一點隱含地使用。爲什麼這個明確的Scala調用方法可以隱式解決?

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) {} 
    } 
    } 
} 

編輯:謝謝你的答案至今,其中包括一個指向馬丁·奧德斯基的評論,

「沒有明確的結果類型的隱式轉換隻能在後面的文本 可見其自己的定義。這樣,我們可以避免循環參考錯誤。「

我還是有興趣找出1)「循環引用錯誤」的危險是什麼?2)爲什麼明確的調用有什麼區別?

回答

19

明確歸於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) {} 
    } 
    } 
} 

定義Implicitsbar也可以工作:

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" 
    } 
} 

如果您需要依靠電流範圍內的如下定義的隱式轉換,一定要標註它的返回類型。可以肯定的是,這已經出現在郵件列表中,並且可能是預期的行爲而不是bug。但目前我找不到它。我猜foo中的明確調用會觸發bar返回類型的類型推斷,然後在輸入bar的內容時有效。

UPDATE

什麼是循環引用錯誤的危險?

隱式方法的主體可能會調用需要隱式轉換的方法。如果這兩者都有推斷的返回類型,那麼你處於僵局。這不適用於你的例子,但編譯器不會嘗試檢測這個。

爲什麼顯式調用有所作爲?

顯式調用較早觸發對隱式方法的返回類型的類型推斷。下面是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

+0

這是(應該是)spec'ed。 Paulp最近剛剛發掘了這張票。讓我看看我是否找不到它... – 2010-04-28 17:17:41

+5

在這裏:https://lampsvn.epfl.ch/trac/scala/ticket/801 – 2010-04-28 17:22:30

3

如果你把object Implicits第一,它的工作原理。這看起來像是一個錯誤,在邏輯上做了多個編譯器傳遞;它假定它在編譯bar時可以不知道string2Wrapper。我的猜測是,如果你使用它,它知道它不知道string2Wrapper究竟是什麼,它實際上是編譯Implicits,然後意識到==>是在String上隱式定義的。

編輯:基於Retronym發佈的內容,也許它是一個「功能」而不是bug。對我來說似乎仍然很棘手!

12

如果你晚上晚上只是ooooone,你會看到我昨天添加的錯誤消息。

<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" 
     ^
相關問題