Kotlin~Functional programming Two brushes: higher-order functions and lambda expressions

1.introduce
  • What is a higher-order function?
    A function that takes a function as a parameter or returns a function is called a higher-order function.
    With lambda in the function, the function of the function belongs to the higher order function. The function of java has existing output followed by input, and the function of kt has input followed by output.
  • lambda expressions
    In Kotlin, a function exists as a first-class citizen and can be passed as a value. A lambda is a small piece of code encapsulated as an anonymous function that is passed to a function as a parameter value for its use. It is also divided into ordinary lambda and lambda expressions with an acceptor.

Note:
Lambda eliminates the link between interface definition and implementation, which is conditional. This interface must have only one abstract method to implement before Lambda can be used instead (such as OnClickListener, OnItemClickListener). If there are more than one abstract method, Lambda cannot be used instead!

2.Use examples

This paper mainly introduces lambda declaration + implementation, nesting, type derivation, anonymous functions, input and output, etc.

package com.hynson.learn

class HigherOrderFunc1 {
    // The compiler automatically deduces the return type from lambda
    fun show1(num: Int, lambda: (Int) -> String) = lambda.invoke(num)

    // Defining a higher-order function is equivalent to defining a rule and giving the implementation to the caller
    fun show2(n1: Int, n2: Int, n3: Int, lambda: (Int, Int, Int) -> Int) = lambda(n1, n2, n3)

    // Functions of functions
    fun show3(n1: Int, n2: Int): (Int, Int) -> String = { n3, n4 ->
        "show3 :${n1 + n2 + n3 + n4}"
    }
}

fun main() {
    // Declaration, use lambda to describe the declaration of a function

    val methodDefine: (String, Double) -> Any

    // Declaration+Implementation
    var method1: (Int) -> String = {
        it.toString()
    }
    var method2: (Int, Int) -> Unit = { _, n2 -> // _on behalf of rejection
        println("method2 :$n2$")
    }
    var method3 = { num: Int -> print("num:$num") }
    method3 = { print("Covered Value:$it") } // Support coverage

    // lambda expression does not support default values
    fun(str1: String?/* = "default"*/, str2: String) {}

    var method4: (String?, String) -> Unit = { str1, /*default */str2 ->
        print("str1$str1")
    }

    // By adding an anonymous function to the Sring class, our lambda body will hold the String itself.
    val method5: String.() -> Unit = {
        println("$this")
    }
    "TEST".method5()
    val method6: Int.(Int) -> String = {
        "The result of adding two numbers together ${this + it}"
    }
    println(1.method6(2))// this is the first parameter by default
    println(method6(1, 2))

    val func1 = HigherOrderFunc1()
    val ret = func1.show1(89) {
        "Conversion results"
    }
    println("show1 :$ret")

    val ret1 = func1.show2(1, 2, 3) { n1, n2, n3 ->
        n1 + n2 + n3
    }
    val ret2 = func1.show2(1, 2, 3) { n1, n2, n3 ->
        n1 * n2 * n3
    }
    println("show2 :$ret1")
    println("show2 :$ret2")

    // local final anonymous function
    val ret3 = fun(n1: Int, n2: Int): (Int, Int) -> String = { n3, n4 ->
        "ret3 :${n1 + n2 + n3 + n4}"
    }

    // public static function
    val ret4 = func1.show3(1, 2)(3, 4)
    println(ret3(1, 2)(100, 200))
    println(ret4)

    // lambda nesting
    val ret5: (Int) -> (String) -> (String) -> Int =
        {
            {
                {
                    55
                }
            }
        }
    ret5(4)("dd")("44")
}
package com.hynson.learn

fun main() {

    // Default Unit
    fun t01(){ 1}
    fun t02(){ 7.5f}
    fun t03(){ true}

    fun t04():String { return "test"} // Default String, within a function body, the return xxx compiler does not support type derivation

    fun s01() = { } // () ->Unit, function again

    fun s02() = run{ println()} // The return type of run function determined from inside out is generic and returns Unit type
    fun s03() : Boolean = run { true }
    fun s04() : (Int) -> Boolean = { true } // Input (int) ->Output Boolean

    s03()
    s04()(4)

    fun s05() = { n1:Int ->
        println("$n1")
        true
    }
    s05()(34)

    // fun keywords + declarations are not normally used in development, lambda + functions = = higher-order functions
    fun s06(){

    }
    val s07 = {

    }
    // Difference: s06 is a function, s07 receives a variable of an anonymous function that can execute the anonymous function

}
/*
// Extension function, who do you extend this==xxx itself
// Default public static
fun Glide.show(){
    // this == Glide
}
fun OkHttp.showInfo(){
}
*/

Higher Order Function + Expanded Function Understanding, Its Evolution, Order of Multiple lambda Parameters, Demonstrating Custom Built-in Higher Order Functions

Fun < omnipotent type > omnipotent type. run (block: omnipotent type.) - > (omnipotent type) = block()
The first this is extended, the second this on the caller is an anonymous extension, inside lambda
T. () The lambda given to the block causes the lambda implementation to hold this == T itself.
T.(T) The lambda given to the block will hold it== T itself inside the lambda implementation body.

class HigherOrderFunc2 {
    fun login(name: String, pwd: String, respResult: (Boolean) -> Unit) {
        if (name == "test" && pwd == "1234")
            respResult(true)
        else
            respResult(false)
    }
    fun show(name: String = "test", action: (String) -> Unit) = action(name)
    // Multiple lambda
    fun show2(lambda1: (Int) -> Unit, lambda2: (String) -> Unit) {
        lambda1(100)
        lambda2("test")
    }
}

fun main() {
    val test1 = HigherOrderFunc2()
    test1.login("test", "1234") {
        println("Logon Results $it")
    }

    test1.show(name = "Li Si", action = {
        println("Version 1 $it")
    })
    // Version 2, the compiler prompts the Lambda argument should be moved out of parentheses compiler not to recommend this usage
    test1.show(name = "Li Si", {
        println("Version 2 $it")
    })
    test1.show("Li Si") {
        println("Version 3 $it")
    }
    test1.show {
        println("Version 4 $it")
    }
    // Specify parameter order explicitly, which is useful when there are many parameters
    test1.show2(lambda1 = {
        println("lambda1")
    }, lambda2 = {
        println("lambda2")
    })
    test1.show2(lambda2 = {
        println("lambda2")
    }, lambda1 = {
        println("lambda1")
    })

    // Chain is also supported, but note that chain calls here must follow the order in which the functions are implemented or the compiler will fail
    test1.show2(lambda1 = {
        println("lambda1")
    }) {
        println("lambda2")
    }

    // Higher Order Function+Extended Function
    "dd".run {
        println("Running ${it.length}")
    }
}

inline fun <T, R> T.run(block: (T) -> (R)): R {
    return block(this)
}

A comprehensive example shows the convenience of click event management with higher-order functions and lambda and the function reference.
The above code comes from the enjoyment class and is only for learning communication Thank you!

package com.hynson.learn

class ClickListener<T> {
    // Execute Action
    private val actions = arrayListOf<(T?) -> Unit>()

    // Execution data
    private val resIds = arrayListOf<(T?)>()

    /**
     * Add Click Event
     */
    fun addListener(id:T?, action:(T?) -> Unit){
        val index = resIds.indexOf(id)
        if(index == -1){
            actions += action
            resIds += id
        }
        else {
            actions[index] = action
            println("View $id Repeat add event...")
        }
    }

    /**
     * Simulate Click Events
     */
    fun touchListeners() {
        if(actions.isEmpty()) return
        actions.forEachIndexed { index, item ->
            item.invoke(resIds[index])
        }
    }
}

fun main() {
    val listener = ClickListener<Int>()
    listener.addListener(1){
        println("Clicked $it")
    }
    listener.addListener(2) {
        println("Clicked $it Mode 1 ")
    }
    // Function Reference
    listener.addListener(2,::handle)
    listener.addListener(3,::handle)

    listener.touchListeners()
}

fun <T> handle(id: T?){
    println("Clicked $id Mode 2")
}
3.Lambda application scenarios
  • Use with collections to map, filter, and so on
val languages = listOf("Java","Kotlin","Python","JavaScript")
languages.filter {
it.contains("Java")
}.forEach{
println(it)
}
  • Instances of alternative functional interfaces
//Replace View.OnClickListener interface
mName.setOnClickListener {

}
//Replace Runnable Interface
mHandler.post {

}
  • Combining higher-order functions, functional programming is implemented to make the code concise.
    For example:https://www.cnblogs.com/LinkinPark/p/5232977.html

The above code has been uploaded to github Click to view source code Welcome to Star Exchange and Discussion ~~

Tags: Java Design Pattern kotlin

Posted on Tue, 21 Sep 2021 12:42:50 -0400 by pattyb