这个Scheme列表迭代器如何使用带有当前continuation的调用



我正在尝试读取以下代码:

(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在这个例子中是如何工作的吗?

感谢

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

这里有一个不使用延续的简单例子:

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

如果不使用continuation,就很难区分。以下是我们实际使用它的几个地方:

> (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时,控制流跳回到call/cc获取continuation的位置。把call/cc表达式想象成一个洞,它被传递给k的任何东西填满。

list-itercall/cc的一个更复杂的用法,可能很难开始使用它

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

以下是正在发生的事情的草图:

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

正如我所说,这是call/cc的一个相当复杂的使用,但我希望这足以通过这个例子。为了更温和地介绍续集,我建议你选择《老练的策划人》。

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

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

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

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

因此,基本上,当f在没有当前延续(cc(的情况下被调用时,函数被应用于2,然后返回3。当使用当前延续时,参数被应用于2,这迫使程序跳到调用当前延续的点,从而返回2。它可以用于生成返回,也可以用于挂起执行流。

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

这本质上是:

(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)

希望它更容易理解。

最新更新