Hallo zusammen!
Was ist denn besser? Eine Latte von UND-verknüpften Bedingungen -die
auch Rückgabewerte von Funktionsaufrufen beinhalten-, in einer
if-Abfrage und lieber ineinander mit aufsteigender Komplexität
verschachtelt, um Rechenzeit zu sparen?
Danke & Grüße
Blub
Blub schrieb:> in einer if-Abfrage und lieber ineinander
Äh! Zuviel "UND"! ;-)
Sollte natürlich "ODER" lauten:
"...in einer if-Abfrage, ODER lieber ineinander ..."
Kannst Du ruhig hintereinander schreiben. Da von links nach rechts
abgearbeitet wird, und bei dem ersten false eh abgebrochen wird.
Um Rechenzeit zu sparen am besten die Bedingungen die am
häufigsten/schnellsten false liefern ganz nach links schreiben.
Richtig, beides ist (zumindest in C und einigen anderen Sprachen)
äquivalent. Immer daryn denken falls eine der aufgerufenen Funktionen
gewünschte Seiteneffekte hat.
Stefan P. schrieb:> Kannst Du ruhig hintereinander schreiben. Da von links nach rechts> abgearbeitet wird, und bei dem ersten false eh abgebrochen wird.> Um Rechenzeit zu sparen am besten die Bedingungen die am> häufigsten/schnellsten false liefern ganz nach links schreiben.
Super! Danke! Die Antwort, die ich gebraucht und erhofft habe! ;-)
user schrieb:> in C ist die Auswertungsreihenfolge der Argumente undefiniert
In C ist die Reihenfolge definiert. Grob gesagt: sie erfolgt immer
links-nach-rechts ausser bei:
Blub schrieb:> Was ist denn besser?
Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer
Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.
1
bool first_parameter_valid = p1 >= 4 && p1 < 20;
2
bool second_parameter_valid = p2 >= 3 && p2 < 99;
3
4
if ( first_parameter_valid && second_parameter_valid )
Torsten R. schrieb:> Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer> Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.
Torsten R. schrieb:> Achim, das war nur ein Beispiel! ;-)
Das verstehe ich, Torsten, und mit Deinem Beispiel bist Du konform zu
Lehrbüchern für guten Code. Vor allem, wenn man McCabe und anderen
Metriken folgt, ebenso TTD (Unittests), und vorwiegend orthogonale,
unabhängige Modulen von je ~1000 Zeilen programmiert.
Sobald man größere Projekte hat, mit Modulen von mehrern 1000 Zeilen und
einer durch die reale Welt intensiven faktische Verknüpfung, dann rückt
ein Problem in den Vordergund: Die Lesbarkeit (Geschwindigkeit) des
Quellcodes. Und hier die Begrenzung von Token sowie die Anzahl der
Indirektionsebenen.
Hier als Beispiel: Diese if-Schleife wurde durchlaufen, und jemand fragt
sich, wieso. Wenn dort alle 100 Abfragen direkt untereinander stehen,
kann er diese (mit dem Auge) scannen und ggf. direkt mit seiner IDE
nähere Informatione zu p1 oder p2 bekommen. Bei first_parameter_valid
muss er dazu erst dorthin springen.
Viele Funktionen, die Mc-Cabe senken oder Unittests vereinfachen sollen,
erschweren real die Lesbarkeit und machen den Code (durch weggekapselten
Kontext) unsicherer.
Torsten R. schrieb:> Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer> Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.
Dann fällt aber (zumindest teilweise) die genannte short-circuit
evaluation weg. Bei deinen einfachen Variablenabfragen mag das
egal sein, aber wenn zwischendrin eine komplexere Funktion aufgerufen
wird, berechnest du ggf. ein Ergebnis, welches für die Katz' ist.
Noch schlimmer, das Ergebnis könnte undefiniert sein oder eine
Speicherschutzverletzung bringen. Überleg' dir mal, wie du das
mit dem Zwischenspeichern in Variablen hier machst bzw. was dann
passiert:
1
if(ptr!=NULL&&eval_data(ptr->data)!=42){
2
// …
3
}
Danach weißt du, warum man eine wohldefinierte short-circuit
evaluation in einer Sprache braucht. (Pascal hatte sie zumindest
im ersten Standard nicht, sondern hat es dem Compiler überlassen.
In der Folge musste man dann immer zweimal if verschachteln.)
versteht mich nicht falsch, ich sage nicht, dass diese der einzige,
wahre Weg ist! Ich wollte nur darauf hinweisen, dass dies ein Mittel
sein kann, die Lesbarkeit zur erhöhen (Zitat: "wenn das ggf. die
Lesbarkeit erhöht.")
Und ja, natürlich muss man short circuit berücksichtigen. Das muss man
aber auch, wenn man den gesamten Ausdruck in einem hinschreibt.
Torsten R. schrieb:> const bool not_42 = data_exists && eval_data(ptr->data) != 42;
Das aber setzt zwingend funktionierende short-circuit evaluation
voraus, sonst knallt's, wenn ptr dereferenziert wird, um "eval_data"
aufzurufen.
Rufus Τ. F. schrieb:> Torsten R. schrieb:>> const bool not_42 = data_exists && eval_data(ptr->data) != 42;>> Das aber setzt zwingend funktionierende short-circuit evaluation> voraus, sonst knallt's, wenn ptr dereferenziert wird, um "eval_data"> aufzurufen.
Oh mann, ließt den hier niemand mehr, sondern stürzt sich nur noch auf
das letzte Posting?
Sorry, aber ich bin jetzt raus.
Keine Ahnung, was "leßen" sein soll - aber in einer Diskussion, wo um
die Notwendigkeit oder nicht-Existenz der "short circuit evaluation"
gestritten wird ... nehme ich den Thread vermutlich anders wahr als Du.
Rufus Τ. F. schrieb:> Keine Ahnung, was "leßen" sein soll - aber in einer Diskussion, wo um> die Notwendigkeit oder nicht-Existenz der "short circuit evaluation"> gestritten wird ... nehme ich den Thread vermutlich anders wahr als Du.
Naja, so ganz nachvollziehen kann ich den Sinn deines Postings aber auch
nicht. Nachdem Torsten meinte, dass man
ersetzen könnte, meinst du, dass das aber zwingend short-circuit
evaluation benötigt. Das hat aber das Original auch schon. Außerdem
hatte er das in seinem Posting schon selber explizit erwähnt:
Torsten R. schrieb:> Und ja, natürlich muss man short circuit berücksichtigen. Das muss man> aber auch, wenn man den gesamten Ausdruck in einem hinschreibt.
Dumdi D. schrieb:> und hier das ärgerliche: beim überladenen && (in c++) gibt es wohl keine> short-circuit evaluation.
Wozu brauchst du das? Der Short-Circuit macht ja nur dann Sinn, wenn die
Operanden wie boolesche Werte behandelt werden können. Dann kannst du
für den neuen Datentyp aber auch einfach eine Konvertierungsfunktion
nach bool (operator bool()) schreiben und die normale &&-Operation mit
Short-Circuit verwenden.
Oder nimm Haskell ;-)
Da wird defaultmäßig lazy evaluiert, was das Short-Circuiting innerhalb
einer selbstgeschriebenen Funktion automatisch nach außen trägt. Solche
Funktonen wie && und || sind dort überhaupt nichts Spezielles und auch
nicht auf boolesche Werte beschränkt.