Expressões contextuais e omitidas
Expressões contextuais são expressões que só são válidas em determinados contextos, como o uso de nomes de itens em expressões de copiar e atualizar sem ter que qualificá-las.
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. 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 de 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 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. Você também pode usar intervalos para criar uma nova matriz a partir de uma existente fatiando, 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 fim sempre precisam ser especificados. A única exceção é quando você usa um Range
para fatiar uma matriz. Nesse caso, os valores iniciais ou finais do intervalo podem ser razoavelmente inferidos pelo compilador.
Nos exemplos de fatiamento de matriz anteriores, é razoável para o compilador assumir que o final do intervalo pretendido deve ser o índice do último item na matriz se o tamanho da etapa for positivo. Se o tamanho da etapa for negativo, então o final do intervalo provavelmente deve ser o índice do primeiro item na matriz, 0
. O inverso vale para o início do intervalo.
Para resumir, se você omitir o valor inicial do intervalo, o valor inicial inferido
- é zero se nenhuma etapa for especificada ou se a etapa especificada for positiva.
- é o comprimento da matriz menos um se a etapa especificada for negativa.
Se você omitir o valor final do intervalo, o valor final inferido
- é o comprimento da matriz menos um se nenhuma etapa for especificada ou se a etapa especificada for positiva.
- é zero se a etapa especificada for negativa.
Q# portanto, permite o uso de intervalos abertos dentro de expressões de fatiamento 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];
Como a determinação se a etapa do intervalo é positiva ou negativa acontece no tempo de execução, o compilador insere uma expressão adequada que será avaliada no tempo de execução. Para valores finais omitidos, a expressão inserida é step < 0 ? 0 | Length(arr)-1
, e para valores iniciais omitidos é step < 0 ? Length(arr)-1 | 0
, onde step
é a expressão dada para a etapa do intervalo ou 1
se nenhuma etapa for especificada.