본문 바로가기

프로그래밍/Kotlin

[Kotlin 요약 정리] 10. 함수형 프로그래밍과 람다

10. 함수형 프로그래밍과 람다

1) 함수형 프로그래밍

- 함수를 일급 객체로 사용하는 프로그래밍 패러다임

- 객체지향 프로그래밍에서 클래스를 일급 객체로 사용한다고 하면 함수형 프로그래밍에서는 함수가 일급 객체로 사용된다. 따라서 매개변수와 반환 값을 함수로 이용할 수 있어야한다.

- 순수 함수 사용 원칙

*순수함수: 함수 외부의 다른 값을 변경하지 않는 함수

- 데이터 불변성: 데이터는 변경되지 않으며 프로그램의 상태만 표현한다.

- 장점: 코드가 간결해져서 개발 생산성과 유지 보수성이 증대되며 동시성 작업을 더욱 쉽고 안전하게 구현할 수 있다.

 

2) 변수에 함수 대입

- 함수를 변수에 대입하려면 람다 함수를 이용하거나 함수 참조를 이용한다.

 

val say = { name: String, age: Int ->

   println("Hello $name")

   "$name's age: $age"

}



fun hello(){

   println("Hello?")

}



fun main() {

   val a = say("Nick", 10)

   println(a)



   println()



   val b = ::hello

   b()

}

// 결과

Hello Nick

Nick's age: 10



Hello?



3) 람다 표현식

- 익명 함수를 지칭하는 용어

- 코드의 간결함을 주 목적으로 이용

- 규칙

중괄호 { } 로 감싸서 표현해야 한다.

괄호 안에 화살표 -> 가 있으며 왼쪽은 매개변수, 오른쪽은 함수 내용이다.

매개변수 타입을 선언해야 하며 추론 가능시 생략할 수 있다.

함수의 반환값은 함수 내용의 마지막 표현식이다.

 

fun sum1(x: Int, y: Int): Int {

   return x+y

}



val sum2 = { x: Int, y: Int -> x + y }



fun main() {

   val a = sum1(1,2)

   val b = sum2(1, 2)

   println("$a, $b")

}

// 결과

3, 3

 

- 람다식을 선언과 동시에 실행할 수 있다.

 

fun main() {

   { x:Int -> println("lambda $x") }(10)

   run { println("lambda") }

}

// 결과

lambda 10

lambda

 

- 변수에 함수를 담을 수 있다.

 

fun main() {

   val num = { 10 + 20 } // 매개변수가 없을 경우 화살표 생략 가능

   val a = num()

   println(a)



   val check = { x: Int ->

       val result = x < 10

       println(if(result) "10 미만" else "10 미만이 아님")

       result // 마지막 표현식이 반환 값

   }



   val b = check(5)

   val c = check(15)

   println("b: $b / c: $c")

}

// 결과

30

10 미만

10 미만이 아님

b: true / c: false

 

- 매개변수가 1개라면 별도의 정의 없이 it 예약어를 통해 쉽게 사용 가능

 

val lambda1: (Int) -> Int = { it + 10 }

val lambda2: (Int) -> Int = { i -> i +10 }

// 위 두 함수는 같다.



fun main() {

   println(lambda1(1))

   println(lambda2(1))

}

// 결과

11

11

 

4) 함수 타입

- 함수의 매개변수 혹은 반환타입에 대한 명시를 함수 타입이라고 한다.

- typealias를 이용해서 타입을 정의 후 쉽게 사용할 수 있다.

 

typealias MyType = (Int, String) -> Boolean



fun fun1(): MyType = { i, j -> i.toString() == j }

val fun2: MyType = { i, j -> i.toString() == j }



fun main() {

   val fu = fun1()

   val a= fu(1, "1")

   val b = fun2(1, "2")

   println("a: $a / b: $b")

}

// 결과

a: true / b: false