4

我正在尝试阅读此代码:

(define list-iter
  (lambda (a-list)
    (define iter
      (lambda ()
        (call-with-current-continuation control-state)))
    (define control-state
      (lambda (return)
        (for-each
          (lambda (element)
            (set! return (call-with-current-continuation
                           (lambda (resume-here)
                             (set! control-state resume-here)
                             (return element)))))
          a-list)
        (return 'list-ended)))
    iter))

谁能解释call-with-current-continuation这个例子中的工作原理?

谢谢

4

3 回答 3

3

call-with-concurrent-continuation或简称的本质call/cc是在程序执行期间获取检查点或延续的能力。然后,您可以通过像函数一样应用它们来返回这些检查点。

这是一个不使用延续的简单示例:

> (call/cc (lambda (k) (+ 2 3)))
5

如果您不使用延续,则很难区分。以下是我们实际使用它的一些地方:

> (call/cc (lambda (k) (+ 2 (k 3))))
3
> (+ 4 (call/cc (lambda (k) (+ 2 3))))
9
> (+ 4 (call/cc (lambda (k) (+ 2 (k 3)))))
7

当调用 continuation 时,控制流会跳回到 continuation 被抓取的地方call/cc。把call/cc表达式想象成一个洞,被传递给的任何东西填满k

list-iter是 的一个更复杂的用法call/cc,并且可能是一个难以开始使用它的地方。首先,这是一个示例用法:

> (define i (list-iter '(a b c)))
> (i)
a
> (i)
b
> (i)
c
> (i)
list-ended
> (i)
list-ended

这是正在发生的事情的草图:

  1. list-iter返回一个没有参数的过程i
  2. i被调用时,我们立即获取一个延续并将其传递给control-state. 当调用绑定到 的那个延续时return,我们将立即返回调用的那个人i
  3. 对于列表中的每个元素,我们获取一个新的延续并用该新延续覆盖 的定义control-state,这意味着我们将在下一个步骤 2 出现时从那里继续。
  4. 在为下一次设置完成后control-state,我们将列表的当前元素传递回return延续,产生列表的一个元素。
  5. 再次i调用时,从步骤 2 开始重复,直到for-each完成整个列表的工作。
  6. 用调用return延续'list-ended。由于control-state没有更新,'list-ended每次i调用它都会不断返回。

正如我所说,这是一个相当复杂的用法call/cc,但我希望这足以完成这个示例。对于延续的更温和的介绍,我建议选择The Seasoned Schemer

于 2011-04-12T03:17:27.897 回答
0

基本上,它以函数f作为参数,并应用于f程序的当前上下文/状态。

来自维基百科:
(define (f return)
(return 2)
3)

(display (f (lambda (x) x))) ; displays 3

(display (call-with-current-continuation f)) ; displays 2

所以基本上当 f 在没有 current-continuation (cc) 的情况下被调用时,函数被应用到 2,然后返回 3。当使用 current-continuation 时,参数被应用到 2,这迫使程序跳转到current-continuation 被调用,因此返回 2。它可用于生成返回,或暂停执行流程。

如果您了解 C,请这样想:在 C 中,您可以获取指向函数的指针。您还有一个退货机制。假设 return 采用了与函数采用相同类型的参数。假设您可以获取其地址并将该地址存储在变量中或将其作为参数传递,并允许函数为您返回。它可以用来模拟 throw/catch,或者作为协程的一种机制。

于 2011-04-12T03:22:26.880 回答
0

这本质上是:

(define (consume)
  (write (call/cc control)))

(define (control ret)
   (set! ret (call/cc (lambda (resume)
                        (set! control resume)
                        (ret 1))))
   (set! ret (call/cc (lambda (resume)
                        (set! control resume)
                        (ret 2))))
   (set! ret (call/cc (lambda (resume)
                        (set! control resume)
                        (ret 3)))))

(consume)
(consume)
(consume)

希望它更容易理解。

于 2015-06-27T15:37:14.653 回答