值函数最常用的场景是作为高阶函数的输入,假设定义了如下整型数组:
scala> val arrInt=Array(1,2,3,4)
arrInt: Array[Int] = Array(1, 2, 3, 4)
现在希望能够将数组中所有的元素加1,可以通过Array提供的map方法来处理,map方法的定义如下所示。
def map[B](f: (A) ⇒ B):Array[B]
该方法使用了泛型,泛型B指的是数组最终返回的元素类型,f表示作用于数组各元素上的函数,(A) ⇒ B为函数的类型,表示的是该函数的输入参数类型为A,返回值类型为B。这里我们定义如下值函数作为map函数的输入。
scala> val increment=(x:Int)=>x+1
increment: Int => Int = <function1>
使用时直接将变量increment作为函数的参数使用。
scala> arrInt.map(increment)
res0: Array[Int] = Array(2, 3, 4, 5)
在实际使用时,如果值函数只使用一次,则常常直接作为函数参数。
scala> arrInt.map((x:Int)=>x+1)
res1: Array[Int] = Array(2, 3, 4, 5)
在实际使用时,值函数还可以对其进行简化,对于代码arrInt.map((x:Int)=>x+1),由于arrInt为整型数组,因此传入map的函数输入类型可以通过类型推断得到,arrInt.map((x:Int)=>x+1)可以简写为以下所示。
//值函数省略参数类型,参数类型通过类型推断得到
scala> arrInt.map((x)=>x+1)
res2: Array[Int] = Array(2, 3, 4, 5)
arrInt.map((x)=>x+1)中的值函数(x)=>x+1参数只有一个,在这种条件下,可以将值函数输入参数的括号去掉。
//值函数参数只有一个时,可以省略括号
scala> arrInt.map(x=>x+1)
res3: Array[Int] = Array(2, 3, 4, 5)
代码arrInt.map(x=>x+1)中的值函数x=>x+1输入参数在符号=>右边只出现一次,此时可以用占位符对该值函数进行进一步简化。
//值函数参数在=>右边只出现一次时,可以用占位符_对函数进行简化
scala> arrInt.map(_+1)
res4: Array[Int] = Array(2, 3, 4, 5)
需要特别注意的是,代码arrInt.map(_+1)合法是因为arrInt是Int类型的数组,可以进行类型推断,但如果将_+1赋值给变量时会出错。
scala> val increment=1+_
<console>:7: error: missing parameter typefor expanded function ((x$1) => 1.+(x$1))
valincrement=1+_
^
scala> val increment=_+1
<console>:7: error: missing parameter typefor expanded function ((x$1) => x$1.$plus(1))
valincrement=_+1
^
不管是val increment=1+_还是val increment=_+1,其出错原因是编译器无法进行类型推断的,虽然代码中有+1或1+这种表达式,但它不足以让编译器知道确定的类型,因为无论是1+字符串类型还是字符串类型+1,1+Double类型还是Double类型+1等都是合法的。要合法使用上面的代码,需要明确指定类型。
//明确指定类型
scala> val increment=(_:Int)+1
increment: Int => Int = <function1>
scala> val increment=1+(_:Int)
increment: Int => Int = <function1>
还有一种方式,是指定increment的具体类型。
//指定increment的参数类型为(Int)=>Int,即函数的输入参数为Int类型,返回值的类型为Int
scala> val increment:(Int)=>Int=1+_
increment: Int => Int = <function1>




