Wyrażenia kontekstowe i pominięte
Wyrażenia kontekstowe to wyrażenia, które są prawidłowe tylko w niektórych kontekstach, takich jak użycie nazw elementów w wyrażeniach kopiowania i aktualizacji bez konieczności ich kwalifikowania.
Wyrażenia można pominąć , gdy można je wywnioskować i automatycznie wstawić przez kompilator, na przykład w przypadku instrukcji evaluate-and-reassign.
Zakresy otwarte to kolejny przykład, który ma zastosowanie zarówno do wyrażeń kontekstowych, jak i pominiętych. Są one prawidłowe tylko w określonym kontekście, a kompilator tłumaczy je na wyrażenia normalne Range
podczas kompilacji, wnioskowając odpowiednie granice.
Wartość typu Range
generuje sekwencję liczb całkowitych określoną przez wartość początkową, wartość kroku (opcjonalnie) i wartość końcową. Na przykład Range
wyrażenie 1..3
literału generuje sekwencję 1,2,3. Podobnie wyrażenie 3..-1..1
generuje sekwencję 3,2,1. Za pomocą zakresów można również utworzyć nową tablicę na podstawie istniejącej, na przykład fragmentując:
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]
Nie można zdefiniować nieskończonego zakresu w elem Q#. Zawsze należy określić wartości początkowe i końcowe. Jedynym wyjątkiem jest użycie obiektu Range
w celu wycinek tablicy. W takim przypadku wartości początkowe lub końcowe zakresu można rozsądnie wywnioskować przez kompilator.
W poprzednich przykładach fragmentowania tablicy uzasadnione jest założenie, że docelowy koniec zakresu powinien być indeksem ostatniego elementu w tablicy, jeśli rozmiar kroku jest dodatni. Jeśli rozmiar kroku jest ujemny, zakres prawdopodobnie powinien być indeksem pierwszego elementu w tablicy . 0
Odwrotność zawiera początek zakresu.
Podsumowując, jeśli pominięto wartość początkową zakresu, wnioskowana wartość początkowa
- jest zero, jeśli nie określono żadnego kroku lub określony krok jest dodatni.
- jest długością tablicy minus jeden, jeśli określony krok jest ujemny.
Jeśli pominięto wartość końcową zakresu, wnioskowana wartość końcowa
- jest długością tablicy minus jeden, jeśli nie określono żadnego kroku lub określony krok jest dodatni.
- wartość zero, jeśli określony krok jest ujemny.
Q# w związku z tym umożliwia użycie zakresów otwartych w wyrażeniach fragmentowania tablicy, na przykład:
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];
Ponieważ określenie, czy krok zakresu jest pozytywny, czy negatywny występuje w czasie wykonywania, kompilator wstawia odpowiednie wyrażenie, które będzie oceniane w czasie wykonywania. W przypadku pominiętych wartości końcowych wstawione wyrażenie to step < 0 ? 0 | Length(arr)-1
, a dla pominiętych wartości początkowych to step < 0 ? Length(arr)-1 | 0
, gdzie step
jest to wyrażenie podane dla kroku zakresu lub 1
jeśli nie określono żadnego kroku.