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又了更深刻的理解.

  • 相关阅读:
    账户余额查询SQL(分类帐)
    基本值集定义
    EBS 各模块数据传送至总帐 需要运行的请求
    OU、库存组织与子库存
    AP 付款凭证
    WIP 完工入库单
    R12客户表结构分析
    ORACEL R12 总账和子账的关系
    JavaScript(转)
    ftp服务自动上传6410版子上的开发环境的设置
  • 原文地址:https://www.cnblogs.com/sniperHW/p/3116884.html
Copyright © 2011-2022 走看看