[Scala] Scala 2.10 新功能--模組化語言

Scala 2.10.0

話說一月份的時候,Scala 2.10.0 已經正式釋出了,官方網站上列出了不少新功能,但剛好一月份也在趕工工作上的東西,所以沒有時間抓來玩玩。

這幾日趁著放年假,想說 Lift 也已經支持 Scala 2.10.0 了,所以就試著把 BeDone 升級到 Scala 2.10.0,順便筆記一下幾個比較有趣的功能。

模組化語言

升級到 Scala 2.10.0 後,最明顯的一個事情就是很多專案編譯的時候會跑出警告!雖然程式依然都可以正常運作,但編譯時看到一堆警告還是挺煩人的……

舉例來說,像下面這個簡單的程式範例:

object Test
{
    case class Point(x: Int, y: Int)

    implicit def toPoint(cord: (Int, Int)) = Point(cord._1, cord._2)

    def main(args: Array[String])
    {
        val point: Point = (0, 0)

        println(point)
    }
}

編譯時會出現下面的訊息,告訴你有警告,如果重新加上 -feature 這個參數來編譯,則會告訴你是因為你用到了 implicit conversion 的關係,告訴你要把他 enable 起來。

brianhsu@USBGentoo ~/test/src/main/scala $ scalac Test.scala
warning: there were 1 feature warnings; re-run with -feature for details
one warning found
brianhsu@USBGentoo ~/test/src/main/scala $ scalac -feature Test.scala
Test.scala:4: warning: implicit conversion method toPoint should be enabled
by making the implicit value language.implicitConversions visible.

會出現這個警告,是因為 Scala 2.10.0 加上了一個叫做 Modularized Language Features 的概念,也就是把整個程式語言的功能給模組化了,讓你可以控制你要用哪些功能。

畢竟從以前到現在,有一派的觀點是認為 Scala 太複雜了,有許多進階的功能,而這些功能可能會被誤用,或是造成初學者的困擾。

為了解決這個問題,Scala 2.10.0 就加入了 Modularized Language Features 的設定,也就是說,讓你可以控制你要用 Scala 這個語言的哪些 subset。

使用某個語言的 subset 本身並不是什麼特別新奇的事,像 JavaScript: The Good Parts 裡面,就提倡只使用 JavaScript 裡的所謂的 Good Part 的 subset。

只是 Scala 2.10.0 把他更具體了一點--當你使用到你沒有預期使用的功能的時候,會吐警告給你,告訴你你可能用到了進階的功能囉!

上面的例子就是這樣,在 Scala 2.10.0 裡面,定義新的 implicit conversion 被歸類到進階功能,如果想要使用的話,得告訴 Scala Compiler 你知道你在用 implicit conversion,而且這正是你想要的。

要做到這件事有兩個方法,第一個是在程式碼裡 import 那些進階功能,他們都在 scala.language 這個 object 裡面:

/*
 * 我知道我在定義新的 implicit conversion,不要阻止我!
 */
import language.implicitConversions

object Test
{
    implicit def toPoint(cord: (Int, Int)) = Point(cord._1, cord._2)

    case class Point(x: Int, y: Int)

    def main(args: Array[String])
    {
        val point: Point = (0, 0)

        println(point)
    }
}

這樣子編譯的時候就不會出現警告了,因為你告訴了 Scala 編譯器你知道自己在做什麼。

不過這麼做會有個小問題,就是 scala.language 是 Scala 2.10 以後才有的,所以上面的程式明明就是合法的 Scala 2.9 的語法,但會因為找不到 scala.language 而無法編譯過關,變成無法向後相容舊的 Scala 編譯器。

所以 Scala 2.10 也提供了另一個方法來告訴編譯器你要使用的 Scala Feature,而不需要直接改動程式碼,那就是在編譯的時候加上 -language:[功能] 這個參數,像上面的程式碼我們可以這樣編譯:

brianhsu@USBGentoo ~/test/src/main/scala $ scalac -language:implicitConversions Test.scala
brianhsu@USBGentoo ~/test/src/main/scala $ scala Test
Point(0,0)

像這樣子使用 -language 參數,就可以在不改動程式碼的情況下,告 Scala Compiler 你想要使用哪一些 language feature 囉。

回響