21 Stimmen

Suche nach Beispielen für die "echte" Verwendung von Fortsetzungen

Ich versuche, das Konzept der Fortsetzungen zu begreifen, und habe mehrere kleine Lehrbeispiele wie dieses aus dem Wikipedia-Artikel :

(define the-continuation #f)

(define (test)
  (let ((i 0))
    ; call/cc calls its first function argument, passing 
    ; a continuation variable representing this point in
    ; the program as the argument to that function. 
    ;
    ; In this case, the function argument assigns that
    ; continuation to the variable the-continuation. 
    ;
    (call/cc (lambda (k) (set! the-continuation k)))
    ;
    ; The next time the-continuation is called, we start here.
    (set! i (+ i 1))
    i))

Ich verstehe, was diese kleine Funktion bewirkt, aber ich kann keine offensichtliche Anwendung dafür erkennen. Ich erwarte zwar nicht, dass ich in nächster Zeit überall in meinem Code Fortsetzungen verwenden werde, aber ich wünschte, ich wüsste ein paar Fälle, in denen sie sinnvoll sein können.

Ich bin also auf der Suche nach explizit nützlichen Codebeispielen, die zeigen, was Fortsetzungen mir als Programmierer bieten können.

Zum Wohl!

5voto

Ich stieß auf eine Implementierung des amb Betreiber in diese Stelle von http://www.randomhacks.net , unter Verwendung von Fortsetzungen.

Hier ist das, was die amb opeerator tut:

# amb will (appear to) choose values
# for x and y that prevent future
# trouble.
x = amb 1, 2, 3
y = amb 4, 5, 6

# Ooops! If x*y isn't 8, amb would
# get angry.  You wouldn't like
# amb when it's angry.
amb if x*y != 8

# Sure enough, x is 2 and y is 4.
puts x, y 

Und hier ist die Umsetzung des Beitrags:

# A list of places we can "rewind" to
# if we encounter amb with no
# arguments.
$backtrack_points = []

# Rewind to our most recent backtrack
# point.
def backtrack
  if $backtrack_points.empty?
    raise "Can't backtrack"
  else
    $backtrack_points.pop.call
  end
end

# Recursive implementation of the
# amb operator.
def amb *choices
  # Fail if we have no arguments.
  backtrack if choices.empty?
  callcc {|cc|
    # cc contains the "current
    # continuation".  When called,
    # it will make the program
    # rewind to the end of this block.
    $backtrack_points.push cc

    # Return our first argument.
    return choices[0]
  }

  # We only get here if we backtrack
  # using the stored value of cc,
  # above.  We call amb recursively
  # with the arguments we didn't use.
  amb *choices[1...choices.length]
end

# Backtracking beyond a call to cut
# is strictly forbidden.
def cut
  $backtrack_points = []
end

Ich mag amb !

3voto

A. Rex Punkte 31159

Fortsetzungen können in "realen" Beispielen immer dann verwendet werden, wenn der Programmablauf nicht linear oder nicht einmal vorherbestimmt ist. Eine bekannte Situation ist Webanwendungen .

3voto

Greg Punkte 1214

Fortsetzungen sind eine gute Alternative zu Thread-per-Request in der Serverprogrammierung (einschließlich Webanwendungs-Frontends).

Bei diesem Modell starten Sie nicht jedes Mal einen neuen (schweren) Thread, wenn eine Anfrage eingeht, sondern Sie beginnen einfach mit der Arbeit in einer Funktion. Wenn Sie dann bereit sind, die E/A zu blockieren (d.h. aus der Datenbank zu lesen), übergeben Sie eine Fortsetzung an den Network Response Handler. Wenn die Antwort zurückkommt, führen Sie die Fortsetzung aus. Mit diesem Schema können Sie viele Anfragen mit nur wenigen Threads bearbeiten.

Dadurch wird der Kontrollfluss komplexer als bei der Verwendung von blockierenden Threads, aber bei hoher Last ist er effizienter (zumindest auf der heutigen Hardware).

2voto

Zorf Punkte 5860

Der amb-Operator ist ein gutes Beispiel, das eine prolog-ähnliche deklarative Programmierung ermöglicht.

In diesem Moment programmiere ich eine Musikkompositionssoftware in Scheme (ich bin Musiker und habe so gut wie keine Ahnung von der Musiktheorie und analysiere gerade meine eigenen Stücke, um zu sehen, wie die Mathematik dahinter funktioniert).

Mit dem Operator amb kann ich einfach die Bedingungen eingeben, die eine Melodie erfüllen muss, und Scheme das Ergebnis ausrechnen lassen.

Fortsetzungen werden wahrscheinlich wegen der Sprachphilosophie in Scheme eingebaut. Scheme ist ein Rahmenwerk, das es Ihnen ermöglicht, fast jedes Programmierparadigma, das in anderen Sprachen zu finden ist, durch die Definition von Bibliotheken in Scheme selbst zu realisieren. Fortsetzungen dienen dazu, eigene abstrakte Kontrollstrukturen wie 'return' und 'break' zu schaffen oder deklarative Programmierung zu ermöglichen. Scheme ist mehr "verallgemeinernd" und bittet darum, dass solche Konstrukte auch vom Programmierer spezifiziert werden können.

1voto

Tom Dunham Punkte 5611

Wie wäre es mit dem Google Mapplets API ? Es gibt eine Reihe von Funktionen (alle enden auf Async ), dem Sie einen Rückruf übergeben. Die API-Funktion führt eine asynchrone Anfrage durch, ruft das Ergebnis ab und übergibt dieses Ergebnis dann an Ihren Callback (als "nächste Aufgabe"). Klingt sehr ähnlich wie Fortsetzung des Passspiels zu mir.

Ce site Beispiel zeigt einen sehr einfachen Fall.

map.getZoomAsync(function(zoom) {
    alert("Current zoom level is " + zoom); // this is the continuation
});  
alert("This might happen before or after you see the zoom level message");

Da dies Javascript ist, gibt es keine Optimierung des Heckaufrufs Der Stack wächst also mit jedem Aufruf einer Fortsetzung, und Sie geben schließlich den Kontrollfaden an den Browser zurück. Trotzdem denke ich, dass es eine schöne Abstraktion ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X