[Scheme]Understanding the Yin-Yang Puzzle

這題目確實比較殺腦細胞...函數

 

原題:lua

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))

 

它會輸出「@*@**@***@****@*****@******@*******@********...spa

 

怎麼理解呢?翻譯

個人方案是移除call/cc,以純函數的方案從新表示該問題,而後應用代換模型code

 

首先,continuation是什麼?blog

它是一個過程,以一個值爲參數,這個值對應call/cc的返回;將實參應用在continuation這個過程上,應該至關於運行程序自己it

 

原則上,continuation中應該包含整個調用棧上各幀及運算的一系列closure,以free variable的方式連接起來,不過因爲本題及其簡單,大大簡化了continuation的近似。io

 

首先,yang-continuation怎麼表達?function

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

意思是,提供yin這個free variable,就返回一個continuation;若是你以參數yang(至關於call/cc的返回)調用continuation,就至關於運行程序(即原題中let*的第二部分)class

 

再來看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)
相關文章
相關標籤/搜索