5

Continuation describes what happens next with some value, right? Isn't that just a function that takes a value and does some computation?

(+ (* 2 3) 5)

the continuation of (* 2 3) is (+ _ 5)

(define k (lambda (v) (+ v 5)))

What is the point of using call/cc in here and not using the function k ?

4

3 回答 3

6

真的。所有程序都有继续,直到它停止。一个延续通常是底层实现完成的计算中的一个步骤。

你的例子:

(+ (* 2 3) 5)

组合 + 取决于组合 * 先完成。因此(+ result 5)确实是 的延续(* 2 3)。在这种情况下,这不是一个程序。的用处call/cc是当你有一个你后悔并想要做其他事情的延续,或者你想稍后再回到这个。让我们做第一个:

(define g 0)
(call/cc 
  (lambda (exit)
    (/ 10 (if (= g 0) (exit +Inf.0) g))))

显然,当 if 的结果完成时,有一个除法是延续,但由于exit运行,整个事情都会短路以返回 +Inf.0。

如果不让它在之后进行除法,你将如何用一个程序来做到这一点?在这种风格下,你不能。

这并不是真正的魔法,因为 Scheme 将您的代码转换为继续传递样式(=CPS)并且在 CPS 中 call/cc 并没有什么特别之处。在 CPS 中编写代码并非易事。

这是 CPS 的定义call/cc

(define (kcall/cc k consumer)
  (consumer k (lambda (ignore v) (k v))))
于 2013-08-29T23:57:14.437 回答
4

恭喜!你刚刚发明了连续传递风格!你所做的和它之间的唯一区别call/cccall/cc它会自动完成,并且不需要你重新构建你的代码。

于 2013-08-30T20:54:50.610 回答
2

“延续”是计算的整个未来。计算中的每个点都有一个延续,简单来说,您可以将其视为当前程序计数器和当前堆栈。Schemecall/cc函数方便地捕获当前配置并将其打包成一个函数。当您调用该函数时,您会恢复到计算中的那个点。因此,延续与函数非常不同(但延续函数是一个函数)。

有两种常见情况通常call/cc适用:

  1. 非本地出口。你建立一个延续,做一些计算,突然结束你调用延续的计算。

  2. 重新启动/重新输入计算。在这种情况下,您保存延续,然后根据需要再次调用它。

这是案例 #1 的示例:

(begin
  ;; do stuff
  (call/cc (lambda (k)
              ;; do more

             ;; oops, must 'abort'
             (k 'ignore)))
  ;; continue on
  )

以下是案例 #2 的示例:

> (define c #f)
> (let ((x 10))
   (display (list (+ 1 (call/cc (lambda (k) (set! c k) x))) 111))
   (display " more"))
(11 111) more
> (c 20)
(21 111) more
> (c 90)
(91 111) more

对于这种情况#2,值得注意的是,延续将您带回到顶级 read-eval-print 循环 - 这使您有机会在此示例中重新调用延续!

于 2013-08-30T22:24:24.067 回答