In Algo & Data II haben wir diese immer benutzt, um eine (lange) Funktion zu beenden oder zurückzugeben
Der BFS-Algorithmus zur Durchquerung von Bäumen wurde beispielsweise folgendermaßen implementiert:
(define (BFS graph root-discovered node-discovered edge-discovered edge-bumped . nodes)
(define visited (make-vector (graph.order graph) #f))
(define q (queue.new))
(define exit ())
(define (BFS-tree node)
(if (node-discovered node)
(exit node))
(graph.map-edges
graph
node
(lambda (node2)
(cond ((not (vector-ref visited node2))
(when (edge-discovered node node2)
(vector-set! visited node2 #t)
(queue.enqueue! q node2)))
(else
(edge-bumped node node2)))))
(if (not (queue.empty? q))
(BFS-tree (queue.serve! q))))
(call-with-current-continuation
(lambda (my-future)
(set! exit my-future)
(cond ((null? nodes)
(graph.map-nodes
graph
(lambda (node)
(when (not (vector-ref visited node))
(vector-set! visited node #t)
(root-discovered node)
(BFS-tree node)))))
(else
(let loop-nodes
((node-list (car nodes)))
(vector-set! visited (car node-list) #t)
(root-discovered (car node-list))
(BFS-tree (car node-list))
(if (not (null? (cdr node-list)))
(loop-nodes (cdr node-list)))))))))
Wie Sie sehen, wird der Algorithmus beendet, wenn die Funktion node-discovered den Wert true liefert:
(if (node-discovered node)
(exit node))
die Funktion liefert auch einen "Rückgabewert": 'node'
Warum die Funktion beendet wird, liegt an dieser Anweisung:
(call-with-current-continuation
(lambda (my-future)
(set! exit my-future)
Wenn wir exit verwenden, kehrt es in den Zustand vor der Ausführung zurück, leert den Aufrufstapel und gibt den Wert zurück, den Sie ihm gegeben haben.
Im Grunde genommen wird call-cc (hier) verwendet, um aus einer rekursiven Funktion herauszuspringen, anstatt darauf zu warten, dass die gesamte Rekursion von selbst endet (was bei umfangreichen Berechnungen ziemlich teuer sein kann)
ein weiteres kleineres Beispiel, das dasselbe mit call-cc tut:
(define (connected? g node1 node2)
(define visited (make-vector (graph.order g) #f))
(define return ())
(define (connected-rec x y)
(if (eq? x y)
(return #t))
(vector-set! visited x #t)
(graph.map-edges g
x
(lambda (t)
(if (not (vector-ref visited t))
(connected-rec t y)))))
(call-with-current-continuation
(lambda (future)
(set! return future)
(connected-rec node1 node2)
(return #f))))