首页 > 代码库 > call/cc分析一例
call/cc分析一例
(define (fact n) (let ((r 1) (k ‘void)) (call/cc (lambda (c) (set! k c))) (set! r (* r n)) (set! n (- n 1)) (if (= n 1) r (k ‘recurse))))(fact 5)老师:为什么能工作?学生:不知道!老师:(call/cc (lambda (c) (set! k c))) 干了什么?学生:call/cc 的全称是 call-with-current-continuation, 它调用一个单参数的函数,调用时把当前延续作为那个单参数函数的参数。 所以,上式就是把当前延续存入 k 中。老师:当前延续是什么?学生:(escaper (lambda (~) (~ (set! r (* r n)) (set! n (- n 1)) (if (= n 1) r (k ‘recurse)))))老师:怎么存入 k ?学生:(set! k (escaper (lambda (~) (~ (set! (* r n)) (set! n (- n 1)) (if (= n 1) r (k ‘recurse))))))老师:(call/cc (lambda (c) (set! k c))) 和 (set! k (escaper (lambda (~) (~ (set! (* r n)) (set! n (- n 1)) (if (= n 1) r (k ‘recurse)))))) 等价吗,可以相互替换吗?学生:可以!(define (fact n) (let ((r 1) (k ‘void)) (set! k (escaper (lambda (~) (~ (set! (* r n)) (set! n (- n 1)) (if (= n 1) r (k ‘recurse)))))) ;; A (set! r (* r n)) (set! n (- n 1)) (if (= n 1) r (k ‘recurse)))) ;; B老师:为什么能工作?学生:跟踪一下 (fact 5) 就知道了B: n=5 => r=5, n=4 [ n != 1,continue ]A: n=4 => r=20, n=3 [ n != 1, continue ]A: n=3 => r=60, n=2 [ n != 1, continue ]A: n=2 => r=60, n=1 [ n == 1, return r and escape ]老师:为什么是递归的?学生:因为延续是一种函数,延续递归了,这个延续函数就递归了。老师:这里的延续本质上还是递归。尽管延续被叫做有上下文的 goto,这个程序也可以看成用了 goto 的。(define (fact n) (let ((r 1) (k ‘void)) (call/cc (lambda (c) (set! k c))) (set! r (* r n)) (set! n (- n 1)) (if (= n 1) r (k ‘recurse) ;; => go back to (call/cc (lambda (c) (set! k c))) )))学生:但这只是一种“比喻”,实质上它是递归!老师:你说的对。
call/cc分析一例
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。