[Kotlin] 4-1. 고차함수와 람다식

leeeha·2022년 6월 21일
0

코틀린

목록 보기
10/29
post-thumbnail

출처: https://www.boostcourse.org/mo132/lecture/59975

람다식의 구성

변수에 지정된 람다식

package chap04.section1

fun main() {
    val result: Int

    // 일반 변수에 람다식 할당
    //val multi = { a: Int, b: Int -> a * b }
    val multi: (a: Int, b: Int) -> Int = { a, b -> a * b }

    // 람다식이 할당된 변수는 함수처럼 사용 가능
    result = multi(3, 5)
    println(result)
}

표현식이 2줄 이상일 때

자료형의 생략

package chap04.section1

fun main() {
    val multi: (Int, Int) -> Int = { x: Int, y: Int -> x * y }
    val multi1 = { x: Int, y: Int -> x * y } // 선언 자료형 생략 
    val multi2: (Int, Int) -> Int = { x, y -> x * y } // 람다식 매개변수 자료형 생략
    val multi3 = { x, y -> x * y } // error 
}

리턴값이 없거나 매개변수가 하나일 때

람다식 안에 람다식이 있는 경우


람다식과 고차함수 호출하기

고차함수의 형태

값에 의한 호출

코틀린에서 값에 의한 호출은 함수가 인자로 전달될 경우, 람다식 함수는 값으로 처리되어 그 즉시 함수가 수행된 후 결과를 반환한다.

package chap04.section2

fun main() {
    val result = callByValue(lambda()) // 람다 함수 호출
    println(result)
}

fun callByValue(b: Boolean): Boolean { // 일반 변수 타입으로 선언된 매개변수 
    println("callByValue function")
    return b
}

val lambda: () -> Boolean = { // 람다 표현식이 2줄 이상일 때는
    println("lambda function")
    true// 마지막 표현식 반환 
}

lambda function
callByValue function
true

이름에 의한 호출

그렇다면, 람다 함수가 인자로 전달되는 즉시 실행되는 것이 아니라, 실제로 그 함수가 사용될 때 실행되게 하려면 어떻게 해야 할까? 람다 함수의 이름을 인자로 넣어서 사용하면, 람다식 자체가 매개변수에 복사되고 해당 함수가 사용되기 전까지는 함수가 실행되지 않는다. 람다 함수가 호출되어 사용될 때 비로소 그 함수의 내용이 실행된다! 이것을 잘 이용하면, 즉시 실행할 필요가 없는 코드를 작성하는 경우, 이름에 의한 호출 방법으로 필요할 때만 람다 함수가 작동하게 만들 수 있다!

package chap04.section2

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
}

callByName function
otherLambda function
true

다른 함수 참조에 의한 호출

예제 1

package chap04.section2

fun sum(x: Int, y: Int) = x + y

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

fun main() {
    //funcParam(3, 2, sum) // error (sum은 람다식이 아님)
   println(funcParam(3, 2, ::sum)) // 함수 참조에 의한 호출
}

5

예제 2

package chap04.section2

fun main() {
    // 1. 인자와 리턴값이 있는 함수
    val res1 = funcParam(3, 2, ::sum)
    println(res1)

    // 2. 인자가 없는 함수
    hello(::text) // 다른 함수 참조에 의한 호출 (hello 자체는 리턴값 없음) 

    // 3. 일반 변수에 함수를 값처럼 할당하는 경우
    val likeLambda = ::sum
    println(likeLambda(6, 6))
}

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

fun text(a: String, b: String) = "Hi! $a $b"
fun hello(body: (String, String) -> String): Unit {
    println(body("Hello", "World"))
}

5
Hi! Hello World
12


람다 함수의 매개변수

매개변수 개수에 따라 람다식 구성하기

예제 1

package chap04.section2

// 매개변수가 없는 람다 함수 out
fun noParam(out: () -> String) = println(out())

// 매개변수가 1개인 람다 함수 out
fun oneParam(out: (String) -> String) {
    println(out("OneParam"))
}

// 매개변수가 2개인 람다 함수 out
fun moreParam(out: (String, String) -> String) {
    println(out("OneParam", "TwoParam"))
}

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

    oneParam({ a -> "Hello World! $a" })
    oneParam{ a -> "Hello World! $a" } // 소괄호 생략
    oneParam { "Hello World! $it" } // 매개변수가 1개일 때는 화살표를 생략하고 it로 대체 가능! 

    moreParam { a, b -> "Hello World! $a $b" } // 매개변수명 생략 불가
}

Hello World!
Hello World!
Hello World! OneParam
Hello World! OneParam
Hello World! OneParam
Hello World! OneParam TwoParam

예제 2 (매개변수 생략)

package chap04.section2

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

fun main() {
    // 첫번째 문자열은 사용하지 않고 생략하는 경우
    moreParam { _, b -> "Hello World! $b" }
}

Hello World! TwoParam

일반 매개변수와 람다식 매개변수를 같이 사용

package chap04.section2

fun withArgs(a: String, b: String, out: (String, String) -> String){
    println(out(a, b))
}

fun main() {
    // 일반 매개변수와 람다식을 같이 사용하는 경우
    withArgs("Arg1", "Arg2", { a, b -> "Hello World! $a $b "})

    // 마지막 인자가 람다식이면 소괄호 바깥으로 뺄 수 있음.
    withArgs("Arg1", "Arg2") { a, b -> "Hello World! $a $b " }
}

Hello World! Arg1 Arg2
Hello World! Arg1 Arg2

두 개의 람다식을 가진 함수

package chap04.section2

fun twoLambda(first: (String, String) -> String, second: (String) -> String){
    println(first("OneParam", "TwoParam"))
    println(second("OneParam"))
}

fun main() {
    // 두 개의 람다식을 가진 함수  
    twoLambda({a, b -> "First $a $b"}, {"Second $it"})

    // 마지막 인자로 사용된 람다식은 소괄호 바깥으로 분리 
    twoLambda({a, b -> "First $a $b"}) {"Second $it"}
}

First OneParam TwoParam
Second OneParam
First OneParam TwoParam
Second OneParam

profile
습관이 될 때까지 📝

0개의 댓글