racket学习-call/cc (let/cc)

时间:2023-02-19 09:14:54

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

racket学习-call/cc (let/cc)的更多相关文章

  1. Adobe CC Family (CC 2015) 大师版

    Adobe CC Family (CC 2015) 大师版 v5.6#2 ###请彻底卸载旧版后再安装本版! 更新 Adobe Digital Publishing CC 2016.1更新 Adobe ...

  2. Adobe 系列软件通用破解方式(animate cc,Photoshop cc,Flash cc)等

    破解之前准备工作: ①:安装好 试用版的 Adobe软件 ②:下载好破解软件: amtemu.v0.9.2-painter,下载地址:链接:http://pan.baidu.com/s/1nvNR74 ...

  3. cc.progressFromTo cc.progressTo(action 在duration中ProgressTimer的Percentage变化)

    let progressTimer= new cc.ProgressTimer(new cc.Sprite(fileName));this.addChild(progressTimer);progre ...

  4. racket 学习笔记

    length: (define (my-length lst) (if (empty? lst) 0 (+ (my-length (rest lst)) 1))) map: (define (my-m ...

  5. muduo网络库源码学习————Timestamp.cc

    今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...

  6. 学习:CC断点

    断点介绍: shark恒老师说有四种说法,但是其实都是相同的 第一个读法:普通断点 第二个读法:F2断点 第三个读法:INT3断点( int3其实就是汇编指令 ) 第四个读法:CC断点 (CC其实就是 ...

  7. Linux CC攻击脚本

    CC(ChallengeCollapsar)主要是用来攻击页面的.大家都有这样的经历,就是在访问论坛时,如果这个论坛比较大,访问的人比较多,打开页面的速度会比较慢,访问的人越多,论坛的页面越多,数据库 ...

  8. PHP开发中常见的安全问题详解和解决方法(如Sql注入、CSRF、Xss、CC等

    页面导航: 首页 → 网络编程 → PHP编程 → php技巧 → 正文内容 PHP安全 PHP开发中常见的安全问题详解和解决方法(如Sql注入.CSRF.Xss.CC等) 作者: 字体:[增加 减小 ...

  9. call/cc 总结 | Scheme

    call/cc 总结 | Scheme 来源 https://www.sczyh30.com/posts/Functional-Programming/call-with-current-contin ...

随机推荐

  1. Linux虚拟机的安装(使用Centos6.3)

    1.什么是虚拟机? 虚拟机指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统 2.安装Linux虚拟机前要做的准备 2.1:一台windows环境的pc 2.2:下载VM ...

  2. 分别用ToolBar和自定义导航栏实现沉浸式状态栏

    一.ToolBar 1.在build.gradle中添加依赖,例如: compile 'com.android.support:appcompat-v7:23.4.0' 2.去掉应用的ActionBa ...

  3. 安装GIT,集成到Powershell中

    1.首先安装GIT http://msysgit.github.io 下载最新版,然后安装.没什么好说的. 装完之后,把 安装路径/bin 加入到环境变量的Path中 2.删除Git的右键菜单 安装完 ...

  4. Ajax 知识点

    AJAX 即"Asynchronous Javascript And XML"(异步JavaScript和XML) Ajax 不是某种编程语言,只是一种在无需重新加载整个网页的情况 ...

  5. spring源码分析(一)IoC、DI

    创建日期:2016.08.06 修改日期:2016.08.07 - 2016.08.12 交流QQ:992591601 参考书籍:<spring源码深度解析>.<spring技术内幕 ...

  6. whoami 和 Who am i

    ① 两个命令在一般的情况下,似乎效果是一样的 ② 但是当你执行完su 命令切换用户后,就不一样了,who am i 显示最早login的账户,而whoami 显示切换后的账户 例如: -bash-3. ...

  7. 0c-33-&commat;class&comma;循环retain

    2个对象互相有着引用,A中有B,B中有A. // 对于循环retain的情况,对象不能够释放,此时只能让一方使用assign一方使用retain,retain用于对象assign用于基本类型,assi ...

  8. app间互相启动及传参数

    http://blog.sina.com.cn/s/blog_13bc6705b0102wmc5.html http://blog.csdn.net/iefreer/article/details/8 ...

  9. 11&lowbar; for 练习 &lowbar; Math&period;sqrt

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  10. centos7下安装指定版本mysql5&period;7&period;23

    现在mysql版本已经到MySQL 8.0(GA)稳定版本了,所以需求是想简单又快速在centos7下安装指定版本例如MySQL 5.7(GA)版本有下面这种方法 首先需要到mysql官网这里下载对应 ...