Expressões contextuais e omitidas
As expressões contextuais são válidas apenas em determinados contextos, como no uso de nomes de item em expressões de cópia e atualização sem necessidade de qualificação.
Além disso, as expressões podem ser omitidas quando podem ser inferidas e inseridas automaticamente pelo compilador, como é o caso nas instruções de avaliação e reatribuição.
Os intervalos abertos são outro exemplo que se aplicam a expressões contextuais e omitidas. Eles são válidos apenas dentro de um determinado contexto, e o compilador os traduz em expressões normais Range
durante a compilação, inferindo limites adequados.
Um valor do tipo Range
gera uma sequência de inteiros, especificada por um valor inicial, um valor de etapa (opcional) e um valor final. Por exemplo, a expressão 1..3
do literal Range
gera a sequência 1,2,3. Da mesma forma, a expressão 3..-1..1
gera a sequência 3,2,1. Os intervalos também podem ser usados para criar uma matriz usando outra existente por divisão, 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 final sempre precisam ser especificados. A única exceção é quando você usa um Range
para dividir uma matriz. Nesse caso, o valor inicial ou final do intervalo pode ser inferido corretamente pelo compilador.
Nos exemplos de divisão de matriz anteriores, é plausível que o compilador assuma que o final do intervalo pretendido seja o índice do último item na matriz quando o tamanho da etapa é positivo. Quando o tamanho da etapa é negativo, o final do intervalo provavelmente é o índice do primeiro item na matriz, 0
. O inverso ocorre para o início do intervalo.
Para resumir, quando você omitir o valor inicial do intervalo, o valor inicial inferido
- será zero se não for especificada nenhuma etapa ou se a etapa especificada for positiva.
- será o comprimento da matriz menos um se a etapa especificada for negativa.
Quando você omitir o valor final do intervalo, o valor final inferido
- será o comprimento da matriz menos um se não for especificada nenhuma etapa ou se a etapa especificada for positiva.
- será zero se a etapa especificada for negativa.
Portanto, o Q# permite usar intervalos com final em aberto em expressões de divisão 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];
Em tempo de execução, é determinado se a etapa de intervalo é positiva ou negativa, portanto, o compilador insere uma expressão adequada que será avaliada em tempo de execução. Para valores finais omitidos, a expressão inserida é step < 0 ? 0 | Length(arr)-1
. Para valores iniciais omitidos, é step < 0 ? Length(arr)-1 | 0
, em que step
é a expressão fornecida para a etapa de intervalo ou 1
se nenhuma etapa é especificada.