傳值參數在函數調用以前表達式會被求值,例如Int,Long等數值參數類型;傳名參數在函數調用前表達式不會被求值,而是會被包裹成一個匿名函數做爲函數參數傳遞下去,例如參數類型爲無參函數的參數就是傳名參數。下文將舉例說明這二者的區別。express
在下面的示例中,編譯器檢測到strToInt接受一個傳值參數,因此先對傳入的參數表達式{println("eval parameter expression"); "123"}
,而後再講求值結果傳遞給strToInt。函數
object Test { def strToInt(s: String) = { println("call strToInt") s.toInt } def main(args: Array[String]) { strToInt({println("eval parameter expression"); "123"}) } } //輸出: eval parameter expression call strToInt
在strToInt
函數聲明中添加一個=>
,參數s的類型就變成了無參函數,類型爲:() => String
,按照Scala針對無參函數的簡化規則,此處省略了()
。由於參數s的類型是無參函數,因此此處是按名傳遞。code
object Test { def strToInt(s: => String) = { println("call strToInt") s.toInt } def main(args: Array[String]) { strToInt({println("eval parameter expression"); "123"}) } } //輸出: call strToInt eval parameter expression
從上面的輸出能夠看出,參數表達式在strToInt
函數調用以後才被求值。其實此處編譯器自動將參數表達式{println("eval parameter expression"); "123"}
轉換成匿名的無參函數,並傳遞給s
。編譯器
invode函數的參數f的類型爲柯里化函數String => Int => Long
, 此處爲按值傳遞。io
object Test { def invode(f: String => Int => Long) = { println("call invoke") f("1")(2) } def curry(s: String)(i: Int): Long = { s.toLong + i.toLong } def main(args: Array[String]) { invode{println("eval parameter expression");curry} } } //輸出: eval parameter expression call invoke
invode函數的參數f的類型爲一個無參函數,該無參函數的返回類型爲柯里化函數String => Int => Long
, 由於參數f的類型是無參函數,因此此處是按名傳遞。編譯
object Test { def invode(f: => String => Int => Long) = { println("call invoke") f("1")(2) } def curry(s: String)(i: Int): Long = { s.toLong + i.toLong } def main(args: Array[String]) { invode{println("eval parameter expression");curry} } } //輸出: call invoke eval parameter expression
若是參數類型是無參函數,則按名傳遞,不然按值傳遞。注意,若是參數類型是函數類型,但不是無參函數,仍是按值傳遞,例如:匿名函數
object Test { def strToInt(s: (String) => Int) = { println("call strToInt") s("123") } def main(args: Array[String]) { strToInt({println("eval parameter expression"); (s: String) => s.toInt}) } } //輸出: eval parameter expression call strToInt