코딩하는 개굴이

[Kotlin] 함수/람다 함수 내의 반환 return 본문

안드로이드/KOTLIN

[Kotlin] 함수/람다 함수 내의 반환 return

개굴이모자 2023. 1. 21. 23:20
반응형

해당 글을 정리하게 된 이유를 본론에 들어가기 앞서 잠시 얘기해보자면, 코드 작성 시 당황했던 것이 있었기 때문이다.

서론에 관심이 없다면 아래 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 과 같이 특정 라벨을 붙이는 것은 값을 반환하지 않는 것과 동일하고, 바로 뒤에 반환할 값을 지정할 수 있다.

 

 

참고 링크

반응형
Comments