Frage

Ich bin versucht, herauszufinden, wie ich das tun kann "early return" in einem Schema Verfahren ohne mit einem top-Niveau if oder cond wie konstruieren.

(define (win b)
 (let* ((test (first (first b)))
        (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                       (enumerate (length b)))))
  (when (and (not (= test 0)) result) test))
 0)

Zum Beispiel, in dem obigen code, ich will win zurück test wenn die when Bedingung erfüllt ist, andernfalls 0 zurück.Was jedoch passiert, ist, dass die Prozedur wird immer gibt 0 zurück, unabhängig von dem Ergebnis der when Zustand.

Der Grund, warum ich bin Strukturierung meinen code auf diese Weise ist, weil in diesem Verfahren muss ich tun, zahlreiche, komplexe Prüfungen (mehrere Blöcke ähnlich dem let* in dem Beispiel) und alles in einem großen cond wäre sehr unhandlich.

War es hilfreich?

Lösung

Hier ist, wie sich Anruf- / cc zu bauen return verwenden.

(define (example x)
  (call/cc (lambda (return)
    (when (< x 0) (return #f))
    ; more code, including possible more calls to return
    0)))

Einige Schemata definieren ein Makro namens let / cc, dass Sie etwas von dem Rauschen des Lambda fallen lässt:

(define (example x)
  (let/cc return
    (when (< x 0) (return #f))
    0))

Natürlich, wenn Ihr Schema nicht, geschweige / cc ist trivial zu schreiben.


Das funktioniert, weil Anruf / cc den Punkt speichert, an dem sie als Fortsetzung genannt wurde. Es geht, dass eine Fortsetzung seiner Funktion Argument. Wenn ruft die Funktion, dass eine Fortsetzung, Schema abandons was Call-Stack es bisher gebaut hatte und weiter vom Ende des Anruf / cc Anrufs. Natürlich, wenn die Funktion nie die Fortsetzung ruft, dann gibt es nur normal.

Fortsetzungen nicht wirklich bekommen knifflige, bis Sie sie von dieser Funktion beginnen Rückkehr, oder vielleicht sie in einer globalen Datenstruktur zu speichern und später wieder aufrufen. Ansonsten sind sie wie jede andere Sprache der strukturierten-GOTO-Anweisungen (while / for / Pause / Rückgabe / continue / Ausnahmen / Bedingungen).


Ich weiß nicht, was Ihre vollständiger Code aussieht, aber es könnte besser sein, mit dem cond zu gehen und zu Faktor aus den komplexen Kontrollen in separate Funktionen. Needing return und let* ist in der Regel ein Symptom für allzu zwingend notwendig, Code. Allerdings sollte die Anruf- / cc Methode Code Arbeits für bekommen.

Andere Tipps

Eine Möglichkeit wäre, die Rekursion zu verwenden, anstatt Looping, dann ein vorzeitiges Ausscheiden erreicht wird durch nicht weiter Rekursion.

Sie können verwenden Sie den "Aufruf mit aktuellen Fortsetzung" Unterstützung zu simulieren, die eine Rückkehr.Es gibt ein Beispiel auf wikipedia.Die Funktion wird aufgerufen call-with-current-continuation, obwohl es oft ein alias mit der Bezeichnung call/cc das ist genau die gleiche Sache.Es gibt auch eine etwas sauberere Beispiel hier

Hinweis:Dies ist durchaus eine erweiterte Schema Programmierung, Technik und kann ein bisschen Geist biegen auf den ersten...!!!!

In diesem Fall wollen Sie nicht ein, wenn Sie möchten ein, wenn, wenn auch nicht auf oberster Ebene.

(define (win b)
  (let* ((test (first (first b)))
         (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                        (enumerate (length b)))))
    (if (and (not (= test 0)) result) 
        test
        0)))

Der Grund ist es immer Null zurückkehrte, ist, dass, ob der Körper von der, wenn sie ausgeführt habe, würde das Ergebnis auf den Boden fallen gelassen werden. Sie sehen, das Lambda implizit in der Funktion definiert Form erzeugt ein impliziten Block zu beginnen, so

(define foo 
  (lambda (b)
     (begin
       (let ...)
       0)))

und die Art und Weise beginnen Arbeiten ist, dass sie das Ergebnis der letzten Form im Inneren zurückkehrt, während auf dem Boden alle Zwischenergebnisse fallen. Diese Zwischenergebnisse sollen Nebenwirkungen haben. Sie sind nichts davon mit, was toll ist (!), Aber man muss vorsichtig sein, nur eine Form haben (deren Ergebnis, das Sie wirklich wollen) in der Funktionsdefinition.

Grem

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top