2010-10-18 44 views
11

任何人都可以使用Scala隱式轉換機制解釋我的情況。有一個代碼:關於Scala隱式轉換的問題非歧義性規則

object Main { 
    implicit val x:Int => String = v => "val" 
    implicit def y(v:Int) = "def" 

    def p(s:String) = print(s) 

    def main(args: Array[String]): Unit = { 
     p(1) 
    } 
} 

此代碼打印「val」。但是當我評論第二行時:

//implicit val x:Int => String = v => "val" 

代碼打印「def」。

因此,在這種情況下,隱式轉換(x和y)都是可能的。有一個非歧義規則 - 只有在沒有其他可能的插入轉換時纔會插入隱式轉換。根據這個規則,這個代碼不應該被編譯。但代碼已成功編譯並執行。我不明白?

謝謝。

回答

9

原因在Scala語言規範第6.26.2節中說明。

在將該方法視爲函數之前,需要通過執行eta-expansion將其轉換爲一個函數。因此需要應用更多的隱式轉換,因此選擇val

UPDATE:刪除有缺陷的示例。

不帶參數的方法的評估總是隱含地執行。

+0

你好,莫里茨。謝謝你的回答。因此,當Scala編譯器看到其類型與預期類型不匹配的表達式時,它會查找類型T => F的隱式轉換,如果未找到此類轉換,編譯器會嘗試在可用方法表達式上執行Eta擴展或空應用程序Scala語言規範中的「否則」一詞表示此操作將在之後執行)。我是否理解這一切? – 2010-10-18 21:54:02

+0

但在你的例子中,如果我評論//隱式val =「世界」,代碼將不會被編譯。 Scala編譯器似乎沒有考慮空應用程序。 – 2010-10-18 22:29:47

+0

當應用程序搜索隱式轉換,但僅用於填充其他隱式參數時,空應用程序實際上並未使用AFAICT。如果你編寫'implicit def i2s():Int => String = _.toString',這不會被認爲是從String到Int的轉換的候選對象。除此之外,它是正確的 - 如果不能直接評估值,則6.26.2列表中的轉換從上到下進行嘗試。 – Moritz 2010-10-18 22:45:34