Walking the file tree in Kotlin

fun main() {
    File(".").walkTopDown().forEach { println(it) } // Walk functions all return a sequence of files. This starts at the root directory and navigates to each branch, listing as it goes (directories before files).
    // Also walkBottomUp()
    println("======")
    // We can treat the output like a sequence and filter out the results we want:
    File(".").walkTopDown()
        .filter { it.name.endsWith(".kt") }
        .forEach { println(it) }
    // If you want to do something before or after entering the directory you can use the onEnter and onLeave
    // onEnter takes a lambda that returns a Boolean - if false, is skipped
}

 

Loops in Kotlin

Loops in Kotlin.

enum class Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

fun main() {
    // for (int i = 0; i < 10; i++) does not exist in Kotlin. Use ranges instead:
    for (i in 1..20) {

    }

    val range = 1..5
    val charRange = 'a'..'z' // Valid as long as values are comparable
    val stringRange = "ABC".."XYZ" // Valid as long as values are comparable

    println(3 in range) // true
    println('q' in charRange) // true
    println("CCC" in stringRange) // true
    println("CCCCCC" in stringRange) // Still lower than XYZ
    println("ZZZZZZ" in stringRange)// false
    println(32 !in 1..10) // Not in the range
    println("=======")

    val backwardRange = 5.downTo(1)
    println(5 in backwardRange) // true

    val stepRange = 3..15 // Define initial range
    val step3 = stepRange.step(3) // Take the first and then every third value
    for (i in step3) println(i)
    println("=======")
    // Or
    for (i in 0..20 step 4) println(i)
    println("=======")

    val reverseStep = step3.reversed() // Only works for integers
    for (i in reverseStep) println(i)
    println("=======")
    // Or
    for (i in 20 downTo 15) println(i) // Decrement
    println("=======")
    for (i in 20 downTo 10 step 5) println(i) // Decrement in steps
    println("=======")
    for (i in 1 until 10) println(i) // Excludes last number in range
    println("=======")

    // To loop through a String range we need an iterator, which is included in the String class:
    val aString = "howdy"
    for (a in aString) println(a)
    println("=======")

    val seasons = arrayOf("Spring", "Summer", "Autumn", "Winter")
    for (season in seasons) println(season)
    println("=======")
    println("whatever" !in seasons)
    println("=======")
    val bString = "hello"
    println('e' in bString)
    println('e' !in bString)
    println("=======")

    // Long way
    for (index in seasons.indices) {
        println("${seasons[index]} is season number ${index + 1}")
    }
    println("=======")
    // Or
    seasons.forEach { println(it) } // <- Lambda expression
    seasons.forEachIndexed { index, value -> println("$value is season number $index")} // Equivalent to above expression
    println("=======")

    // We can name loops
    // Say we want to break out of both the j & k loops when k hits 7...
    for (i in 1..3) {
        println("i = $i")
        jloop@ for (j in 1..4) { // Label the loop
            println("j = $j")
            for (k in 5..10) {
                println("k = $k")
                if (k == 7) {
                    break@jloop // Call the @jloop. Also works with continue@jloop
                }
            }
        }
    }
    println("=======")
    // Can get out of hand easily so only use when necessary

    // if (expression) in Kotlin can evaluate to a value, unlike Java
    // Makes ternary operator ( String name = case.equals("uppercase") ? "JOHN" : "john"; ) obsolete
    val someCondition = 69 < 22
    var num: Int
    if (someCondition) { // No return
        num = 50
    } else {
        num = 592
    }
    // Or
    var num2 = if (someCondition) 50 else 592 // returns the int value. Must provide else if using an expression

    // When statement is enhanced switch statement
    val num3 = 200
    val y = 400
    when(num3) {
        100, 600 -> println("100") // If value is 100 or 600
        200 -> println("200")
        in 201..300 -> println("In range 201 to 300") // Ranges allowed
        y + 80 -> println("80 more than y") // Expressions allowed
        else -> "Didn't match anything"
    }

    val obj1: Any = "I'm a string"
    val obj2: Any = BigDecimal(25.2)
    val obj3: Any  = 45

    val something: Any = obj2
    if (something is String) println(something.toUpperCase()) // All of this
    else if (something is BigDecimal) println(something.remainder(BigDecimal(10.5))) // can be replaced
    else if (something is Int) println("${something - 22}") // by the following:

    when (something) {
        is String -> println(something.toUpperCase())
        is BigDecimal -> println(something.remainder(BigDecimal(10.5)))
        is Int -> println("${something - 22}")
    }
    // Can also evaluate to a value
    var z = when (something) {
        is String -> something.toUpperCase()
        is BigDecimal -> something.remainder(BigDecimal(10.5))
        is Int -> "${something - 22}"
        else -> "No idea what type it is"
    }
    // Use with enums
    val timeOfYear = Season.WINTER // See Season enum at top-level
    val str = when(timeOfYear) { // No else required when enum constrains the options
        Season.SPRING -> "Flowers are blooming"
        Season.SUMMER -> "Sun is shining"
        Season.AUTUMN -> "Leaves are falling"
        Season.WINTER -> "It's snowing"
    }
    println(str)
    // Can be used without a value - alternative to if..else:
    val num4 = -50
    val num5 = 25
    if (num4 < num5) {
        println("num4 is less than num5")
    } else if (num4 > num5) {
        println("num4 is greater than num5")
    } else {
        println("num4 = num5")
    }
    // Can be written as
    when {
        num4 < num5 -> println("num4 is less than num5")
        num4 > num5 -> println("num4 is greater than num5")
        else -> println("num4 = num5")
    }
}