Typ podzakresowy (okrojony)


Typ podzakresowy (okrojony) reprezentuje podzbiór elementów innego typu porządkowego (nazywanego typem bazowym). Konstrukcje o postaci Low..High, gdzie Low i High są stałymi wyrażeniami tego samego typu porządkowego i Low jest mniejsze od High, oznaczają podzbiór zawierający wszystkie wartości od Low do High włącznie. Przykładowo, jeśli zadeklarowano typ wyliczeniowy:

type TDniTyg = (Pn, Wt, Sr, Cz, Pt, Sb, Nd);

można zdefiniować typ okrojony:

type TDniRob = Pn..Pt;

gdzie TDniRob zawiera wartości: Pn, Wt, Sr, Cz, Pt.

Można używać stałych numerycznych lub znakowych do definicji typów okrojonych:

type
  SomeNumbers = -128..127;
  Caps = 'A'..'Z';

W takich przypadkach, za typ bazowy uznawany jest najmniejszy typ całkowity lub znakowy zawierający wyspecyfikowany zakres.

Zapisu Low..High można użyć bezpośrednio w deklaracjach zmiennych. Np.:

var SomeNum: 1..500;

deklaruje zmienną całkowitą, której wartość może pochodzić z zakresu od 1 do 500.

Numeracja wartości w typie okrojonym jest zgodna z numeracją w typie bazowym. (w piewrwszym przykładzie, jeśli Dzien jest zmienną o wartości Sr, Ord(Dzien) zwraca 2 niezaleznie od tego, czy Dzien jest typu TDniTyg czy też TDniRob. Inkrementacja lub dekrementacja zmiennych typu okrojonego wykonywana jest wg informacji o typie bazowym. Stąd zapis:

type Percentile = 0..99;
var I: Percentile;
...
I := 100;

powoduje bład,

...
I := 99;
Inc(I);

podstawia wartość 100 pod I (jeśli nie jest aktywna opcja "range-checking" kompilatora).

Użycie stałych wyrażeń jako krańców zakresu może sprawiać trudności syntaktyczne. W dowolnym typie deklaracji, jeśli pierwszym znaczącym znakiem po "=" jest lewy nawias, kompilator uznaje, że definiowany jest typ wyliczeniowy. Dlatego kod:

const
  X = 50;
  Y = 10;
type
  Scale = (X - Y) * 2..(X + Y) * 2;

powoduje błąd. Obejściem problemu będzie zapis unikający znaku "(" jako pierwszego po znaku "=":

type 
  Scale = 2 * (X - Y)..(X + Y) * 2;