這題目確實比較殺腦細胞...函數
原題: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)