Kotlin - 4. Iterator

2021/10/14
language

Iterator, Argument matching

코틀린은 기존 다른 언어의 상태기반의 for 문은 제공하지 않습니다.
모든 for문은 자바의 foreach 형태의 for문 만을 지원합니다. 그럼 단순 반복은 어떻게 할 수 있을까요?

Range

코틀린은 Range로 범위를 표시할 수 있습니다.

1
1..5.forEach {println(it)}

.. 는 1 부터 5까지 1씩 증가하는 IntRange 객체를 만드는 함수 입니다.

IntRange 는 아래의 구조로 되어 있습니다.

1
class IntRange : IntProgression, ClosedRange<Int>

IntProgressing 은 start(시작값), last(끝값), step(건너뛰는 정도의 값)을 가지는 구조체이고 ClosedRange 는 시작값과 끝값을 표현하는 범위표시를 위한 객체입니다. 말그대로 범위를 표시하기 위한 모든 정보가 포함된 객체로 생각하시면 됩니다.

이 Range는 in 연산자(혹은 contains)를 이용해 특정 값이 range 에 포함되어 있는지 체크할 수 있고, for 문에서 블록내 변수에 값을 할당 할 수도 있습니다.

1
if (3 in 1..5) println("true")

또한 range 는 단순 정수 형 뿐만아니라 String 에도 적용이 가능합니다.

range 종류

오름차순의 반복을 원한다면 위에서 사용한 .. 연산자를 사용하면 됩니다. 다만 이 연산자는 끝값을 포함하는 범위이기 때문에, 끝값을 제외한 범위를 원하는 경우 until 함수로 대체 할 수 있습니다.

1
2
3
for (i in 1 until 10) {       // i in [1, 10), 10 is excluded
print(i)
}

내림 차순의 반복을 원하는 경우 downTo 라는 함수를 사용 할 수 있습니다.

1
for (i in 4 downTo 1) print(i)

기본적으로는 반복되는 값은 1 씩 변경이 됩니다. 하지만 1이상 만큼 변화를 원한다면 step 함수로 조절 가능합니다.

1
2
3
4
for (i in 1..8 step 2) print(i) // 1357
println()
for (i in 8 downTo 1 step 2) print(i) // 8642
println()

Collection 반복

코틀린에서 컬렉션의 반복은 자바의 foreach 와 동일합니다.

1
2
3
4
5
val param = listOf(1,2,3)
for (x in param) {
print(x)
}
println() // 1,2,3

다만 리스트는 단순 반복 외에 추가로 현재의 인덱스를 가져오게 할 수도 있습니다.

1
2
3
for ((idx, num) in nums.withIndex()) { // 
println ("$idx -> $num")
}

withIndex 함수는 Iterable<IndextedValue<T>> 를 반환 하는 함수로 각 엘리먼트를 IndexedValue 클래스로 감싸 반복문을 실행하게 해줍니다.

When

코틀린에는 switch 문이 없습니다. 대신 더 많은 기능을 지원하는 when 을 사용할 수 있습니다. when은 if 처럼 표현식으로 사용할 수 도 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// for variable
val msg = when (a) {
1 -> "one"
in 2..3 -> "two or three"
else -> "bigger than three"
}

// for expression
val msg2 = when {
a == 1 -> "a is one"
b in 2..3 -> "b is two or three"
c.isEmpty() -> "c is empty"
else -> "anything else"
}

위 코드처럼 when자체를 표현식으로 사용하면서 내부의 조건문 역시 단일 표현식으로 사용 할 수 있습니다. 그리고 예제의 when은 string 객체를 리턴하지만 아래와 같이 unit 을 리턴하는 형태로도 사용할 수 있습니다. 이런 경우 else는 생략 가능합니다.

1
2
3
4
5
when {
a == 1 -> println("a is one")
b in 2..3 -> println("b is two or three")
c.isEmpty() -> println("c is empty")
}

그리고 when 블록에서 사용가능한 변수도 정의 할 수 있습니다.

1
2
3
4
5
6
7
8
val a = someFunction()
val msg = when (a) {
1 -> "one"
in 2..3 -> "two or three"
else -> "bigger than three"
}

// a isn't use anymore

위 예시처럼 when 만을 위해 특정 변수를 만들어 사용해야하는 경우에는 아래와 같이 더 간략화 할 수 있습니다.

1
2
3
4
5
val msg = when (val a = someFunction()) {
1 -> "one"
in 2..3 -> "two or three"
else -> "bigger than three"
}

when의 변수자리에 단일표현식으로 리턴되는 값을 사용하는 변수를 만들고 when블록 내에서 사용할 수 있습니다. 별거 아닌것처럼 보이지만 이걸 함수에서 사용한다면 블록으로 구현해야할 코드를 단일 표현식으로 줄일 수 있다는 장점이 있습니다.

출처

  • 다재다능 코틀린 프로그래밍
  • 코틀린 공식 문서