【发布时间】:2020-01-06 18:54:55
【问题描述】:
Lisp in Small Pieces 一书展示了从 Scheme 到延续传递风格的转变(第 5.9.1 章,适用于那些可以阅读这本书的人)。转换表示 lambda 形式的延续,call/cc 应该等同于简单的(lambda (k f) (f k k))。
我不明白这是如何工作的,因为函数的应用和延续之间没有区别。
这是一个从除应用程序之外的所有内容中剥离的转换版本(完整版本可在this gist 中找到):
(define (cps e)
(if (pair? e)
(case (car e)
; ...
(else (cps-application e)))
(lambda (k) (k `,e))))
(define (cps-application e)
(lambda (k)
((cps-terms e)
(lambda (t*)
(let ((d (gensym)))
`(,(car t*) (lambda (,d) ,(k d))
. ,(cdr t*)))))))
(define (cps-terms e*)
(if (pair? e*)
(lambda (k)
((cps (car e*))
(lambda (a)
((cps-terms (cdr e*))
(lambda (a*)
(k (cons a a*)))))))
(lambda (k) (k '()))))
现在考虑来自Wikipedia 的 CPS 示例:
(define (f return)
(return 2)
3)
上述转换会将函数体(return 2) 中的应用程序转换为(return (lambda (g13) ...) 2) 之类的东西。延续作为第一个参数传递,值2 作为第二个参数传递。如果return 是一个普通函数,那就没问题了。但是,return 应该是一个延续,它只接受一个参数。
我看不出这些部分是如何组合在一起的。转换如何将延续表示为 lambda 形式而不特别考虑它们的应用?
【问题讨论】:
标签: scheme lisp continuation-passing