lisp - 延续与函数的区别是什么?

标签 lisp scheme continuations callcc

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

(+ (* 2 3) 5)

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

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

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

最佳答案

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

你的例子:

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

关于lisp - 延续与函数的区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18522076/

相关文章:

lisp - 大象数据库

lisp - 将列表传播到父级 sexp

Scheme 格式错误的特殊形式

closures - 闭包和延续之间的区别

java - Java 中的延续

从 Javascript 到 Clojure

design-patterns - 是否有任何动态或基于函数的语言的设计模式

lisp - 有没有更短的方法来编写应用于这样的方案中的列表的函数?

c# - 响应任务完成 : `.ContinueWith()` vs `GetAwaiter().OnCompleted()`

lisp - 取出列表中除最后一次出现的结构之外的所有结构