这个Scheme列表迭代器如何使用call-with-current-continuation?

发布于 2024-11-01 00:20:56 字数 629 浏览 5 评论 0原文

我正在尝试阅读此代码:

(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 在此示例中如何工作吗?

谢谢

I'm trying to read this code:

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

Can anyone explain how call-with-current-continuation works in this example?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ぃ双果 2024-11-08 00:20:56

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

当调用延续时,控制流跳回由 call/cc 获取延续的位置。将 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. list-iter 返回一个没有参数i 的过程。
  2. i被调用时,我们立即获取一个延续并将其传递给control-state。当调用绑定到 return 的延续时,我们将立即返回到调用 i 的人。
  3. 对于列表中的每个元素,我们获取一个新的延续,并用该新的延续覆盖 control-state 的定义,这意味着我们将在下次步骤 2 出现时从那里继续。
  4. 在设置下一次的control-state之后,我们将列表的当前元素传递回return延续,产生列表的一个元素。
  5. 当再次调用 i 时,重复步骤 2,直到 for-each 完成整个列表的工作。
  6. 使用 'list-ending 调用 return 延续。由于 control-state 未更新,因此每次调用 i 时,它都会返回 'list-ending

正如我所说,这是 call/cc 的相当复杂的使用,但我希望这足以完成这个示例。对于延续的更温和的介绍,我建议选择经验丰富的策划者

The essence of call-with-concurrent-continuation, or call/cc for short, is the ability to grab checkpoints, or continuations, during the execution of a program. Then, you can go back to those checkpoints by applying them like functions.

Here's a simple example where the continuation isn't used:

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

If you don't use the continuation, it's hard to tell the difference. Here's a few where we actually use it:

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

When the continuation is invoked, control flow jumps back to where the continuation was grabbed by call/cc. Think of the call/cc expression as a hole that gets filled by whatever gets passed to k.

list-iter is a substantially more complex use of call/cc, and might be a difficult place to begin using it. First, here's an example usage:

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

Here's a sketch of what's happening:

  1. list-iter returns a procedure of no arguments i.
  2. When i is invoked, we grab a continuation immediately and pass it to control-state. When that continuation, bound to return, is invoked, we'll immediately return to whoever invoked i.
  3. For each element in the list, we grab a new continuation and overwrite the definition of control-state with that new continuation, meaning that we'll resume from there the next time step 2 comes along.
  4. After setting up control-state for the next time through, we pass the current element of the list back to the return continuation, yielding an element of the list.
  5. When i is invoked again, repeat from step 2 until the for-each has done its work for the whole list.
  6. Invoke the return continuation with 'list-ended. Since control-state isn't updated, it will keep returning 'list-ended every time i is invoked.

As I said, this is a fairly complex use of call/cc, but I hope this is enough to get through this example. For a gentler introduction to continuations, I'd recommend picking up The Seasoned Schemer.

小草泠泠 2024-11-08 00:20:56

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

来自维基百科:
(定义(f返回)
(返回2)
3)

(display (f (lambda (x) x))) ;显示 3

(display (call-with-current-continuation f)) ;显示 2

因此,基本上,当在没有 current-continuation (cc) 的情况下调用 f 时,该函数将应用于 2,然后返回 3。当使用 current-continuation 时,该参数将应用于 2,这会强制程序跳转到当前延续被调用的位置,并因此返回 2。它可用于生成返回,或暂停执行流程。

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

Basically it takes a function f as its parameter, and applies f to the current context/state of the program.

From wikipedia:
(define (f return)
(return 2)
3)

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

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

So basically when f is called without current-continuation (cc), the function is applied to 2, and then returns 3. When using current-continuation, the parameter is applied to 2, which forces the program to jump to the point where the current-continuation was called, and thus returns 2. It can be used to generate returns, or to suspend execution flow.

If you know C, think about it like this: in C, you can take a pointer to a function. You also have a return mechanism. Suppose the return took a parameter of the same type the function takes. Suppose you could take its address and store that address in a variable or pass it as a parameter, and allow functions to return for you. It can be used to mimic throw/catch, or as a mechanism for coroutines.

盗心人 2024-11-08 00:20:56

这本质上是:

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

希望它更容易理解。

This is essentially:

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

Hope it is easier to understand.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文