Functions
Outline
-
Introduction Functions
-
Higher-order Functions and Lambdas
-
Inline Functions
What is Function?
In Kotlin, functions are first-class citizen.
It means that functions can be assigned to the variables, passed as an arguments or returned from another function.
How many kinds of function?
-
Member functions
-
Tail recursive functions
-
Generic functions
-
Extension functions
-
Higher-order functions and lambdas
-
Inline functions
Member Functions
class Sample() {
fun foo() { print("Foo") }
}
Tail Recursive Functions
fun recursiveFactorial(n: Long) : Long {
return if (n <= 1) {
n
} else {
n * recursiveFactorial(n - 1)
}
}
Generic Functions
fun <T> singletonList(item: T): List<T> {
/*...*/
}
Extension Functions
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}
Higher-order Functions
fun runTransformation(f: (String, Int) -> String): String {
return f("hello", 3)
}
Inline Functions
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
What is higher-order function
A higher-order function is a function that takes functions as parameters, or returns a function.
Collection API
-
foreach
-
filter
-
map
-
reduce
-
flatmap
foreach
val people = listOf(Person("Alice", 29), Person("Bob", 31))
people.foreach{
print(it.name) // output : Alice Bob
}
foreach
filter
val people = listOf(Person("Alice", 29), Person("Bob", 31))
val pList = people.filter{
it.age > 30
}
print(pList) // output: [Person(name=Bob, age=31)]
filter
map
val people = listOf(Person("Alice", 29), Person("Bob", 31))
val pList = people.map{
it.name
}
print(pList) // output: [Alice, Bob]
map
reduce
val people = listOf(Person("Alice", 29), Person("Bob", 31))
val pList = people.map{
it.name
}.reduce{ acc, s->
"$acc,$s"
}
print(pList) // output: Alice,Bob
reduce
,
,
,
flatmap
val people = listOf(
Person("Alice", 29, arrayListOf("A", "B")),
Person("Bob", 31, arrayListOf("C", "D")))
val books = people.flatmap{
it.bookList
}
print(books) // output: [A, B, C, D]
flatmap
[
[
[
]
]
]
Eagerly vs Lazy
-
These Functions create intermediate collections eagerly, meaning the intermediate result of each step is stored in a temporary list.
-
Sequences give you an alternative way to perform such computations that avoids the creation of intermediate temporary objects.
Eagerly
people.map(People::name).fliter{ it.startWith("A")}
Sequences
people.asSequence()
.map(Person::name)
.filter { it.startsWith("A") }
.toList()
Switch Position
people.filter{ it.name.startWith("A")}.map(People::name)
//better than
people.map(People::name).filter{ it.name.startWith("A")}
What is Lambda
Lambda expression or simply lambda is an anonymous function
Single Abstract Method(SAM)
/* Java */
public interface OnClickListener{
void onClick(View v);
}
/* Java */
public class Button {
public void setOnClickListener(OnClickListener l) { ... }
}
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
...
}
}
/* kotlin */
button.setOnClickListener { view -> ... }
Decompile function
fun sum(a: Int, b: Int, lambda: (result: Int) -> Unit): Int {
val r = a + b
lambda.invoke(r)
return r
}
fun main(args: Array<String>) {
sum(1, 2) { println("Result is: $it") }
}
//decompile
public static final void main(@NotNull String[] args) {
//...
sum(1, 2, (Function1)null.INSTANCE);
}
Decompile inline function
inline fun sum(a: Int, b: Int, lambda: (result: Int) -> Unit): Int {
val r = a + b
lambda.invoke(r)
return r
}
fun main(args: Array<String>) {
sum(1, 2) { println("Result is: $it") }
}
//decompile
public static final void main(@NotNull String[] args) {
//...
byte a$iv = 1;
int b$iv = 2;
int r$iv = a$iv + b$iv;
String var9 = "Result is: " + r$iv;
System.out.println(var9);
}
Returns and Jumps
-
return: By default returns from the nearest enclosing function or anonymous function.
-
break: Terminates the nearest enclosing loop.
-
continue: Proceeds to the next step of the nearest enclosing loop.
break and continue
loop@ for (i in 1..100) {
for (j in 1..100) {
if (...) break@loop
}
}
loop@ for (i in 1..100) {
for (j in 1..100) {
if (...) continue@loop
}
}
return outer function
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
// non-local return directly to the caller of foo()
if (it == 3) return
print(it)
}
println("this point is unreachable")
}
output: 12
return lambda function
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
// local return to the caller of the lambda
if (it == 3) return@lit
print(it)
}
print(" done with explicit label")
}
output: 1245 done with explicit label
return lambda function
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
//// local return to the caller of the lambda
if (it == 3) return@forEach
print(it)
}
print(" done with implicit label")
}
output: 1245 done with explicit label
return anonymous function
fun foo() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
// local return to the caller of the anonymous fun
if (value == 3) return
print(value)
})
print(" done with anonymous function")
}
output: 1245 done with anonymous function
return nesting lambda function
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
// non-local return from the lambda passed to run
if (it == 3) return@loop
print(it)
}
}
print(" done with nested loop")
}
output: 12 done with nested loop
return 1 at label
return@a 1
means "return 1 at label @a" and not "return a labeled expression (@a 1)".
Thank you.
Functions
By givemepass
Functions
- 887