博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
racket学习-call/cc (let/cc)
阅读量:5076 次
发布时间:2019-06-12

本文共 2399 字,大约阅读时间需要 7 分钟。

Drracket continuation

文中使用let/cc代替call/cc

Racket文档中,let/cc说明为:
(let/cc k body ...+)
Equivalent to (call/cc (lambda (k) body ...)).

首先,通过一个简单的函数来测试下continuation,注意,下面的函数执行会导致无限循环

#lang racket(define r #f)(define (f) (let/cc k     ;开始捕获continuation,从let/cc开始直到闭括号位置              (set! r k)  ;将continuation保存到变量r中              (println 1) ;continuation内部代码,与普通代码一样执行,没有区别              (r)  ;调用continuation,将导致跳过之后的代码,执行continuation之后的代码即(println 3)              (println 2)  ;上一句调用了continuation,因此此句被跳过,不会执行              ) ;continuation捕获到此结束  (println 3)  ;这是continuation之后的第一句代码,无论在何处调用continuation(r或k)时,都将从此句开始执行  (println 4)  (r)          ;再次调用continuation,将导致再次从continuation结束的地方开始执行,输出3,4后又调用此句,因此导致无限循环  (println 5)  ;上一句调用continuation,从continuation之后开始执行,因此这句不会执行  ) ;函数结束,continuation范围也结束(println "end")  ;此句位置虽在continuation后,但是在函数f之外,因此这句也不会执行

以上代码执行时,会首先输出1,然后无限循环输出3和4,不会输出end,由此例可以看出:

continuation定义从let/cc开始,到闭括号结束,其中BODY部分与其他代码一样执行,没有特殊,调用continuation时,从continuation结束后第一行开始执行,不会
执行continuation内部的代码
continuation后续逻辑,只包含continuation所在函数,与函数外的代码无关

下面的函数,由《Teach Yourself Scheme in Fixnum Days》中13.3中的tree->generator简化而来.

#lang racket(define p  (letrec      ((caller #f)       (generate‐leaves        (lambda ()          (let/cc continuation-1            (set! generate‐leaves                  (lambda ()                    (continuation-1 'resume)))            (caller 21))          (let/cc continuation-2            (set! generate‐leaves                  (lambda ()                    (continuation-2 'resume)))            (caller 22))          (caller '()))))        (lambda ()      (let/cc k        (set! caller k)        (generate‐leaves)))))(p)(p)

过程分析:

1、定义函数p,函数p为letrec的返回,即匿名函数

(lambda ()      (let/cc k        (set! caller k)        (generate‐leaves)))

此时,函数尚未执行,因为caller为空,generate‐leaves为6-17行的函数

2、调用函数p,首先捕获continuation并赋值给caller,相当于注册了一个回调函数,下次调用caller时,函数从continuation之后执行
注意,函数generate‐leaves在捕获continuation的内部,因此调用caller时,不会再次调用generate‐leaves,continuation之后没有代码,因此函数p的返回值即为调用caller的参数
3、调用函数generate‐leaves,捕获当前位置的continuation,并修改函数generate‐leaves为调用当前continuation-1,然后调用caller,程序跳转到caller之后开始执行,caller之后没有代码,因此函数p返回,返回值为caller调用的参数21
4、再次调用函数p,同步骤2
5、再次调用函数generate‐leaves,此时generate‐leaves已经在步骤3中被重新绑定为调用continuation-1,因此调用generate‐leaves,将从continuation-1之后开始执行,即从12行开始执行,捕获continuation-2,重新绑定函数generate‐leaves,并返回值22

转载于:https://www.cnblogs.com/sicf/p/5170086.html

你可能感兴趣的文章
批处理 windows 服务的安装与卸载
查看>>
React文档翻译 (快速入门)
查看>>
nodejs fs路径
查看>>
动态规划算法之最大子段和
查看>>
linux c:关联变量的双for循环
查看>>
深入浅出理解zend framework(三)
查看>>
python语句----->if语句,while语句,for循环
查看>>
javascript之数组操作
查看>>
LinkedList源码分析
查看>>
TF-IDF原理
查看>>
用JS制作博客页面背景随滚动渐变的效果
查看>>
JavaScript的迭代函数与迭代函数的实现
查看>>
一步步教你学会browserify
查看>>
Jmeter入门实例
查看>>
亲近用户—回归本质
查看>>
中文脏话识别的解决方案
查看>>
CSS之不常用但重要的样式总结
查看>>
Python编译错误总结
查看>>
URL编码与解码
查看>>
日常开发时遇到的一些坑(三)
查看>>