반갑습니다!

[Kotlin] 반복문 본문

Kotlin

[Kotlin] 반복문

김덜덜이 2020. 6. 15. 18:38

일반적인 프로그래밍 언어에서 지원하는 반복문을 코틀린에서도 지원한다.

for문

자바에서 사용하던 반복문은 for(int i=0; i<10; i++)의 형태를 가졌다. 코틀린에서는 이를 조금 더 축약하여 for(i in 0..9) 로 사용할 수 있다. 이 때 주의해야할 것은 0..9는 0이상 9이하의 범위를 의미한다. 즉, <=를 의미하는 것이다. 코틀린에서 0이상 10미만의 범위를 나타내기 위해서는 until 키워드를 사용해서 0 until 10로 표현하면 된다.

반복문은 어렵지 않기 때문에 예시를 통해 알아보고 넘어가겠다.

fun main() {
    for(i in 0..10) print("$i ")
    println()
    for(i in 1 until 10) print("$i ")
    println()
    for(i in 0..10 step 2) print("$i ")
    println()
    for(i in 10 downTo 0) print("$i ")
    println()
}

/*
실행 결과
0 1 2 3 4 5 6 7 8 9 10 
1 2 3 4 5 6 7 8 9 
0 2 4 6 8 10 
10 9 8 7 6 5 4 3 2 1 0
 */

while문

while문은 while(조건)으로 구성되어있다. 조건이 True인 경우에 반복문을 수행한다.

fun main() {
    var i = 1
    while (i < 10) {
        print("${i++} ")
    }
    println()
}
/*
실행 결과
1 2 3 4 5 6 7 8 9 
 */

do while문

while문과 조금 다른 do while문이 있다. while문은 조건검사를 하고 반복문을 들어가지만, do while문은 실행한 뒤, 조건을 검사한다는 차이점이 있다.

반복문의 흐름 제어

return의 사용

함수에서 return을 사용하게 되면 return의 아래에 있는 코드들은 실행되지 않는다.

fun main() {
    retFunc()
}

inline fun inlineLambda(a: Int, b: Int, out: (Int, Int) -> Unit) {
    out(a, b)
}

fun retFunc() {
    println("start of retFunc")
    inlineLambda(13, 3) { a, b ->
        val result = a + b
        if(result > 10) return
        println("result: $result")
    }
    println("end of retFunc")
}
/*
실행 결과
Start of retFunc
*/

다음과 같은 코드가 있다고 가정하자. a + b가 10보다 크면 람다 함수를 종료하고 싶다. 하지만 위의 코드에서는 "start of retFunc" 만 출력될 뿐, "end of retFunc"는 출력되지 않는다. 이는 람다 함수에서의 return이 retFunc()를 종료시켰기 때문이다. 이를 비지역반환이라고 한다. 비지역반환을 방지하기 위해서는 '라벨'을 사용하면 된다. 라벨을 붙일 때는 (라벨 이름)@, 라벨을 호출할 때는 @(라벨 이름)으로 사용한다.

fun main() {
    retFunc()
}

inline fun inlineLambda(a: Int, b: Int, out: (Int, Int) -> Unit) {
    out(a, b)
}

fun retFunc() {
    println("Start of retFunc")
    inlineLambda(13, 3) label@{ a, b ->
        val result = a + b
        if (result > 10) return@label
        println("result: $result")
    }
    println("end of retFunc")
}
/*
실행 결과
Start of retFunc
end of retFunc
*/

위의 코드처럼 라벨을 사용하면 흐름 제어를 조금 더 편리하게 할 수 있다. 라벨을 사용하면서 값을 반환하기 위해서는 return@a 1와 같이 사용하면 된다.

또한 람다식 표현식 블록에 직접 라벨을 쓰지 않고 람다식 함수의 명칭을 그대로 라벨처럼 사용할 수 있는데 이것을 암묵적 라벨이라고 부른다.

fun retFunc() {
    println("start of retFunc")
    inlineLambda(13, 3) { a, b -> 
        val result = a + b
        if(result > 10) return@inlineLambda 
        println("result: $result")
    } 
    println("end of retFunc") 
}

위의 내용에서 라벨을 사용하여 비지역반환을 방지하는 방법을 알아보았다. 비지역반환을 방지하는 다른 방법이 있는데 이는 익명 함수를 사용하는 방법이다.

fun main() {
    retFunc()
}

inline fun inlineLambda(a: Int, b: Int, out: (Int, Int) -> Unit) {
    out(a, b)
}

fun retFunc() {
    println("Start of retFunc")
    inlineLambda(13, 3, fun(a: Int, b: Int) {
        val result = a + b
        if (result > 10) return
        println("result: $result")
    })
    println("end of retFunc")
}
/*
실행 결과
Start of retFunc
end of retFunc
 */

이와 같이 익명 함수를 선언하게 되면 return을 하더라도 익명 함수만 종료되기 때문에 비지역반환이 발생하지 않는다.

break / continue

다른 프로그래밍 언어에서처럼 코틀린 역시 break와 continue를 지원한다. 그리고 break와 continue 역시 라벨을 사용하여 흐름 제어를 할 수 있다.

 fun labelBreak() {
     first@for(i in 1..5) {
        second@ for(j in 1..5) {
            if (j == 3) break@first
            println("i: $i, j: $j")
        }        
 }

'Kotlin' 카테고리의 다른 글

[Kotlin] Coroutine Basics  (0) 2020.07.04
[Kotlin] Coroutine Guide  (0) 2020.07.04
[Kotlin] 조건문  (0) 2020.06.15
[Kotlin] 함수형 프로그래밍  (0) 2020.06.09
[Kotlin] 함수  (0) 2020.06.09