Previous article – Kotlin collection sequences use, operator summary

This blog is about the problems I have encountered in learning Kotlin, if there is something wrong, I hope you can help me out, thank you.

A brief introduction to higher-order functions

In a word, higher-order functions: In Kotlin, higher-order functions are those that use functions as arguments or return values of a function.

The arguments are higher-order functions

Let’s take a look at the extension function in the String.kt file

/** * Returns the sum of all values produced by [selector] function applied to each character in the char sequence. */
// Inline functions are used inline with lambdas.
// CharSequence. Is an extension function
public inline fun CharSequence.sumByDouble(selector: (Char) - >Double): Double {
    // The selector argument is also a fun, passing in a char and putting in a Double
    var sum: Double = 0.0
    for (element in this) {
        sum += selector(element)
    }
    return sum
}
Copy the code

This function converts the passed string iterator to a Double, increments, and returns the sum of Double types.

Returns a higher-order function

Here is an example from the official website

// Argument one takes the Lock type and a function that takes no arguments and returns type T
fun <T> lock(lock: Lock, body:()->T):T{
        lock.lock()
        try {
            // The function returns a value
            return body()
        }
        finally {
            lock.unlock()
        }
    }
Copy the code

Let’s look at it a little bit more directly with a pseudocode

fun toBeSynchronized(a) = sharedResource.operation()
val result = lock(lock, ::toBeSynchronized)    

/ / short
val result = lock(lock, {sharedResource.operation()} )
Copy the code

Higher-order functions are commonly used

All concentrated in standard.kt

TODO

Source:

/**
 * Always throws [NotImplementedError] stating that operation is not implemented.
 *
 * @param reason a string explaining why the implementation is missing.
 */
@kotlin.internal.InlineOnly
public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")
// Inline is added to reduce the elapsed time by eliminating the need to jump to the inline function
Copy the code

The run function

@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    // Run also with apply also
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
Copy the code

This contract representation tells the compiler that the effect of calling the run function is to specify that the block lamba expression argument is called at the appropriate place. The appropriate place is that block lambda expressions can only be called during a call to the apply function. When run is called, block expressions cannot be executed. Invocationkind.exactly_once specifies that a block lambda expression can only be called once, and that the outer function must be an inline function. (Contracts are more like telling the compiler its own context.) This function is used when we need to execute a code block, and the code block is independent. That is, I can write some code in the run() function that is independent of the project, because it will not affect the normal operation of the project.

For example:

private fun printString(index: Int) {
        val str = "kotlin"
        var l = kotlin.run {
            when (index) {
                1- > {"java"
                }
                2- > {"php"
                }
                else- > {"lua"
                }
            }
        }.length
        print(str + l)
    }
Copy the code

As in the above code, when print executes, it waits for the result of the run method block to return.

T.run()

T.run() and run() may not seem very different to the eye, but there will be quite a difference when used

Source:

@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T. () - >R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
Copy the code

Let’s use a code to simulate the usage environment

private var str = "java"

    fun printStr(a){
        str.run {
            print("${this.length}")
            print("${this.last()}")
            print("${first()}")}}Copy the code

This keyword can be used in the t. run method block in the above code to replace itself, or can be omitted, more suitable for multiple lines of code using the same object, if viewed through the source code, you can find that block() is a T type extension function.

For more higher-order functions like also with apply, check out Kotlin’s library functions: run, with, let, also, and apply

Next – Kotlin study Notes (14) Shallow reading coroutines