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

原题:

 (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. tomcat提供文件下载

    引用两篇博客:http://blog.csdn.net/yuan882696yan/article/details/26680253 http://www.cnblogs.com/shenliang1 ...

  2. Java里的构造函数(构造方法)

    构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型 ...

  3. STL源码--iterator和traits编程技法

    第一部分 iterator学习 STL iterators定义: 提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表达方式. 任何iteartor都应该提供5 ...

  4. Controller将Model数据传给View层,View层应该如何处理?

    首先,我们在Model层中添加一个Person类. namespace MVCTest.Models{    public class Person    {        public string ...

  5. Java多线程学习(转载)

    Java多线程学习(转载) 时间:2015-03-14 13:53:14      阅读:137413      评论:4      收藏:3      [点我收藏+] 转载 :http://blog ...

  6. javaweb 乱码---汉字存入mysql数据库中变成乱码

    今天郁闷了一天,java程序在向mysql插入数据前不是乱码,数据库安装时也选了编码为utf8(和我程序的编码格式一致).可是插入数据就变成乱码,相当郁闷. 原因:mysql的配置文件中的编码并没有改 ...

  7. Mac OS X上用CoreCLR运行一个真正的.NET控制台程序

    这个真正的控制台程序来自corefxlab,名叫CoreClrHelloWorld,是一个跨平台的.NET控制台演示程序,可以显示微软.Linux.苹果的logo. CoreClrHelloWorld ...

  8. TCP与UDP协议

    传输控制协议(Transmission Control Protocol, TCP)和用户数据报协议(User Datagram Protocol, UDP)是典型的传输层协议. 传输层协议基于网络层 ...

  9. 拒绝低调,国内首家推出微软WP8.1移动开发全套免费课程

    活动类型:公开课 开始时间:2014-10-20 20:00 活动地点:YY频道:85155393 课程简介:学习本次公开课你将收获和体会到:      Windwos Phone8.1的推出正是微软 ...

  10. [Java Web] 1、Web开发初识——一大堆历史和技术名词

    LZ前言 LZ最近发现网络真是个神奇的东西,以前做的好玩的只能自娱自乐(或者说顾影自怜),现在只要发一个帖子,写一个博客,很快能引来一大群小伙伴的围观(有时候还能遇见几个大牛给个战略性的指导)...L ...