본문 바로가기
Boost Course

[코틀린 프로그래밍 기본 1] 6장 코틀린과 표준함수

by kldaji 2021. 7. 20.

6-1 준비운동! 람다식과 고차함수 요약

1) 고차함수

- 함수의 매개변수로 함수를 받거나 함수 자체를 반환할 수 있는 함수입니다.

fun main() {
    val result = high("KLDAJI") { it + 3 } // 3
    val result2 = high("KLDAJI2", ::inc) // 일반 함수 -> 람다식, 1
    println("result : $result, result2: $result2")
}

fun inc(x: Int): Int {
    return x + 1
}

fun high(name: String, body: (Int) -> Int): Int {
    println("name : $name")
    val x = 0
    return body(x)
}

 

6-2 널 포획해야겠어! 클로저(Closure)

1) 클로저

-  내부 함수에서 외부 변수를 사용

fun main() {
    filteredNames(4) // 길이가 4인 이름만 출력
}

fun filteredNames(length: Int) {
    val names = arrayListOf("Kim", "Hong", "Go", "Hwang", "Jeon")
    val filterResult = names.filter {
        it.length == length // 외부 변수 length에 접근
    }
    println(filterResult)
}
fun main() {
    val calc = Calc()
    var result = 0 // 외부의 변수
    calc.addNum(2, 3) { x, y -> result = x + y } // 클로저
    println(result) // 값을 유지하여 5가 출력
}

class Calc {
    fun addNum(a: Int, b: Int, add: (Int, Int) -> Unit) {
        add(a, b)
    }
}

 

6-3 너 한일은 결과와 함께 반환해. 알았지? - let()

1) null 가능성 있는 객체에서 let() 활용하기

fun main() {
    val score: Int? = 32
    checkScoreLet(score)
}

fun checkScoreLet(score: Int?){
    score?.let { println("Score : $it") } // score이 널이 아닌 경우에만 실행
    val str = score.let { it.toString() } // it은 score을 복사한 것
    println(str)
}

2) 체이닝을 사용할 때 let() 활용하기

fun main() {
    var a = 1
    var b = 2
    a = a.let { it + 2 }.let {
        println("a = $a") // a = 1
        val i = it + b // 3 + 2
        i // 5
    }
    println(a) // 5
}

3) 반환값은 바깥쪽의 람다식에서만 적용

fun main() {
    var x = "Kotlin!"
    x = x.let { outer ->
        outer.let { inner ->
            println("Inner is $inner and outer is $outer")
            "Inner String" // 반환되지 않는다.
        }
        "Outer String" // 반환된다.
    }
    println(x) // Outer String
}

※ let은 보통 변수가 한번만 사용되고 버려질 때 유용하게 쓰인다.

※ nullable한 객체에 대해서 유용하게 쓰인다.

※ null 검사로 인한 else문을 하나의 식으로 축약할 수 있다.

 

6-4 너 할일해. 난 그냥 반환할께. 올쏘! - also()

1) also() 활용

fun main() {
    var m = 1
    m = m.also { it + 3 }
    println(m) // 1
}

 

※ let vs also

fun main() {
    data class Person(var name: String, var skills: String)
    var person = Person("Kildong", "Kotlin")
    val a = person.let {
        it.skills = "Android"
        "Success" // 반환
    }
    println(person)
    println("a = $a") // Success

    val b = person.also{
        it.skills = "Java"
        "Success" // 반환 x
    }
    println(person)
    println("b = $b") // person

}

let은 반환값이 존재한다.

also는 반드시 자기 자신 값을 반환한다.

 

※ let, also를 활용한 예제

 

6-5 널 확장 시켜놓고 난 반환한다. - apply()

1) apply() 활용

fun main() {
    data class Person(var name: String, var skills: String)
    var person = Person("Kildong", "Kotlin")

    person.apply { this.skills = "Swift"}
    println(person) // Kildong, Swift

    val retObj = person.apply {
        name = "Sean" // 객체의 값을 변경
        skills = "Java"
    }
    println(person) // Sean, Java
    println(retObj) // Sean, Java

}

2) apply 사용 예제

 

6-6 그냥 실행하고 결과를 반환 - run()

1) run vs apply

fun main() {
    data class Person(var name: String, var skills: String)
    var person = Person("Kildon", "Kotlin")
    var returnObj1 = person.apply {
        name = "Sean"
        skills = "Java"
        "success" // 반환되지 않는다.
    }
    println(person) // Sean, Java
    println(returnObj1) // Sean Java

    var returnObj2 = person.run {
        name = "Dooly"
        skills = "#C"
        "success" // 반환된다.
    }
    println(person) // Dooly, #C
    println(returnObj2) // success
}

 

6-7 난 단독으로 실행되 반환하는 녀석이지 - with()

fun main() {
    data class Person(var name: String, var skills: String)
    var person = Person("Kildon", "Kotlin")
    var returnObj1 = with(person) {
        name = "Sean"
        skills = "Java"
        "success" // 반환된다.
    }
    println(person) // Sean, Java
    println(returnObj1) // Sean Java

}