본문 바로가기
STUDY/Kotlin

Kotlin / 고차함수

by HR_J 2024. 4. 24.

포스트 작성 계기

과제를 진행하다, 함수 안에서 함수를 부르는데 그 부르는 함수 내에서 또 함수를 부르는 기이한 형태도 처리되는 것을 확인했다. 충격과 함께 왜.,.. 이게 되는거지? 를 확인하려고 공부를 시작했다. 목표는 고차함수 개념 알기!!!

고차함수를 보려면 그 이전에 1급함수를 알아야했다.

1급함수,  1급 시민, 1급 객체.. 뭔 비슷한 말들이 너무 많다. 하지만 각각 영어 명칭이 다 따로 있기 때문에 다른점이 있다고 판단. 하나하나 뜯어보기로 한다.

 

1 / 1급 시민(first-class citizen), 1급 객체(first-class object), 그리고 1급 함수(first-class function)

1급 시민 -> { 변수에 담을 수 있음 + 함수의 인자로 전달 가능 + 함수의 반환값으로 전달 가능}

1급 객체 -> { 1급 시만의 조건을 충족하는 객체. 코틀린의 함수는 여기에 해당한다.}

1급 함수 -> {1급 객체의 조건 만족 + 런타임에 생성가능/익명으로 생성가능}

// 1급 시민을 변수에 담을 수 있음
val firstClassCitizen: (Int, Int) -> Int = { a, b -> a + b }

// 1급 시민을 함수의 인자로 전달 가능
fun operateOnNumbers(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// 1급 시민을 함수의 반환값으로 전달 가능
fun returnFunction(): (Int, Int) -> Int {
    return { a, b -> a * b }
}

// 1급 객체인 함수
fun main() {
    // 1급 함수의 사용 예시
    val result = operateOnNumbers(3, 4, firstClassCitizen)
    println("$result")

    val returnedFunction = returnFunction()
    println("${returnedFunction(5, 6)}")
}

 

2 /  고차함수(Higher-order function)

그렇다면 고차함수는?

- 파라미터로 다른 함수를 받는 함수

- 함수를 return 값으로 사용하는 함수

val listOne = listOf(1, 2, 3).map { it + 1 } // listOf(2, 3, 4)

// map 함수
public inline fun <T, R> Iterable<T>.map(
		transform: (T) -> R // 파라미터인데 함수
): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

// mapTo 함수
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(
		destination: C, // ArrayList
		transform: (T) -> R // 전달받은 함수
): C {
    for (item in this)
        destination.add(transform(item))
    return destination
}

 

2-1 / 함수 타입 (function type)

일급 합수 지원을 위한 타입.

함수 표현이 가능하고 lambda와 같은 구조체를 지원한다.

(파라미터)-> 리턴값으로 표현.

(Int) -> String
(Char, Boolean) -> Int
() -> Long // 파라미터가 없으면 빈 괄호
() -> Unit // Unit은 Java의 void return과 같다.
// 아무것도 리턴하지 말라는 것을 명시해두는 것임.

 

함수 타입이 중첩될 수도 있다.

(Int) -> ((Int) -> Int) // 다른 함수를 return 하는 함수
(Int) -> (Int) -> (Int) // ((Int) -> (Int)) -> Int 와 동일

 

2-2 / typealias

특정 타입을 다른 이름으로 사용할 수 있게 해주는 키워드

함수 타입에도 typealias 를 적용할 수 있다.

typealias TestFunction = (Int) -> Int

val funcOne: TestFunction = {x -> x + 1} // 람다 객체
println(funcOne(1)) // invoke 함수처럼 사용될 수 있음