본문 바로가기
Android

[Doit 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 정리 5 - 람다 함수와 고차 함수

by 들풀민들레 2022. 2. 28.
본 글은 [Doit 깡샘의 안드로이드 앱 프로그래밍 with 코틀린 - 이지스퍼블리싱 (2022)] 의 내용을 발췌한 것입니다.
좀더 자세한 내용은 책 혹은 인강을 통해 확인해 주세요.

 

 

 

람다 함수


람다 함수는 코틀린뿐만 아니라 많은 프로그래밍 언어에서 제공하는 익명 함수anonymous function 정의 기법입니다. 람다 함수는 주로 함수를 간단하게 정의할 때 이용하며 람다식이라고도 합니다. 코틀린으로 프로그램을 작성하다 보면 람다 함수를 많이 쓰는데, 이는 코틀린에서 고차 함수를 지원하기 때문입니다.
고차 함수는 매개변수나 반환값으로 함수를 이용하는데, 람다 함수는 주고받을 함수를 간단하게 정의할 때 사용합니다. 즉, 람다 함수는 그 자체도 가치가 있지만 고차 함수를 이해하고 사용하려면 꼭 알아야 합니다.

 

람다 함수 선언과 호출


일반적으로 함수는 fun 키워드로 선언합니다. 그런데 람다 함수는 fun 키워드를 이용하지 않으며 함수 이름이 없습니다. 람다 함수는 중괄호 { }로 표현합니다.

 

fun 함수명(매개변수) { 함수 본문 }
{ 매개변수 -> 함수 본문 }

코틀린에서 람다 함수를 사용하는 규칙은 다음과 같습니다.
• 람다 함수는 { }로 표현합니다.
• { } 안에 화살표( -> )가 있으며 화살표 왼쪽은 매개변수, 오른쪽은 함수 본문입니다.
• 함수의 반환값은 함수 본문의 마지막 표현식입니다.

 

람다 함수의 작성법을 일반 함수와 비교해 보겠습니다. 일반 함수는 fun 키워드와 함수 이름으로 선언했습니다.

 

fun sum(no1: Int, no2: Int): Int {
	return no1 + no2
}

 

똑같은 함수를 람다 함수로 선언하면 오른쪽과 같습니다. 중괄호 { } 영역에 람다 함수를 선언했습니다. 

 

val sum = {no1: Int, no2: Int -> no1 + no2}

 

함수 선언문인데도 fun 키워드를 사용하지 않았으며 함수 이름도 없습니다. 중괄호 안의 화살표를 기준으로 왼쪽에는 Int 타입의 매개변수를 2개 선언했으며, 오른쪽에는 실행문을 작성했습니다. 이 함수를 호출하면 실행문의 결괏값을 반환합니다. 람다 함수는 본문에서 마지막 실행문의 결과가 함수의 반환값입니다. 따라서 위 코드에서는 no1 + no2의 결과가 함수의 반환값이 됩니다.

 

그런데 람다 함수는 이름이 없으므로 함수명으로 호출할 수 없습니다. 그래서 보통은 람다 함수를 변수에 대입해 사용합니다. 위 코드에서는 sum이라는 변수에 대입했습니다. 따라서 오른쪽처럼 호출할 수 있습니다.

 

sum(10, 20)

람다 함수를 변수에 대입하고 이를 이용해 람다 함수를 호출한 구문입니다. 그런데 람다 함수를 항상 변수에 대입해서 사용해야 하는 것은 아닙니다. 만약 람다 함수를 선언하자마자 함수를 호출하고자 한다면 오른쪽처럼 작성하면 됩니다.

 

{no1: Int, no2: Int -> no1 + no2} (10, 20)

중괄호 { } 부분이 람다 함수입니다. 함수는 어디선가 소괄호 ( )를 이용해 호출해 주어야 실행됩니다. 그러므로 중괄호 뒤에 소괄호를 이용해 함수를 선언하자마자 호출한 구문입니다. 소괄호 안은 람다 함수에 선언한 매개변수에 맞추어 인자를 전달한 것입니다.

 

매개변수 없는 람다 함수


함수에 매개변수가 항상 있어야 하는 것은 아닙니다. 람다 함수에서 화살표 왼쪽이 매개변수를 정의하는 부분인데 매개변수가 없을 경우 비워 두면 됩니다. 

 

{-> println(“function call”)}

 

그런데 이처럼 매개변수가 없을 때는 화살표까지 생략해도 됩니다.

 

{println(“function call”)}

 

매개변수가 1개인 람다 함수


람다 함수를 선언할 때 매개변수는 중괄호 안 화살표 왼쪽에 선언합니다. 그런데 람다 함수의 매개변수가 1개일 때는 매개변수를 선언하지 않아도 함수로 전달된 값을 쉽게 이용할 수 있습니다. 일반적으로 매개변수가 1개인 람다 함수는 다음처럼 작성합니다. Int 타입의 매개변수가 1개인 람다 함수를 선언하고 이를 호출한 코드입니다.

 

fun main() {
	val some = {no: Int -> println(no)}
	some(10)
}

그런데 위와 같은 람다 함수를 다음처럼 작성할 수도 있습니다.

fun main() {
	val some: (Int) -> Unit = {println(it)}
	some(10)
}

위 코드를 보면 람다 함수의 중괄호 안에 화살표가 없으므로 매개변수가 없는 것처럼 보입니다. 하지만 람다 함수 앞에 (Int) -> Unit이 매개변수가 1개인 람다 함수임을 알려 줍니다. 이처럼 람다 함수의 매개변수가 1개일 때는 중괄호 안에서 매개변수 선언을 생략하고 println(it)처럼 it 키워드로 매개변수를 이용할 수 있습니다.

 

val some = {println(it)} // 오류!

람다 함수에서 it을 이용해 매개변수를 사용하는 것은 해당 매개변수의 타입을 식별할 수 있을 때만 가능합니다.

 

al some: (Int) -> Unit = {println(it)} // 성공!

위 코드는 람다 함수를 대입한 변수에 함수 타입을 지정했습니다. 즉, 람다 함수의 매개변수 타입을 Int로 선언했으므로 it이 가리키는 데이터가 Int 타입임을 알 수 있습니다.

 

람다 함수의 반환


람다 함수도 함수이므로 자신을 호출한 곳에 결괏값을 반환해야 할 때가 있습니다. 그런데 람다 함수에서는 return 문을 사용할 수 없습니다.

 

val some = {no1: Int, no2: Int -> return no1 * no2} // 오류!

람다 함수의 반환값은 본문에서 마지막 줄의 실행 결과입니다.

 

fun main() {
	val some = {no1: Int, no2: Int ->
		println(“in lambda function”)
		no1 * no2
	}
	println(“result : ${some(10, 20)}”)
}