1
1
---
2
2
layout : tour
3
- title : Multiple Parameter Lists (Currying)
3
+ title : 多参数列表(柯里化)
4
4
5
5
discourse : false
6
6
@@ -13,3 +13,71 @@ language: zh-cn
13
13
next-page : case-classes
14
14
previous-page : nested-functions
15
15
---
16
+
17
+ 方法可以定义多个参数列表,当使用较少的参数列表调用多参数列表的方法时,会产生一个新的函数,该函数接收剩余的参数列表作为其参数。这被称为[ 柯里化] ( https://zh.wikipedia.org/wiki/%E6%9F%AF%E9%87%8C%E5%8C%96 ) 。
18
+
19
+ 下面是一个例子,在Scala集合中定义的特质[ Traversable] ( /zh-cn/overviews/collections/trait-traversable.html ) :
20
+
21
+ ```
22
+ def foldLeft[B](z: B)(op: (B, A) => B): B
23
+ ```
24
+
25
+ ` foldLeft ` 从左到右,以此将一个二元运算` op ` 应用到初始值` z ` 和该迭代器(traversable)的所有元素上。以下是该函数的一个用例:
26
+
27
+ 从初值0开始, 这里 ` foldLeft ` 将函数 ` (m, n) => m + n ` 依次应用到列表中的每一个元素和之前累积的值上。
28
+
29
+ ``` tut
30
+ val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
31
+ val res = numbers.foldLeft(0)((m, n) => m + n)
32
+ print(res) // 55
33
+ ```
34
+
35
+ 多参数列表有更复杂的调用语法,因此应该谨慎使用,建议的使用场景包括:
36
+
37
+ #### 单一的函数参数
38
+ 在某些情况下存在单一的函数参数时,例如上述例子` foldLeft ` 中的` op ` ,多参数列表可以使得传递匿名函数作为参数的语法更为简洁。如果不使用多参数列表,代码可能像这样:
39
+
40
+ ```
41
+ numbers.foldLeft(0, {(m: Int, n: Int) => m + n})
42
+ ```
43
+
44
+ 注意使用多参数列表时,我们还可以利用Scala的类型推断来让代码更加简洁(如下所示),而如果没有多参数列表,这是不可能的。
45
+
46
+ ```
47
+ numbers.foldLeft(0)(_ + _)
48
+ ```
49
+ 像上述语句这样,我们可以给定多参数列表的一部分参数列表(如上述的` z ` )来形成一个新的函数(partially applied function),达到复用的目的,如下所示:
50
+
51
+ ``` tut
52
+ val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
53
+ val numberFunc = numbers.foldLeft(List[Int]())_
54
+
55
+ val squares = numberFunc((xs, x) => xs:+ x*x)
56
+ print(squares.toString()) // List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
57
+
58
+ val cubes = numberFunc((xs, x) => xs:+ x*x*x)
59
+ print(cubes.toString()) // List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000)
60
+ ```
61
+
62
+ 最后,` foldLeft ` 和 ` foldRight ` 可以按以下任意一种形式使用,
63
+ ``` tut
64
+ val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
65
+
66
+ numbers.foldLeft(0)((sum, item) => sum + item) // Generic Form
67
+ numbers.foldRight(0)((sum, item) => sum + item) // Generic Form
68
+
69
+ numbers.foldLeft(0)(_+_) // Curried Form
70
+ numbers.foldRight(0)(_+_) // Curried Form
71
+
72
+ (0 /: numbers)(_+_) // Used in place of foldLeft
73
+ (numbers :\ 0)(_+_) // Used in place of foldRight
74
+ ```
75
+
76
+
77
+ #### 隐式(implicit)参数
78
+ 如果要指定参数列表中的某些参数为隐式(implicit),应该使用多参数列表。例如:
79
+
80
+ ```
81
+ def execute(arg: Int)(implicit ec: ExecutionContext) = ???
82
+ ```
83
+
0 commit comments