Lisp 延续与函数的区别是什么?
Continuation用一些值来描述接下来发生的事情,对吗? 这不只是一个取值并进行计算的函数吗Lisp 延续与函数的区别是什么?,lisp,scheme,continuations,callcc,Lisp,Scheme,Continuations,Callcc,Continuation用一些值来描述接下来发生的事情,对吗? 这不只是一个取值并进行计算的函数吗 (+ (* 2 3) 5) (*23)的延续是(++u5) 在这里使用call/cc而不使用k函数有什么意义?正确。所有程序都会继续,直到停止。一个延续通常是基础实现完成的计算中的一个步骤 你的例子是: (+ (* 2 3) 5) 组合+取决于先完成的组合*。因此,(+result 5)实际上是(*23)的延续。但在这种情况下,这不是一个过程。call/cc的有用之处在于,当你有一个续集时,你
(+ (* 2 3) 5)
(*23)
的延续是(++u5)
在这里使用
call/cc
而不使用k
函数有什么意义?正确。所有程序都会继续,直到停止。一个延续通常是基础实现完成的计算中的一个步骤
你的例子是:
(+ (* 2 3) 5)
组合+取决于先完成的组合*。因此,(+result 5)
实际上是(*23)
的延续。但在这种情况下,这不是一个过程。call/cc
的有用之处在于,当你有一个续集时,你会后悔,想做些别的事情,或者你想以后再做。让我们做第一件事:
(define g 0)
(call/cc
(lambda (exit)
(/ 10 (if (= g 0) (exit +Inf.0) g))))
显然,当if的结果完成时,有一个除法是继续,但是由于退出
被运行,整个过程会短路,返回+Inf.0
如果不让它在事后进行除法,你会怎么做?在这种风格中,你不能
这并不是很神奇,因为Scheme将您的代码转换为CPS,而在CPS中,call/cc并没有什么特别之处。在CPS中编写代码并不是件小事
以下是CPS对call/cc
(define (kcall/cc k consumer)
(consumer k (lambda (ignore v) (k v))))
恭喜你!你刚刚发明了连续传球的风格!你所做的事情与
call/cc
之间的唯一区别在于call/cc
自动执行,并且不需要你重新构造代码。一个“延续”是计算的整个未来。计算中的每一点都有一个延续,简单地说,可以将其视为当前程序计数器和当前堆栈。Schemecall/cc
函数可以方便地捕获当前配置并将其打包成一个函数。当您调用该函数时,您将返回到计算中的该点。因此,延拓函数与函数非常不同(但延拓函数是函数)
有两种常见情况下,通常会应用call/cc
:
对于本例#2,值得注意的是,continuation将您带回顶级的read-eval-print循环,这使您有机会在本例中重新调用continuation 您不能使用参数取当前延续(作为函数)的
call/cc
。编辑您的问题以使用呼叫/cc
!阅读wikipage上的“我没有使用call/cc,我使用的是表示延续的等效函数”?延续在语法上是一个函数,但它表示控制传输。它的调用协议不同于函数的调用协议——它应该永远不会返回。
(define (kcall/cc k consumer)
(consumer k (lambda (ignore v) (k v))))
(begin
;; do stuff
(call/cc (lambda (k)
;; do more
;; oops, must 'abort'
(k 'ignore)))
;; continue on
)
> (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