A higher-order function is a function that takes functions as parameters, or returns a function.
Kotlin functions are first-class, which means they can be stored in variables and data structures, and can be passed as arguments to and returned from other higher-order functions. You can perform any operations on functions that are possible for other non-function values.
These types have a special notation that corresponds to the signatures of the functions - their parameters and return values:
All function types have a parenthesized list of parameter types and a return type: (A, B) -> C denotes a type that represents functions that take two arguments of types A and B and return a value of type C. The list of parameter types may be empty, as in () -> A. The Unit return type cannot be omitted.
Function types can optionally have an additional receiver type, which is specified before the dot in the notation: the type A.(B) -> C represents functions that can be called on a receiver object A with a parameter B and return a value C. Function literals with receiver are often used along with these types.
Suspending functions belong to a special kind of function type that have a suspend modifier in their notation, such as suspend () -> Unit or suspend A.(B) -> C.
The function type notation can optionally include names for the function parameters: (x: Int, y: Int) -> Point. These names can be used for documenting the meaning of the parameters.
You can also give a function type an alternative name by using a type alias:
typealias ClickHandler = (Button, ClickEvent) -> Unit
A value of a function type can be invoked by using its invoke(...) operator: f.invoke(x) or just f(x).
If the value has a receiver type, the receiver object should be passed as the first argument. Another way to invoke a value of a function type with receiver is to prepend it with the receiver object, as if the value were an extension function: 1.foo(2).
val intPlus: Int.(Int) -> Int = Int::plus
println(intPlus.invoke(1, 1))
println(intPlus(1, 2))
println(2.intPlus(3))
Output: 2-3-5
Lambda expressions and anonymous functions are function literals. Function literals are functions that are not declared but are passed immediately as an expression. Consider the following example:
max(strings, { a, b -> a.length < b.length })
The function max is a higher-order function, as it takes a function value as its second argument. This second argument is an expression that is itself a function, called a function literal, which is equivalent to the following named function:
fun compare(a: String, b: String): Boolean = a.length < b.length
The full syntactic form of lambda expressions is as follows:
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
A lambda expression is always surrounded by curly braces.
Parameter declarations in the full syntactic form go inside curly braces and have optional type annotations.
The body goes after the ->.
If the inferred return type of the lambda is not Unit, the last (or possibly single) expression inside the lambda body is treated as the return value.
If you leave all the optional annotations out, what's left looks like this:
val sum = { x: Int, y: Int -> x + y }
According to Kotlin convention, if the last parameter of a function is a function, then a lambda expression passed as the corresponding argument can be placed outside the parentheses:
val product = items.fold(1) { acc, e -> acc * e }
Such syntax is also known as trailing lambda.
If the lambda is the only argument in that call, the parentheses can be omitted entirely:
run { println("...") }
It's very common for a lambda expression to have only one parameter.
If the compiler can parse the signature without any parameters, the parameter does not need to be declared and -> can be omitted. The parameter will be implicitly declared under the name it:
ints.filter { it > 0 } // this literal is of type '(it: Int) -> Boolean'
Function types with receiver, such as A.(B) -> C, can be instantiated with a special form of function literals – function literals with receiver.
As mentioned above, Kotlin provides the ability to call an instance of a function type with receiver while providing the receiver object.
Inside the body of the function literal, the receiver object passed to a call becomes an implicit this, so that you can access the members of that receiver object without any additional qualifiers, or access the receiver object using a this expression.
This behavior is similar to that of extension functions, which also allow you to access the members of the receiver object inside the function body.
Here is an example of a function literal with receiver along with its type, where plus is called on the receiver object:
val sum: Int.(Int) -> Int = { other -> plus(other) }
Kotlin is a object oriented language as well as functional language also. function can be declared on top level
Functions in kotlin are first_class_citizen. means treated like an object. can be passed as argument, can be returned from function can be store in variable
This is not higher order function but ,
A variable of function type. like data type we can define function type also to make a variable of function type and that can hold the function reference, mentioned with "::"
Function that accept an argument as a function or return a function called higher order function
Calculator is a higher order function as he receives a function as a parameter.
Why do we do that? why do we send a function as a parameter?
Ans: Sometime we send parameters along with functionality.
Ex: A if the function is handling server response then that can be success or error so in that case we can make handleResponse function as a hire order function and send all possible functionality as a higher order function.
Ex: B if you want to perform same click event on check box check and on check box label also then make a function and pass it into the function so that the same function can be applied on both check checked event and on label click event
Lamda's anonymous functions.
Lamda is a block of code covered by {}. it can be of multiple line and last line is the return value of lamda
If lamda is the last parameter then we can take it out of parenthesis for the more redability