zoukankan      html  css  js  c++  java
  • shceme学习:continuation(3)阴阳谜题

    本篇分析continuation的一个著名例子"阴阳迷题",这是由David Madore先生提出的,原谜题如下:

    (let* ((yin ((lambda (foo) (display "@") foo) (call/cc (lambda (bar) bar))))
           (yang ((lambda (foo) (display "*") foo) (call/cc (lambda (bar) bar)))))
      (yin yang))

    这里引用了http://www.ibm.com/developerworks/cn/linux/l-schm/part3/中的一些简化手段将其中的lambda表达式定义为过程,使其看起来更清晰:

    (define bar (lambda (bar) bar))
    (define foox (lambda (foo) (display "@") foo))
    (define fooy (lambda (foo) (display "*") foo))

    则上面的繁琐的表达式可以变成为:

     (let* ((yin (foox (call/cc bar)))
           (yang (fooy (call/cc bar))))
      (yin yang))

    将let*改变成let,使其进一步简化为:

      (let ((yin (foox (call/cc bar))))
         (let ((yang (fooy (call/cc bar))))
      (yin yang)))

     这里要说明的一点是,链接处介绍的最后一个简化也就是下面这个:

    最后将let去掉,继而成为:
    ((foox (call/cc bar)) (fooy (call/cc bar)))

    其实是错误的.

    Ok,我们开始人肉解释器的运行:

    (let ((yin (foox (call/cc bar))))
        (let ((yang (fooy (call/cc bar))))
    (yin yang)))

    首先注意到(call/cc bar)会返回一个continuation,这里将第一行和第二行的continuation分别标识为c1,c2. 所以上面代码相当于:

    (let ((yin c1));输出@
        (let ((yang c2));输出*
    (yin yang)))

    而(yin yang)就变成了(c1 c2).(c1 c2)相当于下面的调用

    (define (c1 c2)
        (let ((yin (foox c2)));输出@
            (let ((yang (fooy (call/cc bar))));输出*
        (yin yang)))
    )

    用同样的手段,将(let ((yang (fooy (call/cc bar))))简化成(let ((yang c3))

    (define (c1 c2)
        (let ((yin c2))
            (let ((yang c3))
        (yin yang)))
    )

    所以最后的(yin yang)变成了(c2 c3),而(c2 c3)又相当于下面的函数调用:

    (define (c2 c3)
        (let ((yin c1))
        (let ((yang (fooy c3)));输出*
        (yin yang)))
    )

    继续简化:(yin yang)变成(c1 c3),(c1 c3)又等价于:

    (define (c1 c3)
        (let ((yin (foox c3)));输出@
            (let ((yang (fooy (call/cc bar))));输出*
        (yin yang)))
    )

    将(let ((yang (fooy (call/cc bar))))用(let ((yang c4))替代(yin yang)变成了(c3 c4)

    (define (c3 c4)
        (let ((yin c2))
            (let ((yang (fooy c4)));输出*
        (yin yang)))
    )

    简化后(yin yang)变成(c2 c4),我们又回到这一步

    (define (c2 c4)
        (let ((yin c1))
        (let ((yang (fooy c4)));输出*
        (yin yang)))
    )

    (yin yang)变成(c1 c4)

    现在看下至今为止的输出:@*@**@***

    好了,人肉scheme解释器的过程到此结束,因为这个程序会无休止的运行下去,所以人肉分析也是无休止的.

    经过上述分析之后,相信对阴阳迷题和continuation又了更深刻的理解.

  • 相关阅读:
    Samba 4.0 RC3 发布
    SymmetricDS 3.1.7 发布,数据同步和复制
    Express.js 3.0 发布,Node.js 的高性能封装
    GIFLIB 5.0.1 发布,C语言的GIF处理库
    jQuery UI 1.9.1 发布
    SVN Access Manager 0.5.5.14 发布 SVN 管理工具
    DynamicReports 3.0.3 发布 Java 报表工具
    HttpComponents HttpClient 4.2.2 GA 发布
    AppCan 2.0 正式发布,推移动应用云服务
    Ruby 2.0 的新功能已经冻结
  • 原文地址:https://www.cnblogs.com/sniperHW/p/3116884.html
Copyright © 2011-2022 走看看