1. 程式人生 > >kotlin 複合函式 函式鏈式呼叫 以及偏函式

kotlin 複合函式 函式鏈式呼叫 以及偏函式

package kotlinall.chapter5

import java.io.OutputStream
import java.nio.charset.Charset

//複合函式
//求f(g(x))的值
val add5={i:Int->i+5}
val mutilplyBy2 = {i:Int-> i*2}


//複合函式 擴充套件Function1的擴充套件方法 infix 中綴表示式
//Function1 傳入1個引數的函式 P1 接收的引數型別 P2返回的引數型別
//擴充套件方法andThen接收一個 一個引數的函式 他的引數 是add5的返回值 再返回最終結果
//andThen左邊的函式  Function1<P1,P2> 接收一個引數P1 返回結果P2
//andThen右邊的函式 function:Function1<P2,R> 引數為左邊函式的返回值P2 返回結果R
//聚合的結果返回函式Function1<P1,R> 是以P1作為引數 R做為結果的函式
//相當於P1,P2 聚合 P2,R 返回 P1,R
//f(g(x))  P1相當於x P2 相當於g(x)返回值 返回的結果Function1<P1,R> R相當於f(g(x)) 的返回值
//Function1<P1,P2> 相當於g(x)
//function:Function1<P2,R> 相當於x
//g(x).andThen(f(g(x)))
infix fun<P1,P2,R> Function1<P1,P2>.andThen(function:Function1<P2,R>):Function1<P1,R>{
    return fun(p1:P1):R{
        return function.invoke(this.invoke(p1))//先執行函式 p1返回p2 再執行 function(p2)返回R
    }
}
//compose左邊函式接收引數P2 返回R
//compse右邊函式 接收引數P1 返回P2
//返回結果函式P1,R
//相當於先執行右邊返回了P1,P2  在執行P2,R函式 聚合成P1,R
//g(f(x))
//f(x).compose(g(f(x)))
infix fun<P1,P2,R> Function1<P2,R>.compose(function:Function1<P1,P2>):Function1<P1,R>{
    return fun(p1:P1):R{
        return this.invoke(function.invoke(p1))
    }
}
//複合函式
fun executeFuhe(){
    println(mutilplyBy2(add5(8)))//(5+8)*2
    val add5andThen = add5 andThen mutilplyBy2
    println(add5andThen(8))
    val add5ComposeThen = add5 compose  mutilplyBy2
    println(add5ComposeThen(8))//g(f(x)) 先*2 再+5
}

//函式的鏈式呼叫
//Currying 多元函式變成一元函式的呼叫鏈
fun hello(x:String,y:Int,z:Double):Boolean{
    return true
}
//多個引數的函式 演變成多個單引數函式的鏈式呼叫
//fun curriedHello(x:String):(y:Int)->(z:Double)->Boolean{
//}
fun log(tag:String,target:OutputStream,message:Any?){
    target.write("[$tag] $message\n".toByteArray())
}

fun log1(tag:String) = fun(target:OutputStream)=fun(message:Any?)=target.write("[$tag] $message\n".toByteArray())
//三個函式鏈式呼叫的擴充套件方法
fun <P1,P2,P3,R> Function3<P1,P2,P3,R>.curry() = fun(p1:P1)=fun(p2:P2)=fun(p3:P3) = this(p1,p2,p3)
fun curryExecute(){
    log("gac",System.out,"HelloWorld")
    log1("gacmy")(System.out)("hello worldAgain")
    ::log.curry()("gacmy")(System.out)("hello worldAgain") //不需要寫鏈式呼叫方法 統一為模板方法
}


//偏函式
//
fun pianhanshu(){
    val consoleLog=::log.curry()("gac")(System.out)
    consoleLog("hello pioanhanshu")

    val makeString = fun(byteArray:ByteArray,charset:Charset):String{
        return String(byteArray,charset)
    }
    //偏函式
    val makeStringGBK = makeString.partial2(charset("GBK"))
    makeStringGBK("反反覆覆付".toByteArray())
}
//偏函式的模板方法 固定第二個引數 只需要 最後傳入一個引數的函式
fun <P1,P2,R> Function2<P1,P2,R>.partial2(p2:P2) = fun(p1:P1) = this(p1,p2)

//偏函式的模板方法 固定第一個引數 只需要 最後傳入一個引數的函式
fun <P1,P2,R> Function2<P1,P2,R>.partial(p1:P1) = fun(p2:P2) = this(p1,p2)


fun main(args: Array<String>) {
   executeFuhe()
   curryExecute()
    pianhanshu()

}