scala之传名参数和传值参数

简介

传值参数(by-value parameter) 在函数调用之前表达式会被求值,例如IntLong等数值参数类型;传名参数(by-name parameter) 在函数调用前表达式不会被求值,而是作为一个匿名函数传递。在介绍两者区别之前,先说一下 => 的用法。

=> 用法

=> 用法主要有以下几点:

  • 对于值,相当于lambda表达式:

    1
    2
    scala> List(1, 2, 3).map{(x: Int) => x * 2}
    res0: List[Int] = List(2, 4, 6)
  • 对于类型,=> 用于分开两端的类型。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> val test: Function1[Int, String] = myInt => "myInt: " + myInt.toString
    test: Int => String = <function1>

    scala> test(10)
    res0: String = myInt: 10

    scala> val test: Int => String = myInt => "myInt: " + myInt.toString
    test: Int => String = <function1>

    scala> test(10)
    res1: String = myInt: 10
  • 如果参数为空,即 => 左边为空,形式为 ()=>T

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> val test: Function0[String] = () => "Hello world"
    test: () => String = <function0>

    scala> test()
    res11: String = Hello world

    scala> val test: () => String = () => "Hello world"
    test: () => String = <function0>

    scala> test()
    res12: String = Hello world
  • 如果无返回值,即形式为 A[,B,…]=>Unit

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> val test: Function1[Int, Unit] =myInt => println(myInt)
    test: Int => Unit = <function1>

    scala> test(10)
    10

    scala> val test: Int => Unit =myInt => println(myInt)
    test: Int => Unit = <function1>

    scala> test(10)
    10
  • 如果无参数无返回值,即形式为 []=>Unit

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> val test: Function0[Unit] = () => println("Hello world")
    test: () => Unit = <function0>

    scala> test()
    Hello world

    scala> val test: () => Unit = () => println("Hello world")
    test: () => Unit = <function0>

    scala> test()
    Hello world
  • 如果作为一个函数的参数的类型声明,且坐便没有符号,如def func(param: => T)。这种形式叫做传名参数

  • 在case语句中,=> 用于分隔模式和结果表达式。

传值参数

先对表达式进行计算,然后将结果带入函数。

  • 简单类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    object Demo01 {
    def strToInt(s: String) = {
    println("call strToInt")
    s.toInt
    }

    def main(args: Array[String]): Unit = {
    strToInt({
    println("call by value"); "10"
    })
    }
    }
    //output:
    //call by value
    //call strToInt
  • 复杂类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    object Demo02 {
    def func(f: String => Int => Long): Long = {
    println("call func")
    f("1")(2)
    }

    def curry(s: String)(i: Int): Long = {
    s.toLong + i.toLong
    }

    def main(args: Array[String]): Unit = {
    func {
    println("call by value")
    curry
    }
    }
    }
    //output:
    //call by value
    //call func

传名参数

参数在进入函数后,每次在函数体内调用的时候才会计算。

  • 简单类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    object Demo01 {
    def strIoInt(s: => String): Int = {
    println("call strToInt")
    s.toInt
    }

    def main(args: Array[String]): Unit = {
    strIoInt({
    println("call by name")
    "10"
    }
    )
    }
    }
    // output:
    // call strToInt
    // call by name
  • 复杂类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    object Demo02 {
    def func(f: => String => Int => Long): Long = {
    println("call func")
    f("1")(2)
    }

    def curry(s: String)(i: Int): Long = {
    s.toLong + i.toLong
    }

    def main(args: Array[String]): Unit = {
    func {
    println("call by name")
    curry
    }
    }
    }
    // output:
    // call func
    // call by name

总结

() => T 可以简写成 => T

  • 示例-1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    object Demo03 {
    def strIoInt(s: () => String): Int = {
    println("call strToInt")
    s().toInt
    }

    def main(args: Array[String]): Unit = {
    // 注意调用的顺序
    strIoInt({
    println("call by value")
    () => {
    println("call by name"); "10"
    }
    }
    )
    }
    }
    // output:
    // call by value
    // call strToInt
    // call by name
  • 示例-2
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    object Demo04 {
    def func(f: () => String => Int => Long): Long = {
    println("call func")
    f()("1")(2)
    }

    def curry(s: String)(i: Int): Long = {
    s.toLong + i.toLong
    }

    def main(args: Array[String]): Unit = {
    // 注意调用的顺序
    func({
    println("call by value")
    () => {
    println("call by name")
    curry
    }
    }
    )
    }
    }
    // output:
    // call by value
    // call func
    // call by name