본문 바로가기

코틀린

[Kotlin] control flow

Condition expressions

 대중적으로 많이 사용하는 언어들은 조건을 검사할때 조건문 ( Conditional Statement ) 을 사용한다. 그러나 코틀린은 러스트처럼 조건문 대신 조건식 ( Conditional Expression ) 을 이용한다. 

 이때 문장 ( Statement ) 과 표현식 ( Expression ) 은 다음과 같다.

  • Statement : 특정 명령을 실행하거나 지시하는 코드 조각 단위
  • Expression : 값으로 평가될 수 있는 코드 조각 단위

 조건의 검사에 표현식을 사용하는 경우,  조건의 결과를 값으로써 사용할 수 있다는 장점이 있다. 또한 표현식은 문장에 포함되므로 꼭 값으로 평가되지 않아도 상관 없다. 즉, 조건의 분기에 더해 값으로써의 역할을 추가적으로 수행할 수 있다.

 코틀린의 조건식은 2가지가 존재한다. 

  • If expression : If , else 을 이용한 통상적인 조건식
  • When expression : switch 문과 유사한 조건식

If expression

// 일반적인 코드
fun abs(value : Int) : Int {
    if (value < 0) {
        return -value
    }
    else {
        return value
    }
}

// expression 성질 이용
fun abs(value : Int) : Int = if (value < 0)  -value else value

val sign_num = if ( a >= 0 ) a else 0

fun abs(value : Int) : Int {
    return if (value < 0) {
        -value
    }
    else {
        value
    }
}

 일반적인 조건 분기로 사용할 수도 있고, 표현식의 성질을 이용하여 삼항 연산자처럼 사용할 수도 있다. 이때 각 블럭의 마지막의 값은 return 문 없이도 반환된다 ( value ) .

When expression

 타 언어의 패턴 매칭, switch 구문 및 if / else 체인 기능을 when 표현식으로 모두 처리할 수 있도록 만든 느낌이다. 설정된 분기 조건을 위에서 아래로 평가하며, 조건을 만족하면 이후 분기는 무시한다.

var x = getRandInt()
when (x) {
    in 1..5 -> println("between 1 and 5")
    in 6..10 -> println("between 6 and 10")
    else -> println("i don't know")
}

 일반적인 switch 문은 변수 x에 대해서만 나타내는 것이 일반적이나, 코틀린의 when 문은 x 없이 조건만을 나열해 if else 문처럼 작성할 수도 있다.

when {
    rec is Square -> println("rec is square")
    !seq.condition -> println("condition is false!")
    else -> println("don't know ...")
}

  표현식 ( expression ) 에 속하기 때문에 선언과 대입으로 분리된 식을 단순화할 수 있다는 특징이 있다.

var case : Int = when(val num = getRandInt()) {
    in 0..25 -> 1
    in 26..50 -> 2
    !in 70..80 -> 3
    else -> {
        println("num is $num")
        -1
    }
}

For loop

 코틀린의 for 문은 Iterator 기반으로 동작하므로 자바스크립트의 for ~ of 문이나 파이썬의 for문과 유사하다.  Iterable<> 인터페이스의 iterator 함수를 포함하여 몇몇 인터페이스들을 구현하면 for 문에서 사용할 수 있게 된다. 예시

for (i in 1..9 step 2) print("$i ") println()

for (i in 10 downTo 0 step 2) print("$i ") println()
// 아래 코드와 동일
for (i in 10.downTo(0).step(2)) print("$i ") println()

While loop

 통상적인 while 문과 동일하다. do ~ while 문은 조금 다른데, 조건을 판단할 때 do ~ while 블럭 내에 존재하는 변수를 사용 할 수 있다는 점이 인상적이다.  while 문 내부의 변수 자체는 순회할 때마다 당연히 초기화되므로 사용법은 제한적이다.

fun getRandInt() : Int = Random.nextInt(0..100)

do {
    val condition = getRandInt()
} while(condition >= 50)

Return & jump

코틀린에서 jump expression은 3가지가 있다고 한다.

  1. return : 가장 근접한 함수 혹은 익명 함수를 탈출한다.  
  2. break :  가장 근접한 루프를 탈출한다.
  3. continue : 가장 근접한 루프의 다음 스텝으로 뛰어넘는다.

 

Nothing Type

  위 3개의 표현식은 따로 인자가 없는 경우 ( return 문에 반환값이 없거나 ... ) Nothing 타입이 되기도 한다. 단, Nothing 타입의 의미는 "절대 반환하지 않는다" 라는 의미를 가진다. 사용되는 경우는 다음과 같다.

  1. 도달할 수 없는 코드의 위치를 표현
  2. 예외 처리 중 반환

 정상적인 상황에서는 볼 일이 없다. 공식 문서에서는 다음 예시를 통해 Nothing type을 설명한다.

val s = person.name ?: return

 person.name 이 존재하지 않는 경우 가장 근접한 함수를 탈출한다. 변수 s의 타입이 Nothing이 되지만, return에 의해 함수를 탈출하여 이후 코드는 실행되지도 않으므로 "절대 반환하지 않는다" 라는 의미와 맞다. 참고로 코틀린에서는 타 언어의 void 반환형에 대응되는 함수가 Unit 타입을 반환하므로 Nothing은 대부분 예외처리 과정에서 발생한다.

 Nothing? 타입은 해당 변수의 타입을 추론할 방법이 전혀 없는 상황에서 사용된다. 변수는 반드시 null 또는 Nothing 값만을 가져야 한다.

val k = null
val arr2 = listOf(null)

 위 코드의 변수 k 및 arr2 는 타입을 추론할만한 수단이 전혀 없으며, 값으로 null을 가진다. 따라서 Nothing? 타입으로 타입을 유추할 수 없다는 의미가 된다.

label

 라벨을 이용하면 언급한 표현식들의 동작을 라벨이 지정된 위치에 대해 점프를 수행하도록 위치를 지정할 수 있다. 

// 일반적인 for문
loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (i + j == 150) break@loop
    }
}

// 람다식
intArrayOf(1,2,3,4,5).forEach foe@{
    if (it == 3) return@foe
    println(it)
}

// 무명 함수
intArrayOf(1,2,3,4,5).forEach (foe@fun (it:Int){
    if (it == 3) return@foe
    println(it)
})

  run을 이용하면 러스트의 loop ~ break 처럼 값을 반환할 수도 있다.

var result = run loop@{
    var y = 1
    do {
        y *= y
        y += 1
        if(y >= 100) return@loop y // y를 반환
    } while(true)
}
println("result is $result")

Exception

 코틀린의 예외처리는 try ~ catch ~ finally 구문을 기본으로 하며, throw을 통해 예외를 던질 수 있다. 

 공식 설명에 따르면 자바에서 지원하는 checked exception이 존재하지 않는다고 한다. 해당 예외는 Runtime Exception 을 상속하지 않으며, try-catch 혹은 throw로 명시적 처리가 문법적으로 강제되는 예외로, 예외 처리를 강제로 요구하는 것이 생산성을 떨어뜨리는 영향을 주기 때문에 코틀린에서는 이를 지원하지 않는다. 

 throw을 수행하면 Nothing 타입을 반환한다.

'코틀린' 카테고리의 다른 글

[코틀린] 자바&코틀린 라이브러리 검색  (0) 2022.11.05
[Kotlin] 상속  (0) 2022.10.10
[Kotlin] 생성자  (0) 2022.09.06
[Kotlin] 기본 타입  (0) 2022.09.03
[Kotlin] 기본 타입과 내부 처리  (0) 2022.09.01