【问题标题】:What distinguishes a continuation from a function?延续与函数的区别是什么?
【发布时间】:2013-09-02 13:03:15
【问题描述】:

Continuation 描述了接下来会发生什么并具有一定的价值,对吧? 这不就是一个接受一个值并进行一些计算的函数吗?

(+ (* 2 3) 5)

(* 2 3) 的延续是(+ _ 5)

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

在这里使用call/cc而不使用函数k有什么意义?

【问题讨论】:

  • 您不要使用call/cc,其参数 采用当前延续(作为函数)。编辑您的问题以使用call/cc!阅读continuation上的维基页面
  • 我用的不是call/cc,我用的是等价函数代表延续?
  • Continuation 在语法上是一个函数,但它表示控制转移。它的调用协议与函数的不同——它应该永远不会返回。

标签: lisp scheme continuations callcc


【解决方案1】:

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

你的例子:

(+ (* 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 将您的代码转换为 Continuation Passing Style(=CPS) 并且在 CPS 中 call/cc 并没有什么特别之处。在 CPS 中编写代码并非易事。

这是call/cc的CPS定义

(define (kcall/cc k consumer)
  (consumer k (lambda (ignore v) (k v))))

【讨论】:

    【解决方案2】:

    恭喜!你刚刚发明了连续传递风格!您所做的与 call/cc 之间的唯一区别是 call/cc 会自动执行此操作,并且不需要您重新构建代码。

    【讨论】:

      【解决方案3】:

      “延续”是计算的整个未来。计算中的每个点都有一个延续,简单来说,您可以将其视为当前程序计数器和当前堆栈。 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 循环 - 这使您有机会在此示例中重新调用延续!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-08
        • 2021-02-14
        • 1970-01-01
        • 1970-01-01
        • 2014-05-30
        • 2011-08-28
        相关资源
        最近更新 更多