Frage

Dies hängt damit zusammen Was ist Anruf/CC?, aber ich wollte diese Frage nicht für meine eigenen Zwecke missbrauchen, und einige ihrer Argumente, wie die Analogie zu setjmp/longjmp, entgehen mir.

Ich glaube, ich habe eine ausreichende Vorstellung davon, was eine Fortsetzung ist. Ich betrachte sie als eine Momentaufnahme des aktuellen Aufrufstapels.Ich möchte nicht auf die Diskussion eingehen, warum dies interessant sein könnte oder was man mit Fortsetzungen machen kann.Meine Frage lautet konkreter: Warum muss ich für call/cc ein Funktionsargument angeben?Warum gibt call/cc nicht einfach die aktuelle Fortsetzung zurück, damit ich damit machen kann, was ich will (speichern, aufrufen, was auch immer)?In einem Link von dieser anderen Frage (http://community.schemewiki.org/?call-with-current-continuation-for-C-programmers), heißt es: „Im Wesentlichen ist es nur eine saubere Möglichkeit, die Fortsetzung zu Ihnen zu bringen und spätere Sprünge zurück zum gespeicherten Punkt nicht zu behindern.“, aber ich verstehe es nicht.Es erscheint unnötig kompliziert.

War es hilfreich?

Lösung 4

Gegen gemeinsamen SO Netiquette ich meine eigene Frage zu beantworten, aber mehr als Herausgeber als der Anbieter der Antwort.

Nach einer Weile begann ich eine ähnliche Frage über LTU . Immerhin, das sind die Leute, die Sprache Design erwägen den ganzen Tag, nicht wahr, und einer der Antworten schließlich mit mir gekickt. Nun genannten Dinge hier, z.B. von Eli oder in der ursprünglichen Frage, macht viel mehr Sinn für mich. Es ist alles, was in der Fortsetzung aufgenommen wird, und wo die angelegte Fortsetzung einsetzt.

Einer der Poster bei LTU schrieb:

  

"können Sie genau sehen, wie aufrufe / cc ermöglicht es Ihnen,‚halten die Art und Weise aus.‘Mit em oder erhalten / cc Sie brauchen eine Art von Test zu tun, um zu bestimmen, ob Sie einen Rücksprung oder einfach nur den Anfang nennen. im Grunde genommen Anruf / cc hält die Verwendung der Fortsetzung der Fortsetzung aus, während mit get / cc oder em, die Fortsetzung seiner Verwendung enthält und so (in der Regel) benötigen Sie einen Test zu Beginn der Fortsetzung hinzuzufügen (dh unmittelbar nach get / cc / em) den „mit den Fortsetzungsteilen“ aus dem „Rest der Fortsetzung“ Teile zu trennen. "

Das trieb es für mich nach Hause.

Danke Jungs sowieso!

Andere Tipps

Wenn Sie ein Konstrukt verwenden wie Jay zeigt, dann können Sie die Fortsetzung packen, aber in einer Weise, dass der Wert ergriffen wird bereits verdorben, weil Sie bereits in dieser Fortsetzung. Im Gegensatz dazu kann call/cc verwendet werden, um die Fortsetzung zu greifen, das ist noch anhängig außerhalb des aktuellen Ausdrucks. Zum Beispiel ist eine der einfachsten Anwendungen von Fortsetzungen ist eine Art eines abort zu implementieren:

(call/cc (lambda (abort)
           (+ 1 2 (abort 9))))

Sie können das tun, nicht mit dem Betrieb Sie beschreiben. Wenn Sie versuchen, es:

(define (get-cc) (call/cc values))
(let ([abort (get-cc)]) (+ 1 2 (abort 9)))

Sie dann einen Fehler über 9 als Verfahren zur Anwendung. Dies geschieht, weil abort mit dem neuen Wert von let zum 9 springt zurück - was bedeutet, dass Sie jetzt eine zweite Runde des gleichen Zusatz Ausdruck, außer dass jetzt abort ist verpflichtet, 9 ...

tun

Zwei weitere relevante Hinweise:

  1. Für eine schöne eine praktische Einführung in Fortsetzungen finden Sie unter PLAI .
  2. call/cc ist ein wenig komplex, dass es in einer Funktion übernimmt - ein konzeptionell einfacher zu bedienen Konstrukt ist let/cc, die Sie in einigen Implementierungen wie PLT Scheme finden. Das obige Beispiel wird (let/cc abort (+ 1 2 (abort 9))).

Das wäre weniger vielseitig.Wenn Sie dieses Verhalten wünschen, können Sie einfach Folgendes tun:

(call/cc (lambda (x) x))

Schauen Sie sich die Beispielverwendungen von Fortsetzungen in „Darrell Ferguson und Dwight Deugo“ an.„Anruf mit aktuellen Fortsetzungsmustern“.8. Konferenz über Mustersprachen von Programmen.September 2001.“ (http://library.readscheme.org/page6.html) und versuchen Sie, sie mit einem wie oben definierten Aufruf/CC-Return umzuschreiben.

Ich schlage vor, beginnend selbst zu fragen: was es ist eine First-Class-Fortsetzung zu sein bedeutet

?

Die Fortsetzung eines Ausdrucks besteht im wesentlichen aus zwei Stücken von Daten: eine erste, die Schließung (d.h. environment) dieses Ausdrucks; und zweitens eine Darstellung dessen, was mit dem Ergebnis des Ausdrucks erfolgen. Eine Sprache mit erstklassigen Fortsetzungen, dann ist eine, die Verkapselung von Datenstrukturen aus folgenden Teilen und welche behandelt diese Datenstrukturen genauso wie jedes andere.

Anruf / cc ist eine besonders elegante Art und Weise, diese Idee zu verwirklichen: die aktuelle Fortsetzung wird als Verfahren verpackt bis der kapselt etwas-ist-zu-sein-done-mit-dem-Ausdruck als das, was das Verfahren ist bei der Anwendung auf der Ausdruck; darstellen, bedeutet die Fortsetzung so einfach, dass die Schließung dieses Verfahrens die Umwelt am Standort enthält sie aufgerufen wurde.

Sie könnte sich vorstellen, die Idee der First-Class-Fortsetzungen auf andere Weise zu realisieren. Sie würden nicht nennen werden / cc, und es ist schwer für mich, sich vorzustellen, wie eine solche Darstellung einfacher sein könnte.

Auf einer Trennnote, sollten Sie die Implementierung von let / cc, die Eli erwähnt, die ich lieber bind / cc nennen:

(define-syntax bind/cc
    (syntax-rules ()
        ((bind/cc var . body)
             (call/cc (lambda (var) . body)))))

Und als eine Übung, wie würden Sie Anruf / cc basierend auf bind / cc implementieren?

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