这题目确实比较杀脑细胞...

原题:

 (let* ((yin
((lambda (cc) (display "@") cc) (call-with-current-continuation (lambda (c) c))))
(yang
((lambda (cc) (display "*") cc) (call-with-current-continuation (lambda (c) c)))))
(yin yang))

它会输出“@*@**@***@****@*****@******@*******@********...”

怎么理解呢?

我的方案是移除call/cc,以纯函数的方案重新表示该问题,然后应用代换模型

首先,continuation是什么?

它是一个过程,以一个值为参数,这个值对应call/cc的返回;将实参应用在continuation这个过程上,应该相当于运行程序本身

原则上,continuation中应该包含整个调用栈上各帧及运算的一系列closure,以free variable的方式链接起来,不过由于本题及其简单,大大简化了continuation的近似。

首先,yang-continuation怎么表达?

 (define (make-yang-continuation yin)
(lambda (yang)
(putc #\*)
(yin yang))
)

意思是,提供yin这个free variable,就返回一个continuation;如果你以参数yang(相当于call/cc的返回)调用continuation,就相当于运行程序(即原题中let*的第二部分)

再来看yin-continuation的表示:

 (define yin-continuation
(lambda (yin)
(putc #\@)
(let ((yang-continuation (make-yang-continuation yin)))
(yang-continuation yang-continuation)))
)

这个continuation不需要free variable,因此直接define;它接收一个值yin(即call/cc的返回),再以它为free variable定义yang-continuation,最后,以yang-continuation自身作为参数来继续执行(对应原题中call/cc的参数(lambda (c) c))。

最后,运行整个程序:

 (yin-continuation yin-continuation)

即,yin-continuation以continuation自身作为yin的初始值,运行整个程序。

完整代码:

 #lang racket

 (define n 0)
(define (putc c)
(cond
((< n 100) (set! n (+ n 1)) (display c))
((= n 100) (set! n (+ n 1)) (newline))
(else 'ok))
) (define (make-yang-continuation yin)
(lambda (yang)
(putc #\*)
(yin yang))
) (define yin-continuation
(lambda (yin)
(putc #\@)
(let ((yang-continuation (make-yang-continuation yin)))
(yang-continuation yang-continuation)))
) (yin-continuation yin-continuation)

这里putc打印无限输出串的前100个字符

因为只涉及纯函数,可以开始代换模型了。

下面我将yin-continuation记为y,make-yang-continuation记为m,(y x)可以代换,((m x1) x2)可以代换,前者代换的时候输出@,后者输出*:

(y y) =>

@ ((m y) (m y)) =>
@* (y (m y)) => @* @ ((m (m y)) (m (m y))) =>
@* @* ((m y) (m (m y))) =>
@* @** (y (m (m y))) => @* @** @ ((m (m (m y))) (m (m (m y)))) =>
@* @** @* ((m (m y)) (m (m (m y)))) =>
@* @** @** ((m y) (m (m (m y)))) =>
@* @** @*** (y (m (m (m y)))) => ...

总算找到一个能把自己糊弄过去的说法...

ps. 有人看不懂scheme,给个lua的翻译版,应该没有理解障碍了(是移除call/cc后的版本,包含了我部分解题思路)。你觉得这谜题容易懂吗:

 local n =
function putc(c)
if n < then
n = n +
io.write(c)
elseif n == then
n = n +
os.exit()
end
end function make_yang_continuation(yin)
return function(yang)
putc('*')
yin(yang)
end
end
function yin_continuation(yin)
putc('@')
local yang_continuation = make_yang_continuation(yin)
yang_continuation(yang_continuation)
end yin_continuation(yin_continuation)

[Scheme]Understanding the Yin-Yang Puzzle的更多相关文章

  1. scheme 阴阳谜题

    本篇分析continuation的一个著名例子"阴阳迷题",这是由David Madore先生提出的,原谜题如下: (let* ((yin ((lambda (foo) (disp ...

  2. call/cc 总结 | Scheme

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

  3. 开始学习Scheme

    开始学习Scheme   函数式编程(Functional Programming)是在MIT研究人工智能(Artificial Intelligence)时发明的,其编程语言为Lisp.确切地说,L ...

  4. [Scheme]一个Scheme的Metacircular evaluator

    这个解释器可以用来跑前面两篇文章的例子,所以一并扔出来,三部曲哈哈. Lisp内置的S-expression相当于解析好的语法树,而借助quasiquote和unquote又很容易进行语法树层面的变换 ...

  5. 初识Continuation

    本文来自网易云社区 作者:陆艺 上学时看了SICP之后就对scheme这个看上去比较古怪的语言产生了兴趣. 虽然书里并没有涉及scheme太多语法以及语言上特性的一些东西, 作为一个喜欢折腾的人, 手 ...

  6. Rust 阴阳谜题,及纯基于代码的分析与化简

    Rust 阴阳谜题,及纯基于代码的分析与化简 雾雨魔法店专栏 https://zhuanlan.zhihu.com/marisa 来源 https://zhuanlan.zhihu.com/p/522 ...

  7. KDD2016,Accepted Papers

    RESEARCH TRACK PAPERS - ORAL Title & Authors NetCycle: Collective Evolution Inference in Heterog ...

  8. CSS画图

    The Shapes of CSS All of the below use only a single HTML element. Any kind of CSS goes, as long as ...

  9. [SQL Server] 特殊字符、上标、下标处理

    今天遇到一个问题是往 SQL Server 中导入像m².m³这样的单位数据,可是在 SQL Server 中查看到的都是 m2.m3,于是在网上查了一下资料,顺便摘录下来供日后查阅. 一  Wind ...

随机推荐

  1. iOS 关于nil和Nil及null与<null>的区别

    问题是这样的. NSDictionary *sample = [NSJSONSerialization JSONObjectWithData:received options:NSJSONReadin ...

  2. 导航VC的左右item代码

    代码控制左右item: UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeCustom];     btnCancel.frame= ...

  3. jquery 编码解码

    中文转Unicode:HttpUtility.UrlEncodeUnicode(string str); 转换后中文格式:"%uxxxx" 举例:"柳_abc123&qu ...

  4. java编程规范

    一.规范存在的意义 应用编码规范对于软件本身和软件开发人员而言尤为重要,有以下几个原因: 1.好的编码规范可以尽可能的减少一个软件的维护成本 , 并且几乎没有任何一个软件,在其整个生命周期中,均由最初 ...

  5. Magcodes.WeiChat——通过CsvFileResult以及DataAnnotations实现导出CSV文件

    我们先来看看效果图: 从上图中可以看出,导出的文件中列名与表格名称保持一致,并且忽略了某些字段. 相关代码实现 我们来看相关代码: 页面代码: @using (Html.BeginForm(" ...

  6. GNU libc (Glibc) 2.18 发布

    标准C库Glibc发布2.18正式版.2013-08-12 上一个版本是2012-12-25的2.17. 详细改进:Version 2.18 * The following bugs are reso ...

  7. JS自动化

    写在前面 记得当时刷笔试题的时候有了解过“前端工程化”,无非就是用自动化工具帮助开发人员完成一些小细节,提高工作效率之类的,不过当时可没想到可维护性这么远 构建项目 -> 模块化开发 -> ...

  8. [51单片机] EEPROM AT24c02 [存储\读取一个字节]

    /*----------------------------------------------- 名称:IIC协议 EEPROM24c02 存数读取数据 内容:此程序用于检测EEPROM性能,测试方 ...

  9. Hadoop Capacity Scheduler源码实现剖析

    作者: 大圆那些事 | 文章可以转载,请以超链接形式标明文章原始出处和作者信息 网址: http://www.cnblogs.com/panfeng412/archive/2013/09/13/had ...

  10. Windows 服务器开通防火墙后,IISFTP和Serv U开通的FTP账号不能登录

    应广大服务器客户要求一至反应Windows 服务器开通防火墙后,IISFTP和Serv U开通的FTP账号不能登录,出现列表超时的情况,特提供以下解决方案: 1. IIS FTP用户解决方法: 在防火 ...