Seite 1 von 2
Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 14.12.2011 18:53
von alen
Hallo Community,
ich bin mal wieder in Sachen PB unterwegs und stosse auf ein Grundsatzproblem.
Es wird eine Procedure abgearbeitet die sich selbst wieder aufruft. Nach dem Beispiel als wenn man durch Verzeichnissse oder in der Registry den kompletten Pfad durchsucht. So weit, so gut. Klappt auch.
Was ich brauche ist aus dieser Rekursiven Procedure beim Vorkommen einer Bedingung frühzeitig ausszuteigen mit einem Rückggabewert bsp. der String der dort gefunden wurde. Sprich sobald die Bedingung eintrifft, mit dem Rückgabewert im Gepäck aus der Procedure raus.
Welches ist die beste Praxis für sowas ? Komme auf keine praktikable Lösung.
Grüße
Alen
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 14.12.2011 19:33
von RSBasic
Suchst du vielleicht ProcedureReturn?
Oder bei Schleifen Break?
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 14.12.2011 20:32
von NicTheQuick
Ich würde das so in der Art machen:
Code: Alles auswählen
Procedure recursiveFunction(parameter1, parameter2, *cancelRecursion.Integer = 0)
Protected cancel.i = #False
If (*cancelRecursion = 0)
*cancelRecursion = @cancel
EndIf
;mach was
result = recursiveFunction(wert1, wert2, *cancelRecursion)
If (*cancelRecursion\i)
;brich die Rekursion ab
ProcedureReturn
EndIf
;mach was
result = recursiveFunction(wert1, wert2, *cancelRecursion)
If (*cancelRecursion\i)
;brich die Rekursion ab
ProcedureReturn
EndIf
;mach was
;usw.
If irgendwas_schlimmes_ist_passiert
*cancelRecursion\i = #True
ProcedureReturn
EndIf
;alles ok, gib Ergebnis aus
ProcedureReturn ergebnis
EndProcedure
Debug recursiveFunction(123, 456)
Ich hoffe der Code ist selbsterklärend.
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 14.12.2011 21:21
von Danilo
RSBasic hat geschrieben:Suchst du vielleicht ProcedureReturn?
Oder bei Schleifen Break?
Das heißt aber das bei einer Rekursionstiefe von beispielsweise 10.000 dann
auch 10.000 male zurückgesprungen wird.
Ich vermute mal das alen mit aussteigen meinte, die ganze Rekursion komplett
und unverzüglich zu verlassen und nicht tausende male zurück zu springen.
Für PB ist mir dafür aber auch kein sauberer Weg bekannt. Mit Goto rausspringen
räumt den Stack nicht auf. Exceptions gibt es nicht.
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 14.12.2011 21:46
von ts-soft
Code: Alles auswählen
EnableExplicit
Global newvalue
Procedure Zaehle(value)
value + 1
If value < 1000
Zaehle(value)
Else
newvalue = value
ProcedureReturn
EndIf
EndProcedure
Zaehle(1)
Debug newvalue
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 14.12.2011 22:52
von NicTheQuick
Weiterhin sei noch gesagt, dass man jede Rekursion auch in eine Iteration verwandeln kann. Dazu baut man sich einfach seinen eigenen Stack, falls man ihn überhaupt braucht. Das kommt eben immer auf das zu Grunde liegend Problem an. Aber funktionieren tut es alle mal und man bekommt außerdem keinen Stack-Overflow, der bei tiefen Rekursionen mal schnell erreicht sein kann. Interessanterweise stürzt bei PB einfach das Programm samt Debugger ab, wenn man einen Stack-Overflow provoziert. Ich denke das sollte der Debugger eigentlich auch abfangen.
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 15.12.2011 15:06
von CSHW89
Etwas unsauber, aber mit Speicherung des Stacks, und Goto gehts so:
Code: Alles auswählen
Global __SaveStack
Macro SaveStack()
CompilerIf #PB_Compiler_Processor =#PB_Processor_x86
!MOV dword[v___SaveStack],ESP
CompilerElse
CompilerIf #PB_Compiler_Processor =#PB_Processor_x64
!MOV qword[v___SaveStack],RSP
CompilerElse
CompilerError "Processor not supported by try/catch handler"
CompilerEndIf
CompilerEndIf
EndMacro
Macro GotoBack()
CompilerIf #PB_Compiler_Processor =#PB_Processor_x86
!MOV ESP,dword[v___SaveStack]
CompilerElse
CompilerIf #PB_Compiler_Processor =#PB_Processor_x64
!MOV RSP,qword[v___SaveStack]
CompilerElse
CompilerError "Processor not supported by try/catch handler"
CompilerEndIf
CompilerEndIf
Goto back
EndMacro
Procedure Rec(n)
Debug "Start "+Str(n)
If (n = 0)
GotoBack()
EndIf
Rec(n-1)
Debug "Hier kommste niemals hin"
EndProcedure
Procedure test()
Protected str.s
str = "Fertig!"
SaveStack()
Rec(5)
back:
Debug str
EndProcedure
test()
Mit einem etwas modifiziertem Code aus dem CodeArchiv benutze ich das immer für Try/Catch-Blöcke, und funktioniert wunderbar.
lg Kevin
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 15.12.2011 15:09
von ts-soft
Abgesehen davon, das dieser Code bei mir einen ASM error wirft, warum wollt Ihr immer den Stack
bereinigen, das macht PB doch bei einem ProcedureReturn automatisch, sollte also vollkommen
unnötig sein?
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 15.12.2011 15:14
von NicTheQuick
Nein, PB macht das nicht, wenn man einfach so mit einem Goto aus einer Procedure heraus springt.
Re: Prinzipfrage: Ausstieg aus einer Rekusiven Procedure
Verfasst: 15.12.2011 15:20
von ts-soft
NicTheQuick hat geschrieben:Nein, PB macht das nicht, wenn man einfach so mit einem Goto aus einer Procedure heraus springt.
Naja, aber warum sollte man mit einem Goto aus der Procedure springen, das ist es ja was ich nicht verstehe,
ist doch vollkommen unnötig oder übersehe ich hier etwas?
IMHO kann man rekursive Funktionen problemlos mit einem ProcedureReturn verlassen, so habe ich das gelesen.