zoukankan      html  css  js  c++  java
  • [Scheme]Understanding the Yin-Yang Puzzle

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

    原题:

    1 (let* ((yin
    2          ((lambda (cc) (display "@") cc) (call-with-current-continuation (lambda (c) c))))
    3        (yang
    4          ((lambda (cc) (display "*") cc) (call-with-current-continuation (lambda (c) c)))))
    5     (yin yang))

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

    怎么理解呢?

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

    首先,continuation是什么?

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

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

    首先,yang-continuation怎么表达?

    1 (define (make-yang-continuation yin)
    2   (lambda (yang) 
    3     (putc #*) 
    4     (yin yang))
    5   )

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

    再来看yin-continuation的表示:

    1 (define yin-continuation
    2   (lambda (yin)
    3     (putc #@)
    4     (let ((yang-continuation (make-yang-continuation yin)))
    5       (yang-continuation yang-continuation)))
    6   )

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

    最后,运行整个程序:

    1 (yin-continuation yin-continuation)

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

    完整代码:

     1 #lang racket
     2 
     3 (define n 0)
     4 (define (putc c)
     5   (cond
     6     ((< n 100) (set! n (+ n 1)) (display c))
     7     ((= n 100) (set! n (+ n 1)) (newline))
     8     (else 'ok))
     9   )
    10 
    11 (define (make-yang-continuation yin)
    12   (lambda (yang) 
    13     (putc #*) 
    14     (yin yang))
    15   )
    16 
    17 (define yin-continuation
    18   (lambda (yin)
    19     (putc #@)
    20     (let ((yang-continuation (make-yang-continuation yin)))
    21       (yang-continuation yang-continuation)))
    22   )
    23 
    24 (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后的版本,包含了我部分解题思路)。你觉得这谜题容易懂吗:

     1 local n = 0
     2 function putc(c)
     3     if n < 100 then 
     4         n = n + 1
     5         io.write(c)
     6     elseif n == 100 then 
     7         n = n + 1
     8         os.exit()
     9     end
    10 end
    11 
    12 function make_yang_continuation(yin)
    13     return function(yang)
    14         putc('*')
    15         yin(yang)
    16     end
    17 end
    18 function yin_continuation(yin)
    19     putc('@')
    20     local yang_continuation = make_yang_continuation(yin)
    21     yang_continuation(yang_continuation)
    22 end
    23 
    24 yin_continuation(yin_continuation)
  • 相关阅读:
    Fidder4 顶部提示 “The system proxy was changed,click to reenable fiddler capture”。
    redis 哨兵 sentinel master slave 连接建立过程
    虚拟点赞浏览功能的大数据量测试
    python基础练习题(题目 字母识词)
    python基础练习题(题目 回文数)
    python基础练习题(题目 递归求等差数列)
    python基础练习题(题目 递归输出)
    python基础练习题(题目 递归求阶乘)
    python基础练习题(题目 阶乘求和)
    python基础练习题(题目 斐波那契数列II)
  • 原文地址:https://www.cnblogs.com/cbscan/p/3746861.html
Copyright © 2011-2022 走看看