function
A function is a block of code organized for a specific function. The function definition format is as follows:
- Fun :[return value type]{[function body]}
- Fun function name = [expression]
fun sum(arg1: Int, arg2: Int): Int {
return arg1 + arg2
}
Copy the code
If the function method body has only one line of code, we can change {} to = without return, and the value of the expression will be returned as the function value:
fun sum(arg1: Int, arg2: Int) = arg1 + arg2
Copy the code
Default return value type
Any function has a return value. In general, the method body of a function uses a return to return the result. However, some functions do not need to return the result, so you can omit the return:
fun main(args: Array<String>){... }Copy the code
Even if there is no return in the body of a function, the function still has a return value type. The default return value type is Unit, but Unit is usually omitted:
fun main(args: Array<String>): Unit{... }Copy the code
Anonymous functions
An anonymous function is a function that has no name, but needs to be assigned to a variable, otherwise the IDE will report an error:
// Sum, whose value is a function
val sum = fun(arg1: Int, arg2: Int): Int {
return arg1 + arg2
}
fun main(args: Array<String>): Unit {
val result = sum(1.2)
println(result) / / 3
}
Copy the code
In this case, sum is a variable, but its value is a function.
Lambda expressions
Lambda expressions are also “anonymous functions”, but in a slightly different format:
- {[argument list] -> [function body, last line is return value]}
val sum = { arg1: Int, arg2: Int ->
println("$arg1 + $arg2 = ${arg1 + arg2}")
arg1 + arg2
}
fun main(a){
println(sum(1.2)) / / 3
}
Copy the code
The return value of a Lambda expression is the result of the last line in the expression.
The type of a Lambda
In Kotlin, both constants and variables have their own types, such as Human. If a variable’s value is a Lambda expression, what is its type? That’s right, Lambda:
- () -> Unit: no parameter, return value null
- (Int) -> Int: Passes an integer and returns an integer
- (String, (String)->String) -> Boolean: Pass String, Lambda expression, return Boolean
// lambda type :(Int,Int) -> Int
val sum = { arg1: Int, arg2: Int -> arg1 + arg2 }
// lambda type :() -> Unit
val printlnHello = {
println("Hello")}Copy the code
Calls to Lambda expressions
As with anonymous functions, a variable with a value of a Lambda expression can execute a Lambda expression in one of two ways:
- with
(a)
The calling - with
invoke()
call
println(sum(1.2)) / / 3
println(sum.invoke(1.2)) / / 3
Copy the code
Actually, () is invoke().
Simplification of Lambda expressions
- The last Lambda can be removed when a function argument is called
- The function argument has only one Lambda, and the parentheses can be omitted when called
- Lambda has only one argument, which defaults to it
- A function whose input argument returns the same value as the parameter may be passed in as an argument as a function reference
Let’s look at forEach, an extension to Array:
/** * Performs the given [action] on each element. */
public inline fun <T> Array<out T>.forEach(action: (T) - >Unit): Unit {
for (element in this) action(element)
}
Copy the code
ForEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach forEach Action action of type (T -> Unit Lambda), return Unit (that is, no return value), forEach forEach forEach forEach The action argument is also used to process the iterated elements.
We won’t go into details about the extension function here, but we’ll cover it in future articles. We just need to know what forEach does.
val args = arrayOf("1"."2"."3"."l"."q"."r")
// Use for-in to iterate through the array and print the element contents
for (arg in args) {
println(arg)
}
Copy the code
ForEach = forEach; forEach = forEach; forEach = forEach; forEach = forEach; forEach = forEach
// complete Lambda
args.forEach({ it -> println(it) })
// Lambda simplified
args.forEach({ println(it) })
// Rename the parameter it. Ele cannot be omitted
args.forEach({ ele -> println(ele) })
Copy the code
Lambda defaults to it when it has only one argument. Of course, you can rename it if you don’t want to use it, but if you rename it, you can’t omit it. In addition to omitting the default argument it, there are ways to simplify Lambda expressions:
// The last Lambda can be moved out when a function argument is called
args.forEach(){ println(it) }
// The function argument has only one Lambda, and the parentheses can be omitted when called
args.forEach{ println(it) }
Copy the code
This is the simplified version of Kotlin’s Lambda expression, and we will often encounter the final simplified version in future development.
Lambda expressions and function references
Go back to the action type of the forEach extension function:
// action: (T) -> Unit
public inline fun <T> Array<out T>.forEach(action: (T) - >Unit): Unit {
for (element in this) action(element)
}
Copy the code
Now look at the definition of println() :
// println: (Any?) -> Unit
public actual inline fun println(message: Any?). {
System.out.println(message)
}
Copy the code
Println () is defined as a Lambda for action. In this scenario, we can also convert the Lambda expression required by the forEach parameter action into a reference to the println function, which uses :: :
// A function whose input parameter returns the same value as its parameter can be passed in as an argument as a function reference
args.forEach(::println)
Copy the code
Lambda expressions jump out of forEach
Here is a serious superclass, do not understand it does not matter, you can skip ~
Requirement: When iterating through a group of numbers, break the loop when an element q is found.
val args = arrayOf("1"."2"."3"."l"."q"."r")
for (arg in args) {
if (arg == "q") break
println(arg)
}
println("The End") // 1 2 3 l The End
Copy the code
ForEach = forEach = forEach = forEach = forEach = forEach
fun main(a) {
val args = arrayOf("1"."2"."3"."l"."q"."r")
args.forEach {
if (it == "q") break // IDE error: 'break' and 'continue' are only allowed inside a loop
print("$it ")
}
println("The End")}Copy the code
Lambda expressions are just expressions, not loops, so we can’t use break and continue, so we have to use return to interrupt the loop:
fun main(a) {
val args = arrayOf("1"."2"."3"."l"."q"."r")
args.forEach { // 1 2 3 l
if (it == "q") return
print("$it ")
}
println("The End") // Will not be executed
}
Copy the code
At first glance, The use of return for interrupt traversal looks like it, but The absence of “The End” means that The return does not interrupt traversal, but rather interrupts The current main function for The same reason: Lambda expressions are just expressions.
For Lambda expressions, Kotlin provides labeled returns, which can be used to jump out of traversal using the return@xxx method in Lambda expressions. Try this:
fun main(a) {
val args = arrayOf("1"."2"."3"."l"."q"."r")
args.forEach {
if (it == "q") return@forEach
print("$it ")
}
println("The End") // 1 2 3 l r The End
}
Copy the code
What happens when the program skips q and continues? This goes back to the nature of Lambda expressions. A Lambda expression in forEach is actually a function body, so the tag return return@xxx exits the function body only by exiting the current call. Is there no way to implement this requirement using forEach? Yes, forEach alone will not do, you need to configure StreamApi to filter the array and then iterate through it:
val args = arrayOf("1"."2"."3"."l"."q"."r") args.takeWhile { it ! ="q" }.forEach { print("$it ") }
println("The End")// 1 2 3 l The End
Copy the code