Autor: Bob Duff, AdaCore
Temat: Perełka Ady #2 — Notacja <> może być wykorzystana w agregatach to uzyskania domniemanej wartości poszczególnych składowych.
Zaczynamy ...
Z poprzedniej perełki wiemy już, że Ada 2005 zezwala na agregaty w przypadku typów ograniczonych. Taki agregat musi być użyty do inicjalizacji pewnych obiektów (wśród których mamy przekazywanie parametrów, w którym to przypadku inicjalizujemy parametry formalne). Agregaty ograniczone mają cechę "wbudowane w miejscu" w obiekcie będącym inicjalizowanym.
Oto przykład:
type Limited_Person is limited record Self : Limited_Person_Access := Limited_Person'Unchecked_Access; Name : Unbounded_String; Age : Natural; Shoe_Size : Positive; end record; X : aliased Limited_Person := (Self => null, -- Źle! Name => To_Unbounded_String (”John Doe”), Age => 25, Shoe_Size => 10); X.Self := X’Access;
Jest dosyć niewygodnym ustalać wartość Self na wartość złą (null), a następnie poprawianie tego. Irytującym jest również, że mamy (poprawną) domniemaną wartość dla Self, lecz w Adzie 95 nie możemy używać w agregatach wartości domniemanych. Ada 2005 wzbogaca składnię agregatów - "<>" oznacza: "skorzystaj z wartości domniemanej, jeśli takowa jest".
Teraz możemy zapisać:
X : aliased Limited_Person := (Self => <> Name => To_Unbounded_String (”John Doe”), Age => 25, Shoe_Size => 10)
Zapis "Self => <>" oznacza wykorzystanie wartości domniemanej Limited_Person'Unchecked_Access. Ponieważ Limited_Person pojawia się wewnątrz deklaracji typu, Self odwołuje się do "bieżącej instacji" typu, w naszym przypadku do X. Tak więc, ustalamy wartość X.Self na X'Unchecked_Access.
Notacja wykorzystująca zapis "<>" w agregatach może być niebezpieczna, gdyż może pozostawić pewne składowe niezainicjowane. "<>" oznacza: "wykorzystaj wartość domniemaną". Jeśli typ składowej jest skalarem i brak jest wartości domniemanej składowej rekordu, to wartość składowej pozostaje nieustalona.
Dla przykładu, jeśli mamy agregat typu String jak poniżej:
Uninitialized_String_Const : constant String := (1 .. 10 => <>);
otrzymujemy 10 znakowy łańcuch, którego wszystkie znaki mają nieprawidłową wartość. Zwróćmy uwagę, że jest to równie niebezpieczne jak:
Uninitialized_String_Var : String (1 .. 10); -- brak inicjalizacji Uninitialized_String_Const : constant String := Uninitialized_String_Var;
Wniosek: należy być bardzo ostrożnym w przypadku niezainicjowanych obiektów skalarnych.



