Scala:Function(高階函數語言程式設計)
一個可以進行高階函數語言程式設計的模組,我們來看看它都實現了哪些操作,並結合原始碼理解一下。
- def chain[a](fs: Seq[(a) ⇒ a]): (a) ⇒ a
把一些列的方法串起來,挨個執行,每個方法的結果,回作為下一個方法的入參
/**定義兩個函式*/
def fun1 = (v:Int) => {
val result = v * 10
println(result)
result
}
def fun2 = (v:Int) => {
val result = v * 100
println(result)
result
}
//使用
val funs = Seq(fun1,fun2)
Function.chain[Int](funs)(2)
/**fun1的結果作為fun2的入參
20
2000
*/
看下chain的原始碼
def chain[a](fs: Seq[a => a]): a => a = { x => (x /: fs) ((x, f) => f(x)) }
看到 /: 這個符號是不是有點眼熟,我們在Scala:Array(集合、序列)裡提到過序列的操作中就有這個操作符,他會遍歷序列中的元素去執行指定的操作。
- def const[T, U](x: T)(y: U): T
這是一個返回常量的方法,直接返回 x 值,看原始碼
def const[T, U](x: T)(y: U): T = x
假如我們要把一個序列中的元素替換成同一個值,我們可以使用序列的map方法
List(1, 2, 3, 4, 5).map(_=>7)
那這時我們可以用const來處理
List(1, 2, 3, 4, 5).map(Function.const(7))
/**對應原始碼中的x就是7,y就是List中的每個元素
如果我們按照 x+":"+y的形式列印,就是
7:1
7:2
7:3
7:4
7:5
*/
- def tupled[a1, a2, b](f: (a1, a2) ⇒ b): ((a1, a2)) ⇒ b
將二元函式轉換為一個一元函式,引數為Tuple2型別
def tupleFunc = (a:Int,b:Int) => {
a+b
}
/**使用*/
val funs = Function.tupled(tupleFunc)
val v = (1,3)
println(v.getClass.getName)
println(funs(v)) // 4
- def tupled[a1, a2, a3, b](f: (a1, a2, a3) ⇒ b): ((a1, a2, a3)) ⇒ b
道理同 tupled[a1, a2, b] - def tupled[a1, a2, a3, a4, b](f: (a1, a2, a3, a4) ⇒ b): ((a1, a2, a3, a4)) ⇒ b
道理同 tupled[a1, a2, b] def tupled[a1, a2, a3, a4, a5, b](f: (a1, a2, a3, a4, a5) ⇒ b): ((a1, a2, a3, a4, a5)) ⇒ b
道理同 tupled[a1, a2, b]def untupled[a1, a2, b](f: ((a1, a2)) ⇒ b): (a1, a2) ⇒ b
作用和tupled[a1, a2, b]相反
def tupleFunc = (v:Tuple2[Int,Int]) => {
v._1 + v._2
}
//轉換
val funs = Function.untupled(tupleFunc)
println(funs(2,6)) /** 8 */
- def untupled[a1, a2, a3, b](f: ((a1, a2, a3)) ⇒ b): (a1, a2, a3) ⇒ b
道理同 tupled[a1, a2, b] - def untupled[a1, a2, a3, a4, b](f: ((a1, a2, a3, a4)) ⇒ b): (a1, a2, a3, a4) ⇒ b
道理同 tupled[a1, a2, b] def untupled[a1, a2, a3, a4, a5, b](f: ((a1, a2, a3, a4, a5)) ⇒ b): (a1, a2, a3, a4, a5) ⇒ b
道理同 tupled[a1, a2, b]def uncurried[a1, a2, b](f: (a1) ⇒ (a2) ⇒ b): (a1, a2) ⇒ b
把一個柯里化函式轉換為但 2 個引數的函式
/**宣告一個柯里化函式*/
def curriedSum = (x:Int)=>(y:Int) => x + y
//轉換
val funs = Function.uncurried(curriedSum)
println(funs(1,6)) // 7
原始碼
方法返回結果是帶(a1, a2)兩個引數的函式
def uncurried[a1, a2, b](f: a1 => a2 => b): (a1, a2) => b = {
(x1, x2) => f(x1)(x2)
}
- def uncurried[a1, a2, a3, b](f: (a1) ⇒ (a2) ⇒ (a3) ⇒ b): (a1, a2, a3) ⇒ b
道理同 uncurried[a1, a2, b] - def uncurried[a1, a2, a3, a4, b](f: (a1) ⇒ (a2) ⇒ (a3) ⇒ (a4) ⇒ b): (a1, a2, a3, a4) ⇒ b
道理同 uncurried[a1, a2, b] def uncurried[a1, a2, a3, a4, a5, b](f: (a1) ⇒ (a2) ⇒ (a3) ⇒ (a4) ⇒ (a5) ⇒ b): (a1, a2, a3, a4, a5) ⇒ b
道理同 uncurried[a1, a2, b]def unlift[T, R](f: (T) ⇒ Option[R]): PartialFunction[T, R]
將 A => Option[B] 型別的函式轉換為 PartialFunction[T, R] 型別函式
def optionFun(x : Int) = {
println(x)
if (x > 0) Some(x*10) else None
}
//使用
val funs = Function.unlift(optionFun)
val chars = Array(1,2,3)
//collect需要PartialFunction型別引數
val newchars = chars.collect(funs)
println(newchars.mkString(","))
/**輸出為 10,20,30 */
原始碼(內部呼叫的是PartialFunction.unlifted方法)
def unlift[T, R](f: T => Option[R]): PartialFunction[T, R] = PartialFunction.unlifted(f)