The official explanation: https://www.kotlincn.net/docs/reference/scope-functions.html
Select function
Features | Object Reference | return value | It is an extension function |
---|---|---|---|
let |
it |
Lambda results | Yes |
run |
this |
Lambda results | Yes |
run |
- | Lambda results | No: there is no context object to call |
with |
this |
Lambda results | No: context object as a parameter. |
apply |
this |
Context object | Yes |
also |
it |
Context object | Yes |
The following is a brief guide accordance with the intended function of choice:
- Lambda execution on a non-null object:
let
- The expressions as variables into partial ranges:
let
- Object Configuration:
apply
- Object configuration and results:
run
- Needed for the operation of the expression statement: non-extension
run
- Additional effects:
also
- Group objects function call:
with
Overlapping with different functions, so you can select specific functions according to the agreed project or team use.
Although the scope of the function is a way to make the code more concise, but avoid overuse them: it will reduce the readability of the code and cause errors. Avoid nesting range of functions and link them to be careful: it is easy for the current context object and this
confused values or of it
.
takeIf
versus takeUnless
In addition to the range of the function, further comprising a standard library function takeIf
and takeUnless
. These functions allow you to check the state of the object is embedded in the call chain.
When invoked on an object having provided predicates and predicate if the object takeIf
matches the object is returned. Otherwise, it returns null
. Thus, takeIf
a single object filtering function. In turn, takeUnless
the object if the object does not match the predicate is returned if the match the object is returned null
. This object may be used as the parameter lambda it
( ).
val str = "Hello"
val caps = str.takeIf { it.isNotEmpty() }?.toUpperCase()
//val caps = str.takeIf { it.isNotEmpty() }.toUpperCase() //compilation error
println(caps)
In the takeIf
link to other functions and then takeUnless
, do not forget to check the implementation of air safety or call ( ?.
), because their return value can be empty.
fun displaySubstringPosition(input: String, sub: String) {
input.indexOf(sub).takeIf { it >= 0 }?.let {
println("The substring $sub is found in $input.")
println("Its start position is $it.")
}
}
displaySubstringPosition("010000011", "11")
displaySubstringPosition("010000011", "12")
to sum up:
the difference:
Since the range of the function is very similar nature, and therefore the difference between them is important to understand. Each range function has two main differences:
- Context object reference to the way
- return value.
apply:
Context object may be used as Receiver this
( ). The return value is the object itself
also:
Context object used as a parameter it
( ). The return value is the object itself
The above are two ways to return the object itself may call chain to perform more complex processing.
---------------------------------------------------------------------------
run
And with
invoke the same as the let
spread function of the context object
let:
Context object used as a parameter it
( ). The return value is the result of lambda.
with:
Non-expanded functions: context object passed as a parameter, but the lambda, which can be used as Receiver ( this
). The return value is the result of lambda.
run:
Context object may be used as Receiver this
( ). The return value is the result of lambda.
The above three ways to return the result value of lambda.