Goto considered harmful!? (Fork aus: Welche Sprachfeatures sollte man vermeiden)
-
@hustbaer sagte in Welche Sprachfeatures sollte man vermeiden?:
Ich denke @Swordfish meint dass man immer alles einfach auf return umstellen kann.
Immer alles? Nein. Oft bis fast immer? Ja.
Wenn es nur mit Verrenkungen geht dann bin ich natürlich auch für eine Sprungmarke. Aber wenn es anders geht, dann bitte anders. Deswegen wollte ich ja auch von @john-0 ein nachvollziehbares Beispiel haben.
-
@Swordfish sagte in Welche Sprachfeatures sollte man vermeiden?:
@SeppJ Condition variable?
Future?
Semaphor?
Mutex?Und: nein, bitte nicht! Unnötige "exit_my_middle_loop" Variablen sind zum Kotzen. Das macht doch alles nur unglaublich unübersichtlich und mühsam zu lesen. Und fehleranfällig.
-
Variable.
@hustbaer sagte in Welche Sprachfeatures sollte man vermeiden?:
Und: nein, bitte nicht! Unnötige "exit_my_middle_loop" Variablen sind zum Kotzen. Das macht doch alles nur unglaublich unübersichtlich und mühsam zu lesen. Und fehleranfällig.
Ja. Ich warte noch immer auf das real world example.
-
@Swordfish sagte in Welche Sprachfeatures sollte man vermeiden?:
Variable.
@hustbaer sagte in Welche Sprachfeatures sollte man vermeiden?:
Und: nein, bitte nicht! Unnötige "exit_my_middle_loop" Variablen sind zum Kotzen. Das macht doch alles nur unglaublich unübersichtlich und mühsam zu lesen. Und fehleranfällig.
Ja. Ich warte noch immer auf das real world example.
Das war ein real world example. Du wirst dir doch wohl vorstellen können, dass es viele Algorithmen gibt, bei denen man bei Erreichen einer bestimmten Bedingung einen zugehörigen Pfad abbrechen will und mit dem nächsten weiter macht. Wer das mit unnötigen Condition-Variablen im inneren Loop macht, gehört nicht an Computerzeit gelassen. Wer seine verschachtelten Loop nur zwecks Ablaufsteuerung in Unterfunktionen verteilt, gehört ebenfalls nicht an ein Computerprogramm.
-
@SeppJ sagte in Welche Sprachfeatures sollte man vermeiden?:
...
Wer seine verschachtelten Loop nur zwecks Ablaufsteuerung in Unterfunktionen verteilt, gehört ebenfalls nicht an ein Computerprogramm.Das ist einfach nur Käse...
Die Aussage ist einfach nur Käse...Edit für Tyrdal:
Sepp´s Aussage.
-
@DocShoe Was ist Käse? SeppJs Aussage oder Funktionen zu nutzen?
Ich persönlich würde jederzeit die Unterteilung in Funktionen einem goto vorziehen. Da ist deutlich sauberer.
-
Nix Käse. Du möchtest logisch zusammenhängende Dinge zerpflücken, weil du sonst deine Ablaufsteuerung nicht programmiert bekommst? Und dann hast du deine logische Ablaufsteuerung über mehrere Funktionen verteilt, so dass man alle Unterfunktionen kennen muss, um den Code zu verstehen? Das hältst du für eine gute Idee?
-
@SeppJ sagte in Welche Sprachfeatures sollte man vermeiden?:
Nix Käse. Du möchtest logisch zusammenhängende Dinge zerpflücken, weil du sonst deine Ablaufsteuerung nicht programmiert bekommst? Und dann hast du deine logische Ablaufsteuerung über mehrere Funktionen verteilt, so dass man alle Unterfunktionen kennen muss, um den Code zu verstehen? Das hältst du für eine gute Idee?
Wenn mein Code durch die Einrückungen erst mitten auf dem Bildschirm anfängt? Wenn ich in verschiedenen Schleifenrümpfen gotos habe, die an Sprungmarken springen, die ich aufgrund der Anzahl der Zeilen nicht mal sehen kann, weil ich dazu scrollen muss? Ja, dann zerpflücke ich lieber meine Schleifen.
PS:
Der Beweis/use case, dass Schleifen/goto performanter sind als Schleifen/Lambdas/Funktionen steht immer noch aus.
-
@DocShoe sagte in Welche Sprachfeatures sollte man vermeiden?:
PS:
Der Beweis/use case, dass Schleifen/goto performanter sind als Schleifen/Lambdas/Funktionen steht immer noch aus.Mehrere Sprungmarken kannst du überhaupt gar nicht mit Funktionen emulieren. Da kannst du nichts vergleichen. Und es hat doch auch niemand gefragt. Und wenn überhaupt, dann wäre die Schuldigkeit doch bei den Funktionen-als-Ablaufsterung-Vertretern, zu zeigen, dass es keine Nachteile hätte.
-
@DocShoe So wie ich das sehe, geht auch um den umgekehrten Fall. Du hast eine Formel (mit ggf. mehreren Variablen, also 3 Indizes und einem Array (oder auch 2x2=4 Indizes und 2 Arrays - oder sogar 2x4=8 Indizes für 2 4d-Arrays) und ein if - und dann musst du bei Funktionen kompliziert diese Werte alle übergeben, nur um ein goto zu vermeiden? Anstelle von sagen wir 20 Zeilen für die gesamte Funktion hast du nun den relevanten Teil anderswo hin (in eine Funktion) verschoben, sodass man nicht mehr erkennt, was eigentlich genau berechnet wird. Vor allem weil man auch die Funktionsargumente leicht vertauschen kann.
Und wenn die verschachtelten Schleifen jeweils andere Schleifenlevel "break"en sollen, wie machst du das dann?
Achtung: ich sage nicht, dass dieser Usecase häufig vorkommt.
-
@SeppJ sagte in Welche Sprachfeatures sollte man vermeiden?:
@DocShoe sagte in Welche Sprachfeatures sollte man vermeiden?:
PS:
Der Beweis/use case, dass Schleifen/goto performanter sind als Schleifen/Lambdas/Funktionen steht immer noch aus.Mehrere Sprungmarken kannst du überhaupt gar nicht mit Funktionen emulieren. Da kannst du nichts vergleichen. Und es hat doch auch niemand gefragt. Und wenn überhaupt, dann wäre die Schuldigkeit doch bei den Funktionen-als-Ablaufsterung-Vertretern, zu zeigen, dass es keine Nachteile hätte.
Sehe ich anders. C++ best practices und Guidelines raten von goto ab. Dann kommt jemand daher und sagt: "Ich muss das hier benutzen, weil mir sonst Performancenachteile entstehen." Dieser jemand sollte jetzt begründen, warum er goto benutzt und welche Nachteile ihm entstehen, wenn´s er nicht tut. Oder anders gesagt: goto sollte die Ausnahme sein, und dann muss man auch begründen, warum die Ausnahme gerechtfertigt ist.
Edit:
Thread Fork?
-
Das goto harmful ist, bestreitet doch keiner. Aber hier geht es um den einen typischen Fall, wo es gut und nötig ist. Die Begründungen dafür wurden oben doch ausführlich gegeben.
-
@john-0 sagte in Welche Sprachfeatures sollte man vermeiden?:
@DocShoe sagte in Welche Sprachfeatures sollte man vermeiden?:
In diesem Bereich bist du.
Das ist der Bereich in dem man
goto
nutzt, und es ist eine legitime Nutzung vongoto
. Mit der Begründung das wird ja nur von wenigen genutzt könnte man in C++ etliches herauswerfen.Um wieviel Prozent ist denn
for ( int i = 0; i < 100; ++i ) { for ( int j = 0; < j < 100; ++j ) { if ( Abbruch ) goto exitlabel: } } exitabel:
performanter als
bool exit_calc = false; for ( int i = 0; i < 100 && !exit_calc; ++i ) { for ( int j = 0; < j < 100 && !exit_calc; ++j ) { if ( Abbruch ) exit_calc = true; } }
ich hab da ernsthafte Zweifel, dass man da überhaupt einen Unterschied messen kann.
-
@SeppJ sagte in Welche Sprachfeatures sollte man vermeiden?:
Wer seine verschachtelten Loop nur zwecks Ablaufsteuerung in Unterfunktionen verteilt, gehört ebenfalls nicht an ein Computerprogramm.
Und wer seine Funktionen bis zur Unleserlichkeit tief verschachtelt, damit sie auf gar keinen Fall mehr intuitiv sind, gehört standrechtlich erschossen
-
@DocShoe sagte in Goto considered harmful!? (Fork aus: Welche Sprachfeatures sollte man vermeiden):
Sehe ich anders. C++ best practices und Guidelines raten von goto ab.
C++ Core Guidelines ES.76: Avoid goto
Exception
Breaking out of a nested loop. In that case, always jump forwards.
-
@It0101 sagte in Welche Sprachfeatures sollte man vermeiden?:
exit_calc
Es geht weniger darum ob und wie viel die
exit_calc
Variante langsamer ist. Es geht darum dass sie viel schwerer zu lesen ist. In echt sind das ja keine leeren Schleifen. Da ist noch Code, meist in jeder Schleife (also z.B. Code der nach der inneren Schleife noch in der äusseren Schleife ausgeführt wird). Und das wird dann ganz schnell ganz unübersichtlich.Die
goto
Variante ist dagegen quasi immer trivial zu lesen.
-
@hustbaer sagte in Welche Sprachfeatures sollte man vermeiden?:
@It0101 sagte in Welche Sprachfeatures sollte man vermeiden?:
exit_calc
Es geht weniger darum ob und wie viel die
exit_calc
Variante langsamer ist. Es geht darum dass sie viel schwerer zu lesen ist. In echt sind das ja keine leeren Schleifen. Da ist noch Code, meist in jeder Schleife (also z.B. Code der nach der inneren Schleife noch in der äusseren Schleife ausgeführt wird). Und das wird dann ganz schnell ganz unübersichtlich.Die
goto
Variante ist dagegen quasi immer trivial zu lesen.Das mag sein, aber das war nicht das Argument. @john-0 hat explizit mit der Performance argumentiert.
Die Goto-Variante ist auch nur dann besser zu lesen, wenn das Sprungziel nicht auf der nächsten Seite ist. Und wenn hier, wie man so hört, die tief-verschachtelten Schleifen hart durchgezogen werden, und im inneren der Schleifen irgendwo auch nur ein bisschen sinnvoller Sourcecode drin ist, dann ist der Spaß mindestens eine Seite groß. Viel Spaß beim Suchen des Sprungziels
Ich bin aber ehrlich: ich stehe überhaupt nicht auf Verschachtelungstiefen. Im allgemeinen habe ich selten mehr als zwei Ebenen innnerhalb einer Funktion/Methode. Die vier verschachtelten Schleifen triggern mich also hart
-
@It0101 Ah, OK. Die Beiträge bestimmter Leute sehe ich ja nicht
Viel Spaß beim Suchen des Sprungziels
F12/Alt-G/was auch immer der Shortcut für "go to definition" ist. Bzw. ohne Tool-Support einfach ein "find" mit dem Namen des Labels machen.
Das Suchen des Sprungziels ist ein triviales Problem.
Den Code Zeile für Zeile durchzugehen um zu sehen was noch alles ausgeführt wird nachdem die Hilfsvariable gesetzt wurde ist dagegen nicht trivial.
Ich hab da Fälle gesehen wo alle verschachtelten Schleifen auf eine Bildschirmseite gepasst haben, und es einem trotzdem das Hirn zerbröselt hat beim Versuch zu verstehen wie der Abbruch da genau funktioniert. Super "lustig" ist dann auch das Fehlersuchen in solchem Code.
-
@manni66 sagte in Goto considered harmful!? (Fork aus: Welche Sprachfeatures sollte man vermeiden):
@DocShoe sagte in Goto considered harmful!? (Fork aus: Welche Sprachfeatures sollte man vermeiden):
Sehe ich anders. C++ best practices und Guidelines raten von goto ab.
C++ Core Guidelines ES.76: Avoid goto
Exception
Breaking out of a nested loop. In that case, always jump forwards.
Dann nehmen wir mal das Beispiel aus den Guidelines:
void foo() { for (int i = 0; i < imax; ++i) for (int j = 0; j < jmax; ++j) { if (a[i][j] > elem_max) goto finished; // ... } finished: // ... }
geht auch als
void bar() { [&] { for (int i = 0; i < imax; ++i) for (int j = 0; j < jmax; ++j) { if (a[i][j] > elem_max) return; // ... } } (); //... }
-
@DocShoe sagte in Goto considered harmful!? (Fork aus: Welche Sprachfeatures sollte man vermeiden):
geht auch als
Es mag sein, dass das Beispiel dort ungeschickt gewählt ist. Es ging mir aber auch nur darum, dass zumindest die Core Guidelines explizit eine Ausnahem vom kein goto machen.