Algo&Data IIでは、(長い)関数から「終了」または「戻る」ためにこれらを常に使用していました
たとえば、ツリーをトラバースするためのBFSアルゴリズムは、次のように実装されました。
(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)))))))))
ご覧のとおり、node-discovered関数がtrueを返すと、アルゴリズムは終了します。
(if (node-discovered node)
(exit node))
関数は「戻り値」も提供します:'ノード'
関数が終了する理由は、次のステートメントによるものです。
(call-with-current-continuation
(lambda (my-future)
(set! exit my-future)
exitを使用すると、実行前の状態に戻り、呼び出しスタックが空になり、指定した値が返されます。
したがって、基本的に、call-ccは、再帰全体が自動的に終了するのを待つのではなく、再帰関数からジャンプするために(ここで)使用されます(多くの計算作業を行う場合は非常にコストがかかる可能性があります)
call-ccで同じことを行う別の小さな例:
(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))))