Trees Die VDM-Basistypen Maps

Optionals

 

Was sind Optionals ?

Definition Ein Optional  enthält entweder ein Objekt vom angegebenen Elementtyp oder einen besonderen Wert nil , der anzeigt, daß das Optional gerade kein gültiges Objekt enthält. Das Optional ist dann auch nicht vorhanden. Dies sind die beiden möglichen Interpretationen von nil, die in der Praxis benötigt werden.

Diese Formulierungen erinnern Sie vielleicht an den NULL-Pointer  in C, der gerade auf kein Objekt zeigt. Tatsächlich ist nil diesem NULL-Pointer sehr ähnlich, kann jedoch für beliebige Elementtypen eingerichtet werden; den NULL-Pointer gibt es eben nur für Pointer.

  Abstraktion! Wenn Sie den ungültigen Zustand eines beliebigen Objekts in einer Applikation modellieren wollen, machen Sie sich Gedanken, welche Werte in der Praxis auftreten können, also ,,gültige`` Zustände beschreiben; aus der Menge der übrigen Zustände wählen Sie dann einen heraus, der in der gesamten Applikation für die Modellierung eines ungültigen Objekts dienen soll. Das Optional hilft Ihnen dabei, die Konsistenz der Applikation zu wahren, indem Sie abstrahieren vom tatsächlichen Inhalt des Objekts, wenn es ungültig ist: Sie legen einmal, bei der Definition des Optionals mit der DSL, den Wert des Objekts fest, der nil repräsentieren soll -- in der Applikation können Sie dann die Optional-Operationen verwenden, ohne über den tatsächlichen ,,Wert`` von nil nachzudenken. Gerade bei vielen verschiedenen nil-Werten für verschiedene Objekttypen werden Sie es zu schätzen wissen, immer die gleichen Operationen zu verwenden. Ein weiterer positiver Nebeneffekt: muß irgendwann und unvorhersehbar der Wert für nil geändert werden (weil der einst gewählte Wert plötzlich doch ,,gültig`` ist), brauchen Sie nur eine Stelle in der DSL-Spezifikation zu ändern und die Applikation neu zu übersetzen -- die Wartung wird durch Verwendung von Optionals also einfacher!

DSL Um in der DSL-Spezifikation ein Optional Anopt für einen Domain  tex2html_wrap_inline6370 zu definieren, schreiben Sie

displaymath2838

Anwendungen Wegen der Ähnlichkeit mit NULL-Pointern in C ist deren ,,klassische`` Anwendungsmöglichkeit durch Optionals realisierbar: die Repräsentation eines nicht vorhandenen Nachfolgers in einer rekursiven Struktur  (z.B. das Ende einer verketteten Liste oder die Blatt-Ebene eines Binärbaumes). Eine eher philosophische Anmerkung dazu: Die Sichtweise des Abbruchs einer rekursiven Struktur mit einer (grundsätzlich beliebigen) Ende-Markierung in Form von nil ist wesentlich ,,natürlicher`` und abstrakter -- weil sie mehr an die eigentliche Aufgabenstellung der Modellierung einer rekursiven Struktur angelehnt ist -- als wenn Sie nur die aus der Implementation erwachsende Möglichkeit der Ende-Markierung mit dem NULL-Pointer in Erwägung ziehen.

Sie können Optionals aber auch z.B. im Compilerbau gut einsetzen, da die Grammatik-Spezifikationen mit der BNF (Backus-Naur-Form) ebenfalls den optionalen Fall kennen (der auch mit eckigen Klammern dargestellt wird). Der zu schreibende Parser für die Syntaxanalayse muß in der Lage sein, fehlende Teile in irgendeiner Form darzustellen; dazu eignen sich Optionals.

Beispiel: Die Grammatik der zweiseitigen Bedingung in C (in Form von if...else) sieht vor, daß der ELSE-Zweig auch entfallen kann:

IF-ELSE::=IF (expression) statement ; [ ELSE statement ; ]
*[1.5ex]

Dieser Abschnitt enthält nur die Beschreibung des VDM-Basistyps ,,Optional`` und die verfügbaren Implementationen und Operationen; ein Anwendungsbeispiel finden Sie im Abschnitt 5.8 5.8 über Trees.

Optional-Implementationen

Für Optionals stehen zwei Implementationen zur Verfügung:

Optional-Operationen

Zur Veranschaulichung der Operationen dienen folgende Variablen:

 DOMAINS 
 *
Nopt= [ Nat0 ] 
 *
Sopt		=		[ Nset ] 
 *
Nset		=		Nat0 -set 
 *
 tex2html_wrap_inline6814  
 *
Nat0		a, b; 
 *
Nopt		o, p; 
 *
Nset		s1, s2; 
 *
Sopt		so1, so2;

Optional-Konstruktoren

mk Mitmkerzeugen Sie ein Optional, das einen gültigen Wert enthält. Der Name wird mit dem Namen des Elementtyps und dem Optional-Namen erweitert; daher ist der Umgang mit mk recht umständlich. Tip: verwenden Sie lieber die Operation mk_opt, sie hat die gleiche Wirkung.

o = mk_nat0_nopt(14);
*[1.5ex]

mk_opt mk_optist die ,,bessere`` Variante zu mk, da der VDM-Basistyp ,,Optional`` am Namen erkennbar ist und die Nomenklatur leichter zu behalten ist, weil sie den bisher kennengelernten Normen entspricht.

so1 = mk_opt_sopt(mk_one_nset(9));
*[1.5ex]

mk_nil Mitmk_nilerzeugen Sie ein Optional-Objekt mit dem Wert nil. Wenn Sie einem Optional, das gerade einen gültigen Inhalt hat, den Wert nil geben möchten, sollten Sie den vorherigen Inhalt mit del1 oder del löschen, wenn er nicht noch von anderer Stelle referenziert wird -- Sie verhindern so eine Verschwendung von Speicherplatz.

del1_sopt(so1);
* so1 = mk_nil_sopt();
*[1.5ex]

Optional-Prädikate

is_eq Mitis_eqtesten Sie, ob zwei Optionals entweder beide das gleiche Element enthalten oder beide gerade nil sind.

is_eq_nopt(mk_opt_nopt(14),mk_nil_nopt()) == FALSE
*[1.5ex]

is_ge Mitis_getesten Sie, ob ein Optional gerade größer oder gleich einem anderen Optional ist. Der Vergleich ist nur definiert, wenn is_ge auch für den Elementtyp erhältlich ist, also z.B. nicht für den Typ Sopt !

is_gr Mitis_grtesten Sie, ob ein Optional gerade größer als ein anderes Optional ist. Der Vergleich ist ebenfalls nur definiert, wenn is_gr auch für den Elementtyp erhältlich ist.

Die Operationen is_ge und is_gr werden nur der Vollständigkeit halber bereitgestellt, denn einige Implementationen von anderen VDM-Basistypen erwarten die Existenz dieser Prädikate bei allen ihren Elementtypen, auch bei Optionals; ob diese Prädikate irgendwie sinnvoll sind, ist unwichtig. Sie werden diese Prädikate bei eigenen Optional-Anwendungen in der Regel nicht selbst benötigen.

is_nil is_nilliefert TRUE, wenn das Optional gerade den Wert nil hat.

is Der Name der Operation is wird sowohl mit dem Namen des Elementtyps als auch mit dem Optional-Namen erweitert und liefert TRUE genau dann wenn is_nil das Ergebnis FALSE hat und umgekehrt.

o = mk_nat0_nopt(14);
* tex2html_wrap_inline6453 is_nat0_nopt(o) == TRUE
* tex2html_wrap_inline6453 is_nil_nopt(o) == FALSE
*[1.5ex]

Es gibt ein weiteres Prädikat, das aber gleichzeitig ein Element liefert, wenn es erfüllt ist: is_opt wird daher bei den Selektions-Operationen erläutert.

Optional: Selektion

s swird (wie auch mk und is) sowohl mit dem Namen des Elementtyps als auch mit dem Optional-Namen erweitert und liefert -- wenn das Optional nicht gerade nil enthält -- den Element-Wert.

if (is_nat0_nopt(o)) { a = s_nat0_nopt(o); process_nat0(a); }
*[1.5ex]

is_opt is_opt ist eine Verknüpfung der Prüfung, ob ein Optional gerade einen gültigen Wert hat (mit is) und, im Erfolgsfall, Selektion des Elements (mit s). Das Resultat ist vom Typ Bool, im Falle der Erfüllung dieses Prädikats wird das Element in einem Referenzparameter geliefert.
Das obige Beispiel zu skann also auch einfacher formuliert werden:

if (is_opt_nopt(o,&a)) process_nat0(a);
*[1.5ex]

Trees Die VDM-Basistypen Maps

VDM Class Library