Share via


Declarações e Reatribuições de Variáveis

Os valores podem ser vinculados a símbolos com as let instruções e mutable . Estes tipos de enlaces fornecem uma forma conveniente de aceder a um valor através da alça definida. Apesar da terminologia enganosa emprestada de outros idiomas, os identificadores declarados num âmbito local e que contêm valores são denominados variáveis. Isto pode ser enganador porque let as instruções definem identificadores de atribuição única, que são identificadores que permanecem vinculados ao mesmo valor durante a validade. As variáveis que podem ser novamente vinculadas a diferentes valores em diferentes pontos do código têm de ser explicitamente declaradas como tal e são especificadas com a mutable instrução .

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

Neste exemplo, a let instrução declara uma variável com o nome var1 que não pode ser reatribuída e contém sempre o valor 3. A mutable instrução define uma variável var2 que está temporariamente vinculada ao valor 3 , mas que pode ser reatribuída a um valor diferente mais tarde ao utilizar uma set instrução, conforme mostrado na última linha. Pode expressar a mesma instrução com a versão set var2 += 1;mais curta , como é comum noutros idiomas. Para obter mais informações, veja Avaliar e reatribuir instruções.

Para resumir:

  • let é utilizado para criar um enlace imutável.
  • mutable é utilizado para criar um enlace mutável.
  • set é utilizado para alterar o valor de um enlace mutável.

Para as três instruções, o lado esquerdo consiste num símbolo ou numa cadeia de identificação de símbolos. Se o lado direito do enlace for uma cadeia de identificação, essa cadeia de identificação poderá estar totalmente ou parcialmente desconstruída após a atribuição. O único requisito para a desconstrução é que a forma da cadeia de identificação no lado direito corresponda à forma da cadeia de identificação de símbolos no lado esquerdo. A cadeia de identificação de símbolos pode conter cadeias de identificação aninhadas ou símbolos omitidos, ou ambos, indicados por um caráter de sublinhado. Por exemplo:

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]

Todas as atribuições em Q# obedecem às mesmas regras de desconstrução, incluindo, por exemplo, atribuições de qubits e atribuições de variáveis de ciclo.

Para ambos os tipos de enlaces, os tipos de variáveis são inferidos a partir do lado direito do enlace. O tipo de uma variável permanece sempre o mesmo e uma set instrução não pode alterá-la. As variáveis locais podem ser declaradas como mutáveis ou imutáveis. Existem algumas exceções, como variáveis de ciclo em ciclos, em for que o comportamento é predefinido e não pode ser especificado. Os argumentos de função e operação estão sempre imutavelmente vinculados. Em combinação com a falta de tipos de referência, conforme abordado no tópico Imutabilidade , isto significa que uma função ou operação chamada nunca pode alterar quaisquer valores do lado do autor da chamada.

Uma vez que os estados dos Qubit valores não são definidos ou observáveis a partir de dentro Q#do , tal não impede a acumulação de efeitos colaterais quânticos, que são observáveis apenas através de medições. Para obter mais informações, veja Quantum data types (Tipos de dados quânticos).

Independentemente da forma como um valor está vinculado, os valores em si são imutáveis. Em particular, isto aplica-se a matrizes e itens de matriz. Ao contrário das linguagens clássicas populares em que as matrizes são frequentemente tipos de referência, as matrizes em Q# - como todos os tipos - são tipos de valor e sempre imutáveis; ou seja, não pode modificá-las após a inicialização. Alterar os valores acedidos por variáveis de tipo de matriz requer, assim, construir explicitamente uma nova matriz e reatribuí-la ao mesmo símbolo. Para obter mais informações, veja Imutability (Imutabilidade) e Copy and update expressions (Expressões de cópia e atualização).

Instruções evaluate-and-reassign

As instruções do formulário set intValue += 1; são comuns em muitos outros idiomas. Aqui, intValue tem de ser uma variável vinculada de forma silenciosa do tipo Int. Estas instruções proporcionam uma forma conveniente de concatenação se o lado direito consistir em aplicar um operador binário e o resultado for a recuperação para o argumento esquerdo do operador. Por exemplo, este segmento de código

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

incrementa o valor do contador counter em cada iteração do for ciclo e é equivalente a

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

Existem instruções semelhantes para um vasto leque de operadores. A set palavra-chave nessas instruções evaluate-and-reassign tem de ser seguida por uma única variável mutável, que é inserida como a subexpressão mais à esquerda pelo compilador. Essas instruções evaluate-and-reassign existem para todos os operadores em que o tipo da subexpressão mais à esquerda corresponde ao tipo de expressão. Mais precisamente, estão disponíveis para operadores binários lógicos e bits, incluindo a mudança para a direita e para a esquerda, expressões aritméticas, incluindo exponenciação e modulus, e concatenações, bem como expressões de cópia e atualização.

O exemplo de função seguinte calcula a soma de uma matriz de Complex números:

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;
}

Da mesma forma, a seguinte função multiplica cada item numa matriz com o fator especificado:

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;
}

Para obter mais informações, veja Expressões contextuais, que contêm outros exemplos em que as expressões podem ser omitidas num contexto específico quando uma expressão adequada pode ser inferida pelo compilador.