continuation 及阴阳谜题的详细解释

call-with-current-continuation: obtains its continuation and passes it to procedure. The continuation itself is represented by a procedure. Each time this procedure is applied to zero or more values, it returns the values to the continuation of the call/cc application. If procedure returns normally, the values returned by call/cc are the values returned by procedure.

non-local exit from recursion
(define product
(lambda (ls)
(call/cc
(lambda (break)
(let f ([ls ls])
(cond
[(null? ls) 1]
[(= (car ls) 0) (break 0)]
[else (* (car ls) (f (cdr ls)))]))))))

(((call/cc (lambda (k) k)) (lambda (x) x)) "HEY!")
((k (lambda (x) x)) "HEY!")
==> ;the continuation is: (lambda (x) x)
(((lambda (x) x) (lambda (x) x)) "HEY!")
==> "HEY!"


(let ([x (call/cc (lambda (k) k))])
(x (lambda (ignore) "hi")))
==> ; bind k to x
(k (lambda (ignore) "hi"))
==> ; the continuation is: bind k to x, apply x to (lambda ...)
((lambda (ignore) "hi") (lambda (ignore) "hi"))
==>
"hi"


let-values is a convenient way to receive multiple values and bind them to variables.
(let-values ([(a b) (values 1 2)] [c (values 1 2 3)])
(list a b c)) <graphic> (1 2 (1 2 3))

values: accepts any number of arguments and simply return the arguments to its contiuation.

call-with-values: applies consumer to the values returned by invoking producer without arguments.

a continuation may accept zero or more than one value:
(call-with-values
(lambda ()
(call/cc (lambda (k) (k 2 3))))
(lambda (x y) (list x y))) ==> (2 3)

更复杂的例子:阴阳谜题
(let* ((yin
((lambda (cc) (display "@") cc) (call/cc (lambda (c) c))))
(yang
((lambda (cc) (display "*") cc) (call/cc (lambda (c) c)))))
(yin yang))
==> @*@**@***@****@*****@******@*******@********@*********@**...

对let绑定变量进行计算:
第一个: 生成lambda表达式l1, 由call/cc生成延续记做k1, 作为实际参数传入l1, 调用(l1 k1),副作用是打印 @, 返回值是k1, 绑定到变量名yin;
第二个: 生成lambda表达式l2, 由call/cc生成延续记做k2, 作为实际参数传入l2, 调用(l2 k2),副作用是打印 *, 返回值是k2, 绑定到变量名yang;
对let body进行计算:
变量名查找替换,结果是(k1 k2)。 (k1 k2)的意思是把k2返回到k1延续,即上面蓝色开始的:
调用(l1 k2), 打印 @,返回k2, 绑定到yin;
继续计算第二个: 生成lambda表达式l2', 由call/cc生成新的延续记做k3, 调用(l2' k3), 打印 *, 返回k3,绑定到yang;
继续对let body进行计算: 变量名替换,结果是(k2 k3)。(k2 k3)含义是把k3返回到k2延续,即上面红色开始的:
调用(l2 k3),打印 *, 返回k3, 绑定到yang;
继续对let body进行计算:变量名替换,注意k2环境下yin是k1, 结果是(k1 k3)。(k1 k3)是把k3返回到k1延续之处,即上面蓝色开始的:
调用(l1 k3), 打印*, 返回k3, 绑定到yin;
继续计算第二个: 生成lambda表达式l2'', 由call/cc生成新的延续记做k4, 调用(l2'' k4), 打印 @,返回k4, 绑定给yang.
继续对let body进行计算...
把上面绿色标记的顺序串起来就解释了阴阳谜题的输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值