Seite 2 von 3
Re: Problem mit Variablen vom Typ Double
Verfasst: 07.06.2017 21:31
von man-in-black
Hi Kurzer,
Also ich nehme das Goto noch immer sehr gerne, wenn ich am Anfang von Prozeduren diverse Bedingungen prüfe und bei Nichtbestehen dann die Prozedur mit Fehler abbreche.
ProcedureReturn wirkt wie ein Break für die Procedure
(sofern nicht bekannt)
Code: Alles auswählen
...
If Bedingung1 = #False : iFehler = 1 : ProcedureReturn #Error: EndIf
...
MFG
MIB
Re: Problem mit Variablen vom Typ Double
Verfasst: 07.06.2017 22:12
von Kurzer
man-in-black hat geschrieben:ProcedureReturn wirkt wie ein Break für die Procedure
(sofern nicht bekannt)
Doch, ist bekannt. Bei einfachen Prozeduren springe ich auch ggf. gleich oben wieder raus, doch in der Regel sehen meine Prozeduren so wie mit dem Goto aus, wenn "unten" noch eine gemeinsame Fehlerbehandlung erfolgt (Strukturen o. Variablen zurücksetzen, Debug- oder Requesterausgaben, andere Proceduraufrufe... etc.). Ich finde das dann übersichtlicher, weil jeder Block für sich getrennt ist. Oben alle Prüfungen, unten die Fehlerbehandlung und in der Mitte der eigentliche Funktionsblock.
Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 08:43
von GPI
Gerade hier wäre es besonders leicht:
Code: Alles auswählen
Procedure MeineProc()
Protected.i iFehler
iFehler=#ok
If Bedingung1 = #False : iFehler = 1: EndIf
If Bedingung2 = #False : iFehler = 2: EndIf
If Bedingung3 = #False : iFehler = 3: EndIf
ProcedureReturn iFehler
EndProcedure
oder weil es ein abstraktes beispiel ist, wie wäre es so:
Code: Alles auswählen
Procedure MeineProc()
Protected.i iFehler
iFehler=#ok
repeat
If Bedingung1 = #False : iFehler = 1:break: EndIf
If Bedingung2 = #False : iFehler = 2:break: EndIf
If Bedingung3 = #False : iFehler = 3:break: EndIf
until #true
ProcedureReturn iFehler
EndProcedure
Ist imo übersichtlicher als ein Goto, weil du hier auch siehst, ob du alle Schleifen etc. richtig schließt. Bspw. einfach aus einer For-Next-Schleife kann bei anderen Programmiersprachen durchaus Probleme bereiten.
Ich möchte einfach an das "Goto Fail" von Apple erinnern

Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 10:15
von Nino
GPI hat geschrieben:NicTheQuick hat geschrieben:Vampirmonster hat geschrieben:Ja, Leute hassen das arme GOTO
Ich hasse es nicht, denn es gibt immer noch Einsatzgebiete, in denen es den Programmfluss vereinfachen kann.
Mag sein. Aber es ist wie ein Schleudersitz in Flugzeug: Nur weil er da ist, muss man nicht bei jeder Gelegenheit drauf hauen. zu 99% gibt es deutlich elegantere Methoden als ein Goto.
Sehr treffend und anschaulich formuliert!
Dass erfahrene Programmierer und studierte Informatiker Goto selten ganz gezielt in ausgewählten Situationen einsetzen, weil sie genau wissen was sie tun: Das sind gerade die geschätzten max. 1% der Fälle von Goto-Verwendung, die
nicht das Problem ausmachen.

Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 10:22
von NicTheQuick
Wenn wir schon dabei sind, dann darf ich euch diesen Artikel noch ans Herz legen:
Anatomy of a “goto fail” – Apple’s SSL bug explained, plus an unofficial patch for OS X! (Englisch)
Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 10:50
von GPI
Was mir gerade kommt, ich würde das vermutlich auch so schreiben:
Code: Alles auswählen
Procedure MeineProc()
If Bedingung1 = #False
ProcedureReturn #Fehler1
ElseIf Bedingung2 = #False
ProcedureReturn #Fehler2
ElseIf Bedingung3 = #False
ProcedureReturn #Fehler3
Else
;Mache das, was gewünscht ist.
ProcedureReturn #OK
EndIf
EndProcedure
Gibt hunderte Lösungen ohne Goto

Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 11:49
von Kurzer
GPI, Das deckt aber nicht die gemeinsame Fehlerbehandlung ab, die ich erwähnte:
doch in der Regel sehen meine Prozeduren so wie mit dem Goto aus, wenn "unten" noch eine gemeinsame Fehlerbehandlung erfolgt (Strukturen o. Variablen zurücksetzen, Debug- oder Requesterausgaben, andere Proceduraufrufe... etc.). Ich finde das dann übersichtlicher, weil jeder Block für sich getrennt ist. Oben alle Prüfungen, unten die Fehlerbehandlung und in der Mitte der eigentliche Funktionsblock.
Aber wie dem auch sei, macht sicher jeder so, wie es ihm am ehesten liegt.

Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 12:55
von Nino
Interessanter Artikel. Vielen Dank für den Link!
Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 14:26
von GPI
Kurzer hat geschrieben:GPI, Das deckt aber nicht die gemeinsame Fehlerbehandlung ab, die ich erwähnte:
Och, auch kein Problem
Code: Alles auswählen
Procedure Test()
ret=#ok
if Bedingung1=#false
ret=#fehler1
elseif Bedingung3=#false
ret=#fehler2
elseif bedingung3=#false
ret=#fehler3
endif
if ret=#ok
;okteil
else
;fehlerbehandlung
endif
procedurereturn ret
endprocedure
Ein Goto ist definitiv nicht nötig...
Re: Problem mit Variablen vom Typ Double
Verfasst: 08.06.2017 17:41
von NicTheQuick
@GPI:
Stell dir vor du musst verschiedene Resourcen nacheinander erstellen, z.B. mehrere AllocateMemory(). Falls das dritte fehlschlägt, musst du die ersten beiden Speicherbereiche wieder freigeben. Mit deinem
If-ElseIf-Konstrukt ist das umständlich bzw. in Purebasic gar nicht möglich, da man nicht gleichzeitig eine Zuweisung und Bedingung in einem Ausdruck schreiben kann. Deswegen nutzt man gerne verschachtelte Ifs.
Code: Alles auswählen
Global.i mem1, mem2, mem3
Procedure init()
mem1 = AllocateMemory(1000)
If mem1
mem2 = AllocateMemory(1000)
If mem2
mem3 = AllocateMemory(1000)
If mem3
;alles okay, weiter geht's
Else
FreeMemory(mem2)
FreeMemory(mem1) ;Redundanz -> Schlecht!
Debug "Fehlgeschlagen"
ProcedureReturn #False
EndIf
Else
FreeMemory(mem1)
Debug "Fehlgeschlagen"
ProcedureReturn #False
EndIf
Else
Debug "Fehlgeschlagen"
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
oder eben Gotos
Code: Alles auswählen
Global.i mem1, mem2, mem3
Procedure init()
mem1 = AllocateMemory(1000)
If Not mem1 : Goto error : EndIf
mem2 = AllocateMemory(1000)
If Not mem2 : Goto error2 : EndIf
mem3 = AllocateMemory(1000)
If Not mem3 : Goto error3 : EndIf
ProcedureReturn #True
error3:
FreeMemory(mem2)
error2:
FreeMemory(mem1)
error:
ProcedureReturn #False
EndProcedure