preface

I often read some basic libraries written by people in the company (based on Kotlin) and couldn’t quite understand them. There are always various keywords and functions, I don’t know whether they are deliberately using them or what they are doing, so I started to learn from the Scope Function that appears most frequently.

The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object. When you call such a function on an object with a lambda expression provided, it forms a temporary scope. In this scope, you can access the object without its name. Such functions are called scope functions. There are five of them: let, run, with, apply, and also.

So there are 5 Scope functions in total. What are their functions? I don’t think there is any real effect, maybe some operations are put in a function, the code is cleaner, because you can not use them at all.

The overview of source code

Take a look at the source code

/** * Calls the specified function [block] with `this` value as its receiver and returns its result. * * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#run). */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T. () - >R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

/** * Calls the specified function [block] with the given [receiver] as its receiver and returns its result. * * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#with). */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T. () - >R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

/** * Calls the specified function [block] with `this` value as its receiver and returns `this` value. * * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#apply). */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T. () - >Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

/** * Calls the specified function [block] with `this` value as its argument and returns `this` value. * * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#also). */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) - >Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

/** * Calls the specified function [block] with `this` value as its argument and returns its result. * * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#let). */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) - >R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)}Copy the code

Inline Function

You can see that all five methods are Inline functions. This is understandable, because the Java code will generate a Function object when the methods are compiled, and there will be unnecessary object creation, etc., so we use the keyword inline to inline the code directly. This is also something from Kotlin, which acts on the compiler to optimize the code. Does not affect the function body logic.

Extension Function

Also, you can see that four of the methods are Extension Functions, which is a concept from Kotlin. Extension Functions support adding new Functions to a class.

For example, you could write it like this

fun String.hello(world : String) : String {
    return "hello " + world;
}
fun main(a) {
    System.out.println("abc".hello("world"));
}
Copy the code

Static hello (); static hello (); static Hello ();

Generic Function

Also, you can see that all five methods are generic, which is why you can use the Extension Function to call any of the four methods on any class except with(with itself is not Extention Function).

There are different

As you can see above, these five methods have a lot in common, but they also have some subtle differences.

The official website has said very well, and summarized into the table ~~ I will not go to translate again

Two points, basically

1.The way to refer to the context object.

2.The return value.

Function Object reference Return value
let it Lambda result
run this Lambda result
run Lambda result
with this Lambda result
apply this Context object
also it Context object

There are two runs, and yes, there is a run method, but I don’t know why it exists

// This simply returns the result of a lambda function. Why provide a method like this?
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
Copy the code

Actually these a few methods can turn each other, just have a few convenient and inconvenient problem, the official has proposal only, with need not, how to use, still see yourself.