Study/kotlin

[코틀린 프로그래밍] Chapter.04 외부 반복과 아규먼트 매칭

에디개발자 2021. 4. 13. 07:00
반응형

나를 닮았다고 한다...

소스 코드에서 많은 비중을 차지하고 있는 for문을 코틀린에서 우아하게 다루는 방법을 정리해보겠습니다.

범위와 반복

코틀린에서 제공하는 레인지를 설정할 수 있습니다.

val oneToFive: IntRange = 1..5
val aToE: CharRange = 'a'..'e'

반복

자바에서 일반적인 for문과 비교해보겠습니다.

// Java
for (int i = 0; i < 5; i++) {
    // logic..            
}

Kotlin

// 정방향
for ( i in 1..5) {
    // logic..
}

// 후방향
for ( i in 5.downTo(1)) {
    // logic...
}

 

until : 마지막값을 포함 시키지 않는 

for (i in 1 until 5) {
    print("$i, ")
}
// 1,2,3,4,

 

step : 건너뛰기 기능

for (i in 1 until 10 step 3) {
    print("$i, ")
}
// 1, 4, 7,

 

filter : 원하는 값만 추출하는 기능

for (i in (1..9).filter { it % 3 == 0 || it % 5 == 0 }) {
    print("$i, ")
}
// 3, 5, 6, 9,

 

배열과 리스트의 반복

코틀린에서는 배열을 만드는 방법은 arrayOf()를 이용하자!

val array = arrayOf(1, 2, 3)

 

List<T>의 인스턴스는 listOf()를 이용하자!

val list = listOf(1, 2, 3)

for 반복문에서 인덱스 사용방법

val names = listOf("NAM", "NUM", "NIM")

// 방법1
for ( index in names.indices) {
    println("index is ${names.get(index)}")
}

// 방법2
for ((index, name) in names.withIndex()) {
    println("position of $name is $index")
}

 

When

코틀린에는 swtich문이 없습니다. 대신 When을 사용합니다. 

표현식 When

먼저 자바의 코드로 예로 들어보겠습니다.

// bad!!
fun isAlive(alive: Boolean, numberOfLiveNeighbors: Int): Boolean {
    if (numberOfLiveNeighbors < 2) {
        return false
    }
    if (numberOfLiveNeighbors > 3) {
        return false
    }
    if (numberOfLiveNeighbors == 3) {
        return true
    }
    return alive && numberOfLiveNeighbors == 2
}

 

소스가 지저분해 보입니다. 이 코드는 코틀린의 When 표현식으로 리팩토링해보겠습니다.

// good!!
fun isAliveGood(alive: Boolean, numberOfLiveNeighbors: Int) = when {
    numberOfLiveNeighbors < 2 -> false
    numberOfLiveNeighbors > 3 -> false
    numberOfLiveNeighbors == 3 -> true
    else -> alive && numberOfLiveNeighbors == 2
}

 

When을 사용할 때는 되도록이면 Any타입의 변수를 받는 것은 피하자! Any 타입의 변수를 받는 예제코드를 살펴보겠습니다.

fun whatToDo(dayOfWeek: Any) = when (dayOfWeek) {
    "Saturday", "Sunday" -> "Relax"
    in listOf("Monday", "Tuesday", "Wednesday", "Thursday") -> "Work hard"
    in 2..4 -> "Work hard"
    "Friday" -> "Party"
    is String -> "What?"
    else -> "No clue"
}

println(whatToDo("Sunday"))  // Relax
println(whatToDo("Wednesday"))  // Work hard
println(whatToDo(3))  // Work hard
println(whatToDo("Friday"))  // Party
println(whatToDo("Munday"))  // What?
println(whatToDo(8))  // No clue

표현식으로 When이 사용될 경우 else는 필수입니다.

주의할 점!!
여기까지 살펴본 When의 -> 뒤에 오는 코드는 짧은 단일 표현식이었습니다. 
만약에 -> 블록을 사용할 수 있지만 사용하지 않는 것을 권장합니다. 나만 읽을 수 있는 코드를 짜고 싶다면 말리지 않겠지만 나중에 내가 봐도 못 알아 볼 수 있습니다. 되도록이면 단일 표현식 혹은 메소드를 호출합니다.

 

명령문 When

위 코드를 명령문으로 수정해보겠습니다.

fun whatToDo(dayOfWeek: Any) = when (dayOfWeek) {
    "Saturday", "Sunday" -> println("Relax")
    in listOf("Monday", "Tuesday", "Wednesday", "Thursday") -> println("Work hard")
    in 2..4 -> println("Work hard")
    "Friday" -> println("Party")
    is String -> println("What?")
//    else -> println("No clue")
}

println"Sunday")  // Relax
println("Wednesday")  // Work hard
println(3)  // Work hard
println("Friday")  // Party
println("Munday")  // What?
println(8)  // No clue

When을 명령문으로 사용하면 else는 필수가 아닙니다.

 

When과 변수의 스코프

when 명령문 혹은 표현식에 사용되는 변수는 외부에서 전달받지 않아도 됩니다. 

// not bad.. not good..
fun systemInfo1(): String {
    val numberOfCores = Runtime.getRuntime().availableProcessors()  
    return when (numberOfCores) {  // 내부 변수 사용
        1 -> "1 core, packing....."
        in 2..16 -> "You have $numberOfCores cores"
        else -> "$numberOfCores cores!, I wan..."
    }
}

 

위 코드를 더 개선해보자

// good!!
fun systemInfo2(): String {
    return when (val numberOfCores = Runtime.getRuntime().availableProcessors()) {
        1 -> "1 core, packing....."
        in 2..16 -> "You have $numberOfCores cores"
        else -> "$numberOfCores cores!, I wan..."
    }
}

 

정리

- 코틀린의 명령형 반복은 다른 주요 언어들의 반복보다 더 풍부한 기능과 표현을 제공
- 틀별한 클래스인 범위를 이용해서 높은 레벨의 추상화를 제공. 그리고 범위를 이용해서 정방향/역방향 반복, 스킵 등을 쉽게 만들어 줌
- 콜렉션에서의 반복도 역시 마찬가지!
- when이 만들어주는 전달인자 매칭 문법이 기존의 조건문을 사용할 때 딸려오는 코드의 노이즈를 제거한다.

반응형