2012-03-07 49 views
6

意外行爲我昨天有一個奇怪的錯誤,我最終淪爲下面的代碼:與implicits

Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> class X extends Function[String, Int] { def apply(x: String) = Integer.parseInt(x) } 
defined class X 

scala> implicit val x = new X 
x: X = <function1> 

scala> "56"/2 
res2: Int = 28 

我預計這將拋出一個異常,因爲字符串沒有一個/方法。相反,Scala將隱式變量作爲​​隱式方法處理(因爲它實現Function[String,Int])並將字符串「56」轉換爲整數56.

這是如何工作的?基於隱式搜索的規則,我並不認爲會考慮作爲函數的隱式變量。

+1

尼斯通知,謝謝。 – Odomontois 2012-03-07 18:10:05

+0

實際上,一個'隱含def'轉換的工作原理是因爲它會自動轉換成一個函數值(這就是_eta expansion_)。 – 2012-03-07 20:17:26

回答

7

隱式轉換的語義是你所觀察到什麼。如果通過隱式方法定義的隱式轉換,

trait A 
trait B 

implicit def aToB(a : A) : B = new B {} 

你會看到,你現在有一個隱含的函數值A => B

scala> implicitly[A => B] 
res1: A => B = <function1> 

而且,你有一個方法與束縛的視圖,

def foo[T <% B](t : T) : B = t 

這等同於,

def foo[T](t : T)(implicit conv : T => B) : B = conv(t) 

即。對應於視圖邊界的隱式參數與隱式方法定義產生的隱式函數值形式完全相同。

+0

那麼是隱式方法減少到函數類型的隱式變量?或者Scala處理這兩種情況? – Bill 2012-03-08 00:18:50

+1

在任何情況下,該方法必須作爲函數值(包括涉及視圖邊界的應用程序)被指定,是的。在我的例子中,如果你只是做了(新的A {}:B),那麼該方法將被應用,而不是實際創建一個函數對象,但機制是相同的,因此你觀察到的行爲。 – 2012-03-08 00:24:25