Prozedur und Funktion
-
Vielleicht will er ja nicht alles fangen
-
DEvent schrieb:
Aber das Java's checked exceptions were a mistake (and here's what I would like to do about it)
Sehe ich ein, dass Checked Exceptions bei "Zwischen APIs" Probleme machen.Eigentlich nicht. Die hätten einfach nur ihr Interface richtig designen müssen und z.B. ne ObjectPoolException werfen können. Und ab wann so irgendwas ne "Zwischen API" sein? Jede API ist irgendwo zwischen Programm und Java API, egal ob ObjectPool, DB oder GUI.
Ich Programmier ja schon ne Weile kein Java mehr, aber sind die noch nicht auf die Idee gekommen sowas wie Autoboxing für Exceptions zu machen?
statt:public void doSomething() throws MyException { try { doSomething0(); } catch (IOException e) { throw new MyException(e); } catch (SQLException e) { throw new MyException(e); } catch ... finally { } }
irgendwie sowas
public void doSomething() autoThrows MyException { doSomething0(); // Compiler macht automatisch "throw new MyException(e)", wenn hier checked Exceptions geworfen werden. }
falls gleich wieder einer keine Phantasie hat und wegen finally jammert.
public void doSomething() autoThrows MyException { try{ doSomething0(); // Compiler macht automatisch "throw new MyException(e)", wenn hier checked Exceptions geworfen werden. } finally{...} }
müsste dann auch gehen
-
Gerade fällt mir noch eine Situation ein, wo die Trennung zwischen Prozedur und Funktion sehr sinnvoll ist:
// Delphi Runtime Library, SysUtils.pas: ... // Generic Anonymous method declarations type TProc = reference to procedure; TProc<T> = reference to procedure (Arg1: T); TProc<T1,T2> = reference to procedure (Arg1: T1; Arg2: T2); TProc<T1,T2,T3> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3); TProc<T1,T2,T3,T4> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4); TFunc<TResult> = reference to function: TResult; TFunc<T,TResult> = reference to function (Arg1: T): TResult; TFunc<T1,T2,TResult> = reference to function (Arg1: T1; Arg2: T2): TResult; TFunc<T1,T2,T3,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3): TResult; TFunc<T1,T2,T3,T4,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4): TResult; TPredicate<T> = reference to function (Arg1: T): Boolean;
Hätte man nicht zwischen Funktionen und Prozeduren unterschieden, müßte man eine Prozedurreferenz etwa als
TMethod<T, Void>
deklarieren. Dabei ist zu beachten, daß esvoid
eigentlich nur in C und C++ gibt. Wer schon einmal eine generische Delegatenklasse in C++ implementiert hat, dürfte auch schon unangenehme Bekanntschaft mitvoid
und der dafür meist nötigen Sonderbehandlung gemacht haben. Der Standard sieht ja sogar speziellereturn void
-Ausnahmeregelungen vor, die die Angelegenheit etwas vereinfachen, aber das Problem nicht beseitigen. Hier ist eine klare Unterscheidung zwischen Prozeduren und Funktionen hilfreich.(Natürlich gibt das jetzt auch keinen Aufschluß darüber, was man sich ursprünglich dabei gedacht haben mag. Closures waren vermutlich bei den Altvorderen noch nicht eingeplant
)
-
mycomment schrieb:
Ich Programmier ja schon ne Weile kein Java mehr, aber sind die noch nicht auf die Idee gekommen sowas wie Autoboxing für Exceptions zu machen?
Das tolle dabei ist aber, genau wie bei dem manual-boxing von DEvent, dass man das fangen der exceptions plötzlich unnötig kompliziert macht.
denn statt FileNotFound fange ich plötzlich MyException muss mit ner Schleife durch alle causes gehen um den korrekten Typen zu finden.
Das ist kompletter schwachsinn. da kann man gleich throws Exception sagen... Man hat dadurch nämlich checked exceptions ausgetrickst. man hat die sicherheit die sie bieten sollten eliminiert und es schwerer gemacht bestimmte fehler explizit zu behandeln.
-
Aber die hl. Kuh lebt noch.
-
audacia schrieb:
Hätte man nicht zwischen Funktionen und Prozeduren unterschieden, müßte man eine Prozedurreferenz etwa als
TMethod<T, Void>
deklarieren. Dabei ist zu beachten, daß esvoid
eigentlich nur in C und C++ gibt. Wer schon einmal eine generische Delegatenklasse in C++ implementiert hat, dürfte auch schon unangenehme Bekanntschaft mitvoid
und der dafür meist nötigen Sonderbehandlung gemacht haben. Der Standard sieht ja sogar speziellereturn void
-Ausnahmeregelungen vor, die die Angelegenheit etwas vereinfachen, aber das Problem nicht beseitigen. Hier ist eine klare Unterscheidung zwischen Prozeduren und Funktionen hilfreich.Eigentlich ist es ja egal, ob ich zwischen void und nicht-void unterscheide oder zwischen Prozedur und Funktion. Wenn ich dich richtig verstanden habe, liegt das Problem nur an der Codegenerierung von C++. Ist das so?
-
mngbd schrieb:
Eigentlich ist es ja egal, ob ich zwischen void und nicht-void unterscheide oder zwischen Prozedur und Funktion.
Auf Sprachebene? Ja. Es ist nur ein ästhetischer Unterschied.
mngbd schrieb:
Wenn ich dich richtig verstanden habe, liegt das Problem nur an der Codegenerierung von C++. Ist das so?
Nein. Ob deine Sprache nun explizit durch verschiedene Keywords zwischen Prozedur und Funktion unterscheidet wie Pascal oder ob du Prozeduren mit void als Rückgabetyp deklarierst, ist nebensächlich. Ich meinte, daß die Unterscheidung zwischen
TFunc<>
undTProc<>
sinnvoll ist. Wenn man beide einheitlich behandelt, muß man einen Marker-Typen für Prozeduren benutzen (in C++ ist dasvoid
, in Delphi müßte man einen eigenen Typen definieren); zumindest in C++ muß man dann öfters auf TMP zurückgreifen, umvoid
gesondert zu behandeln, und das ist meist außerordentlich häßlich. Darum halte ich es hier für sinnvoll, einfach in Prozeduren und Funktionen zu trennen.
-
audacia schrieb:
Darum halte ich es hier für sinnvoll, einfach in Prozeduren und Funktionen zu trennen.
Diese Trennung kannst du, wenn du es willst, ja in C++ auch machen - bei delegates meine ich. Dann verlierst du die unnötige komplexität durch void.
-
Shade Of Mine schrieb:
audacia schrieb:
Darum halte ich es hier für sinnvoll, einfach in Prozeduren und Funktionen zu trennen.
Diese Trennung kannst du, wenn du es willst, ja in C++ auch machen
Natürlich. Das war ja auch nicht mein Punkt.
-
Shade Of Mine schrieb:
mycomment schrieb:
Ich Programmier ja schon ne Weile kein Java mehr, aber sind die noch nicht auf die Idee gekommen sowas wie Autoboxing für Exceptions zu machen?
Das tolle dabei ist aber, genau wie bei dem manual-boxing von DEvent, dass man das fangen der exceptions plötzlich unnötig kompliziert macht.
denn statt FileNotFound fange ich plötzlich MyException muss mit ner Schleife durch alle causes gehen um den korrekten Typen zu finden.
Den Anderen weg kann man dann natürlich auch automatisch machen, z.B.
catch containing (FileNotFoundException e)... //fängt alle direkten und geboxten FileNotFoundExceptions
Und wenn mans es komplizierter will könnte man sich auch noch sowas vorstellen
catch containing (FileNotFoundException e) and not containing (DBException)...//fängt alle direkten und geboxten FileNotFoundExceptions die nicht aus der DB-Schicht kommen.
dann wird es aber aufwendiger zum Auswerten.
Das ist kompletter schwachsinn. da kann man gleich throws Exception sagen... Man hat dadurch nämlich checked exceptions ausgetrickst. man hat die sicherheit die sie bieten sollten eliminiert und es schwerer gemacht bestimmte fehler explizit zu behandeln.
Du hast immer noch die Sicherheit, dass du checked Exceptions nicht verlierst, sondern nen Compileerror bekommst. Man darf dann natürlich nicht in RuntimeExceptions boxen bzw. ist selber verantwortlich, wenn man es macht.
Außerdem könnte man das Exceptionboxing auch noch optional einschränken.public void doSomething() autoThrows MyException(IOException, SQLException) {...
Dann bekommst du immer noch nen Compileerror, wenn du was einbaust, was ne andere Exception wirft.