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)
  • 相关阅读:
    004.Docker镜像管理
    001.Heartbeat简介
    005.Docker存储管理
    006.Docker网络管理
    012.Docker仓库管理
    013.Docker私有仓库多Harbor同步部署
    007.基于Docker的Etcd分布式部署
    008.Docker Flannel+Etcd分布式网络部署
    009.Docker Compose部署及基础使用
    002.Open-Falcon Server部署及Agent监控
  • 原文地址:https://www.cnblogs.com/cbscan/p/3746861.html
Copyright © 2011-2022 走看看