kotlin

Kotlin 함수형 프로그래밍

임베디드 친구 2024. 12. 19. 13:06
반응형

Kotlin 언어는 함수형 프로그래밍의 특징을 적극적으로 지원합니다. 함수형 프로그래밍은 함수를 일급 객체로 취급하여, 함수를 변수에 할당하거나 다른 함수의 인자로 전달할 수 있는 프로그래밍 패러다임입니다. 이번 포스팅에서는 Kotlin에서 함수형 프로그래밍의 기본 개념을 소개하고, 고차 함수와 람다를 사용해 프로그램을 더 유연하게 작성하는 방법을 살펴보겠습니다.

함수형 프로그래밍의 특징

함수형 프로그래밍의 주요 특징은 다음과 같습니다:

  1. 일급 함수(First-Class Function): 함수를 변수에 저장하거나 다른 함수의 인자로 전달할 수 있습니다.
  2. 순수 함수(Pure Function): 같은 입력에 대해 항상 같은 출력을 보장하며, 부작용이 없는 함수입니다.
  3. 고차 함수(Higher-Order Function): 함수를 인자로 받거나 함수를 반환하는 함수입니다.
  4. 람다(Lambda): 익명 함수로 불리며, 함수형 프로그래밍에서 자주 사용됩니다.

Kotlin은 이러한 함수형 프로그래밍의 개념을 자연스럽게 지원하며, 이러한 특징을 사용해 코드의 가독성과 유지보수성을 높일 수 있습니다.

고차 함수와 람다

고차 함수란?

고차 함수는 함수를 인자로 받거나 반환하는 함수입니다. 고차 함수는 코드 재사용성을 높이고, 함수를 추상화하여 더 깔끔한 코드를 작성하는 데 유용합니다.

Kotlin에서는 함수를 인자로 받는 고차 함수를 쉽게 작성할 수 있습니다. 예를 들어, 두 숫자를 연산하는 함수를 고차 함수로 정의할 수 있습니다.

fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
    return operation(x, y)
}

fun main() {
    val add = { a: Int, b: Int -> a + b }
    val multiply = { a: Int, b: Int -> a * b }

    println(calculate(5, 3, add)) // 출력: 8
    println(calculate(5, 3, multiply)) // 출력: 15
}

위 코드에서 calculate 함수는 operation이라는 함수를 인자로 받아 두 숫자를 연산합니다. addmultiply는 람다 표현식으로 정의된 함수이며, 각각 덧셈과 곱셈을 수행합니다. calculate 함수를 호출할 때 addmultiply를 인자로 전달하여 동작을 결정할 수 있습니다.

람다 표현식

람다는 익명 함수로, 간단하게 함수를 정의할 수 있는 방법입니다. 람다 표현식은 중괄호 {}로 감싸고, 인자와 화살표 ->를 사용해 인자와 반환값을 구분합니다.

val greet = { name: String -> "Hello, $name!" }

fun main() {
    println(greet("Kotlin")) // 출력: Hello, Kotlin!
}

위 코드에서 greet는 람다 표현식으로 정의된 함수이며, name이라는 인자를 받아 인사말을 반환합니다. 이처럼 람다는 간결한 형태로 함수를 정의할 수 있어, 일회성 함수나 간단한 로직을 구현할 때 유용합니다.

람다와 고차 함수의 예제

고차 함수와 람다를 사용하여 리스트의 각 요소를 변환하거나 필터링할 수 있습니다. Kotlin의 표준 라이브러리는 이러한 함수형 프로그래밍의 특징을 잘 활용할 수 있는 다양한 고차 함수를 제공합니다.

예를 들어, map 함수는 리스트의 각 요소에 함수를 적용하여 새로운 리스트를 생성합니다.

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    val doubled = numbers.map { it * 2 }
    println(doubled) // 출력: [2, 4, 6, 8, 10]
}

위 코드에서 map 함수는 리스트 numbers의 각 요소에 람다를 적용하여 모든 값을 두 배로 늘린 새로운 리스트를 반환합니다. it 키워드는 람다의 단일 인자를 나타내는 키워드로, 코드의 간결성을 높여줍니다.

filter 함수

filter 함수는 조건에 맞는 요소들만 걸러내는 고차 함수입니다.

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5, 6)
    val evenNumbers = numbers.filter { it % 2 == 0 }
    println(evenNumbers) // 출력: [2, 4, 6]
}

위 코드에서 filter 함수는 리스트 numbers에서 짝수만 걸러내어 새로운 리스트 evenNumbers를 생성합니다. 람다 표현식을 사용하여 조건을 간단하게 정의할 수 있습니다.

확장 함수

확장 함수는 기존 클래스에 새로운 함수를 추가하는 기능입니다. 확장 함수를 사용하면, 기존 클래스를 상속하지 않고도 마치 해당 클래스의 멤버인 것처럼 함수를 사용할 수 있습니다.

예를 들어, String 클래스에 새로운 확장 함수를 정의해 보겠습니다.

fun String.greet(): String {
    return "Hello, $this!"
}

fun main() {
    val name = "Kotlin"
    println(name.greet()) // 출력: Hello, Kotlin!
}

위 코드에서 greetString 클래스의 확장 함수로, 문자열 인스턴스에 greet() 함수를 호출할 수 있게 해줍니다. 이를 통해 기존 클래스의 기능을 확장하여 더 유연하게 코드를 작성할 수 있습니다.

확장 함수는 함수형 프로그래밍과 결합하여 강력한 도구가 될 수 있습니다. 예를 들어, 컬렉션의 각 요소에 대해 확장 함수를 적용하여 특정 작업을 수행할 수 있습니다.

fun List<Int>.sumAll(): Int {
    return this.reduce { acc, i -> acc + i }
}

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    println(numbers.sumAll()) // 출력: 15
}

위 코드에서 sumAllList<Int> 클래스에 대한 확장 함수로, 리스트의 모든 요소를 더한 값을 반환합니다. reduce 함수를 사용하여 리스트의 요소들을 순차적으로 누적하여 합계를 구합니다.

요약

Kotlin은 함수형 프로그래밍을 적극적으로 지원하여 개발자가 더 유연하고 간결한 코드를 작성할 수 있도록 돕습니다. 고차 함수와 람다 표현식은 코드를 재사용하고 추상화하는 데 매우 유용하며, 확장 함수는 기존 클래스에 새로운 기능을 추가하여 코드의 가독성과 유지보수성을 높일 수 있습니다.

이번 포스팅에서는 Kotlin의 함수형 프로그래밍 기초 개념을 살펴보았으며, 고차 함수와 람다, 확장 함수에 대해 예제와 함께 설명했습니다. 앞으로도 이러한 기능들을 적극적으로 활용하여 더욱 간결하고 효율적인 Kotlin 프로그램을 작성해 보세요!

반응형