let it also apply, takeIf, takeUnless are the extension functions in Kotlin.
To understand this function, you must understand in <Boilers. "β Extension functions and Lambda functions .
Extension function:
Using the extension function, we can create a function for the class without inheriting the class.
Kotlin, similar to C # and Gosu, provides the ability to extend a class with new functionality without inheriting from the class or using any type of design, such as Decorator. This is done through special ads called extensions. Kotlin supports extension functions and extension properties.
So, to find only numbers in String , you can create a method like below without inheriting the String class.
fun String.isNumber(): Boolean = this.matches("[0-9]+".toRegex())
you can use the above extension function like this,
val phoneNumber = "8899665544" println(phoneNumber.isNumber)
which prints true .
Lambda functions:
Lambda functions are like an interface in Java. But in Kotlin, lambda functions can be passed as a parameter in functions.
Example:
fun String.isNumber(block: () -> Unit): Boolean { return if (this.matches("[0-9]+".toRegex())) { block() true } else false }
You can see that the block is a lambda function and is passed as a parameter. You can use the function above, for example,
val phoneNumber = "8899665544" println(phoneNumber.isNumber { println("Block executed") })
The above function will print as follows:
Block executed true
I hope you now have an idea about extension functions and Lambda functions. Now we can move on to the Extension functions one by one.
let be
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
The above function uses two types of T and R.
T.let
T can be any object, for example, the String class. therefore, you can call this function with any objects.
block: (T) -> R
In the let parameter, you can see the lambda function above. In addition, the caller is passed as a parameter to the function. That way you can use the caller of the class inside the function. then it returns R (another object).
Example:
val phoneNumber = "8899665544" val numberAndCount: Pair<Int, Int> = phoneNumber.let { it.toInt() to it.count() }
In the above example, let it accept String as a parameter of its lambda function and return Pair in response.
Another extension function works in the same way.
also
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
the extension function also takes the calling class as a parameter to the lambda function and returns nothing.
Example:
val phoneNumber = "8899665544" phoneNumber.also { number -> println(number.contains("8")) println(number.length) }
To apply
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
The same as the same caller, which is passed as a function, so you can use functions and other properties without calling it or the parameter name.
Example:
val phoneNumber = "8899665544" phoneNumber.apply { println(contains("8")) println(length) }
In the above example, you can see the functions of the String class directly called inside the lambda function.
takeIf
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null
Example:
val phoneNumber = "8899665544" val number = phoneNumber.takeIf { it.matches("[0-9]+".toRegex()) }
In the above example, number will have the string phoneNumber , only it matches regex . Otherwise, it will be null .
takeUnless
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null
This is the opposite of takeIf.
Example:
val phoneNumber = "8899665544" val number = phoneNumber.takeIf { it.matches("[0-9]+".toRegex()) }
number will have the string phoneNumber if regex does not match. Otherwise, it will be null .