티스토리 뷰

반응형

Kotlin Lamda Return 가능한가?

Kotlin 에서 Lamda 안에서 return 이 가능할까요? ‘당연히 Return 다 되는거 아니야?’ 라고 생각 할 수 있습니다. 그렇지만 모든 경우 Lamda의 return을 제공하고 있지 않습니다.

그럼 어느경우 가능하고 어느경우 안되는 것인지 알아보겠습니다.

 

Lamda는 무엇인지부터 살펴 봐야겠습니다.

 

Lamda Expression란?

Lamda는 Java SDK 1.8부터 추가되어 자바의 큰 변화를 주었습니다. 람다식의 도입으로 인해 자바는 객체지향언어인 동시에 함수형 언어가 되었습니다.

위키에서는 람다를 어떻게 정의하고있을까요?

 

  람다식, 또는 람다 함수라 부른다. 프로그래밍서 사용되는 개념으로, 익명 함수(匿名函數, Anonymous functions)를 지칭하는 용어이다.
  -나무위키

 

람다식을 간단히말하면 메서드를 하나의 ‘식(expression) 으로 표현한 것입니다. 다시말해, 람다식으로 표현하면 메서드의 이름과 반환값이 없어지므로 람다식을 ‘익명함수(anonymous function)’ 이라고도합니다.

 

그렇다면 어떻게 람다식을 표현 할 수 있을까요?

예를 들어봅시다.

두 값을 비교해서 큰 값을 리턴해 주는 함수가 있다고 합시다. 이 함수를 람다식으로 표현하면 어떻게 할 수 있을까요?

fun max(a:Int, b:Int) : Int {
 return if(a > b) a else b
} 



위 두 값을 비교하는 함수를 람다식으로 표현하면 간단히 표현 할 수 있습니다.

(a, b) -> if(a > b) a else b

 

 

또 다른 방법으로 사용한 전통적인 방법으로 0부터 10까지 출력하는 함수를 보겠습니다.

for (i in 0 until 10) {
    println(i)
}

 

람다식을 사용하여 만드는 방법을 살펴보겠습니다.

(0 until 10).forEach { println(it) }

 

아직 람다식에 대한 이해가 부족한 사람은 전통적인 코딩컨벤션이 가독성이 높다고 생각할 수 있습니다. 그렇다면 안드로이드에서 자주 사용하는 코드로 예를 들어 보겠습니다.

 

체크 버튼의 클릭 이벤트를 람다로 표현하면 어떻게 표현할 수 있을까요?

먼저 람다 사용 안한 리스너를 사용하면 다음과 같습니다.

binding.btnCheck.setOnClickListener(object : OnClickListener{
  override fun onClick(p0: View?) {     
	 println("click")
  }
})

 

람다식로 표현한 방법은 다음과 같이 간단히 표현 할 수 있습니다.

binding.btnCheck.setOnClickListener{     
	 println("click")
}

 

람다는 고차함수로도 사용할 수 있습니다.

고차함수란 함수를 인자로 받던가 결과값으로 반환 할 수 있는 함수 입니다.

 

고차함수의 예를 들어보겠습니다. 음식을 입력하면 음식 옆에 날짜를 찍어주는 함수를 만들어야한다고 가정하겠습니다. 고차함수로 표현하면 다음과 같습니다.

fun addOrderDate(order: (String) -> String) : () -> String {
	return {order("2023-05-07")}
}

fun main() {
  val food = "bread"
  val result = addOrderDate({item} -> "$item bread"})
	println(result())
} // print : 2023-05-07 bread

 

람다식은 고차함수로 함수의 인자로 넣을 수도 있으며, Return Type 으로도 표현할 수 있습니다.

위의 예제는 매개변수 하나를 람다식으로 선언했으며, 함수 호출시에 매개변수에 람다식을 넣어야합니다. 반환 타입 또한 람다식으로 되어 있어 result가 아닌 result() 로 함수 선언하여 return 을 받을 수 있습니다.

 

람다식은 반복코드 및 고차함수에서도 사용할 수 있는 람다는 프로그래밍의 효율성을 높여주는 효과가 있음을 확인할 수 있습니다.

 

  어떤 프로그래밍 언어의 함수 구현에서 함수를 인자로 넘길 수 있거나 반환할 수 있을 때 함수를 일급 객체(first-class object, 언어 내부에서 값으로 표현되고 전달될 수 있는 자료형)로 취급한다고 하고, 함수를 인자로 받거나 결과로 반환하는 함수를 고차함수(高次函數)라 한다. 수학의 범함수와 맥락이 비슷하다.   -나무위키

 

 

Lamda 의 return 은 모두 가능한가?

Lamda 식에 대해서 알아봤으니 다시 포스트 주제인 Kotlin Lamda Return 가능한가? 의 질문을 하겠습니다.

람다식에서 return 을 해주는 것은 자유로울까요?

 

아쉽게도 Kotlin Document에서는 Lamda 의 return을 제한하고 있습니다.

 

fun foo() {
    ordinaryFunction {
        return // ERROR: cannot make `foo` return here
    }
}

위와 같이 람다식으로 구현한 명명된 함수 또는 익명함수를 종료하기 위해서 return 을 사용할 수 없습니다.

lamda 안에서는 return 을 금지하고 있습니다. 그 이유는 람다는 둘러싸는 함수(여기서는 foo())를 반환할 수 없기 때문에 람다 내에서 return 이 금지됩니다.

만약 사용하려면 Label 을 사용하면 return 처리를 할 수 있습니다.

fun foo() {
    ordinaryFunction look@{
        return@look // OK: label return
    }
}

 

또 다른 lamda 의 retrun 방법은 명명된 함수 또는 익명함수를 inline 함수로 만드는 것입니다.

Lamda에서는 inline 함수로 만든 함수의 return 을 허용하고 있습니다.

fun foo() {
    inlined {
        return // OK: the lambda is inlined
    }
}

위와 같은 returns을 non-lacal returns 으로 부릅니다. 인라인 함수 안에서의 retrun 은 인라인 함수를 포함하는 root 에서 return 이 발생합니다. 즉, 인라인 함수에서의 return은 foo() 을 반환할 수 있게 됩니다.

kotlin에서 제공하는 forEach 은 inline 함수로써 return 을 사용할 수 있습니다.

fun hasZeros(ints: List<Int>): Boolean {
    ints.forEach {
        if (it == 0) return true // returns from hasZeros
    }
    return false
}

 

마무리

Kotlin Lamda 에서의 return 처리를 알아보기위해서 Lamda에 대해서 간단히 개념을 익혔고, Kotlin Lamda Return 이 언제 가능한지 알아봤습니다.

많은 개발자들이 익명함수 또는 람다식에서의 return 이 가능하다고 알고있습니다. 대부분 forEach 과 같은 inline 함수에서 return 을 사용하여서 가능하다고 생각할 수 있는데요. 정확히는 forEach 문은 inline 함수여서 return 이 가능한거였습니다.

Kotlin Lamda 에서 return 이 언제 가능하고 불가능한지 확인 후 사용하기를 권장 드립니다.

 

참고자료

inline-functions - kotlin 공식문서

[kotlin] 람다식에서 return을 사용해보자 ! -golucky.log

 

반응형
댓글