조용한 담장

[코틀린] Kotlin : Control Flow 본문

kotlin

[코틀린] Kotlin : Control Flow

iosroid 2019. 12. 31. 16:07

코틀린(kotlin) 의 control flow 부분을 살펴보자. if, when, for, while

원문 https://kotlinlang.org/docs/reference/control-flow.html 을 보며 정리.

If Expression

grammar for if

if is an expression.

kotlin 에서 if 는 control flow 를 위한 키워드일 뿐 아니라 표현식이 이기도 하다.
어떤 동작의 결과를 리턴하는 표현식으로써도 동작한다는 의미이다.

val max = if (a > b) a else b

if () 의 결과에 따라 max 는 a 나 b 의 값을 가진다.

val max = if (a > b) {
    print("Choose a")
    a
} else {
    print("Choose b")
    b
}

{ }​ 안에 코드 동작을 더 넣을 수 있다.
전통적인 if else 모양이지만 값이 리턴되는 표현식이라는 것이 다르다.
단, if 를 표현식으로 쓰기 위해선 모든 경우의 리턴값이 존재해야 하므로 else branch 가 반드시 함께 사용되야 한다.

val max = if (a > b) a // error 
// 'if' must have both main and 'else' branches if used as an expression

기본적인 statement 로써의 사용법은 특이한것은 없다.

// Traditional usage 
var max = a 
if (a < b) max = b

if (a > b) {
    max = a
}

// With else 
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}

When Expression

grammar for when

when can be used either as an expression or as a statement.

C/C++ 의 switch 와 같은 동작을 한다.

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // Note the block
        print("x is neither 1 nor 2")
    }
}

x 가 1 이거나 2 이면 print() 가 호출되고, 그 외의 경우엔 else 문이 실행된다.
위 예제처럼 statement 로 쓰일수도 있고 if 처럼 expression 으로 쓰일수도 있다.
이때도 else 가 반드시 함께 쓰여야 한다.

val a = 1
val b = when(a) {
    1 -> 1
    else -> 0
}
print(b)

{ } 을 사용할 수 있고 분기하는 조건 (branch condition) 을 ​,​ 로 묶을수도 있다.

val b = when(a) {
    1, 2 -> {
        println("1 or 2")
        1
    }
    else -> 0
}

1, 2 같은 정해진 상수값이 아닌 임의의 값을 가지는 표현식으로 분기 조건을 쓸수 도 있다.

val x = 1
val s = "1"
when (x) {
    parseInt(s) -> print("s encodes x")
    else -> print("s does not encode x")
}

값이 범위 표현식(range) 또는 collection 안에 존재하는지 확인하는 표현식(​in!in)으로 분기 조건을 쓸 수 있다.

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

데이터 타입을 확인하는 is​!is 를 분기 조건으로 쓸 수 있다.

fun hasPrefix(x: Any) = when(x) {
    is String -> x.startsWith("prefix")
    else -> false
}

when 에 인자(argument)가 없으면 각 분기조건은 boolean expression 처럼 쓰이게 되어 ​if-else if 처럼 쓸 수 있다.
각 분기 조건의 값이 true 일 때 수행되고 false 이면 다음 조건으로 넘어간다.

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

when subject 의 내부에서 생성한 변수를 body 내에서 사용할 수 있다.

fun Request.getBody() =
        when (val response = executeRequest()) { // when subject 에서 response 생성
            is Success -> response.body // when 의 body 내에서만 response 사용 가능
            is HttpError -> throw HttpException(response.status)
        }

For Loops

grammar for for

for 는 iterator 를 제공하는 어떤 것에서나 반복 루프를 수행한다.

iterator 를 제공하는 경우는 아래와 같다.

  • has a member- or extension-function iterator()
    • has a member- or extension-function next()​, and
    • has a member- or extension-function hasNext() that returns Boolean.
for (item in collection) print(item)
for (item: Int in ints) {
    // ...
}

숫자 범위 표현식(range expression)에 사용

for (i in 1..3) {
    println(i)
}
for (i in 6 downTo 0 step 2) {
    println(i)
}

for 와 range 나 array 로 반복동작을 구현한 코드의 경우 index-based loop 으로 컴파일 되며 이는 iterator 를 생성하지 않는다.
이 경우에는 아래와 같이 index 기반으로 사용한다.

for (i in array.indices) {
    println(array[i])
}
for ((index, value) in array.withIndex()) {
    println("the element at $index is $value")
}

while Loops

grammar for while

반복문 while 과 do while 이 있다.

while (x > 0) {
    x--
}

do {
    val y = retrieveData()
} while (y != null) // y is visible here!

 

Comments