Seite 1 von 2

Woher kommt das Type = NoneType?

Verfasst: Dienstag 10. Juni 2008, 20:24
von Karl
Ich bin gerade dabei, einen Brainfuckinterpreter in Python zu schreiben.
Ich hatte schon ein oder 2 Denkfehler die mich viel Zeit gekostet haben, bis ich endlich mal drauf gekommen bin, worauf ich nicht geachtet hab ... Aber das hier übersteigt meine Fähigkeiten oO
Die Variable i ist immer int, bis dann plötzlich mal ein TypeError auftritt, der mir sagt, dass ``i += 1`` ungütlig ist, da i vom Typ NoneType ist.

Ich poste jetzt nur mal den wichtigsten Teil:

Code: Alles auswählen

    def loop_begin(self, i):
        if self.array[self.pointer] == 0:
            x = 1
            for i in xrange(len(self.code)):
                if self.code[i] == "[":
                    x += 1
                if self.code[i] == "]":
                    x -= 1
                    if x == 0:
                        return i
        else:
            self.tmp.append(i)
            return i
                

    def loop_end(self, i):
        if self.array[self.pointer] == 0:
            self.tmp.pop()
            return i
        else:
            x = self.tmp.pop()
            self.tmp.append(x)
            return x
        

    def run(self):
        output = ""
        i = 0
        while i < len(self.code):
            if self.code[i] == "+":
                self.increase_field()
                
           [...]

            elif self.code[i] == "[":
                i = self.loop_begin(i) #HIER
                
            elif self.code[i] == "]":
                i = self.loop_end(i)
            i += 1
        print output
            

    
x = Brainfuck()
x.code = ",->,>+>>+<<<[>>>[<<<<+>>>>-]<<[-]<<[>>+<<-[>>>>+<<<<-]]>-]>[++++++.[-]]"
x.run()
Ich hab mal alles andere, was nicht's mit den Schleifen [] zu tun hat, ausgelassen.
Kann ich aber, wenn's funktioniert auch mal reinstellen, um mich anmeckern zu lassen :)
Wenn der Code an manchen Stellen etwas komplizierter geschrieben ist, als nötig, dann tut's mir leid ;)
Jedenfalls hab ich durch einsetzen von ``print`` an allen möglichen Stellen herausgefunden, wo genau das Problem liegt.
Unmittelbar, nachdem in der Methode ``self.run()`` die Zeile ``i = self.loop_begin(i)`` ausgeführt wird (im Code mit einem Kommentar geschildert, damit ihr's direkt findet), scheint i = NoneType zurückgegeben zu werden.
Innerhalb der Methode passiert scheinbar nichts mehr, denn ein ``print`` vor jedem return erzielt keinen Effekt.
Direkt danach hat i den Typ NoneType ...

Woran liegt das?
Ich versteh das nicht ...
Danke schonmal für eure Hilfe :)

Verfasst: Dienstag 10. Juni 2008, 20:58
von Joghurt
Der erste Teil der if-Bedingung in loop_begin hat nicht für alle Fälle ein return. In den Fällen führt das zu einem impliziten return None, und somit ist i dann auch None

Verfasst: Dienstag 10. Juni 2008, 21:00
von Hyperion
Du benutzt i zum einen als Zählvariable und dann weist Du i gleichzeitig Werte aus einer Methoden zu? Ich wette da passiert das Unheil ... woher weißt Du, dass da immer etwas sinnvolles zurückkommt?

Desweiteren könnte etwas im gekürzten Teil passieren, was i nicht gut tut! Denn die Bedingungen, die Du hier aufführst müssen ja nicht zwangsweise eintreten.

Woher weißt Du, dass der Fehler genau da auftritt, wo Du ihn markierst? Und wo tritt er auf? Bei der Zuweisung wohl doch kaum! Und ansonsten muss es ja in der Methode loop_begin passieren ...

Wie gesagt, das i += 1 weiter unten sagt ja noch nichts darüber aus, wo das i zu None wird!

edit: Zu langsam!

Und Jogurt hat wohl Recht!

Verfasst: Dienstag 10. Juni 2008, 21:03
von numerix
Das ist einfach erklärt:
In Python liefert JEDE Funktion einen Rückgabewert. Wenn du nicht mit return .. explizit einen Wert zurücklieferst, dann ist es None.
Im Fall von loop_begin() ist die Rückgabe von i an bestimmte Bedingungen geknüpft. Trifft keine davon zu - und der Fall ist bei dir möglich - dann endet
die Funktion ohne expliziten Rückgabewert und liefert None zurück.

Da du zu None nicht 1 dazuaddieren kannst, kommt die Fehlermeldung.

Edit: Zu langsam :cry:

Verfasst: Dienstag 10. Juni 2008, 21:14
von Karl
Joghurt hat geschrieben:Der erste Teil der if-Bedingung in loop_begin hat nicht für alle Fälle ein return. In den Fällen führt das zu einem impliziten return None, und somit ist i dann auch None
Ich hab auch nach Absenden des Posts genau daran gedacht, aber dann hab ich mir die Funktion nochmal angeschaut:
if und else.
Da sind doch alle Fälle mit einbegriffen? Oder hab ich das irgendwas falsch verstanden?
Aber okay, wenn ich so weiter drüber nachdenke, ist das die einzig logische Erklärung, nur hab ich vorhin nicht dran geglaubt :o
Hyperion hat geschrieben:Du benutzt i zum einen als Zählvariable und dann weist Du i gleichzeitig Werte aus einer Methoden zu? Ich wette da passiert das Unheil ... woher weißt Du, dass da immer etwas sinnvolles zurückkommt?

Desweiteren könnte etwas im gekürzten Teil passieren, was i nicht gut tut! Denn die Bedingungen, die Du hier aufführst müssen ja nicht zwangsweise eintreten.

Woher weißt Du, dass der Fehler genau da auftritt, wo Du ihn markierst? Und wo tritt er auf? Bei der Zuweisung wohl doch kaum! Und ansonsten muss es ja in der Methode loop_begin passieren ...

Wie gesagt, das i += 1 weiter unten sagt ja noch nichts darüber aus, wo das i zu None wird!

edit: Zu langsam!

Und Jogurt hat wohl Recht!
Du hast gar nicht gelesen, was ich schon gesagt hab. Dann hättest du dir viele sinnlose Fragen und Ausrufe sparen können ...
Mir war also klar, dass die Variable durch die Methode loop_begin auf NoneType gesetzt wird und mir war auch klar, dass dies direkt passiert und kein return zurückkommt. Nur wie oben schon geschrieben hab ich das nicht für den möglichen Grund gehalten.

@pütone, ha ha! zu langsam :p
Ich danke euch, und werd das jetzt mal umsetzen, hoffentlich klappts :)
Immer schön wie schnell man hier Antworten bekommt.

Edit: Wunderbar! :) Einfach das else raus, kurz die 2 Zeilen eingerückt und schon klappt's für wirklich alle else-Fälle :)
Vielen Dank, jetzt klappt alles perfekt

Verfasst: Dienstag 10. Juni 2008, 22:48
von Leonidas
Karl hat geschrieben:Ich hab auch nach Absenden des Posts genau daran gedacht, aber dann hab ich mir die Funktion nochmal angeschaut:
if und else.
Da sind doch alle Fälle mit einbegriffen? Oder hab ich das irgendwas falsch verstanden?
Aber okay, wenn ich so weiter drüber nachdenke, ist das die einzig logische Erklärung, nur hab ich vorhin nicht dran geglaubt :o
Nein. Wenn ``self.array[self.pointer] == 0`` zutrifft wechselt er in den 1. ``if``-Zweig dort wird nur wenn ``self.code == "]":`` und gleichzeitig ``x == 0`` ist überhaupt ein Rückgabewert gegeben. In allen anderen Fällen kommt da ``None`` raus.

Verfasst: Dienstag 10. Juni 2008, 23:23
von Karl
Leonidas hat geschrieben:Nein. Wenn ``self.array[self.pointer] == 0`` zutrifft wechselt er in den 1. ``if``-Zweig dort wird nur wenn ``self.code == "]":`` und gleichzeitig ``x == 0`` ist überhaupt ein Rückgabewert gegeben. In allen anderen Fällen kommt da ``None`` raus.

Nein, das kann's nicht sein.
Ich nehm's dir jetzt auch nicht übel, dass du dich nicht genau mit dem Code befasst hast, aber meiner Meinung nach führt die for-Schleife zwangsläufig zum Ende. Da wird lediglich überprüft, wo die zugehörige end-Klammer ist, und die existiert - in einem funktionierendem Brainfuck Programm - immer. Folglich geht's in jedem Fall bis zum return weiter.
Was noch dagegn spricht, es funktioniert alles, obwohl ich an diesem Teil gar nichts geändert hab, ich habe nur das else weggenommen:

Code: Alles auswählen

    def loop_begin(self, i):
        if self.array[self.pointer] == 0:
            x = 1
            for i in xrange(len(self.code)):
                if self.code[i] == "[":
                    x += 1
                if self.code[i] == "]":
                    x -= 1
                    if x == 0:
                        return i
        #hier wäre normalerweise else
        self.tmp.append(i)
        return i
Aber das versteh ich immer noch nicht so ganz, ich dachte ein if/else Konstrukt würde alle möglichen Fälle abdecken :x

PS: Mir fällt grad auf, dass ich aus'm 2. if auch einfach ein elif hätte machen können. Gibt sich das irgendwas? Oder ist das im Prinzip egal und nur in Verbindung mit else nützlich?[/code]

Verfasst: Dienstag 10. Juni 2008, 23:29
von Leonidas
Karl hat geschrieben:PS: Mir fällt grad auf, dass ich aus'm 2. if auch einfach ein elif hätte machen können. Gibt sich das irgendwas? Oder ist das im Prinzip egal und nur in Verbindung mit else nützlich?
Naja, zwischen if und elif besteht durchaus ein Unterschied.

Code: Alles auswählen

val = "ab"
if 'a' in val:
   print 'ja'
elif 'b' in val:
    print 'ja, auch'

Code: Alles auswählen

val = "ab"
if 'a' in val:
   print 'ja'
if 'b' in val:
    print 'ja, auch'

Verfasst: Dienstag 10. Juni 2008, 23:37
von Karl
Okay stimmt ;)
Daran hab ich gerade echt nicht gedacht. Wobei das bei mir aufgrund von sich gegenseitig ausschließenden Bedingungen dann wohl egal ist-
Aber hast du (oder jemand anders) ne Idee, warum in der Methode ein if/else-Konstrukt nicht alle Fälle abdeckt? Ist ja offensichtlich so, aber ich weiß immer noch nicht, warum :x
Edit: Sry die Doppelpunkt-X Smilies sehen so böse aus, ist aber nicht so gemeint ;) Ich bin's nur gewohnt das zu schreiben, keine Ahnung wieso

Verfasst: Dienstag 10. Juni 2008, 23:49
von EyDu
Das liegt daran, dass der else-Block nicht mehr ausgewertet wird, sobald du den dazugehörigen if-Block betreten hast. Die inneren ifs sind vollkommen unabhängig von den umschließenden.

Teste das einfach mal am diesem Stück Code indem du mit den Werten von a und b ein wenig rumspielst.

Code: Alles auswählen

if a:
    print "if"
    if "b":
        print "b"
else:
    print "else"

Verfasst: Mittwoch 11. Juni 2008, 00:00
von Karl
EyDu hat geschrieben:Das liegt daran, dass der else-Block nicht mehr ausgewertet wird, sobald du den dazugehörigen if-Block betreten hast. Die inneren ifs sind vollkommen unabhängig von den umschließenden.

Teste das einfach mal am diesem Stück Code indem du mit den Werten von a und b ein wenig rumspielst.

Code: Alles auswählen

if a:
    print "if"
    if "b":
        print "b"
else:
    print "else"
Hm, das ist mir schon klar.
Sorry, ich glaub ich kann mich einfach nicht ausdrücken :)
Ich mach's nochmal ganz langsam und ganz deutlich, was ich meine.

Also der Code sah, als er noch nicht funktionierte folgendermaßen aus:

Code: Alles auswählen

    def loop_begin(self, i):
        if self.array[self.pointer] == 0:
            x = 1
            for i in xrange(len(self.code)):
                if self.code[i] == "[":
                    x += 1
                if self.code[i] == "]":
                    x -= 1
                    if x == 0:
                        return i
        else:              # else noch da -> funktioniert NICHT!
            self.tmp.append(i)
            return i
Jetzt funktioniert er und sieht so aus:

Code: Alles auswählen

    def loop_begin(self, i):
        if self.array[self.pointer] == 0:
            x = 1
            for i in xrange(len(self.code)):
                if self.code[i] == "[":
                    x += 1
                if self.code[i] == "]":
                    x -= 1
                    if x == 0:
                        return i
        # else nicht mehr da ... der Code FUNKTIONIERT!
        self.tmp.append(i)
        return i
So das hat jetzt gar nichts mit den inneren if's zu tun, da die, wie ich oben erklärt habe, zwangsläufig innerhalb einiger Schleifendurchläufe True sind und somit ``return i`` ausgeführt wird.
Deshalb geht es nur um das äußere if und das else.
Und _mit_ else krieg ich folgendes:

Code: Alles auswählen

>>> ================================ RESTART ================================
>>> 
5
6

Traceback (most recent call last):
  File "C:\Python25\test.py", line 120, in <module>
    x.run()
  File "C:\Python25\test.py", line 113, in run
    i += 1
TypeError: unsupported operand type(s) for +=: 'NoneType' and 'int'
Ohne klappt es ...
Daraus schließe ich, dass if/else nicht alle Fälle berücksichtigt? Das hat mich sehr gewundert, darum war ich auch erst so ratlos, als ich hier gefragt habe, warum zur Hölle mein Programm nicht so richtig will.
Ich hoffe ihr habt jetzt verstanden, was ich meine. Das andere wäre ja recht trivial gewesen ;)

Verfasst: Mittwoch 11. Juni 2008, 00:59
von EyDu
Hab mir schon gedacht, dass meine Antwort zu trivial ist, aber lieber so eine kurze Antwort geben, als erst mal stundenlang zu suchen. Jetzt sehe ich auch die Markierung "HIER"... :roll:

Finde doch mal die Variablenbelegungen raus, bevor "loop_begin" das "None" liefert. Etwas seltsam finde ich, dass du in "loop_begin" immer über die vollständige Länge des Codes iterierst.

Das

Code: Alles auswählen

if self.array[self.pointer] == 0:
            x = 1
            for i in xrange(len(self.code)):
                if self.code[i] == "[":
                    x += 1
                if self.code[i] == "]":
                    x -= 1
                    if x == 0:
                        return i
Kanns man übrigens besser als

Code: Alles auswählen

if self.array[self.pointer] == 0:
            x = 1
            for index, elem enumerate(self.code)
                if elem == "[":
                    x += 1
                elif elem == "]":
                    x -= 1
                    if x == 0:
                        return index
schreiben.

Verfasst: Mittwoch 11. Juni 2008, 01:26
von Karl
EyDu hat geschrieben:Hab mir schon gedacht, dass meine Antwort zu trivial ist, aber lieber so eine kurze Antwort geben, als erst mal stundenlang zu suchen. Jetzt sehe ich auch die Markierung "HIER"... :roll:

Finde doch mal die Variablenbelegungen raus, bevor "loop_begin" das "None" liefert. Etwas seltsam finde ich, dass du in "loop_begin" immer über die vollständige Länge des Codes iterierst.
Ich mach euch ja keinen Vorwurf daraus, dass ihr euch nicht durch jeden Code wühlen wollt ;)
Aber irgendwie nervt's mich langsam, da eigentlich noch keiner was geschrieben hat, was das Problem betrifft :) Das war eher Zufall, dass die Antworten praktisch eine Problemlösung darstellen.
Wie im 1. Post geschrieben (jaja so lange her :D) hab ich schon an allen möglichen stellen ein print eingebaut. ``print i`` um genau zu sein ;)
Daraus hat sich ergeben, dass unmittelbar nach Aufruf der Funktion ``loop_begin``, in welcher die return-Anweisungen nicht mehr erreicht werden (beide nicht) der Wert NoneType zugewiesen wurde.
Ich hab aber jetzt noch ein paar Kleinigkeiten geändert, es scheint jetzt doch auch mit dem else-Teil zu funktionieren. Wobei ich das immer noch ein wenig merkwürdige finde, aber wahrscheinlich würde man den Fehler entdecken, wenn man jeden Schritt des Programms nachvollziehen würde.
Vielleicht gibt's ja doch einen Fall, in dem die return-Anweisung im if-Zweig nicht erreicht wird. Jedenfalls klappt's jetzt bei mir :)
Aber genau wissen, was ich alles geändert hab, tu ich auch nicht mehr ...
EyDu hat geschrieben: Das

Code: Alles auswählen

if self.array[self.pointer] == 0:
            x = 1
            for i in xrange(len(self.code)):
                if self.code[i] == "[":
                    x += 1
                if self.code[i] == "]":
                    x -= 1
                    if x == 0:
                        return i
Kanns man übrigens besser als

Code: Alles auswählen

if self.array[self.pointer] == 0:
            x = 1
            for index, elem enumerate(self.code)
                if elem == "[":
                    x += 1
                elif elem == "]":
                    x -= 1
                    if x == 0:
                        return index
schreiben.
Hm, enumerate kenn ich eigentlich gar nicht und der Code hat wohl ein paar Syntaxfehler ;o

Verfasst: Mittwoch 11. Juni 2008, 06:45
von Hyperion
Karl hat geschrieben: Jetzt funktioniert er und sieht so aus:

Code: Alles auswählen

    def loop_begin(self, i):
        if self.array[self.pointer] == 0:
            x = 1
            for i in xrange(len(self.code)):
                if self.code[i] == "[":
                    x += 1
                if self.code[i] == "]":
                    x -= 1
                    if x == 0:
                        return i
        # else nicht mehr da ... der Code FUNKTIONIERT!
        self.tmp.append(i)
        return i
So das hat jetzt gar nichts mit den inneren if's zu tun, da die, wie ich oben erklärt habe, zwangsläufig innerhalb einiger Schleifendurchläufe True sind und somit ``return i`` ausgeführt wird.
Kann ja nicht sein! Wenn dem so wäre, hätte der Code mit else auch funktionieren müssen. Das das in irgend einer Form klappt ist nun klar, da im Falle, dass an einem Punkt der If-Verschachtelungen keine Bedingung True wird, auf jeden Fall am Ende ein expliziter return Wert zurückgegeben wird.
Deshalb geht es nur um das äußere if und das else.
Nein. s.o.
EyDu hatte Dir doch ein schönes kleines Beispiel geschrieben. Hast Du damit mal herumprobiert? Ansonsten mach doch mal folgendes: Mal Dir das ganze Konstrukt als Baum auf (Weißt Du was Bäume sind in der Domäne Informatik? http://de.wikipedia.org/wiki/Bin%C3%A4rbaum)
Es muss ein vollständiger binärer Baum - d.h. an jedem inneren Knoten müssen zwei Äste abzweigen - dabei rauskommen, wenn Du alle Fälle abdecken und nicht an irgend einer Stelle aus der Verschachtelung rausfliegen willst. Wenn Du das tust, wirst Du sofort merken, dass da an einer Stelle ein Ast fehlt!

@all: Wäre so etwas nicht eigentlich leicht als Test möglich? Kann ja eigentlich nicht so schwer sein, ein Tool zu schreiben, dass das testet - oder kann pylint so etwas?

Verfasst: Mittwoch 11. Juni 2008, 07:44
von BlackJack
@Karl: Hör doch mal auf anderen vor zu werfen, sie würden sich nicht mit Deinem Quelltext im Detail beschäftigen wollen und gehe mal auf die direkten Antworten auf das Problem ein. In diesem Quelltext:

Code: Alles auswählen

    def loop_begin(self, i): 
         if self.array[self.pointer] == 0: 
             x = 1 
             for i in xrange(len(self.code)): 
                 if self.code[i] == "[": 
                     x += 1 
                 if self.code[i] == "]": 
                     x -= 1 
                     if x == 0: 
                         return i 
         else: 
             self.tmp.append(i) 
             return i
besteht im ``if``-Zweig die Möglichkeit, dass *kein* ``return`` ausgeführt wird, und dann wird `None` zurückgegeben. Und das trotz Deiner Behauptung das könne nie passieren. Da es aber *doch* passiert, stell doch mal Deine Sicht der Dinge in Frage und nicht die der Leute, deren Sicht mit denen des Python-Interpreters deckt. *Der* hat nämlich immer Recht.

Verfasst: Mittwoch 11. Juni 2008, 13:41
von Karl
BlackJack hat geschrieben:@Karl: Hör doch mal auf anderen vor zu werfen, sie würden sich nicht mit Deinem Quelltext im Detail beschäftigen wollen und gehe mal auf die direkten Antworten auf das Problem ein. In diesem Quelltext:

Code: Alles auswählen

    def loop_begin(self, i): 
         if self.array[self.pointer] == 0: 
             x = 1 
             for i in xrange(len(self.code)): 
                 if self.code[i] == "[": 
                     x += 1 
                 if self.code[i] == "]": 
                     x -= 1 
                     if x == 0: 
                         return i 
         else: 
             self.tmp.append(i) 
             return i
besteht im ``if``-Zweig die Möglichkeit, dass *kein* ``return`` ausgeführt wird, und dann wird `None` zurückgegeben. Und das trotz Deiner Behauptung das könne nie passieren. Da es aber *doch* passiert, stell doch mal Deine Sicht der Dinge in Frage und nicht die der Leute, deren Sicht mit denen des Python-Interpreters deckt. *Der* hat nämlich immer Recht.
Okay, ich korregiere mich.
Die Möglichkeit besteht tatsächlich, weil ich einen kleinen Fehler eingebaut hab, es müsste x = 0 heißen, keine Ahnung, wie ich auf x = 1 gekommen bin.
Ich war davon überzeugt, dass das if, wenn es aufgerufen wird, zwangsläufig bis zum return durchläuft, aber aufgrund des Fehlers dann eben doch nicht.
Aber mein Vorwurf, dass sich die Leute nicht richtig damit befasst haben, halte ich schon für gerechtfertigt, weil die meisten Antworten irgendwie am Thema vorbeigingen beziehungsweise das Problem falsch interpretiert haben. Ich bin euch aber trotzdem sehr dankbar dafür, dass ihr mir helfen wollt und schätze eure freiwillige Hilfe sehr. Ich bin euch deswegen auch nicht böse, ich will nur eine Tatsache darstellen ;)

@Hyperion: Wie ifs usw funktionieren ist mir eigentlich recht klar ;)
Das Problem lag wie jetzt festgestellt in einem Fehler im Code der ein von mir unerwünschtes Verhalten hervorgebracht hat. Das heißt, es _hätte_ so funktionieren sollen, wie ich es dargestellt habe, aber hat es dann eben doch nicht :o

Also das Problem ist jetzt gelöst, ich danke nochmal für die Antworten.
Tut mir leid, wenn ich manchmal ein wenig ... unverschämt? rüberkomme und mich nicht so recht belehren lasse :p Das nächste mal versuche ich euch einfach direkt zu glauben ;)
Hier war's nur blöd, dass mein Code ohne das else für alle getesteten Beispiele korrekt funktioniert hat und ich deshalb angenommen hab, dass der Code auch korrekt ist und es am else liegen muss.

Verfasst: Mittwoch 11. Juni 2008, 15:08
von numerix
BlackJack hat geschrieben:@Karl: Hör doch mal auf anderen vor zu werfen, sie würden sich nicht mit Deinem Quelltext im Detail beschäftigen wollen und gehe mal auf die direkten Antworten auf das Problem ein.
Ja, in der Tat, Karl, deine Art des Postens ist nicht erfreulich. Schon die ersten Antworten von Joghurt und mir haben das Problem klar benannt - und das dort benannte Problem ist immer noch da. Deine Lösung mit dem weggelassenen "else" zeigt nur, dass du das Problem noch gar nicht erfasst hast.

Hör doch mal auf mit dem "Trial & Error" und dem überheblichen Ton, als müsstest du etwas unglaublich Kompliziertes für Minderbegabte in kleinen Portionen und gut verdaulich anbieten. WIR haben das Problem ja verstanden, DU musst es noch verstehen.

Du hast ja mittlerweile einige konkrete Tipps bekommen ("binärer Baum" z.B.) und Beispielcode zum Testen hast du auch bekommen.

Verfasst: Mittwoch 11. Juni 2008, 15:11
von Hyperion
Karl hat geschrieben: Aber mein Vorwurf, dass sich die Leute nicht richtig damit befasst haben, halte ich schon für gerechtfertigt, weil die meisten Antworten irgendwie am Thema vorbeigingen beziehungsweise das Problem falsch interpretiert haben.
Nein! Da der potenzielle Fehler immer noch besteht (s.u.) und die Antworten zum größten Teil genau auf das immer noch bestehende Problem hingewiesen haben ;-)
@Hyperion: Wie ifs usw funktionieren ist mir eigentlich recht klar ;)
Das Problem lag wie jetzt festgestellt in einem Fehler im Code der ein von mir unerwünschtes Verhalten hervorgebracht hat. Das heißt, es _hätte_ so funktionieren sollen, wie ich es dargestellt habe, aber hat es dann eben doch nicht :o
Ok, aber das Problem besteht immer noch! Schleifen statisch zu verifizieren ist maschinell nicht möglich, da das Problem nur semi-entscheidbar ist. Aber weg von der Theorie. Es mag sein, dass Du in diesem Falle überblickst, dass die Bedingung des if in Zeile 9 auf jeden Fall einmal True ist und somit ein korrektes return stattfindet. Ich kann das so auf die Schnelle nicht und ;-) Insofern ist das Konstrukt immer noch unsicher vom Design her und bei größeren Problemen mit Nebeneffekten nicht mehr beherrschbar.
Insofern liegt die Lösung darin, für jeden Fall ein return einzubauen, damit es eben keine unvorhersehbaren Abbrüche geben kann. Natürlich kann ich solche Konstrukte im kleinen so sicher aufbauen, dass auf jeden Fall einmal eine Bedingung True ist und der einzige Ast einer If-Bedingung angesprungen wird, aber das zu beweisen ist alles andere als trivial und bei größeren Problemen nicht mehr praktikabel.

Ich hoffe Du erkennst spätestens nach diesem Posting, wo der (potenzielle) Fehler liegt :)

Verfasst: Mittwoch 11. Juni 2008, 16:05
von Karl
Das Problem ist doch schon längst behoben und ich hab's auch vorhin schon benannt ;)
Ich hab mich in einem Punkt getäuscht gehabt, weil ich mein if-Zweig für korrekt gehalten habe, aber er war eben nicht korrekt und hat somit nicht das getan, was ich erwartet habe. Jetzt tut er's aber und jetzt bin ich mir auch sicher, dass in jedem Fall ein return zurückgegeben wird, da zu jedem [ in einem korrektem Brainfuckcode auch ein ] gehört, womit die Bedingung immer True ergibt.
So hatte ich mir das auch vorher gedacht, als der Code noch nicht funktioniert hatte und hab deshalb auch einfach mal ganz dreist behauptet: Der Code im if-Zweig gibt auf jeden Fall ein return zurück.
Kommt mal vor, dass man zu fixiert auf eine Sache ist und dann das eigentliche Problem gar nicht erkennt ... Das tut mir jetzt auch im Nachhinein ein wenig Leid weil das den großteil des Threades überflüssig macht :p Und auch mein genervtes Verhalten. Aber aus meiner Sicht die ich _hatte_, die etwas beschränkt war, weil ich nur auf dieses else fixiert war und angenommen hatte, mein if ist korrekt, sah das ganze eben ein wenig anders aus :p

Also tut mir leid, vielleicht liegt's an Schlafmangel (immer schön alles auf äußere Umstände schieben :) ) oder sonstigem ... Ich war wie oben gesagt einfach zu sehr auf das else fixiert und hab den Rest gar nicht mehr richtig überdacht.
Ich hab mir ja schon den Vorsatz gefasst euch beim nächsten Mal gleich zu glauben, aber ich änder ihn jetzt einfach mal ein wenig ab: Ich fasse mir den Vorsatz, beim nächsten Mal genauer über das nachzudenken, was ihr sagt und mich erst eine Weile mit etwas anderem zu beschäftigen, damit ich wieder freier denken kann und nicht so engstirnig bin.

Naja lassen wir's einfach auf sich beruhen, kleine Missverständnisse kommen halt vor.

Verfasst: Mittwoch 11. Juni 2008, 16:31
von Hyperion
Karl hat geschrieben:Das Problem ist doch schon längst behoben und ich hab's auch vorhin schon benannt ;)
Es ist eben nicht wirklich behoben und wo hast Du es benannt?
Jetzt tut er's aber und jetzt bin ich mir auch sicher, dass in jedem Fall ein return zurückgegeben wird, da zu jedem [ in einem korrektem Brainfuckcode auch ein ] gehört, womit die Bedingung immer True ergibt.
Und bei unkorrektem Brainf**ck? (Was uns der Lösung langsam näher führt)
Ich hab mir ja schon den Vorsatz gefasst euch beim nächsten Mal gleich zu glauben, aber ich änder ihn jetzt einfach mal ein wenig ab: Ich fasse mir den Vorsatz, beim nächsten Mal genauer über das nachzudenken, was ihr sagt und mich erst eine Weile mit etwas anderem zu beschäftigen, damit ich wieder freier denken kann und nicht so engstirnig bin.
hehe ... naja, tus lieber noch weiter hier - auch damit am Ende des Threads etwas brauchbares rauskommt, was Suchende weiterbringt! Also besser noch nicht hier abschalten, sondern noch einmal das eigene "Brain" anstregen, damit der Thread nicht so unbefreidigend offen bleibt ;)