scala之旅-核心语言特性【多参数列表(柯里化)】(十二)

方法可以有多个形参列表

例子

这里有个例子,在Scala集合Api中,特性Iterable 定义如下:

trait Iterable[A] {
  ...
  def foldLeft[B](z: B)(op: (B, A) => B): B
  ...
}

foldLeft 将两个参数的函数 op 应用于一个初始值z 上。然后所有集合的元素 ,从左到右。下面的列子是它的用法

起始值为0,foldLeft 这里应用了函数 (m,n)=> m+n 来使列表中的每个元素与前一个值进行累加。

val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val res = numbers.foldLeft(0)((m, n) => m + n)
println(res) // 55

使用案例

建议多个参数列表的使用案例包括:

驱动器类型判断

碰巧在Scala中,类型推断一次处理一个参数列表。你有如下的方法:

def foldLeft1[A, B](as: List[A], b0: B, op: (B, A) => B) = ???

然后你可以用如下的方式调用它,然后发现它不能通过编译

def notPossible = foldLeft1(numbers, 0, _ + _)

你必须用下面的其中的一种方法进行调用:

def firstWay = foldLeft1[Int, Int](numbers, 0, _ + _)
def secondWay = foldLeft1(numbers, 0, (a: Int, b: Int) => a + b)

这是因为Scala不能同时推断函数 _+_ 和 A、B。 通过将参数 op 移动至它自身的参数列表 ,第一个参数列表中的A和B的类型才能推断出来。这个被推断出来的类型就可以被应用与 _+_ 的类型推断,最终推断的结果为 (Int,Int) => Int

def foldLeft2[A, B](as: List[A], b0: B)(op: (B, A) => B) = ???
def possible = foldLeft2(numbers, 0)(_ + _)

这种定义方式就不需要额外的声明,所有参数的类型都能推断出来。

隐式参数

要将某些参数仅指定为隐式,必须将它们放到隐式参数列表中

举例如下

def execute(arg: Int)(implicit ec: scala.concurrent.ExecutionContext) = ???

局部应用

当一个方法被调用时缺少了一些数字或者参数列表,这时候便会产生一个以缺失形参列表作为实参的函数。这个被人称为局部应用的

举例:

val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val numberFunc = numbers.foldLeft(List[Int]()) _

val squares = numberFunc((xs, x) => xs :+ x*x)
println(squares) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)

val cubes = numberFunc((xs, x) => xs :+ x*x*x)
println(cubes)  // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000)

【注: 大概意思就是函数名也可以做变量。触发函数时在这个变量后面加个括号】

原文地址:https://www.cnblogs.com/zhouwenyang/p/13886305.html