Expressões contextuais e omitidas

As expressões contextuais são expressões que só são válidas em determinados contextos, como a utilização de nomes de itens em expressões de cópia e atualização sem ter de as qualificar.

As expressões podem ser omitidas quando podem ser inferidas e inseridas automaticamente pelo compilador, por exemplo, no caso de instruções de avaliação e reatribuição.

Os intervalos abertos são outro exemplo que se aplica a expressões contextuais e omitidas. São válidas apenas num determinado contexto e o compilador traduz-as em expressões normais Range durante a compilação ao inferir limites adequados.

Um valor do tipo Range gera uma sequência de números inteiros, especificada por um valor inicial, um valor de passo (opcional) e um valor final. Por exemplo, a Range expressão 1..3 literal gera a sequência 1,2,3. Da mesma forma, a expressão 3..-1..1 gera a sequência 3,2,1. Também pode utilizar intervalos para criar uma nova matriz a partir de uma existente ao cortar, por exemplo:

    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]

Não é possível definir um intervalo infinito em Q#; os valores de início e de fim têm sempre de ser especificados. A única exceção é quando utiliza uma Range para segmentar uma matriz. Nesse caso, os valores de início ou de fim do intervalo podem ser razoavelmente inferidos pelo compilador.

Nos exemplos anteriores de corte de matriz, é razoável que o compilador assuma que o fim do intervalo pretendido deve ser o índice do último item na matriz se o tamanho do passo for positivo. Se o tamanho do passo for negativo, é provável que a extremidade do intervalo seja o índice do primeiro item na matriz. 0 O converse mantém-se para o início do intervalo.

Para resumir, se omitir o valor de início do intervalo, o valor inicial inferido

  • é zero se não for especificado nenhum passo ou se o passo especificado for positivo.
  • é o comprimento da matriz menos uma se o passo especificado for negativo.

Se omitir o valor final do intervalo, o valor final inferido

  • é o comprimento da matriz menos um se não for especificado nenhum passo ou se o passo especificado for positivo.
  • é zero se o passo especificado for negativo.

Q# assim, permite a utilização de intervalos abertos dentro de expressões de corte de matriz, por exemplo:

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

Uma vez que a determinação de se o passo de intervalo é positivo ou negativo ocorre no runtime, o compilador insere uma expressão adequada que será avaliada no runtime. Para valores finais omitidos, a expressão inserida é step < 0 ? 0 | Length(arr)-1, e para valores de início omitidos é step < 0 ? Length(arr)-1 | 0, onde step está a expressão indicada para o passo de intervalo ou 1 se não for especificado nenhum passo.