코틀린 Returns and jumps

Returns and jumps

코틀린은 세가지 점프 표현식을 가지고 있습니다.

  • return: 기본적으로 return은 가장 가까운 함수 또는 익명함수로부터 반환합니다.

  • break: 가장 가까운 루프를 종료시킵니다.

  • continue: 가장 가까운 루프의 다음 단계로 이동합니다.

이 세가지 표현식은 모두 더 큰 식의 일부로써 사용될 수 있습니다.

val s = person.name ?: return

이런 식의 타입은 Nothing 입니다.

Break and Continue labels

코틀린의 모든 표현식은 라벨을 붙일수 있습니다. 라벨은 @abc, fooBar@ 처럼 라벨의 이름 뒤에 @가 붙는 형태를 갖습니다. 표현식 앞에 라벨을 쓰는 것으로 간단히 라벨링을 할 수 있습니다.

label@ for (i in 1..10) {
	//...
}

이제 라벨을 붙였으면, break와 continue를 라벨을 이용해서 사용할 수 있습니다.

fun main() {
    loop@ for (i in 1..100) {
        for (j in 1..100) {
            if (i == 10) {
                break@loop
            }
        }
        println(i)
    }
}

[출력]
1
2
3
4
5
6
7
8
9

라벨이 붙여진 break는 그 라벨에 해당하는 반복문의 바로 다음으로 이동하게 합니다. continue도 마찬가지입니다. 라벨이 붙은 반복문의 다음 반복으로 넘어가게 만듭니다.

fun main() {
    loop@ for (i in 1..20) {
        for (j in 1..20) {
            if (i < 10) {
                continue@loop
            }
        }
        println(i)
    }
}

[출력]
10
11
12
13
14
15
16
17
18
19
20

Return to labels

코틀린에서 함수는 함수 리터럴, 로컬 함수, 객체식을 사용하여 중첩될 수 있습니다. 한정된 return식은 바깥의 함수로 리턴할 수 있게 해줍니다. 주로 람다식을 리턴하는데 많이 사용됩니다.

아래의 예제를 같이 확인해봅시다. return 식은 가장 가까운 닫힌 함수 foo에 대해 반환합니다.

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")
}

fun main() {
    foo()
}

[출력]
12

이러한 non-local 리턴식은 인라인 함수에 인자로 전달되는 람다식에 대해서만 지원됩니다. 람다식에 대해서 반환하기 위해서는 람다식에 라벨을 붙이고, return의 범위를 제한해야 합니다.

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // non-local return directly to the caller of foo()
        print(it)
    }
    print(" done with explicit label")
}

fun main() {
    foo()
}

[출력]
1245 done with explicit label

위의 리턴식은 오직 람다식에 대해서만 반환을 수행합니다.

때떄로 명시적으로 라벨을 사용하는 것보다 암시적 라벨링이 더 편할때도 있습니다. 람다식은 그것이 인자로 전달되는 함수의 이름으로 암시적으로 라벨링됩니다.

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach // non-local return directly to the caller of foo()
        print(it)
    }
    print(" done with explicit label")
}

fun main() {
    foo()
}

[출력]
1245 done with explicit label

람다식을 익명함수로 대체해서 사용할 수도 있습니다. 익명 함수 내의 return문은 익명 함수로부터 반환할 것입니다.

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
        if (value == 3) return // non-local return directly to the caller of foo()
        print(value)
    })
    print("done with anonymous function")
}

fun main() {
    foo()
}

[출력]
1245 done with anonymous function

위의 세 가지 예제에서, local return의 사용은 일반적인 loop에서 continue를 사용한 것과 유사합니다.

break와 동일하지는 않지만, 다른 람다를 중첩시키고 non-local return을 사용하여 break와 비슷하게 동작하게 할 수 있습니다.

fun foo() {
    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop // non-local return from the lambda passed to run
            print(it)
        }
    }
    print(" done with nested loop")
}

fun main() {
    foo()
}

[출략]
12 done with nested loop

좋은 웹페이지 즐겨찾기