More Kotlin

Kali ini Kita akan membahas Kotlin Basic tentang apa itu Control Flow, Returns & Jumps pada Kotlin. Jika Kalian mengingat Part 1, Kalian melihat pada akhir tutorial ada serpihan code yang mungkin bagi Kalian ada yang sudah mengenal.

Yap, itu adalah Control Flow pada kotlin, terdapat If-else Expression, While Expression dan juga yang lain. Mari kita kupas satu persatu!


If Expression


Ada beberapa cara menulis If Expression pada Kotlin, yaitu


// 1. Cara simple
var max = a
if (a < b) max = b

// 2. Menggunakan else
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}

// Sebagai expression
val max = if (a > b) a else b

Dari sini kita bisa melihat ada banyak cara untuk menggunakan If Expression pada Kotlin. Lalu, apa bedanya? Mari kita Ulik.

Pada cara pertama, kita memberikan nilai pada object max a yang dimana kita menggunakannya pada if operation.

Jika nilai a lebih kecil dari nilai b maka pada fungsi If Kotlin akan langsung me-return value, yaitu mengubah nilai pada object max menjadi b, jika nilai a lebih kecil dari b

Cara kedua, kita menggunakan else untuk fungsi if dimana pada block atau {} merupakan return value yang kita inginkan.

Pada block pertama, jika nilai a lebih besar dari nilai b maka tinggal kita tulis code yang kita inginkan seperti membuat nilai object max menjadi a.

Dan juga jika nilai a ternyata lebih kecil dari nilai b, maka pada block kedua kita mereturn value yang kita inginkan, seperti object max kita beri nilai b.

Cara ketiga, kita membuat object max sebagai sebuah Expression dimana,

if (a > b)

Jika a ternyata lebih besar dari b maka akan langsung membuat value dari object max menjadi a dan begitu juga sebaliknya karena kita memasukkan return value berupa a else b.

Tapi Kita juga bisa loh membuat else digabungkan langsung dengan Expression, maka kode nya akan menjadi seperti ini

fun check(x: Int, y: Int) {
    val result = if (x >= y) {
        println("x >= y")
        true
    } else {
        println("x bukan >= y")
        false
    }
    println("Result [ $result ]\n- - - - - - - -")
}

// Jika kalian ingin melihat hasilnya sendiri pada IntelliJ
fun main() {
    println(check(4, 3))
}

Kita membuat object result yang dimana akan mengecek jika nilai x dan y lebih kecil ~~~

Oh ya, untuk pemahaman tentang perbedaan < / > / <= / >=, kalian bisa melihat penjelasannya disini.

Kembali pada penjelasan, saat object mendeteksi bahwa x lebih kecil dari y maka akan menulis nilai x >= y dan juga true. Dan begitu sebaliknya yang tertulis pada block ke dua.


When Expression


When Expression pada Kotlin merupakan Switch Statement dimana ketika ada beberapa statement dan tiap statement memiliki syaratnya masing-masing. Mari kita lihat contoh kode dibawah ini

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // Note the block
        print("x is neither 1 nor 2")
    }
}

Ketika nilai x merupakan 1 maka akan print x == 1 dan juga yang lain. Setiap statement memili syaratnya masing-masing yang akan di return menggunakan when .

Jika nilai tidak ada yang memenuhi syarat suatu statement, maka fungsi when akan di return ke else.

Jika ada statement yang memiliki beberapa syarat, anda dapat menulis atau menggabungkannya dengan koma ,.

when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}

Kita juga dapat mengecek jika sebuah value ada atau tidak di suatu range atau collection.

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

Dan juga, semenjak Kotlin mengeluarkan versi 1.3, sebuah fungsi when dapat mengambil sebuah subjek variable seperti kode dibawah ini.

/*
 Kode dibawah ini mungkin Akan anda gunakan jika kalian mulai
 menggunakan Kotlin untuk membuah sebuah Aplikasi Android.
*/
fun Request.getBody() =
        when (val response = executeRequest()) {
            is Success -> response.body
            is HttpError -> throw HttpException(response.status)
        }

For Loops


for loop digunakan untuk mengulang (looping) sebuah collection dan juga yang list data yang lain. Pada contoh dibawah, Kita akan menggunakan looping menggunakan range

println("For Loops")
for (i in 1..3) {
    println(i)
}

Kode diatas akan menampilkan sebuah perulangan(loop) mulai angka 1 hingga 3 menggunakan 1..3 yaitu range. Atau Anda ingin membuatnya lebih EPIC

println("Fancier For Loops...")
for (i in 6 downTo 0 step 2) {
    println(i)
}

Loop juga dapat digunakan untuk collection, seperti

println("For Loops With Collections")
val myCollection = listOf("Hey", "There.", "This", "Is", "AnbiDev!")
for (item in myCollection) println(item)

Atau Kalian ingin menggunakan indeces atau withIndex library yang tersedia oleh Kotlin

println("For Loops With Collections on Indices")
for (i in myCollection.indices) {
    println("$i : ${myCollection[i]}")
}

println("For Loops With Collections for Items & Indices")
for ((index, value) in myCollection.withIndex()) {
    println("$index : $value")
}

While Loops


while & do while ๐Ÿค”?

println("While Loops")
var number = 3

while (number > 0) {
    number--
    println("We're still going to decrement the number...")
}

do {
    val anotherNumber = 0
    println("Do While...")
} while (anotherNumber > 0)

println("break")

Mari kita perhatikan kode diatas.

while number > 0

Yang berarti jika nilai dari object number lebih dari 0, maka nilai dari number akan dikurangi dengan number--.

Dan pada do while, sebenarnya sama saja dengan while hanya saja letak lokasi pengecekannya yang berbeda.

Untuk pengecekannya berada di while yang dimana jika anotherNumbersudah sesuai dengan anotherNumber yang berada pada do. Maka tidak akan terjadi perulangan atau loop.


Returns & Jumps


Kotlin memiliki 3 jenis Jumps struktur expression seperti

  • return -> Akan secara default me-return enclosing function terdekat atau anonymous function.
  • break -> Mematikan enclosing loop terdekat.
  • continue -> Melanjutkan proses pada enclosing loop terdekat

Semua expression diatas dapat dijadikan expression yang besar, seperti

val s = person.name ?: return

Dan tipe yang digunakan adalah Nothing Type.


Break & Continue Labels


Semua expression pada Kotlin dapat di mark dengan sebuah label. Label mempunyai penanda yang diawali dengan @ seperti abc@ , anbidev@, fooBar@ adalah label yang valid (lihat grammar).

Untuk melabeli sebuah expression, kita hanya tinggal menginput label didepan sebuah expression.

loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (...) break@loop
    }
}

Dan mengakhirinya dengan break@loop yang sama dengan label jumps dan dieksekusi tepat setelah loop ditandai dengan label. Berikut adalah contoh kodenya

fun breakingTheLoop(x: Int, y: Int) {
    myLoop@ for (a in 0..x) {
        for (b in 0..y) {
            println("[ $a ][ $b ]")
            if (b == 10) {
                break@myLoop // Does not break current loop, but the one above it!
            }
        }
    }
}

fun main() {
    println(breakingTheLoop(2, 4))
}

Return at Labels


Dengan fungsi literals, local functions, object expressions dan juga functions dapat di nested dalam Kotlin. Fungsi returns yang terqualified memungkinkan Kita untuk return diluar function.

Dan yang terpenting adalah gunakan case untuk men-return dari sebuah lambda expression. Recall dengan kode seperti ini

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return // non-local return directly to the caller of foo()
        print(it)
    }
    println("this point is unreachable")
}

fun main() {
    foo()
}

Return expressions men-return dengan enclosing function terdekat seperti foo.

PS : non-local return hanya dapat disupport dengan lambda expressions yang dipass menjadi inline function

Jika Kita perlu men-return sebuah lambda expression, Kita harus memberikan label dan mengkualifikasikannya pada return.

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // local return to the caller of the lambda, i.e. the forEach loop
        print(it)
    }
    print(" done with explicit label")
}

fun main() {
    foo()
}

Sudah pusing belum ๐Ÿฅด? Tenang kok, masih part 2 Xixixixi.

Btw, kode diatas hanya men-return dari lambda expression. Untuk selanjutnya, kita dapat membuatnya lebih mudah untuk menggunakan label yang implisit.

Seperti label yang memiliki nama yang sama dengan function dimana akan membuah lamba expression dapat lewat.

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach // local return to the caller of the lambda, i.e. the forEach loop
        print(it)
    }
    print(" done with implicit label")
}

fun main() {
    foo()
}

Atau juga, hehe banyak ya ๐Ÿ˜…. Tenang, pilih sesuai dengan code style kalian kok.

Kalian juga dapat menggantikan lambda expression dengan anonymous function. Statement return pada anonymous function akan men-return pada dirinya sendiri.

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
        if (value == 3) return  // local return to the caller of the anonymous fun, i.e. the forEach loop
        print(value)
    })
    print(" done with anonymous function")
}

fun main() {
    foo()
}

Catatan :

Menggunakan local function return seperti contoh diatas hampir sama dengan continue pada loop. Tidak ada tujuan yang digunakan untuk break, tapi kita dapat mensimulasikannya dengan menambahkan lambda dan juga non-locally return pada kode, seperti contoh :


fun foo() {
    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop // non-local return from the lambda passed to run
            print(it)
        }
    }
    print(" done with nested loop")
}

fun main() {
    foo()
}

Ketika men-return sebuah nilai, parse memberikan preference untuk qualified return seperti contoh

return@a 1

yang berarti “return 1 pada label @a dan bukan “mengembalikan label expression (@a 1).