컨텍스트 식 및 생략된 식
컨텍스트 식은 특정 컨텍스트에서만 유효한 식입니다. 예를 들어 복사 및 업데이트 식에서 항목 이름을 사용할 때처럼 정규화하지 않아도 됩니다.
평가 및 재할당 문의 경우처럼 컴파일러에서 유추하고 자동으로 삽입할 수 있는 경우 식을 생략할 수 있습니다.
개방형 범위는 컨텍스트 식과 생략된 식 모두에 적용되는 또 다른 예입니다. 특정 컨텍스트 내에서만 유효하며 컴파일러는 적절한 경계를 유추하여 컴파일 중에 정규 Range
식으로 변환합니다.
Range
형식의 값은 시작 값, 단계 값(선택 사항) 및 끝 값으로 지정된 정수 시퀀스를 생성합니다. 예를 들어 Range
리터럴 식 1..3
은 시퀀스 1,2,3을 생성합니다. 마찬가지로 3..-1..1
식은 시퀀스 3,2,1을 생성합니다. 범위는 기존 배열을 조각화하여 새 배열을 만드는 데에도 사용할 수 있으며, 예를 들면 다음과 같습니다.
let arr = [1,2,3,4];
let slice1 = arr[1..2..4]; // contains [2,4]
let slice2 = arr[2..-1..0]; // contains [3,2,1]
Q#에서는 무한 범위를 정의할 수 없습니다. 항상 시작 값과 끝 값을 지정해야 합니다. 유일한 예외는 Range
를 사용하여 배열을 조각화하는 경우입니다. 이 경우에는 범위의 시작 또는 끝 값을 컴파일러가 합리적으로 유추할 수 있습니다.
이전 배열 조각화 예제를 보면, 단계 크기가 양수인 경우 컴파일러는 의도한 범위 끝이 배열의 마지막 항목 인덱스여야 한다고 가정하는 것이 타당합니다. 단계 끝이 음수이면 범위 끝은 배열의 첫 번째 항목 인덱스인 0
일 가능성이 높습니다. 그 반대는 범위 시작에 대해 적용됩니다.
요약하자면, 범위 시작 값을 생략하는 경우 유추되는 시작 값은
- 지정된 단계가 없거나 지정된 단계가 양수이면 0입니다.
- 지정된 단계가 음수이면 배열 길이에서 1을 뺀 값입니다.
범위 끝 값을 생략하는 경우 유추되는 끝 값은
- 지정된 단계가 없거나 지정된 단계가 양수이면 배열 길이에서 1을 뺀 값입니다.
- 지정된 단계가 음수이면 0입니다.
따라서 Q#에서는 다음 예제와 같이 배열 조각화 식 내에서 개방형 범위 사용을 허용합니다.
let arr = [1,2,3,4,5,6];
let slice1 = arr[3...]; // slice1 is [4,5,6];
let slice2 = arr[0..2...]; // slice2 is [1,3,5];
let slice3 = arr[...2]; // slice3 is [1,2,3];
let slice4 = arr[...2..3]; // slice4 is [1,3];
let slice5 = arr[...2...]; // slice5 is [1,3,5];
let slice7 = arr[4..-2...]; // slice7 is [5,3,1];
let slice8 = arr[...-1..3]; // slice8 is [6,5,4];
let slice9 = arr[...-1...]; // slice9 is [6,5,4,3,2,1];
let slice10 = arr[...]; // slice10 is [1,2,3,4,5,6];
범위 단계가 양수인지 아니면 음수인지 확인하는 절차는 런타임에 수행되므로, 컴파일러는 런타임에 평가될 적절한 식을 삽입합니다. 생략된 끝 값의 경우 삽입된 식은 step < 0 ? 0 | Length(arr)-1
, 생략된 시작 값의 경우에는 step < 0 ? Length(arr)-1 | 0
입니다. 여기서 step
은 범위 단계에 대해 지정된 식이며 단계를 지정하지 않은 경우 1
입니다.