엔지니어 규의 IT 프로그래밍 다이어리

[Kotlin]13. 고차 함수와 람다 함수 본문

프로그래밍 언어/코틀린

[Kotlin]13. 고차 함수와 람다 함수

엔지니어 규 2022. 5. 18. 21:10
728x90

고차함수

 

고차함수란 함수를 마치 클래스에서 만들어낸 '인스턴스처럼' 취급하는 방법이다.

 

함수를 '패러미터'로 넘겨 줄 수 도 있고 결과값으로 반환 받을수도 있는 방법이다. 코틀린에서는 모든 함수를 고차함수로 사용 가능하다. 

 

아래의 소스코드를 확인해보자

fun main(){
 
    b(::a)
 
    val c: (String) -> Unit = { str -> println("$str 람다함수") }
    b(c)
 
}
 
fun a (str : String){
    println("$str 함수 a")
}
 
fun b ( function: (String) -> Unit){
    function("b가 호출한")
}
 
b가 호출한 함수 a
b가 호출한 람다함수
cs

 

함수 a를 고차함수 형식의 패러미터로 받을수 있도록 하기위해서는,

함수를 받을 파라미터 이름을 function 으로하고 자료형은 a의 함수의 형식을 넘겨 받을수 있도록 해야한다.

 

fun b ( function: (String) -> Unit)

 

위의 소스코드 처럼 "fun b ( function: (함수가 받을 자료형) -> 반환받을 자료형" 처럼 표현한다.

이렇게하면 기술한 형식과 같은 형식의 함수는 모두 패러미터로 받을 수 있다.

 

우리가 받아올 함수 a 는 문자열을 받고 반환형은 없는 함수이므로 괄호안에 String을 써주고,

반환형에는 값이 없다는 형식인 Unit을 써준다.

 

 

또한 함수 b를 호출하되 함수 a 를 파라미터로 넘기기 위해,

고차함수로 넘기려면 함수이름앞에 콜론을 두개 붙여주면된다. (ex b(::a) )

 

 

위 과정을 정리해보면 main 함수가 a 함수를 파라미터로 넘겼고,

b함수는 받아온 a 함수에 "b가 호출한" 이라는 값을 넘겨서 호출한다.

최종적으로 a라는 함수가 실행되면서, "b가 호출한 함수 a" 라는 문자열이 출력되는것을 확인할 수 있다.

 

 

 

람다함수

그런데 파라미터로 넘길 함수를 굳이 이름까지 붙여서 따로 만들어야 할 필요가 있을까?

 

이러한 고민을 해결하기 위해 함수를 람다식으로 표현하는 람다함수 라는 것을 사용한다. 

 

람다함수는 일반함수와 달리 그 자체가 고차함수 이기 때문에 별도의 연산자 없이도 변수에 담을 수 있다. 

아래의 소스코드를 보자.

fun main(){
    
    val c: (String) -> Unit = { str -> println("$str 람다함수") }
    val d = { str : String -> println("$str 람다함수")}
    b(c)
    b(d)

}

 

아래의 소스코드는 일반적인 변수에 자료형을 쓰듯이 (ex : val a: Int) 그자리에 함수의 형식 "(String)->Unit" 을 쓴것이다.

 

다음은 파라미터로 받아온 문자열을 매칭해줄 변수이름을 써주는데,

 

여기서 str은 String으로 받아온 값을 람다함수 내에서 사용할 변수 이름이다.

 

그 이후에는 함수의 형식에서와 같이 화살표 형태를 써준후 실행할 구문을 적어준다.

val c: (String) -> Unit = { str -> println("$str 람다함수") }

 

 

 

람다함수 역시 변수에 할당할 때는 이전에 배웠던 타입추론 기능을 이용하여 좀더 축약해서 기술할 수 있는데

 

아래처럼 함수의 형식을 적지 않고 바로 중괄호안에 직접 패러미터의 자료형을 써서 타입추론이 가능하다.

val d = { str : String -> println("$str 람다함수")}

 

고차함수와 람다함수를 사용하면, 이렇게 함수를 일종의 변수로 사용할 수 있다는 편의성이 있지만
이후 배우게될 컬렉션의 조작이나 스코프 함수의 사용에도 도움이 된다.

 

람다함수의 특별한 케이스

 

 

첫번째

 

람다함수도 여러구문의 사용이 가능하다.

 

val calculate : (Int,Int) -> Int = {a,b ->
    println(a)
    println(b)
    a + b
}

 

위처럼 람다함수로 여러줄을 쓸수 있고 여러줄을 쓸경우는 마지막 줄이 결과값으로 반환된다.

위 소스코드에서는 a+b의 값을 Int로 반환한다.

 

 

두번째

 

파라미터가 없는 람다함수는 실행할 구문만 나열하면 된다.

 

val a : () ->Unit ={println("패러미터가 없어요")}

 

세번째

 

파라미터가 하나뿐이라면 it을 사용한다.

 

val a : (String) -> Unit = {println("$it 람다함수")}

파라미터가 여러개라면 람다함수 내에서 파라미터를 일일이 써줘야하지만 한개뿐이라면 it으로 대체할 수 있다.

728x90
Comments