Kotlin

1. 범위와 반복

1.1. Ranges 클래스

  • kotlin.ranges 를 사용한다.
  • 특정 범위 값들을 반복하기 위해 사용한다.

 

// ranges.kts

// val oneToFive: IntRange = 1..5
// val aToE: CharRange = 'a'..'e'
val seekHelp: ClosedRange<String> = "hell".."help"

println(seekHelp.contains("helm")) //true
println(seekHelp.contains("helq")) //false

 

위 코드에서 helm은 hell 과 help 사이에 존재하는 값임을 알 수 있다.

 

1.2. 정방향 반복

  • for (x in ..) 문법을 이용하여 반복수행이 가능함
// ranges2.kts

// for (i in 1..5) { print("$i, ")}
// for (ch in 'a'..'e') { print("$ch, ")}
// for (word in "hell".."help") { print("$word, ")} //에러 발생

 

ClosedRange<String>에는 iterator() 가 없기 때문에 나중에 객체를 반복하는 확장 함수를 만들 수 있다고 함..

 

1.3. 후방향 반복

  • 정방향(증가) 반복과 반대로 후방향(감소) 반복을 할 수 있다.

 

// reverse.kts

// downTo 메소드 호출
for (i in 5.downTo(1)) { print("$i, ")}

print("\n")

// .과 괄호 생략
for (i in 5 downTo 1) { print("$i, ")}

 

1.4. 범위 안의 값 건너뛰기

  • until() 을 이용해서 범위를 만들면 된다.
  • until() 은 마지막 값을 포함시키지 않는다.
// skipvalues.kts

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

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

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

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

 

2. 배열과 리스트의 반복

  • kotlin 패키지에 포함된 arrayOf() 함수를 사용한다.
  • Int 배열은 intArrayOf() 함수를 사용한다.
  • List<T> 의 인스턴스를 listOf() 함수를 이용해서 만들고, for문을 이용해서 반복할 수 있다.
  • listOf() 를 사용할 경우, 인덱스도 얻을 수 있다.

 

// iterate.kts

//val array = arrayOf(1, 2, 3)
val array = intArrayOf(1, 2, 3)

for (e in array) { print("$e, ")} // 1, 2, 3,

println();

val list = listOf(1, 2, 3)

println(list.javaClass) // class java.util.Arrays$ArrayList
for (e in list) { print("$e, ")} // 1, 2, 3,

 

// index.kts

val names = listOf("Tom", "Jerry", "Spike")

for (index in names.indices) {
    println("Position of ${names.get(index)} is $index")
}

 

구조 분해의 withIndex() 함수를 이용할 수 있다.

 

// withIndex.kts

val names = listOf("foo", "bar", "foobar")

for ((index, name) in names.withIndex()) {
    println("Position of $name is $index")
}

 

3. when 을 사용해야 할 때

  • 코틀린에는 switch 문이 없고 대신 when 이 있음

 

3.1. 표현식으로서의 when

  • when은 if의 확장된 버전 쯤으로 인식하면 될 것 같다.
  • 인자 값이나 표현식을 전달할 수도 있다.

 

// when.kts

/* 기존 if 문
fun isAlive(alive: Boolean, numberOfLiveNeighbors: Int): Boolean {
    if (numberOfLiveNeighbors < 2) { return false}
    if (numberOfLiveNeighbors > 3) { return false}
}
*/

// when 사용
fun isAlive(alive: Boolean, numberOfLiveNeighbors: Int) = when {
    numberOfLiveNeighbors < 2 -> false
    numberOfLiveNeighbors > 3 -> false
    numberOfLiveNeighbors == 3 -> true
    else -> alive && numberOfLiveNeighbors == 2
}

/* 리팩토링
fun isAlive(alive: Boolean, numberOfLiveNeighbors: Int) = alive && numberOfLiveNeighbors == 2 || numberOfLiveNeighbors == 3
*/

isAlive(true, 3)

 

요일별 출력 (해당 예제에서는 예시를 위해 Any 타입을 사용했지만, 최대한 쓰지 않아야 한다고 함)

 

// activity.kts

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

 

3.2. 명령문으로써의 when

  • 위의 함수에서 when을 명령문으로 사용할 수도 있다.
  • 리턴 타입이 명시되어 있지 않으면 Unit 타입으로 리턴된다.

 

// printActivity.kts

fun printWhatToDo(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?")
    }
}

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

 

3.3 when 과 변수의 스코프

  • val 을 when 의 인자로 넣어서 조금이나마 덜 복잡한 코드를 만들 수 있지만, 이후 연산에서는 사용이 불가능한 일회용 변수가 된다.

 

// cores.kts

/*
fun systemInfo(): String {
    val numberOfCores = Runtime.getRuntime().availableProcessors()
    return when (numberOfCores) {
        1 -> "1 core, packing this one to the museum"
        in 2..16 -> "You have $numberOfCores cores"
        else -> "$numberOfCores cores!, I want your machine"
    }
}
*/

fun systemInfo(): String = when (val numberOfCores = Runtime.getRuntime().availableProcessors()) {
    1 -> "1 core, packing this one to the museum"
    in 2..16 -> "You have $numberOfCores cores"
    else -> "$numberOfCores cores!, I want your machine"
}

systemInfo()