Saturday, February 08, 2014

Scala筆記: implicit的奧秘

[1] implicit是什麼? 如何運作?
implicit具有型別轉換的功能, 但他的特殊之處在於, 他是由compiler觸發,
在compile階段若是發現型別相關的錯誤, complier會試圖利用宣告為implict的東西轉型藉此完成compile.

此種自動轉型有以下幾個規則:
1. Marking Rule: 只能使用被宣告為implicit的東西
- 可以是任何variable, function, 或object
2. Scope Rule: 只能利用在同一個scope中, 或是被宣告在companion object可見的scope中, 而且必須能用一層identifier呼叫(用以下例子說明比較清楚)
scala> object test2{
     | implicit def doubleToInt(x: Double) = x.toInt
     | }
defined module test2

scala> object test{
     | import test2._
     | }
defined module test

scala> import test._
import test._

scala> val i: Int = 3.5
<console>:12: error: type mismatch;
 found   : Double(3.5)
 required: Int
       val i: Int = 3.5
                    ^

scala> import test2._
import test2._

scala> val i: Int = 3.5
i: Int = 3
3. Non-Ambiguity Rule: 若是在scope中有超過一種implicit轉換的方式, complie會失敗.
4. One-at-a-time Rule: 一次只能套用一個implicit轉換, chaining(ex: A->B->C)是不行的!
5. Explicits-First Rule: 明確的型別指定具有絕對的優先權, 只有錯誤發生時, compiler才會透過implicit的方式修補.

[2] 甚麼情況會觸發implicit檢查?
1. conversions to an expected type: 型別不對時
scala> val i: Int = 3.5
<console>:7: error: type mismatch;
 found   : Double(3.5)
 required: Int
       val i: Int = 3.5
                    ^

scala> implicit def doubleToInt(x: Double) = x.toInt
doubleToInt: (x: Double)Int

scala> val i: Int = 3.5
i: Int = 3
2. conversions of the receiver of a selection: 找不到對應的函式
- 當沒有某個method時, 會利用implicit去轉型, 檢查是否有對應的method

3. implicit parameters: 找不到對應的參數
- 被宣告為implicit的參數, 在呼叫時沒有被傳入時, 會去尋找被宣告為implicit的東西(有點類似default值的感覺)

[3] 什麼時候適合使用implicit
當你的程式想要與一些現成的library整合時, 就例如你可能有一個購物網站, 系統定義了使用者各種屬性, 也有許多針對使用者資料的操作已經完成. 但現在你的網站希望能提供Facebook或Google帳號登入, 但他們的使用者屬性各不相同, 這時你可以加入implicit的方式自動把透過Facebook或Google api拉回來的型別轉成你的使用者型別, 也同時可以直接享用你已經寫好的各種method.

ref:
- Chapter 21 of Programming in Scala, First Edition Implicit Conversions and Parameters
- A Tour of Scala: Implicit Parameters
- Implicit Classes
- Scala Implicit Conversion

No comments:

Post a Comment