====== guard ======
Mit Ifc::Error schrieb ich eine Fehlerklasse, die einfache Fehlerbeschreibungen mit einer Ortsangabe übernehmen kann, sowie Listen von Fehlern verwalten kann.
Das Makro IFCGUARD sichert ab, dass eine Funktion erfolgreich gelaufen ist und falls nicht, wird der Fehler an die jeweils höherliegende Funktion weitergeleitet.
Das Konzept möchte ich gerne übernehmen:
Eine Funktion, die mit fail aussteigen kann, muss mit validate gerufen werden. Da ein Guard ein fail nur weiterleitet...
Im validate-Part entspricht 'value' dem gültigen Rückgabewert, im else Part dem geworfenen Fehler.
Ein Fehler ist immer eine Liste, die sich mit value$ zu einer kommaseparierten Liste joinen lässt.
fail muss - wie return - immer einen klaren Datentyp zurückgeben. Guard kann nur einen Fehler weiterleiten, wenn diese Funktion den gleichen Fehlertypen
unterstützt.
func( a, b as int ) :=
{
fail "Something happens";
return a+b;
}
caller() as bool :=
{
guard temp is func( 1, 2 );
// Hier kommen wir nur an, wenn func() erfolgreich abläuft.
return true;
}
main() :=
{
validate caller()
print "Das Ergebnis ist " + value$ + "\n";
else
print "Es ist etwas schief gelaufen: %s\n" % value$;
}
Funktionen, die immer gültig enden, aber trotzdem Fehlschlagen können fügen fail und return zusammen:
func( a, b as int ) :=
{
if( a + b > 10 )
fail "Result to big" return 0;
return a+b;
}
main() :=
{
temp = func( 1, 2 ); // Ergebnis passt schon (Definition einer Konstanten)
validate func( 4, 5 )
printf( "ok" );
else
printf( "Fehlgeschlagen: %s" % value );
}
Man kann einen Stack aufbauen:
func( a, b as int ) :=
{
if( a + b > 10 )
fail "Result to big";
return a+b;
}
caller() :=
{
guard( "Called from Caller" ) temp = func( 1, 2 )
}
main() =
{
validate caller()
else for( item in value )
print "%d: %s\n" % { index, item$ };
}
Führt zu:
> 0: Result to big
> 1: Called from Caller
===== Assert =====
Ein Assert prüft den Wahrheitswert (nicht den Fehlercode!) und steigt aus der Funktion aus, wenn der Wahrheitswert "false" ergibt.
Es muss ein Fehler angegeben werden.
func =
return false;
caller() :=
{
assert( "Aufruf von func() fehlgeschlagen" ) func();
}
Zurückgegeben wird ein Fehler, der mit guard weitergeleitet oder gestackt werden kann.
===== Return =====
Möchte man eine Funktion sowieso verlassen, so kann auch return genutzt werden:
Vorheriges Beispiel:
func() = random() %? 1;
caller() =
{
return( "Ergebnis von func falsch" ) func();
}
Die Funktion caller gibt entweder true zurück oder einen Fehler. return kehrt aber im Gegensatz zu Assert grundsätzlich zurück und liefert das gültige Ergebnis des zu prüfenden Ausdrucks zurück.