Einsteiger Fragen

  • Original von macmoonshine
    Ein ehemaliger Kollege hat mal ungefähr Folgendes geschrieben:

    Quellcode

    1. for(int i = 1; i <= 3; i++) {
    2. switch(i) {
    3. case 1:
    4. // auskommentierter Code
    5. break;
    6. case 2:
    7. // auskommentierter Code
    8. break;
    9. case 3:
    10. [self doSomethingTrivial];
    11. break;
    12. }
    13. }
    Alles anzeigen
    Den schreckt wahrscheinlich nichts mehr ab. In einem Gespräch ließ er auch mal die Bemerkung fallen, dass er so programmiert, dass es sehr schwer verständlich ist. Dadurch glaubte er unersetzbar zu sein.

    Ich vermute, dass er Gotos liebt.

    Mhhhh, sieht für mich eher aus, als hätte er da was falsch verstanden
  • Original von Amin Negm-Awad
    Original von MartinH.
    wunderbarer anknüpfpunkt für meine frage ob es schlechter stil ist eine schleife mit break zu verlassen. das ging mir neulich durch den kopf...

    Das ist okay, weil es eine Struktur verlässt.


    Sehe ich auch so, es gibt aber durchaus Leute, die break, continue und return genau so ablehnen wie goto.

    Original von Amin Negm-Awad
    Mir fällt wirklich aktuell kein Beispiel mehr ein, bei dem Goto sinnvoll wäre. Für mich ist das anachronistisch, ich lasse mich aber gerne von einem Beispiel überzeugen.


    Wenn man eine mehrfach verschachtelte Schleife aus einer inneren Schleife heraus komplett verlassen will hilft break nicht unbedingt weiter. Ich denke dabei an so etwas:

    Quellcode

    1. while (outer) {
    2. for (int index = 0; index < count; index++) {
    3. if (something( index )) goto leave_outer;
    4. }
    5. }
    6. leave_outer:


    Bisher bin ich noch nicht in die Verlegenheit gekommen, so etwas machen zu müssen. Aber hier scheint mir das goto sinnvoller, als den Test auf Abbruch in der äußeren Schleife zu wiederholen.
  • Original von dergraf
    Wenn man eine mehrfach verschachtelte Schleife aus einer inneren Schleife heraus komplett verlassen will hilft break nicht unbedingt weiter. Ich denke dabei an so etwas:

    Quellcode

    1. while (outer) {
    2. for (int index = 0; index < count; index++) {
    3. if (something( index )) goto leave_outer;
    4. }
    5. }
    6. leave_outer:


    Quellcode

    1. while (outer) {
    2. for (int index = 0; index < count; index++) {
    3. if (something( index )) {
    4. outer = false;
    5. break;
    6. }
    7. }
    8. }


    Wenn deine Schleife eh eine Abbruchbedingung hat, dann kann man sie auch nutzen. ;)
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Original von Lucas de Vil

    Quellcode

    1. while (outer) {
    2. for (int index = 0; index < count; index++) {
    3. if (something( index )) {
    4. outer = false;
    5. break;
    6. }
    7. }
    8. }


    Wenn deine Schleife eh eine Abbruchbedingung hat, dann kann man sie auch nutzen. ;)


    Das sollte ja nur als Beispiel dienen, hat ja keiner gesagt, dass outer einfach nur eine Bool-Variable sein soll. Und wenn in der äußeren Schleife auch noch weiterer Code vorkommt würde das so auch nicht funktionieren.
  • Original von macmoonshine
    Ein ehemaliger Kollege hat mal ungefähr Folgendes geschrieben:

    Quellcode

    1. for(int i = 1; i <= 3; i++) {
    2. switch(i) {
    3. case 1:
    4. // auskommentierter Code
    5. break;
    6. case 2:
    7. // auskommentierter Code
    8. break;
    9. case 3:
    10. [self doSomethingTrivial];
    11. break;
    12. }
    13. }
    Alles anzeigen
    Den schreckt wahrscheinlich nichts mehr ab. In einem Gespräch ließ er auch mal die Bemerkung fallen, dass er so programmiert, dass es sehr schwer verständlich ist. Dadurch glaubte er unersetzbar zu sein.

    Ich vermute, dass er Gotos liebt.


    Schaffe Probleme, die nur du lösen kannst …
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von dergraf
    Original von Amin Negm-Awad
    Original von MartinH.
    wunderbarer anknüpfpunkt für meine frage ob es schlechter stil ist eine schleife mit break zu verlassen. das ging mir neulich durch den kopf...

    Das ist okay, weil es eine Struktur verlässt.


    Sehe ich auch so, es gibt aber durchaus Leute, die break, continue und return genau so ablehnen wie goto.

    Kann ich sogar verstehen. Aber immerhin hat man da den Vorteil, dass für die im Block angelegten Variablen klar ist, dass sie beseitigt werden, weil eben genau dieser Block verlassen wird.

    Original von dergraf
    Original von Amin Negm-Awad
    Mir fällt wirklich aktuell kein Beispiel mehr ein, bei dem Goto sinnvoll wäre. Für mich ist das anachronistisch, ich lasse mich aber gerne von einem Beispiel überzeugen.


    Wenn man eine mehrfach verschachtelte Schleife aus einer inneren Schleife heraus komplett verlassen will hilft break nicht unbedingt weiter. Ich denke dabei an so etwas:

    Quellcode

    1. while (outer) {
    2. for (int index = 0; index < count; index++) {
    3. if (something( index )) goto leave_outer;
    4. }
    5. }
    6. leave_outer:


    Bisher bin ich noch nicht in die Verlegenheit gekommen, so etwas machen zu müssen. Aber hier scheint mir das goto sinnvoller, als den Test auf Abbruch in der äußeren Schleife zu wiederholen.

    Ja, das Problem mit dem while-do-for-switch-Stack, :) Ich hatte mir auch schon einmal überlegt, ob nicht ein break( ebenen) sinnvoll wäre.

    In der Regel kann man das aber zumindest bei ablehnenden Schleifen recht einfach lösen, ohne die Bedingung zu wiederholen. In deinem Beispiel:

    Quellcode

    1. while( outer ) {
    2. for( int inner = 0; index < count index++ ) {
    3. if( … ) break;
    4. }
    5. if( inner != count ) {
    6. break;
    7. }
    8. }


    Bei verschachtelten while-Schleifen geht das auch:

    Quellcode

    1. while( outer ) {
    2. while( (inner = …) ) {
    3. if( … ) break;
    4. }
    5. if( inner ) {
    6. break;
    7. }
    8. }
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Amin Negm-Awad
    Kannst du mir ein Beispiel nennen, in dem du aktuell ein goto verwendest?


    Klar: In Assemblercode (z.B. in kritischen Abschnitten bei Echtzeitanwendungen auf Embeddedsystemen). Aber das ist nicht der Punkt.

    Aber der Artikel geht genau darum, dass eine Einschränkung der Sprachmittel nicht äquivalent mit strukturierter Programmierung ist. Man kann sowohl strukturiert mit Sprüngen programmieren als auch unstrukturiert ohne. Es geht nicht primär darum, gotos zu verbannen, sondern strukturiert zu programmieren. Zumindest damals war das nicht allen klar.

    Ein Teil von Knuths Text befasst sich mit sinnvollen Möglichkeiten, aus einer oder mehreren Kontrollblöcken auszubrechen - mit dem, was heute weitläufig mit break, continue, und Exceptions möglich ist (und was hier auch gerade wieder diskutiert wird). Die Namen mögen sich geändert haben, aber die Problematik ist immer noch die gleiche. Man kann lange darüber palavern, ob man breaks oder Exceptions mag oder nicht, man kann seine Meinung dazu evangelisieren oder man kann Für, Wider und Alternativen anhand von konkreten Beispielen abwägen. Letzteres passiert in dem Text.

    Don't judge a book by its cover. Read it.
    Multigrad - 360°-Produktfotografie für den Mac
  • Original von mattik
    Original von Amin Negm-Awad
    Kannst du mir ein Beispiel nennen, in dem du aktuell ein goto verwendest?


    Klar: In Assemblercode (z.B. in kritischen Abschnitten bei Echtzeitanwendungen auf Embeddedsystemen). Aber das ist nicht der Punkt.

    Eben. Und dort heißt das dann auch jump, nicht goto. (Mir ist jendefalls noch kein Mnenomic Goto untergekommen. Ich mache das aber schon lange nicht mehr.)

    Original von mattikAber der Artikel geht genau darum, dass eine Einschränkung der Sprachmittel nicht äquivalent mit strukturierter Programmierung ist. Man kann sowohl strukturiert mit Sprüngen programmieren als auch unstrukturiert ohne. Es geht nicht primär darum, gotos zu verbannen, sondern strukturiert zu programmieren. Zumindest damals war das nicht allen klar.

    Na, ja, aktuell ist das aber schon klar.

    Aber gerade bei goto verstehe ich das nicht. goto hält sich bewusst nicht an die Struktur der Sprache, hier also Blöcke. Das ist einfach schon begrifflich unstrukturiert. Blöcke warum auch die Institution, die den Begriff der strukturierten Programmiersprache begründeten.

    Mir scheint das dann eher ein Wortspiel (Struktur im Sinne der SW-Entwicklung vs. Struktur im ungangssprachlichen Sinne von "übershaubar, geplant") zu sein.

    Original von mattikEin Teil von Knuths Text befasst sich mit sinnvollen Möglichkeiten, aus einer oder mehreren Kontrollblöcken auszubrechen - mit dem, was heute weitläufig mit break, continue, und Exceptions möglich ist (und was hier auch gerade wieder diskutiert wird). Die Namen mögen sich geändert haben, aber die Problematik ist immer noch die gleiche. Man kann lange darüber palavern, ob man breaks oder Exceptions mag oder nicht, man kann seine Meinung dazu evangelisieren oder man kann Für, Wider und Alternativen anhand von konkreten Beispielen abwägen. Letzteres passiert in dem Text.

    Don't judge a book by its cover. Read it.


    Ich hatte ja schon skizziert, warum break et al. etwas anderes als gotos sind: Sie akzeptieren die Struktur , weil sie sich auf einen Block beziehen. goto akzeptiert die Struktur nicht.

    Das ist nicht nur ein quantitativer Unterschied.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Amin Negm-Awad
    Eben. Und dort heißt das dann auch jump, nicht goto. (Mir ist jendefalls noch kein Mnenomic Goto untergekommen. Ich mache das aber schon lange nicht mehr.)

    Ach so, wenn Dich das Wort stört: #define jump goto
    An der Sache ändert das nichts.

    Original von Amin Negm-Awad
    Aber gerade bei goto verstehe ich das nicht. goto hält sich bewusst nicht an die Struktur der Sprache, hier also Blöcke. Das ist einfach schon begrifflich unstrukturiert. Blöcke warum auch die Institution, die den Begriff der strukturierten Programmiersprache begründeten.

    Goto hält sich an die Struktur der Sprache. Goto ist sogar Teil der Sprache.

    Goto erlaubt es, den Kontrollfluss über gewisse Blockgrenzen hinweg zu steuern (nicht über alle - z.B. nur innerhalb einer Funktion oder Methode). Damit lässt sich jede Menge Unfug anstellen - gar keine Frage. Dass es manchmal sinnvoll sein kann, den Kontrollfluss über Blockgrenzen hinweg zu steuern (also z.B. einen Block aus der Mitte heraus zu verlassen), ist, glaube ich, auch nicht strittig, denn break und continue sind ja nicht per se böse. Dass eine while-Sprache universell ist, sich also goto immer umgehen lässt, ist auch klar. Die Frage ist doch, ob goto ausschließlich schlecht ist oder ob es Situationen gibt, in denen goto sinnvoll eingesetzt werden kann. Ich glaube schon, beispielsweise, um verschachtelte Schleifen ohne Zustandsoverhead zu verlassen.

    Wenn man Vorkommen von goto grundsätzlich als schlechten Stil definiert, wird es schwierig, Beispiele für einen sinnvollen Einsatz zu finden.

    Original von Amin Negm-Awad
    Mir scheint das dann eher ein Wortspiel (Struktur im Sinne der SW-Entwicklung vs. Struktur im ungangssprachlichen Sinne von "übershaubar, geplant") zu sein.

    Das mag heue als Wortspiel erscheinen, weil die Blockstruktur in höheren imperativen Sprachen das dominante Mittel der Strukturierung ist. Trotzdem ist Blockstruktur eine Teilmenge von Struktur. Struktur im Sinne von SW-Entwicklung kommt aus dem umganssprachlichen Sinn.


    Original von Amin Negm-Awad
    Ich hatte ja schon skizziert, warum break et al. etwas anderes als gotos sind: Sie akzeptieren die Struktur , weil sie sich auf einen Block beziehen. goto akzeptiert die Struktur nicht.

    Das ist nicht nur ein quantitativer Unterschied.


    "break et al" sind kastrierte gotos - das Eingeständnis, dass es ganz ohne Bruch der Blockstruktur umständlich wird. Aus Blöcken rausspringen ist fein, in Blöcke reinspringen ist böse. Dabei sind break und Konsorten semantisch ziemlich abstrus, weil sie Blöcke unterschiedlich behandeln (Schleifen- und case-Blöcke werden anders behandelt als if- und Sequenzblöcke). Wir nehmen das in unserer Alltagsblindheit als naturgegeben an, weil jemand mal gesagt hat, dass goto gefährlich ist.

    Mit fast jedem Sprachkonstrukt lässt sich schlechter Code schreiben. Je mächtiger das Konstrukt ist, desto einfacher ist es, es zu missbrauchen. Daran ist aber nicht das Sprachkonstrukt schuld, sondern derjenige, der den schlechten Code schreibt.
    Multigrad - 360°-Produktfotografie für den Mac
  • Original von mattik
    "break et al" sind kastrierte gotos - das Eingeständnis, dass es ganz ohne Bruch der Blockstruktur umständlich wird. Aus Blöcken rausspringen ist fein, in Blöcke reinspringen ist böse. Dabei sind break und Konsorten semantisch ziemlich abstrus, weil sie Blöcke unterschiedlich behandeln (Schleifen- und case-Blöcke werden anders behandelt als if- und Sequenzblöcke). Wir nehmen das in unserer Alltagsblindheit als naturgegeben an, weil jemand mal gesagt hat, dass goto gefährlich ist.


    Würden break und continue auch if-Blöcke genau so behandeln wie Schleifen wären die nicht mehr so wirklich nützlich und man müsste für den selben Zweck wieder goto verwenden.

    Original von mattik
    Mit fast jedem Sprachkonstrukt lässt sich schlechter Code schreiben. Je mächtiger das Konstrukt ist, desto einfacher ist es, es zu missbrauchen. Daran ist aber nicht das Sprachkonstrukt schuld, sondern derjenige, der den schlechten Code schreibt.


    Ganz meine Meinung.

    Original von FRing
    erinnert mich an Fortran 77 ! Wer von Euch musste noch Fortran im Grundstudium lernen ?
    Oh man, zum Glück ist diese Zeit vorbei !


    Nicht wirklich. Selbst Nicht-Informatiker müssen zum Teil noch Fortran lernen. Ich studiere Chemie, und im Grundpraktikum für theoretische Chemie hätten wir Fortran verwenden sollen. Deswegen, und weil ich lieber im Labor arbeite als hinterm Computer zu sitzen, habe ich mich dann gegen die theoretische Chemie entschieden.
  • Original von mattik
    Original von Amin Negm-Awad
    Eben. Und dort heißt das dann auch jump, nicht goto. (Mir ist jendefalls noch kein Mnenomic Goto untergekommen. Ich mache das aber schon lange nicht mehr.)

    Ach so, wenn Dich das Wort stört: #define jump goto
    An der Sache ändert das nichts.

    Nein, mich stört nicht das Wort.

    Mich stört, dass Assembler keine Blöcke kennt. Es stellt sich da also die Frage, ob ein goto in einer unstrukturierten Programmiersprache unstrukturiert ist. Das war aber nicht die Frage.


    Original von mattik
    Original von Amin Negm-Awad
    Aber gerade bei goto verstehe ich das nicht. goto hält sich bewusst nicht an die Struktur der Sprache, hier also Blöcke. Das ist einfach schon begrifflich unstrukturiert. Blöcke warum auch die Institution, die den Begriff der strukturierten Programmiersprache begründeten.

    Goto hält sich an die Struktur der Sprache. Goto ist sogar Teil der Sprache.

    Ich sprach von der Struktur, nicht von Schlüsselwörtern.
    Die Struktur, nicht jedes einzelne Schlüsselwort, sind Blöcke. C kennt lokale Variablen, anders als Assembler oder altes Basic.

    An diese Struktur hält sich goto nicht. Es ist daher ein Fremdkörper.

    Original von mattik
    Goto erlaubt es, den Kontrollfluss über gewisse Blockgrenzen hinweg zu steuern (nicht über alle - z.B. nur innerhalb einer Funktion oder Methode).

    Genau das hatte ich bereits geschrieben. Schau mal oben.

    Original von mattik
    Damit lässt sich jede Menge Unfug anstellen - gar keine Frage. Dass es manchmal sinnvoll sein kann, den Kontrollfluss über Blockgrenzen hinweg zu steuern (also z.B. einen Block aus der Mitte heraus zu verlassen), ist, glaube ich, auch nicht strittig, denn break und continue sind ja nicht per se böse. Dass eine while-Sprache universell ist, sich also goto immer umgehen lässt, ist auch klar. Die Frage ist doch, ob goto ausschließlich schlecht ist oder ob es Situationen gibt, in denen goto sinnvoll eingesetzt werden kann. Ich glaube schon, beispielsweise, um verschachtelte Schleifen ohne Zustandsoverhead zu verlassen.

    Auch das hatte ich schon alles geschrieben. Das ändert aber nichts daran, dass Blöcke in C-Programm ein Strukturmerkmal ist. break pp. respektieren Blöcke, goto nicht. Damit ist es etwas anderes, siehe oben.

    Original von mattik
    Wenn man Vorkommen von goto grundsätzlich als schlechten Stil definiert, wird es schwierig, Beispiele für einen sinnvollen Einsatz zu finden.

    Ist ja jemanden ansatzweise gelungen. Mir geht es aber nicht darum, ob das schlecht ist. Mir geht es darum, ob es die Struktur berücksichtigt.

    Also kannst du meinetwegen die Frage lesen als eine Aufforderung, ein Beispiel zu finden, ob es einen Fall für ein goto gibt, der die Strukturierung mindestens ebenso abbilden kann wie andere Sprachmittel.

    Und ja, meine Frage war rhetorisch. Und ja, das kann nicht gehen, weil das goto nicht kann.

    Das ändert sich auch nicht dadurch, dass bereits break pp. das nur "halb" machen. Ich hatte bereiots dazu geschrieben, dass break pp. wenigstens die halbe Miete zahlen, während goto keine Miete zahlt.

    Original von mattik
    Original von Amin Negm-Awad
    Mir scheint das dann eher ein Wortspiel (Struktur im Sinne der SW-Entwicklung vs. Struktur im ungangssprachlichen Sinne von "übershaubar, geplant") zu sein.

    Das mag heue als Wortspiel erscheinen, weil die Blockstruktur in höheren imperativen Sprachen das dominante Mittel der Strukturierung ist. Trotzdem ist Blockstruktur eine Teilmenge von Struktur. Struktur im Sinne von SW-Entwicklung kommt aus dem umganssprachlichen Sinn.

    Die Blockstruktur entstand IIRC Anfang der 70er auf der Softwarekrise. Der Artikel ist doch 1974 veröffentlicht worden?

    Jedenfalls ist das alles andere als aktuell. Das ist jetzt 36 Jahre her.

    Original von mattik
    Original von Amin Negm-Awad
    Ich hatte ja schon skizziert, warum break et al. etwas anderes als gotos sind: Sie akzeptieren die Struktur , weil sie sich auf einen Block beziehen. goto akzeptiert die Struktur nicht.

    Das ist nicht nur ein quantitativer Unterschied.


    "break et al" sind kastrierte gotos -

    Nein, break ist eine einbeinige Blockstruktur, weil das eine Bein amputiert wurde, nämlich das Quellbein.
    goto ist eine nullbeinige Blockstruktur, weil beide Beine amputiert wurden, nämlich das Quellbein und das Zielbein.

    Original von mattik
    das Eingeständnis, dass es ganz ohne Bruch der Blockstruktur umständlich wird. Aus Blöcken rausspringen ist fein, in Blöcke reinspringen ist böse.

    Nein. goto springt nicht nur in einen Block herein, sondern aus einem Block heraus und in einen Block herein. Bereits damit ist der Unterschied verdoppelt. Siehe Mietbeispiel, siehe Beinbeispiel.
    (Mit Springen meinst du offensichtlich das "Springen mitten herein/heraus". Dass ich in einen Block am Anfang hereinspringe und aus ihm am Ende herausspringe ist ja nichts Ungewöhnliches und so gewollt.)

    Davon abgesehen: Dass Erzeugen von Objekten in einem Block, etwa lokale Blockvariablen geschieht explizit. Das Beseitigen ist impliziert, sozusagen im }. Wenn ich einen Block verlasse, kann ich das implizieren, weil es bereits impliziert ist. Das Hereinspringen in einen Block, was nur goto erlaubt, ist da anders. Es muss nämlich jetzt etwas machen, was ich eigentlich explizit machen muss und jetzt implizit erfolgt. Oder doch nicht? Oder doch? Es ist also nicht nur das Problem verdoppelt, dass Blöcke nicht respektiert werden, sondern gerade das Hereinspringen erzeugt eine ganz neue Klasse von Problemen.

    Beispiel:

    Quellcode

    1. void function( … )
    2. {
    3. goto other;
    4. int myVar =98:
    5. // some toher Code
    6. int anotherVar = 11;
    7. anotherVar = 12;
    8. other:
    9. }
    Alles anzeigen

    Existieren myVar und anotherVar nach dem Sprung? Mit welchem Wert? Das ist nicht mehr sofort ersichtlich.

    Bei break et al. existiert dieses Problem nicht.

    Original von mattik
    Dabei sind break und Konsorten semantisch ziemlich abstrus, weil sie Blöcke unterschiedlich behandeln (Schleifen- und case-Blöcke werden anders behandelt als if- und Sequenzblöcke). Wir nehmen das in unserer Alltagsblindheit als naturgegeben an, weil jemand mal gesagt hat, dass goto gefährlich ist.

    Ein break in einem if ist unsinnig. Auch ein continue. Das ist offenkundig. Man könnte noch einen Sinn konstruieren, wenn man blocklose ifs hat. Das sind dann aber Teufel und Beelzebub.

    break bezieht sich nie auf case-Blöcke, weil es keine case-Blöcke gibt. ;)

    Es verlässt einen switch-Block, nicht einen case-Block. Das Problem liegt hier auch nicht im break, sondern in der Struktur des switch. Ja, die stört mich auch. Das ist aber ein anderes Thema.

    Original von mattik
    Mit fast jedem Sprachkonstrukt lässt sich schlechter Code schreiben. Je mächtiger das Konstrukt ist, desto einfacher ist es, es zu missbrauchen. Daran ist aber nicht das Sprachkonstrukt schuld, sondern derjenige, der den schlechten Code schreibt.

    Ja, damit kannst du in der Tat jede Strukturierung wegschmeißen.

    Der Unterschied liegt allerdings darin, dass goto die eigene Sprachstruktur verletzt, während es break et al. nur teilweise machen und dabei die Probleme nicht entstehen lassen.

    Aber du kannst mir freilich immer noch ein Beispiel geben. jump in Assembler verletzt die Sprachstruktur jedenfalls nicht, weil (gängiges) Assembler keine Blöcke kennt, sie also nicht verletzen kann.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von dergraf
    Original von mattik
    "break et al" sind kastrierte gotos - das Eingeständnis, dass es ganz ohne Bruch der Blockstruktur umständlich wird. Aus Blöcken rausspringen ist fein, in Blöcke reinspringen ist böse. Dabei sind break und Konsorten semantisch ziemlich abstrus, weil sie Blöcke unterschiedlich behandeln (Schleifen- und case-Blöcke werden anders behandelt als if- und Sequenzblöcke). Wir nehmen das in unserer Alltagsblindheit als naturgegeben an, weil jemand mal gesagt hat, dass goto gefährlich ist.


    Würden break und continue auch if-Blöcke genau so behandeln wie Schleifen wären die nicht mehr so wirklich nützlich und man müsste für den selben Zweck wieder goto verwenden.

    Das ginge schon, weil auf ein if und ein else nicht zwingend ein Block folgen muss. Das ist allerdings auch eher eine – äh – Besonderheit von C, die völlig nutzlos ist.

    Original von dergraf
    Original von mattik
    Mit fast jedem Sprachkonstrukt lässt sich schlechter Code schreiben. Je mächtiger das Konstrukt ist, desto einfacher ist es, es zu missbrauchen. Daran ist aber nicht das Sprachkonstrukt schuld, sondern derjenige, der den schlechten Code schreibt.


    Ganz meine Meinung.

    Meine auch. Hilft aber nicht bei dem Problem.

    Ich ergreife Maßnahmen zur Förderung eines Zieles nicht nur dann, wenn damit das Ziel garantiert erreicht wird.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Amin Negm-Awad
    Original von dergraf
    Würden break und continue auch if-Blöcke genau so behandeln wie Schleifen wären die nicht mehr so wirklich nützlich und man müsste für den selben Zweck wieder goto verwenden.

    Das ginge schon, weil auf ein if und ein else nicht zwingend ein Block folgen muss. Das ist allerdings auch eher eine – äh – Besonderheit von C, die völlig nutzlos ist.


    Das ginge aber nur im einfachstem Fall, wenn außer dem break nichts anderes gemacht werden soll. Aber das scheint mir aber eher die Ausnahme als die Regel zu sein.

    Nur was für einen Nutzen würdest du dir davon versprechen, wenn auf if und else zwingend ein Block folgen müsste? Und wieso sollte das eine Besonderheit von C sein, in sehr vielen (vielleicht sogar den meisten?) Programmiersprachen kann man doch anstelle eines Blocks mit einem einzelnem Statement dieses Statement auch alleine schreiben.

    Für mich ist der Unterschied zwischen den beiden folgenden Zeilen nicht groß genug, um eine Variante davon als mehr oder weniger nützlich zu bezeichnen:

    Quellcode

    1. if (a) b();
    2. if (a) { b(); }
  • @amin: danke! bisher hab ich break noch nicht gebraucht, aber dann muss ich wenigstens kein schlechtes gewissen haben wenn ichs doch mal einsätze.



    Original von macmoonshine
    Ein ehemaliger Kollege hat mal ungefähr Folgendes geschrieben:

    Quellcode

    1. for(int i = 1; i <= 3; i++) {
    2. switch(i) {
    3. case 1:
    4. // auskommentierter Code
    5. break;
    6. case 2:
    7. // auskommentierter Code
    8. break;
    9. case 3:
    10. [self doSomethingTrivial];
    11. break;
    12. }
    13. }
    Alles anzeigen
    Den schreckt wahrscheinlich nichts mehr ab. In einem Gespräch ließ er auch mal die Bemerkung fallen, dass er so programmiert, dass es sehr schwer verständlich ist. Dadurch glaubte er unersetzbar zu sein.

    Ich vermute, dass er Gotos liebt.


    da musste ich doch sehr lachen :D. schon traurig, dass die angst um den job schon leute dazu treibt so zu coden, nur noch sie selbst durchblicken. kleiner vorschlag noch, falls das geht könnte er ja auch einfach gängige begriffe wie "if, for, while, int, string,..." über define in völlig andere dinge ändern. dann blickt er vielleicht bald selbst nicht mehr durch ;).



    an eurer fortran nostalgie kann ich leider nicht teilhaben. das älteste was ich kenn ist turbo pascal oder borland pascal, weis ich schon gar nicht mehr. da war ich etwa 13 und habe versucht erst ein textadventure und dann ein textbasiertes programm bei dem das kampfsystem aus einem pen and paper rpg nachempfunden werden sollte. das hab ich quasi komplett mit case schleifen zusammengebaut, war irgendwo bei der hälfte und hab dann ne fehlermeldung gekriegt, das eine prozedur nicht mehr als 2000 zeilen haben darf. da hab ichs frustriert aufgegeben :D. hätt ich mal die motivation von damals noch...


    so, ich hab auch wieder ne neue frage ;). und zwar hab ich was über properties gelesen und krieg auch hin die normal zu verwenden, aber folgendes schaffe ich nicht:
    angenommen ich hab eine objectinstanz "a" und eine instanz "b", beide von unterschiedlichen klassen. jetzt soll "a" eine property haben, die wie ein zusätzlicher pointer auf "b" wirkt.
    also

    b.wert = 0
    a.prop = b;
    b.wert= 200;
    int test = a.prop.wert;

    jetzt hätte ich gern, das test gleich 200 ist. aber irgendwie krieg ich das nicht hin. jemand ne idee wie das geht, oder mach ich da nen grundsätzlichen denkfehler?
  • Original von MartinH.
    folgendes schaffe ich nicht:
    angenommen ich hab eine objectinstanz "a" und eine instanz "b", beide von unterschiedlichen klassen. jetzt soll "a" eine property haben, die wie ein zusätzlicher pointer auf "b" wirkt.
    also

    b.wert = 0
    a.prop = b;
    b.wert= 200;
    int test = a.prop.wert;

    jetzt hätte ich gern, das test gleich 200 ist. aber irgendwie krieg ich das nicht hin. jemand ne idee wie das geht, oder mach ich da nen grundsätzlichen denkfehler?

    Quellcode

    1. // Class A Header
    2. #import <Cocoa/Cocoa.h>
    3. @class B;
    4. @interface A : NSObject
    5. {
    6. B *prop;
    7. }
    8. @property (retain) B *prop;
    9. @end
    Alles anzeigen

    Quellcode

    1. // Class B Header
    2. #import <Cocoa/Cocoa.h>
    3. @interface B : NSObject
    4. {
    5. int wert;
    6. }
    7. @property (assign) int wert;
    8. @end
    Die Implementierung überlasse ich mal Dir zur Übung. Ist ja nicht mehr viel zu tun.

    Michael
  • erstmal vielen dank michael! ich hab das mal so nachgebaut und es funktioniert mit einem anderen objekt, es funktioniert mit einem int wert, es funktioniert mit nem mutable array, aber es scheint nicht mit nem mutablestring zu gehen.
    hier der relevante teil meines codes:

    Quellcode

    1. @interface GameObject : NSObject
    2. {
    3. NSMutableArray *a;
    4. NSMutableString *s;
    5. }
    6. @property (readwrite,retain) NSMutableString *s;
    7. @property (readwrite,retain) NSMutableArray *a;
    8. @end
    9. @implementation GameObject
    10. @synthesize a,s;
    11. @end
    12. // und dann wo anders irgendwann der aufruf:
    13. GameObject *s1 = [[GameObject alloc] init];
    14. int testint = 333;
    15. NSMutableArray *ar = [NSMutableArray arrayWithCapacity:1];
    16. s1.a = ar;
    17. [ar addObject:[NSNumber numberWithInt:testint]];
    18. testint = 777;
    19. [ar addObject:[NSNumber numberWithInt:testint]];
    20. NSLog(@"%i",[[s1.a objectAtIndex:0] intValue]);
    21. NSLog(@"%i",[[s1.a objectAtIndex:1] intValue]);
    22. NSLog(@"//////////");
    23. NSMutableString *mst = @"blablub";
    24. s1.s = mst;
    25. NSLog(s1.s);
    26. NSLog(mst);
    27. mst = @"hallo hallo";
    28. NSLog(s1.s);
    29. NSLog(mst);
    30. }
    Alles anzeigen


    output:

    Quellcode

    1. 2010-04-09 01:51:17.999 TC_testproject1[9753:20b] 333
    2. 2010-04-09 01:51:18.000 TC_testproject1[9753:20b] 777
    3. 2010-04-09 01:51:18.005 TC_testproject1[9753:20b] //////////
    4. 2010-04-09 01:51:18.013 TC_testproject1[9753:20b] blablub
    5. 2010-04-09 01:51:18.015 TC_testproject1[9753:20b] blablub
    6. 2010-04-09 01:51:18.016 TC_testproject1[9753:20b] blablub
    7. 2010-04-09 01:51:18.017 TC_testproject1[9753:20b] hallo hallo



    wie man sieht funzt das mit dem array prima, aber nicht mit dem NSMutableString. ich meine ich hätte irgendwo mal gelesen, dass nsmutable string beim ändern des wertes nicht den inhalt an der speicherstelle ändert, sondern nen neuen string an einer anderen stelle aufmacht und den pointer auf die neue adresse setzt und die alte wieder freigibt (bzw. ich glaube wenn der pointer umgesetzt wird ist das in etwa das gleiche wie freigeben der alten addresse?!). und wenn ich irgendwo im code schreibe @"test string", dann ist das sozusagen stellvertretend für nen pointer auf eine adresse wo "test string" im speicher steht, und wenn ich irgendeinem NSString object das zuweise, wird der pointer des objectes einfach auf diese neue adresse gesetzt. kann das sein, oder erzähl ich unsinn?
    noch ne verständnisfrage, @class heißt so viel wie "deklaration dieser klasse kommt noch, aber das ist auf jeden fall ne klasse", weil sonst der code nicht kompilieren kann wenn die klasse an der stelle noch nicht deklariert war?
    schreibt ihr eigentlich auch alle mit englischem tastaturlayout, wenn ihr programmiert? mir riet ein freund dazu, weil die klammern und sonderzeichen dann vieeel günstiger liegen. find es sehr ungewöhnlich dauernd zwischen deutsch und englisch zu wechseln, aber ich find es lohnt sich weil []; jeweils nur eine taste brauchen, nix mit shift oder so.
  • Original von dergraf
    Original von Amin Negm-Awad
    Original von dergraf
    Würden break und continue auch if-Blöcke genau so behandeln wie Schleifen wären die nicht mehr so wirklich nützlich und man müsste für den selben Zweck wieder goto verwenden.

    Das ginge schon, weil auf ein if und ein else nicht zwingend ein Block folgen muss. Das ist allerdings auch eher eine – äh – Besonderheit von C, die völlig nutzlos ist.


    Das ginge aber nur im einfachstem Fall, wenn außer dem break nichts anderes gemacht werden soll. Aber das scheint mir aber eher die Ausnahme als die Regel zu sein.

    Nur was für einen Nutzen würdest du dir davon versprechen, wenn auf if und else zwingend ein Block folgen müsste? Und wieso sollte das eine Besonderheit von C sein, in sehr vielen (vielleicht sogar den meisten?) Programmiersprachen kann man doch anstelle eines Blocks mit einem einzelnem Statement dieses Statement auch alleine schreiben.

    Für mich ist der Unterschied zwischen den beiden folgenden Zeilen nicht groß genug, um eine Variante davon als mehr oder weniger nützlich zu bezeichnen:

    Quellcode

    1. if (a) b();
    2. if (a) { b(); }

    Ich sagte ja nicht, dass ich mir einen Nutzen davon verspreche, dass ein Block folgen muss, sondern dass es keinen Nutzen hat, dass kein Block folgen muss.

    Es sind zwei verschiedene Möglichkeiten. Wenn ich zwei Möglichkeiten habe, müssen sich beide rechtfertigen. Sonst ist es einfach eine nutzlose Verkomplizierung.

    Die Gefahr ist halt das Vergessen der Klammern, wenn man den Zweig erweitert.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von MartinH.
    ich meine ich hätte irgendwo mal gelesen, dass nsmutable string beim ändern des wertes nicht den inhalt an der speicherstelle ändert, sondern nen neuen string an einer anderen stelle aufmacht und den pointer auf die neue adresse setzt und die alte wieder freigibt

    Nein, das ist falsch. Das gäbe ja ein schönes Durcheinander, wenn mehrere Objekte Referenzen auf den selben NSMutableString haben.

    Original von MartinH.
    (bzw. ich glaube wenn der pointer umgesetzt wird ist das in etwa das gleiche wie freigeben der alten addresse?!).

    Nein, das nennt man im ungünstigsten Falle ein Speicherleck.

    Original von MartinH.
    und wenn ich irgendwo im code schreibe @"test string", dann ist das sozusagen stellvertretend für nen pointer auf eine adresse wo "test string" im speicher steht, und wenn ich irgendeinem NSString object das zuweise, wird der pointer des objectes einfach auf diese neue adresse gesetzt. kann das sein, oder erzähl ich unsinn?

    Da bringst Du noch ein paar Begriffe durcheinander. Beispiel:

    NSString *aString = @"Test string";

    @"Test string" repräsentiert das NSString Objekt, welches dann an irgendeiner Adresse im Speicher liegt. Der Compiler setzt das entsprechend um.
    NSString *aString ist ein Pointer, der eine Adresse speichern kann.
    NSString *aString = @"Test string"; weist nun die Adresse des NSString Objekts dem Pointer zu.

    In Deinem Beispiel arbeitest Du beim NSMutableArray wie mit einem Objekt, was richtig ist. Bei dem NSMutableString arbeitest Du aber wie mit einem skalarem Datentyp (int, float, ...). Das ist falsch. Auch weist Du dem Pointer für einen NSMutableString, nur einen NSString zu. Der Compiler sollte Dich deswegen auch "ver"warnen. ;)
    Damit Dein Beispiel funktioniert, ersetze Zeile 31 durch

    NSMutableString *mst = [NSMutableString stringWithString:@"blablub"];

    und Zeile 35 durch

    [mst setString:@"hallo hallo"];

    Original von MartinH.
    noch ne verständnisfrage, @class heißt so viel wie "deklaration dieser klasse kommt noch, aber das ist auf jeden fall ne klasse", weil sonst der code nicht kompilieren kann wenn die klasse an der stelle noch nicht deklariert war?

    Korrekt. Damit vermeidet man zirkuläre Imports. Also Header A importiert Header B und Header B importiert Header A.

    Original von MartinH.
    schreibt ihr eigentlich auch alle mit englischem tastaturlayout, wenn ihr programmiert?

    Ich nicht. Aber ich habe mir AutoPairs installiert.

    Michael