변수 선언 및 재할당

letmutable 문을 사용하여 값을 기호에 바인딩할 수 있습니다. 이러한 종류의 바인딩은 정의된 핸들을 통해 값에 액세스하는 편리한 방법을 제공합니다. 다른 언어에서 차용되어 오해의 소지가 있는 용어이긴 하지만 로컬 범위에서 선언되고 값을 포함하고 있는 핸들을 변수라고 합니다. let 문은 유효 기간 동안 동일한 값에 바인딩된 상태로 유지되는 핸들인 단일 할당 핸들을 정의하기 때문에 오해의 소지가 있습니다. 코드의 다른 지점에서 다른 값에 다시 바인딩할 수 있는 변수는 명시적으로 선언해야 하며, mutable 문을 사용하여 지정합니다.

    let var1 = 3; 
    mutable var2 = 3; 
    set var2 = var2 + 1; 

이 예제에서 let 문은 다시 할당할 수 없으며 항상 값 3을 포함하는 var1 변수를 선언합니다. mutable 문은 값 3에 일시적으로 바인딩되지만 마지막 줄에 표시된 것처럼 나중에 set 문을 사용하여 다른 값에 다시 할당할 수 있는 변수 var2를 정의합니다. 다른 언어에서 흔히 볼 수 있는 것처럼 더 짧은 set var2 += 1; 버전으로 동일한 문을 표현할 수 있습니다. 자세한 내용은 평가 및 재할당 문을 참조하세요.

요약:

  • let은 변경할 수 없는 바인딩을 만드는 데 사용됩니다.
  • mutable은 변경 가능한 바인딩을 만드는 데 사용됩니다.
  • set는 변경 가능한 바인딩의 값을 변경하는 데 사용됩니다.

세 문 모두 왼쪽은 기호 또는 기호 튜플로 구성됩니다. 바인딩의 오른쪽이 튜플이면 해당 튜플은 할당 시 전체 또는 일부가 분해될 수 있습니다. 분해를 위한 유일한 요구 사항은 오른쪽에 있는 튜플의 모양이 왼쪽에 있는 기호 튜플의 모양과 일치해야 한다는 것입니다. 기호 튜플은 밑줄로 표시된 중첩된 튜플, 생략된 기호 또는 둘 모두를 포함할 수 있습니다. 예를 들면 다음과 같습니다.

let (a, (_, b)) = (1, (2, 3)); // a is bound to 1, b is bound to 3
mutable (x, y) = ((1, 2), [3, 4]); // x is bound to (1, 2), y is bound to [3, 4]
set (x, _, y) = ((5, 6), 7, [8]);  // x is re-bound to (5,6), y is re-bound to [8]

큐비트 할당 및 루프 변수 할당을 포함하여 Q#의 모든 할당은 동일한 분해 규칙을 따릅니다.

두 가지 바인딩 모두 변수의 형식은 바인딩의 오른쪽에서 유추됩니다. 변수의 형식은 항상 동일하게 유지되며 set 문으로 형식을 변경할 수 없습니다. 지역 변수는 변경 가능하도록 또는 변경이 불가능하도록 선언할 수 있습니다. 동작이 미리 정의되어 있어서 지정할 수 없는 for 루프의 루프 변수와 같은 몇 가지 예외가 있습니다. 함수 및 연산 인수는 항상 변경할 수 없도록 바인딩됩니다. 이와 더불어 불변성 토픽에서 설명한 것처럼 참조 형식이 없기 때문에 호출된 함수 또는 연산이 호출자 쪽에서 값을 변경할 수 없습니다.

Qubit 값의 상태는 Q# 내에서 정의하거나 관찰할 수 없으므로, 측정을 통해서만 관찰할 수 있는 양자 부작용의 누적을 배제하지 않습니다. 자세한 내용은 Quantum 데이터 형식을 참조하세요.

값이 바인딩되는 방식에 관계없이 값 자체는 변경할 수 없습니다. 배열 및 배열 항목은 특히 그렇습니다. 배열이 참조 형식인 경우가 많은 자주 사용되는 클래식 언어와 달리, Q#의 배열은 모든 형식과 마찬가지로 값 형식이며 언제나 변경할 수 없습니다. 즉, 초기화 후에는 수정할 수 없습니다. 따라서 배열 형식의 변수가 액세스하는 값을 변경하려면 새 배열을 명시적으로 생성하고 동일한 기호에 다시 할당해야 합니다. 자세한 내용은 불변성복사 및 업데이트 식을 참조하세요.

평가 및 재할당 문

set intValue += 1; 형식의 문은 다른 많은 언어에서 일반적입니다. 여기서 intValueInt 형식의 변경 가능하게 바인딩된 변수여야 합니다. 오른쪽에는 이항 연산자가 적용되고 결과가 연산자의 왼쪽 인수에 다시 바인딩되는 경우 이러한 문은 편리한 연결 방법을 제공합니다. 예를 들어 다음 코드 세그먼트는

mutable counter = 0;
for i in 1 .. 2 .. 10 {
    set counter += 1;
    // ...
}

for 루프가 반복될 때마다 counter 카운터의 값을 증가시키며 다음 코드와 동일합니다.

mutable counter = 0;
for i in 1 .. 2 .. 10 {
    set counter = counter + 1;
    // ...
}

광범위한 연산자에 대해 유사한 문이 있습니다. 이러한 평가 및 재할당 문에서 set 키워드 뒤에는 변경 가능한 단일 변수가 와야 하며, 이 변수는 컴파일러에서 맨 왼쪽 하위 식으로 삽입됩니다. 이러한 평가 및 재할당 문은 맨 왼쪽 하위 식의 형식이 식 형식과 일치하는 모든 연산자에 대해 존재합니다. 보다 정확하게는 오른쪽 및 왼쪽 시프트를 포함한 이진 논리 및 비트 연산자, 지수 및 모듈러스를 포함한 산술 식, 연결 및 복사 및 업데이트 식에 사용할 수 있습니다.

다음 함수 예제는 Complex 숫자 배열의 합계를 컴퓨팅합니다.

function ComplexSum(values : Complex[]) : Complex {
    mutable res = Complex(0., 0.);
    for complex in values {
        set res w/= Re <- res::Re + complex::Re;
        set res w/= Im <- res::Im + complex::Im;
    }
    return res;
}

마찬가지로 다음 함수는 배열의 각 항목에 지정된 인수를 곱합니다.

function Multiplied(factor : Double, array : Double[]) : Double[] {
    mutable res = new Double[Length(array)];
    for i in IndexRange(res) {
        set res w/= i <- factor * array[i];
    }
    return res;
}

자세한 내용은 컨텍스트 식 섹션을 참조하세요. 이 섹션에는 컴파일러에서 적절한 식을 유추할 수 있는 경우 특정 컨텍스트에서 식을 생략할 수 있는 다른 예제가 포함되어 있습니다.