[Kotlin] 함수/람다 함수 내의 반환 return
해당 글을 정리하게 된 이유를 본론에 들어가기 앞서 잠시 얘기해보자면, 코드 작성 시 당황했던 것이 있었기 때문이다.
서론에 관심이 없다면 아래 Return 에 대한 정리로 바로 넘어가도 된다.
아래 코드의 1번과 같이 코드를 작성하고, “EFGH” 가 출력될 것이라고 생각하고 테스트는 따로 해보지 않은 상태로 PR 을 올렸었다.
그러나, 차후 PR 을 통해 return 이 sample 을 반환할 것이라는 코멘트를 받았다.
그제서야 실행해본 결과 1번이 let을 반환하지 않는다는 것과, 2번처럼 라벨을 명시한 return 을 해야 의도적으로 동작시킬 수 있다는 것을 알게 되었다.
그리하여 본인은 Return 에 대해 좀 더 명확하게 정리 할 필요성을 느끼게 되어서 해당 포스팅을 작성하게 되었다.
// 1번
fun sample() {
abc?.let {
null ?: return
log(”ABCD”)
}
log(”EFGH”)
}
fun sample() {
abc?.let {
null ?: return@let
log(”ABCD”)
}
log(”EFGH”)
}
//EFGH 만 나와야하는데, 1번은 어느것도 안됨 가장 가까운 애의 return 이 아니었다.
(자, 긴 서론이었지만 이제 본론이다.)
Return
일반적으로 return 은 return 문장을 둘러싼 가장 가까운 함수에서 반환하는 역할을 수행하며, 반환값은 있을 수도 없을 수도 있다.
Kotlin 의 Return 특성
- 라벨 반환을 할 수 있는데, 이는 탈출할 특정 대상을 지정할 수 있다.
- Nothing 타입으로 아무것도 반환하지 않을 수 있다.
💡 Return 의 타입 | Return 의 타입은 Nothing 타입으로, 이는 특수하다. 특정 값을 가지지 않아, 함수가 아무것도 반환하지 않는 다는 의미로 return 만 사용할 수 있다. |
Return to Label
non-local return
코틀린에서 코드를 작성하다보면, 람다, 로컬 함수, object 등으로 함수가 중첩되는 경우가 흔하다.
제일 자주 쓰이는 람다 함수에서의 return 을 예시로 들어보자. 아까 위에서 언급했던 예시처럼 아래와 같은 케이스에서는 return 은 가장 가까운 함수에 대해 반환하며, 이를 non-local return 이라고 한다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // non-local return directly to the caller of foo()
print(it)
}
println("this point is unreachable")
}
//RESULT: 12
local return
단, 이러한 non-local return 은 인라인 함수에 대한 람다 표현식에만 적용되며, 만일 람다 자체에서 반환을 하고 싶다면, 아래와 같이 람다 함수명을 명시하여 return 해야한다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // local return to the caller of the lambda - the forEach loop
print(it)
}
print(" done with explicit label")
}
//RESULT: 1245 done with explicit label
위에는 forEach 에 해당하는 람다 expression 을 반환하였는데, forEach 등 특정 라벨에 대해 반환이 필요한 경우 아래와 같이 사용할 수 있다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda - the forEach loop
print(it)
}
print(" done with implicit label")
}
//RESULT: 12 done with implicit label
anonymous function
return 은 함수를 반환하기 때문에 만일 이러한 라벨을 사용하고 싶지 않은 경우, 아래와 같이 익명 함수를 사용하여 반환할 수도 있다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return // local return to the caller of the anonymous function - the forEach loop
print(value)
})
print(" done with anonymous function")
}
//RESULT: 1245 done with anonymous function
💡 값을 반환해야하는 Return | return@foo 1 과 같이 특정 라벨을 붙이는 것은 값을 반환하지 않는 것과 동일하고, 바로 뒤에 반환할 값을 지정할 수 있다. |