rokdocs
v0.1

3.7. 범위 표현식

범위 표현식은 .. 또는 ..= 토큰 (구두점과 연산자 토큰) 으로 시작해서 시작과 끝을 가지는 범위 값을 만들어 줍니다.

range_expr      ::= expr ".." expr        // half-open
                  | expr "..=" expr       // inclusive
                  | ".." expr             // from start
                  | "..=" expr            // from start, inclusive
                  | expr ".."             // unbounded end
                  | ".."                  // full

3.7.1. 여섯 가지 형태

범위 표현식은 다음과 같이 여섯 가지 형태로 쓸 수 있습니다.

0..10           // [0, 1, ..., 9]      배제 끝
0..=10          // [0, 1, ..., 10]     포함 끝
..10            // 0..10 과 동일       시작 생략 (전위)
..=10           // 0..=10 과 동일      시작 생략, 포함 끝
10..            // [10, 11, ...]       끝 생략, 무한
..              // 전체                양쪽 생략, 주로 슬라이싱에서

각 형태의 의미를 정리하면, .. 는 끝을 배제하는 반열림 구간을 만들고, ..= 는 끝을 포함합니다. 시작을 생략하면 0 이나 자료에 따른 기본값으로 처리되고, 끝을 생략하면 무한 또는 자료의 끝까지로 처리됩니다.

3.7.2. desugar

각 형태는 다음과 같이 표준 라이브러리 타입으로 desugar 됩니다.

a .. b          →   Range::new(a, b)
a ..= b         →   RangeInclusive::new(a, b)
.. b            →   RangeTo::new(b)
..= b           →   RangeToInclusive::new(b)
a ..            →   RangeFrom::new(a)
..              →   RangeFull

이 변환에 쓰이는 정확한 표준 라이브러리 트레잇과 타입은 라이브러리 사양에서 정의합니다. 본 문서는 언어가 여섯 형태를 별개의 표현식으로 인식하고 표준 라이브러리 타입의 인스턴스로 desugar 한다는 사실까지만 책임집니다.

3.7.3. 우선순위

우선순위와 결합성 의 등급에서 범위 연산자 (.., ..=) 는 prec=0 비결합으로, null 합체 (??, prec=1) 를 포함한 모든 이항 연산자보다 낮고 대입보다만 높습니다.

0..n + 1            →   0 .. (n + 1)        // + 가 .. 보다 강함
a ?? 0..3           →   (a ?? 0) .. 3       // ?? 가 .. 보다 강함
a..b..c             // ERROR: 범위 연산자는 비결합

이항 연산자 가운데 가장 약하게 묶이기 때문에, 시작과 끝에 산술 표현식을 넣어도 자연스럽게 읽힙니다.

호출 인자 안의 ..x

호출 인자 자리의 ..x 는 범위가 아니라 spread (4.2.6) 입니다. 그래서 f(..5) 는 5 를 펼치는 호출이며, RangeTo 를 넘기려면 괄호로 감쌉니다 (f((..5))). ..=x 는 spread 가 아니므로 인자 자리에서도 범위입니다 (f(..=5) 는 RangeToInclusive 를 넘김).

3.7.4. 사용처

반복

범위 값은 주로 반복문에서 사용됩니다.

for i in 0..10 { ... }

이 경우 범위 값을 루프 표현식 의 for 루프가 받아서 반복합니다. Range 와 RangeInclusive 가 trait 의 Iterator 트레잇을 구현하고 있으면 자동으로 반복됩니다.

슬라이싱과는 별개

슬라이싱과 범위 표현식은 서로 다른 표기라는 점을 유의해야 합니다.

arr[1:3]            // [인덱싱과 슬라이싱](306-indexing-and-slicing.md) 의 슬라이스, 콜론 (`:`) 사용
0..3                // 범위 값, 점 둘 (`..`) 사용

두 표기는 서로 다른 토큰이고 다른 의미를 가집니다. 슬라이싱은 인덱스 표현식의 내부 형태이고, 범위는 값 (Range 타입 인스턴스) 입니다.

패턴 매칭

범위 패턴 (패턴) 도 같은 토큰을 사용합니다. 의미는 그 자리에서 정의됩니다.

match x {
    1..=5 => ...,
    _ => ...,
}

3.7.5. step 은 메서드로

step (보폭) 은 표기 안에 두지 않습니다. 대신 표준 라이브러리의 .step_by(n) 메서드로 처리합니다.

(0..100).step_by(2)         // [0, 2, 4, ..., 98]

이 결정은 rok 의 일반적인 방향 (언어 syntax 는 단순하게 유지하고, 부가 기능은 메서드로 제공) 과 일관됩니다. 슬라이싱의 [::2] 는 별개 표기이며, 그 자리에는 step 이 자연스러워서 도입했습니다.

3.7.6. 역방향

반대 방향으로 반복하고 싶을 때는 .rev() 메서드를 사용합니다.

(0..10).rev()

범위 표기 자체에 음수 step 을 두지는 않습니다.

3.7.7. 빈 범위

시작이 끝보다 크면 빈 범위가 됩니다.

5..3            // 빈 범위, 정상 표현, 반복 시 0회
5..=3           // 빈 범위

이 경우 컴파일 에러가 아니라 반복 0회인 정상 값으로 처리됩니다. 0회 반복이 자연스러운 의미입니다.

3.7.8. 무한 범위의 사용

0.. 같은 열린 범위로 for 를 돌 수 있으며, 루프 안의 break 로 끝냅니다. 값이 타입의 최댓값을 넘으면 산술 overflow 와 같이 다룹니다 (검사가 켜져 있으면 panic).

for i in 0.. {
    if condition(i) { break; }
}

무한 반복 자체는 loop { ... } 와 등가이며, 사용 편의 차이만 있습니다.

GitHub에서 이 페이지 고치기