Today I Learned

외부 반복과 아큐먼트 매칭 본문

Kotlin/다재다능 코틀린 프로그래밍

외부 반복과 아큐먼트 매칭

하이라이터 2023. 7. 21. 14:49
728x90

범위와 반복

레인지 클래스

  • 코틀린은 특정 범위의 값들을 반복하기 위해서 특화된 클래스들로 추상수준을 올렸다.
val oneToFive: IntRange = 1..5
val aToE: CharRange = 'a'..'e'
val seekHelp: ClosedRange<String> = "hell".."help"

 

정방향 반복

  • for(x in ..) 문법을 이용해서 반복문을 수행할 수 있으며, 반목문 안의 변수는 var이 아닌 val로 선언된다.
for (i in 1..5) { print("$i, ") } //1, 2, 3, 4, 5,
for (ch in 'a'..'e') { print(ch) } //abced
  • ClosedRange<T>에는 iterator()가 없기 때문에 반복문으로 사용할 수 없다.
for (word in "hell".."help") { print("$word, ") } //ERROR

 

후방향 반복

  •  5..1로 범위를 만드려하면 동작하지 않는다. 이때는 downTo() 메소드를 사용하면 된다.
for (i in 5.downTo(1)) { print("$i, ") } //5, 4, 3, 2, 1,
  • 중위표기법(infix notaion)을 사용하면 코드를 더 읽기 쉽게 만들 수 있다.
for (i in 5 downTo 1) { print("$i, ") } //5, 4, 3, 2, 1,

 

범위 안의 값 건너뛰기

  • 숫자 범위를 반복할 때 마지막 값을 건너뛰려면 until()을 이용해서 범위를 만들면 된다.
for (i in 1 until 5) { print("$i, ") } //1, 2, 3, 4,
  • c언어에서 사용하는 i=i+3 같은 식으로 값을 건너뛰려면 step() 메소드를 제공한다.
for(i in 1 until 10 step 3) { print("$i, ") } //1, 4, 7,
  • 3의 배수이거나 5의 배수만 반복 같이 순차적이지 않은 방법으로 값을 건너뛰고 싶다면 filter() 메소드를 사용하면 된다.
for (i in (1..9).filter {it % 3 == 0 || it % 5 == 0}) {
  print("$i, ") } //3, 5, 6, 9,
}

 

 

배열과 리스트의 반복

  • arrayOf() 함수를 사용해서 배열을 생성하고 for문으로 배열을 반복할 수 있다.
val array = arrayOf(1, 2, 3)
for (e in array) { print("$e, ") } //1, 2, 3,
  • 비슷하게 listOf() 함수를 이용해서 List<T>의 인스턴스를 만들고, for문으로 반복할 수 있다.
val list = listOf(1, 2, 3)
for (e in list) { print("$e, ") }
  • 값과 인덱스가 함께 필요한 반복문에서는 다음과 같이 사용할 수 있다.
val names = listOf("Tom", "Jerry", "Spike")
for (index in names.indices) {
  println("Position of ${names.get(index} is $index ")
}
  • withIndex() 함수를 사용해서 인덱스와 위치를 한번에 얻을 수도 있다.
for ((index, name) in names.withIndex()) {
  println("Position of $name is $index ")
}

 

when을 사용해야 할 때

  • 코틀린에서는 switch 문 대신에 when이 있다. when은 표현식으로 사용할때와 명령문으로 사용할 때 각각 다르게 쓰인다.

표현식으로서의 when

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을 사용해서 리팩토링하면 다음과 같다.
fun isAlive(alive: Boolean, numberOfLiveNeighbors: Int) = when {
  numberOfLiveNeighbors < 2 -> false
  numberOfLiveNeighbors > 3 -> false
  numberOfLiveNeighbors == 3 -> true
  else -> alive && numberOfLiveNeighbors == 2
}
  • 리턴타입은 타입추론을 이용하게 하고 단일 표현식 함수 문법을 사용했다. 함수에 의해서 리턴되는 값은 when 안의 하나의 표현식에서 나온 값이다.
  • 코틀린 컴파일러는 else 부분이 존재하는지 표현식이 가능한 모든 입력에 대해 값을 생성하는지 검증한다.
  • when에는 값이나 표현식을 전달할 수 있다. 다음 예제는 when에 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

  • 하나 이상의 값에 기반해서 다른 동작을 원한다면 when을 표현식이 아니라 명령문으로 사용하면 된다.
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?")
  }
}

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)) //
  • when이 명령문으로 사용될 때는 else가 없어도 상관없다. 적합한 조건이 없다면 아무런 행동도 하지 않는다.

 

when과 변수의 스코프

fun systemInfo(): String {
  val numberOfCores = Runtime.getRuntime().availableProcessors()
  return when (numberOfCores) {
    1 -> "1 core"
    in 2..16 -> "You have $numbersOfCores cores"
    else -> "$numberOfCores cores!"
  }
}
  • 위 함수는 Runtime의 availableProcessors() 메소드를 이용해서 코어의 숫자를 파악해야 한다. 그리고 코어의 숫자를 담은 변수를 평가하기 위해서 when에 전달된다.
fun systemInfo(): String =
  when (numberOfCores = Runtime.getRuntime().availableProcessors()) {
    1 -> "1 core"
    in 2..16 -> "You have $numbersOfCores cores"
    else -> "$numberOfCores cores!"
  }
  • val을 when의 인자로 넣어버리면 덜 복잡한 짧은 코드를 만들 수 있고, numberOfCores 변수가 when의 결과를 얻을 때만 사용 가능해서 변수의 스코프를 제한할 수 있다.
728x90
Comments