본문 바로가기
Boost Course

[코틀린 프로그래밍 기본 1] 4장. 요술상자, 함수 가지고 놀기

by kldaji 2021. 7. 18.

4-1 이름없는 함수의 또 다른 형태, 람다(Lambda)!

1) 람다식 표현 예제

fun main() {
    // 1) 전체 표현
    val multi1: (Int, Int) -> Int = {x: Int, y: Int -> x * y}

    // 2) 선언 자료형 생략
    val multi2 = {x: Int, y: Int -> x * y}

    // 3) 람다식 매개변수 자료형 생략
    val multi3: (Int, Int) -> Int = {x, y -> x * y}

    // 4) 2줄 이상의 식 - 마지막 값이 반환값이다.
    val multi4: (a: Int, b: Int) -> Int = { a, b ->
        println("a : $a, b : $b")
        a*b
    }
}

 

4-2 고차함수와 람다식의 이해 (1)

1) 값에 의한 호출

- 람다식 반환값 사용

fun main() {
    val result = callByValue(lambda())
    println(result)
}

fun callByValue(b: Boolean): Boolean {
    println("callByValue function")
    return b
}

val lambda: () -> Boolean = {
    println("lambda function")
    true
}

 

2) 이름에 의한 호출

- 람다식 사용

fun main() {
    val result = callByName(otherLambda) 
    println(result)
}

fun callByName(b: () -> Boolean): Boolean { 
    println("callByName function")
    return b()
}

val otherLambda: () -> Boolean = {
    println("otherLambda function")
    true
}

 

3) 다른 함수의 참조에 의한 호출

- 일반 함수를 람다식으로 사용

fun main() {
    val res1 = funcParam(3, 2, ::sum)
    println(res1)

    hello(::text)

    val likeLambda = ::sum
    println(likeLambda(6,6))
}

fun sum(a: Int, b: Int) = a + b

fun text(a: String, b: String) = "Hi! $a $b"

fun funcParam(a: Int, b: Int, c: (Int, Int) -> Int): Int {
    return c(a, b)
}

fun hello(body: (String, String) -> String): Unit {
    println(body("Hello", "World"))
}

 

4-2 고차함수와 람다식의 이해 (2)

1) 매개변수가 없는 람다식

fun main() {
    noParam({ "Hello World!" })
    noParam { "Hello World!" } // 소괄호 생략 가능
}

fun noParam(out: () -> String) = println(out())

 

2) 매개변수가 한 개인 람다식

fun main() {
    oneParam({ a -> "Hello World! $a" })
    oneParam { a -> "Hello World! $a" } // 소괄호 생략 가능
    oneParam { "Hello World! $it" }  // it으로 대체 가능
}

fun oneParam(out: (String) -> String) {
    println(out("OneParam"))
}

 

3) 매개변수가 두 개 이상인 람다식

fun main() {
    moreParam { a, b -> "Hello World! $a $b"} // 매개변수명 생략 불가
    moreParam { _, b -> "Hello World! $b"} // 원하는 매개변수만 사용 가능
}

fun moreParam(out: (String, String) -> String) {
    println(out("OneParam", "TwoParam"))
}

 

 

4-3 다양한 함수의 출격1! (익명함수, 인라인 함수)

fun main() {
    // 익명 함수 - 람다식과 매우 흡사
    val add1 = fun(x: Int, y: Int) = x + y
    println(add1(1, 2))

    val add2 = {x: Int, y: Int -> x + y}
    println(add2(1, 2))

    shortFunc(4) {
        println("a : $it")
    }
}

// 인라인 함수 - 함수를 호출하는 것이 아닌, 호출된 곳에 복사되어 실행된다.
// 함수 호출이 없기 때문에 코드의 성능을 높일 수 있다.
inline fun shortFunc(a: Int, out: (Int) -> Unit) {
    println("Before calling out()")
    out(a)
    println("After calling out()")
}

 

 

4-3 다양한 함수의 출격2! (인라인 함수, 확장 함수)

1) 인라인 함수 일부 제한

fun main() {
    shortFunc(4) {
        println("a : $it")
    }
}

// 인라인 함수 제한 (일부)
inline fun shortFunc(a: Int, noinline out: (Int) -> Unit) {
    println("Before calling out()")
    out(a)
    println("After calling out()")
}

 

2) 비지역 반환 제한

- inline 함수식에서 out 람다식에 return을 넣으면 shortFunc 함수 자체가 같이 종료되기 때문에 이를 방지하기 위해 crossinline이라는 keyword를 넣어 람다식 return을 금지한다.

fun main() {
    shortFunc(4) {
        println("a : $it")
        // return
    }
}

inline fun shortFunc(a: Int, crossinline out: (Int) -> Unit) {
    println("Before calling out()")
    out(a)
    println("After calling out()")
}

 

3) 확장 함수

fun main() {
    val source = "Hello World!"
    val target = "Kotlin"
    
    // 확장함수 사용
    println(source.getLongString(target))
}

// 문자열의 길이가 더 긴 문자열을 반환하는 함수를 확장
fun String.getLongString(target: String): String =
    if (this.length > target.length) this  else target

 

4-3 다양한 함수의 출격3! (중위함수, 꼬리재귀 함수)

1) 중위함수

- .과 ()를 생략하는 함수

fun main() {
    val multi = 3 multiply 10 // 3.multiply(10)
    println(multi)
}

infix fun Int.multiply(x: Int): Int {
    return this * x
}

 

2) 꼬리 재귀 함수

- 스택 오버플로 현상 방지

fun main() {
    val number = 5
    println("Factorial: $number -> ${factorial(number)}")
}

tailrec fun factorial(n: Int, run: Int = 1): Long {
    return if (n == 1) run.toLong() else factorial(n-1, run*n)
}