-
[Kotlin] 코틀린 함수와 함수형 프로그래밍 1Kotlin/Function 2021. 9. 6. 17:34
- 코틀린은 객체지향 프로그래밍 + 함수형 프로그래밍 언어이다.
(참고-함수형프로그래밍이란)
https://mangkyu.tistory.com/111
- 프로그래밍 언어의 함수가 일급 시민(일급 객체)으로 다뤄진다면 일급 함수를 가지고 있는 언어이다.
https://choheeis.github.io/newblog//articles/2020-12/kotlinHigherOrderFunctionAndLambda
일급 객체의 특징
1. 일급 객체는 함수의 매개변수가 될 수 있다.
2. 일급 객체는 함수의 return값이 될 수 있다.
3. 일급 객체를 변수에(=) 값을 할당할 수 있다.
4. 일급 객체는 고유한 구별이 가능하다.(equaliy비교)
- 코틀린의 함수는 일급 함수이다-> 일급 객체의 특징을 만족한다.
1. 코틀린의 함수는 다른 함수의 매개변수가 될 수 있다.
2. 코틀린의 함수는 다른 함수의 return값이 될 수 있다.
3. 코틀린의 함수는 변수에 값을 대입할 수 있다.
4. 코틀린의 함수는 고유한 구별이 가능하다.
함수형 프로그래밍 스타일중 하나인 일급함수 때문에 코틀린은 함수형 프로그래밍을 지원한다고 볼 수 있다.
- 고차함수란
매개변수에 다른 함수가 포함된 경우
함수를 return하는 경우
둘중 하나의 조건을 만족하면 고차함수이다.
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> { return filterTo(ArrayList<T>(), predicate) }
매개변수가 제네릭타입 T 리턴값이 Boolean인 함수를 인자로 받고 있는 고차함수
- 람다 표현식
이름이 없는 함수 인스턴스를 만드는 방법중 한 방법이다.
이후의 포스팅에서 다룰 것이지만 람다 표현식도 어떠한 객체에 해당된다.
람다 표현식을 사용하여 함수를 선언하지 않고 바로 고차함수의 인자에 넣어 일회성으로 사용가능하다.
코틀린의 함수는 일급 함수이고 람다표현식도 함수이니 람다표현식도 일급 객체의 1~4조건이 모두 가능하게 된다.
https://kotlinlang.org/docs/lambdas.html#lambda-expressions-and-anonymous-functions
Lambda expressions and anonymous functions are function literals. Function literals are functions that are not declared but are passed immediately as an expression.
람다 표현식과 익명함수는 function literal이다. function literal이란 함수를 선언하지 않고 표현식으로서 바로 전달되는 함수이다. (익명함수는 람다표현식과 다른내용임. 다음 포스팅에서 적어보도록..)
기존 코드 vs 람다 표현식
fun 고차함수( 함수1 ){ //내용 } fun 함수1(){//내용} fun main(){ val 변수= 함수1인스턴스 고차함수(변수) }
람다 표현식을 사용하지 않은 경우 고차함수의 인자로 넣어줄 함수1을 선언후 함수1을 변수에 담아 변수를 통해 고차함수의 인자로 전달해야 할 것이다.
(함수를 변수에 담는 것은 뒤에서 살펴보겠다, var t=함수()요렇게 하면 함수의 리턴에 해당하는 값이 대입되므로
이렇게 하면 안된다.)
람다 표현식
fun 고차함수( 함수1 ){ //내용 } fun main(){ 고차함수( 람다식을 통해 함수1 인스턴스 구현 ) }
함수1을 정의하지 않고 고차함수의 인자에 람다표현식으로 함수1을 구현하여 즉시 넘겨줄 수 있다.
kotlin reference에서 정의해놓은 람다 표현식 full syntax
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
람다식 자체는 = 뒷부분의 { } 중괄호에만 해당하는데
함수를 변수에 대입하거나 고차함수의 선언시 파라메터의 함수를 어떻게 정의하는지에 대해서 이해하기 쉽도록 코틀린 reference에서는 위의 코드형태로 올려놓은 것 같다.
단계별로 알아보자.
val sum: (Int, Int) -> Int
sum변수는 매개변수가 두개이면서 Int형이면서 return타입이 Int인 함수를 참조하는 변수로
(Int,Int)->Int인 함수 인스턴스는 모두 받을 수 있다.
val sum: (Int, Int) -> Int sum = { x: Int, y: Int -> x + y }
맨위의 full syntax코드는 이 코드와 같다. 변수 선언과 초기화가 분리되어있다.
{ 1번 -> 2번 }
람다식의 2번은 여러줄이 될 수 있으며 마지막 표현식이 return값으로 취급된다.
2번에서 마지막 표현식에 return 문을 사용하면
람다식에 해당하는 함수를 리턴하는 것이 아니라 코드가 main함수 내부에 있다면 main함수를 return하게 된다.
상세한 것은 다음 포스팅에서 볼 수 있다.
(Int,Int)->Int만 만족하면 되므로 다음과 같이 구현 내용이 다른 함수를 람다표현식으로 넣어줄 수 있다.
fun main() { var test: (Int, Int) -> Int = { x: Int, y: Int -> x + y } println(test(10, 10)) //20 test = { x: Int, y: Int -> x - y } println(test(10, 10)) //0 }
변수 test를 어떻게 함수처럼 사용할 수 있는지는 다음 포스팅에서 다룬다.
함수형 프로그래밍이 가지는 함수 특징만 간단하게 느껴보자.
함수를 고차함수의 인자에 넣는 것을 봐보자.
우선 함수를 받는 고차함수를 선언하면
fun highOrder(para: (Int, Int) -> Int) { //고차함수( 파라메터의 인자가 함수 ) println(para(1,2)) } fun main() { val add: (Int, Int) -> Int = { x: Int, y: Int -> x + y } val sub: (Int, Int) -> Int = { x: Int, y: Int -> x - y } println(add(1,2)) //3 println(sub(1,2)) //-1 highOrder(add) //3 highOrder(sub) //-1 }
결과는 이전과 같다.
고차함수 내부에서 인자로 받은 함수를 이용할 수 있다.
고차함수의 인자로 함수자체를 넣는 것이지 함수의인자를 넣는 것이 아님에 주의하자.
고차함수의 매개변수로 어떤 함수를 받느냐에 따라 다른 결과가 나오기 때문에 흥미롭다고 할 수 있다.(덧셈, 뺄셈)
add, sub는 변수인데 어떻게 add(인자들) , sub(인자들)와 같은 함수처럼 사용하는지 궁금할 것이다.
다음 포스팅에서 다루도록 한다.
'Kotlin > Function' 카테고리의 다른 글
[Kotlin] 가변인자 vararg (0) 2021.12.25 [Kotlin] inline function 정리 1 (0) 2021.12.15 [Kotlin] 코틀린 함수와 함수형 프로그래밍 3 (0) 2021.09.08 [Kotlin] 코틀린 함수와 함수형 프로그래밍 2 (0) 2021.09.07 [Kotlin] Extension (Function,Property) (0) 2021.08.16