# 泛函编程（4）－深入Scala函数类

```1 scala> def aMethod(x: Int): Int = x + 10
2 aMethod: (x: Int)Int
3
4 scala> val aFunction = (x: Int) => x + 10
5 aFunction: Int => Int = <function1>```

aMethod 与 aFunction 在类型上是不同的。再看看下面：

```1 scala> aFunction
2 res0: Int => Int = <function1>
3
4 scala> aMethod
5 <console>:9: error: missing arguments for method aMethod;
6 follow this method with `_' if you want to treat it as a partially applied function
7               aMethod```

```1 scala> val toFunction = aMethod _
2 toFunction: Int => Int = <function1>
3
4 scala> toFunction
5 res2: Int => Int = <function1>```

aMethod转换成函数toFunctions后具备了函数的特性。

```1 def main(args: Array[String]): Unit = {
2   println(formatResult("absolute value", -42, abs))
3   println(formatResult("factorial", 7, factorial))
4   println(formatResult("increment", 7, (x: Int) => x + 1))
5   println(formatResult("increment2", 7, (x) => x + 1))
6   println(formatResult("increment3", 7, x => x + 1))
7   println(formatResult("increment4", 7, _ + 1))
8   println(formatResult("increment5", 7, x => { val r = x + 1; r }))
9 }```

```1 The absolute value of -42 is 42
2 The factorial of 7 is 5040
3 The increment of 7 is 8
4 The increment2 of 7 is 8
5 The increment3 of 7 is 8
6 The increment4 of 7 is 8
7 The increment5 of 7 is 8```

```1 scala> (a: Int, b: Int) => a + b
2 res4: (Int, Int) => Int = <function2>```

```1 val addThem = new Function2[Int, Int, Int] {
2   def apply(a: Int, b: Int) = a + b
3 }```

``` 1  def findFirstInt(arr: Array[Int], target: Int): Int = {
2       def loop(idx: Int): Int = idx match {
3           case l if (l >= arr.length) => -1          //indicate not found
4           case i if (arr(i) == target) => idx
5           case _ => loop(idx + 1)
6       }
7       loop(0)
8   }                                               //> findFirst: (arr: Array[Int], target: Int)Int
9   findFirstInt(Array(2,4,3,9,0),3)                //> res53: Int = 2
10   findFirstInt(Array(2,4,3,9,0),7)                //> res54: Int = -1```

``` 1   def findFirstString(arr: Array[String], target: String): Int = {
2       def loop(idx: Int): Int = idx match {
3           case l if (l >= arr.length) => -1        //indicate not found
4           case i if (arr(i) == target) => idx
5           case _ => loop(idx + 1)
6     }
7       loop(0)
8   }                                               //> findFirstString: (arr: Array[String], target: String)Int
9   findFirstString(Array("Hello","My","World"),"My")
10                                                   //> res55: Int = 1
11   findFirstString(Array("Hello","My","World"),"Yours")
12                                                   //> res56: Int = -1```

``` 1 def findFirstA[A](arr: Array[A],target: A)(equ: (A,A) => Boolean): Int = {
2         def loop(idx: Int): Int = idx match {
3           case l if (l >= arr.length) => -1    //indicate not found
4           case i if (equ(arr(i),target)) => idx
5           case _ => loop(idx + 1)
6     }
7       loop(0)
8
9   }                                           //> findFirstA: [A](arr: Array[A], target: A)(equ: (A, A) => Boolean)Int
10   findFirstA[Int](Array(2,4,3,9,0),3)((x,y) => x == y)
11                                               //> res57: Int = 2
12   findFirstA[String](Array("Hello","My","World"),"My")((x,y) => x == y)
13                                               //> res58: Int = 1```

findFirstA是个多态函数。A是一个类型变量。我们可以说findFirstA是个针对类型变量A的多态函数。注意我们在findFirstA增加了一个参数清单- (equ: (A,A) => Boolean)。这是因为我们还无法确定A的类型。那么我们必须提供A类型的对比函数。我们可以用findFirstA针对整数、字串进行操作。我们也可以对其它类型进行操作，只要我们能提供那种类型的比较函数。

`1 def partialApply[A,B,C](a: A, f: (B,C) => C): B => C`

```1   def partialApply[A,B,C](a: A, f: (A,B) => C): B => C = (b: B) => f(a,b)
2                                                   //> partialApply: [A, B, C](a: A, f: (A, B) => C)B => C```

```1 def addTwoParams(a: Int, b: Int) = a + b        //> addTwoParams: (a: Int, b: Int)Int
2   addTwoParams(2,5)                               //> res59: Int = 7
3   val applyOnce = partialApply(2,addTwoParams)    //> applyOnce  : Int => Int = <function1>
4   applyOnce(5)                                    //> res60: Int = 7```

f(a,b,c,...n) = f(a)(b)(c)...(n) = a => b => c => ... => n

`1 def curryTwo[A,B,C](f: (A,B) => C): A => (B => C) `

```1 def curryTwo[A,B,C](f: (A,B) => C): A => (B => C) = (a: A) => ((b: B) => f(a,b))
2                                                   //> curryTwo: [A, B, C](f: (A, B) => C)A => (B => C)
3   val curriedFunction = curry(addTwoParams)       //> curriedFunction  : Int => (Int => Int) = <function1>
4   val curryOnce = curriedFunction(2)              //> curryOnce  : Int => Int = <function1>
5   curryOnce(5)                                    //> res61: Int = 7```

uncurry是curry的反向：把curry函数返还到多参数函数：a => b => c => ... => n  = f(a,b,c,...n)

`1 def uncurry[A,B,C](f: A => B => C): (A,B) => C`

```1   def uncurry[A,B,C](f: A => B => C): (A,B) => C = (a: A, b: B) => (f(a))(b)
2                                                   //> uncurry: [A, B, C](f: A => (B => C))(A, B) => C
3   val uncurriedFunction = uncurry(curriedFunction)//> uncurriedFunction  : (Int, Int) => Int = <function2>
4   uncurriedFunction(2,5)                          //> res62: Int = 7```

uncurriedFunction又变回去了。

最后，示范一个函数组合的例子：

`1 def compose[A,B,C](f: B => C, g: A => B): A => C`

compose是将f和g两个函数组合成另一个函数。看看下面实现和使用示范：

```1 def compose[A,B,C](f: B => C, g: A => B): A => C = (a: A) => f(g(a))
2                                                   //> compose: [A, B, C](f: B => C, g: A => B)A => C
3   val fadd = (x: Int) => x + 2                    //> fadd  : Int => Int = <function1>
4   val fmul = (y: Int) => y * 5                    //> fmul  : Int => Int = <function1>
6   mulThenAdd(2)                                   //> res63: Int = 12```

```1   (fadd compose fmul)(2)                          //> res64: Int = 12
2   (fmul compose fadd)(2)                          //> res65: Int = 20```

```1 def andThen[A,B,C](f: A => B, g: B => C): A => C = (a: A) => g(f(a))
2                                                   //> andThen: [A, B, C](f: A => B, g: B => C)A => C
3  (fadd andThen fmul)(2)                           //> res66: Int = 20```

238 篇文章65 人订阅

0 条评论

## 相关文章

22500

25040

7210

13240

26620

### C++编译与链接（0）-.h与.cpp中的定义与声明

C++中有的东西需要放在可以在.h文件中定义，有的东西则必须放在.cpp文件中定义，有的东西在不同的cpp文件中的名字可以一样，而有的则不能一样 那么究竟哪些东...

68870

12420

### python字符串

1.    S.find(substr,[start,[end]])    返回S中出现substr的第一个字母的标号，如果S中没有substr则返回-1，st...

12620

20340

### 函数指针介绍及其用法

1、前言 　　这里有两个绕来绕去的东西，函数指针和指针函数；对于四个字，我们首先只看后面两个字，这样方便我们记忆； 　　函数指针，本质是指针；是指向函数入口地址...

21810