본문 바로가기
IT/Java & Kotlin

[Kotlin] 1급 시민 함수(first-class citizen)란?

by 큰공 2024. 4. 3.
728x90
반응형

코틀린에서의 1급 시민 함수

코틀린은 현대적이고 다양한 프로그래밍 스타일을 지원하는 다중 패러다임 프로그래밍 언어입니다. 이 언어는 객체지향 및 함수형 프로그래밍 스타일을 모두 효율적으로 지원하며, 이러한 두 가지 패러다임을 조화롭게 결합할 수 있도록 도와줍니다. 이러한 기능 중 하나는 코틀린의 "1급 시민 함수(First-class functions)"입니다.

 

1급 시민 함수란?

1급 시민 함수란 프로그래밍 언어에서 함수를 일반적인 값과 동등하게 취급하는 개념을 나타냅니다. 이는 함수를 변수에 할당하거나 다른 함수의 인자로 전달하거나 함수를 다른 함수의 반환 값으로 사용할 수 있음을 의미합니다. 이러한 특성은 함수를 자유롭게 조작하고 다룰 수 있게 해주며, 함수형 프로그래밍 스타일을 지원하는 데 중요한 역할을 합니다.

 

First-class-citizen

우선 "일급시민" 에 대해서 알아겠습니다. 영어를 직역하면 First-class-citizen으로 단어 뜻은 공정한 대우를 받는 집단의 구성원을 말합니다. 어떠한 혜택이 있는게 아닌 아무런 차별없이 없다는  뜻을 의미한다. 

즉, 변수와 함수를 차별없이 동등하게 대우하겠다는 의미를 내포하고 있씁니다.

 

3가지 특징

  • 함수를 변수에 할당할 수 있다.
  • 함수를 인자로 넘길 수 있다.
  • 함수를 함수의 리턴으로 지정할 수 있다.

위와 같은 특징으로 일급 시민 함수는 변수처럼 자유자제로 사용할 수 있게 됩니다. 

자세하게 예를 들어서 살펴보도록 하겠습니다.

 

함수를 변수에 할당

fun main(args: Array<String>) {
    val test1 = ::print // 함수를 멤버 변수를 이용하여 저장
    val test2 = { print() } // 람다 함수를 변수에 저장
    val test3 = print() // 함수를 호출한뒤 리턴값을 저장
}

fun print() {
    println("CoinPipe")
}

 

  1. val test1 = ::print  이 코드는 print 함수를 변수 test1에 저장합니다. :: 연산자는 함수 참조를 만듭니다. 즉, test1은 print 함수의 참조를 가리키는 변수입니다.
  2. val test2 = { print() }  이 코드는 람다 함수를 변수 test2에 저장합니다. {} 내부에 있는 코드는 람다 함수로, print() 함수를 호출합니다.
  3. val test3 = print()  이 코드는 print() 함수를 호출하고, 그 결과를 변수 test3에 저장합니다.

test2와 같이 람다 함수를 변수에 저장할 수 있는 특징을 가지는 함수를 일급 시민 함수라고 합니다.

 

함수를 인자로 넘기기

함수를 인자로 넘긴다는 의미는, 함수를 다른 함수의 매개 변수로 전달할 수 있다는것을 의미합니다. 

fun main(args: Array<String>) {
    testFunc(test) // 함수를 인자로 넘길 수 있음
}

fun testFunc(f: () -> Unit) {
    f.invoke() // 함수를 실행할 수 있음
}

val test: () -> Unit = {
    println("CoinPipe")
}

 

testFunc(test): testFunc 함수를 호출하며, 이때 test 라는 함수 타입의 변수가 전달됩니다. test 변수는 () -> Unit 타입의 함수를 가리키는 변수입니다.

fun testFunc(f: () -> Unit) { ... }: testFunc라는 이름의 함수를 정의합니다. 이 함수는 () -> Unit 타입의 매개변수 f를 받습니다. 이 f는 아무런 인자도 받지 않고 반환값이 없는 함수를 가리키는 함수형 변수입니다.

f.invoke(): f가 가리키는 함수를 호출합니다. invoke는 Kotlin에서 함수형 객체를 호출하는 메서드입니다. 이 코드는 f가 가리키는 함수를 실행하는 것입니다.

val test: () -> Unit = { ... }: test라는 이름의 변수를 선언하고, 이 변수에 람다 함수를 할당합니다. 이 람다 함수는 단순히 "CoinPipe"라는 문자열을 출력하는 역할을 합니다.

따라서 이 코드는 main 함수가 실행되면 testFunc 함수가 호출되고, 그 안에서 test 변수가 가리키는 람다 함수가 실행되어 "CoinPipe"라는 문자열이 출력됩니다.

 

즉, testFunc(test) 처럼 함수에 함수를 인자로 전달 할 수 있는 특징을 가집니다.

 

함수를 리턴

fun main(args: Array<String>) {
    testFunc() // 함수 호출
}

fun testFunc(): () -> Unit {
    // 람다식을 반환
    return {
        println("CoinPipe")
    }
}

 

testFunc(): testFunc 함수를 호출합니다.

fun testFunc(): () -> Unit { ... }: testFunc라는 이름의 함수를 정의합니다. 이 함수는 매개변수를 받지 않습니다. 반환 타입은 () -> Unit입니다. 즉, 아무런 인자를 받지 않고, 반환값이 없는 함수를 의미합니다.

return { println("CoinPipe") }: testFunc 함수 내부에서는 람다 표현식을 반환합니다. 이 람다 표현식은 단순히 "CoinPipe"라는 문자열을 출력하는 함수입니다.

따라서 이 코드는 main 함수가 실행되면 testFunc 함수가 호출되고, 해당 함수는 람다 표현식을 반환합니다. 반환된 람다 표현식은 실행되어 "CoinPipe"라는 문자열을 출력합니다.

 

즉, return 타입에 람다 형식의 함수를 반환 할 수 있는 특징을 가집니다.

 

요약

이상적인 1급 시민 함수의 특성을 지닌 코틀린 언어에 대해 설명드렸습니다. 간단히 요약하자면:

  1. 1급 시민 함수(First-class functions): 코틀린은 함수를 일반적인 값과 동등하게 취급합니다. 이는 함수를 변수에 할당하거나, 다른 함수의 인자로 전달하거나, 함수를 다른 함수의 반환 값으로 사용할 수 있음을 의미합니다.
  2. 함수를 변수에 할당: 함수를 변수에 할당하여 사용할 수 있습니다. 함수 참조를 이용하여 변수에 할당할 수 있으며, 람다 함수를 변수에 저장할 수도 있습니다.
  3. 함수를 인자로 넘기기: 함수를 다른 함수의 매개변수로 전달할 수 있습니다. 이를 통해 함수의 동작을 다른 함수에게 위임할 수 있습니다.
  4. 함수를 반환하기: 함수를 다른 함수의 반환 값으로 사용할 수 있습니다. 함수를 반환하는 함수를 작성하여 동적으로 함수를 생성하고 반환할 수 있습니다.

이러한 특성들은 코틀린이 다양한 프로그래밍 스타일을 지원하고, 함수형 프로그래밍 스타일을 쉽게 적용할 수 있도록 도와줍니다. 함수형 프로그래밍의 강력한 기능을 활용하여 코드를 더 간결하고 유연하게 작성할 수 있습니다.

728x90
반응형

댓글