[Kotlin] 고차함수와 람다 표현식에 대해서

곽호택·2021년 7월 25일
0

코틀린

목록 보기
2/6
post-thumbnail
post-custom-banner

! 3주에 걸친 앱잼이 끝나고나서 어찌저찌 앱을 구현하기는 했지만 너무 코드가 지저분해서 가독성도 좋지 않고, 수정해야 할 부분들이 많다. 리팩토링과 클린 코드를 위해 코틀린에 대해 더 알 필요가 있다고 생각하여 공부를 했다.

1. 일급 함수(First-class functions)

고차함수와 람다 표현식을 이해하기 위해서는 일급함수에 대해 알아야 한다. 이를 위해 여러 블로그 및 사이트를 찾아봤고 코드차차라는 곳에 자세하게 기술되어 있어 이를 참고하여 공부를 진행했다. codechacha

일급함수는 객체로 취급되는 함수를 의미하고 3가지 특징을 가지고 있다.

  • 일급함수는 함수의 객체로 취급 될 수 있다.

  • 일급 함수는 함수 객체를 인자로 넘길 수 있다.

  • 일급함수는 함수의 return 값이 될 수 있다.

이 3가지 특징을 코드를 통해 알아보겠습니다.

① 일급함수는 함수의 객체로 취급 될 수 있다.

val hi: () -> String = {"hi my friend"}

위의 있는 코드에서 우리는 변수 hi에 "hi my fried"를 return하는 함수를 할당하였습니다.

② 일급 함수는 함수 객체를 인자로 넘길 수 있다.

val hi: () -> String = {"hi my friend"}

fun printHi(func: () -> String){
	print("${func()}")
}

fun main(){
	printHi(hi)
}

여기서 printHi의 경우 인자에 스트링을 리턴받는 함수를 받고 있고 실제로 String을 리턴하는 hi를 printHi의 인자로 넘겼을 때 "hi my friend"가 출력됩니다.

③ 일급함수는 함수의 return 값이 될 수 있다.

val hi: () -> String = {"hi my friend"}

fun printHi() : () -> String {
	return hi
}

fun main(){
	val returned : () -> String = printHi()
    print("${returned()}")
}

printHi 함수의 경우 return 값으로 스트링을 return하는 hi라는 함수를 return합니다. 이 함수를 받아서 호출하는 returned 함수 객체를 만들어 이를 호출할 경우 "hi my friend"가 출력됩니다.

2. 고차 함수(Higher-Ordere Functions)

위에서 정리한 일급 함수의 특징을 잘 숙지하고 있다면 고차 함수에 대한 내용도 쉽게 이해가 가능합니다.

- 일급 함수는 함수 객체를 인자로 넘길 수 있다.

- 일급함수는 함수의 return 값이 될 수 있다.

일급 함수의 3가지 특징 중 위의 2가지 특징을 하나라도 만족시키면 해당 함수를 우리는 고차 함수라고 부릅니다.

val hi: () -> String = {"hi my friend"}

fun printHi(func: () -> String) : () -> String {
	return hi
}

fun main(){
	val returned = printHi(hi)
    print("${returned()}")
}

위의 코드에서 printHi라는 함수는 함수를 인자로 받고 또한 함수를 결과로 return해준다.

여기서 인자로 함수를 넘길 때에는 이름 뒤에 :() -> String과 같이 함수의 타입을 명시해 주어야 하고, 만약 인자로 두개를 넘길 경우
(Int, Int) -> String과 같이 표현이 가능하다. 추가로 return 값이 없을 경우에는 -> 다음에 Unit으로 표현을 하면 된다.

고차함수는 콜백 인터페이스를 사용할 때와 같이 구성 요소 간에 통신할 때 유용하다. 이번 차로 리팩토링 할때 사용해보면 좋을 듯(?)

3. 람다 표현식(Lambda Expression)

코틀린 document 참고

람다 표현식은 이름 없는 함수를 정의하는데 사용하는 함수 표현 방법이다.

이 람다 표현식을 통해 익명 클래스 및 익명 함수를 간결하게 표현할 수 있어서 매우 유용하다. 하지만 디버깅이 어렵고 무분별하게 남발할 경우 오히려 코드 가독성이 떨어지기 때문에 주의해서 사용해야 한다.

max(strings, {a, b -> a.length < b.length})

위의 코드는 고차 함수 이다. 두번째 인자로 함수가 넘겨지기 때문이다.
여기서 {a,b -> a.length < b.length}의 경우에는 다음 보여줄 compare함수와 동일한 기능을 나타낸다.

fun compare(a: String, b: String) : Boolean {
	return a.length < b.length
    }

이 두 가지 코드를 통해 compare라는 이름이 있는 함수를 중괄호 안에 있는 코드로 바꿔 이름이 없는 함수로 표현할 수 있음을 알 수 있다.

람다 표현식 구문

val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
  • 람다 식은 항상 중괄호{}로 둘러 싸여 있다.

  • -> 기호 다음에는 함수의 body 부분이 나타난다.

  • -> 앞에는 함수에 전달된 매개 변수를 입력해준다.

후행 람다 전달

코틀린의 규칙에 따르면 함수의 마지막 매개변수가 함수일 경우 해당 인수로 전달된 람다 표현식을 괄호 밖에 배치할 수 있다. 위의 코드인

max(Strings, {a,b -> a.length < b.length})

를 다음과 같이 나타낼 수 있다.

max(strings) {a,b -> a.length < b.length}

추가로 람다 식에서 만약 매개변수가 하나가 있을 경우에 굳이 매개변수를 선언할 필요가 없고 -> 생략하고 매개 변수를 it으로 표시를 합니다.

일단 여기까지 공부!

profile
잘하고싶다
post-custom-banner

0개의 댓글