2013年10月20日 星期日

探討 scala 的函數呼叫與自動推論型別所產生的模糊情形

     scala 是靜態型別語言,不過他擁有自動推論型別的功能,因此可以減少重複宣告型別的情形。如以下程式碼:


    val a = 1

    由於 1 是整數,因此可以推論出 a 的型別為 int。再看看定義 function 的情形。


    def func(a:int, b:int) = a + b

    func 接受兩個參數,他的資料型別是 int,編譯器會推論出 func 的回傳值為 int。



   看完自動推論型別後,來看看 scala 中怎麼呼叫函數。在 scala 中,呼叫函數時,圓括號是可以省略的。因此,如果有個 function 長這樣。

    def func() = println("test")

    我們可以用 func() 來呼叫函數,也可以用 func 來呼叫函數。而這個特性,會導致一些模糊語意。當你寫 func 時,他有可能只是為了代表 func 這個 function,也有可能代表呼叫 func。來看個例子:


object Test{
  def printString() = println("test")
  def test1(func: () => Unit) = func // return func
  def test2(func: () => Unit) = func() // call func
  def test3(func: () => Unit) = printString // call printString
  def test4(func: () => Unit) = printString() // call printString
  def test5(func: () => Unit): () => Unit = printString // return printString
  def test6(func: () => Unit) = printString _ // return printString

  def main(){
    println("test1: ----------")
    println(test1(printString))
    println("test2: ----------")
    println(test2(printString))
    println("test3: ----------")
    println(test3(printString))
    println("test4: ----------")
    println(test4(printString))
    println("test5: ----------")
    println(test5(printString))
    println("test6: ----------")
    println(test6(printString))
  }
}

Test.main()

    基本上,test2 和 test 4 的結果沒什麼好模糊的,很明確的他是呼叫函數。test1的情形,編譯器會認定是傳回 func 這個物件,而 test3 的情形,則是呼叫 printString。而我們如果要回傳 printString 這個物件,則需要像 test5 一樣,明確寫出他是回傳 function ,所以才不會被呼叫。至於 test1 的情形,如果你希望的是呼叫 func,則需要明確把 () 寫出來。

    scala 中,對於不接受參數的函數定義方式有兩種,一種是 def name() = XXX,另外一種是 def name = XXX。這兩者使用上有些許差異,呼叫後者時,不能使用 name(),只能使用 name。前者加不加 () 都可以。

object Test{
  def printString = println("test")
  def test1(func:  => Unit) = func _ // return func
  def test2(func:  => Unit) = func // call func
  def test3(func:  => Unit) = printString // call printString
  def test6(func:  => Unit) = printString _ // return printString

  def main(){
    println("test1: ----------")
    println(test1(printString))
    println("test2: ----------")
    println(test2(printString))
    println("test3: ----------")
    println(test3(printString))
    println("test6: ----------")
    println(test6(printString))
  }
}

Test.main()


沒有留言:

張貼留言