R の継続
R に callCC という関数があって、
callCC package:base R Documentation Call With Current Continuation Description: A downward-only version of Scheme's call with current continuation.
と書かれていたので、試してみた。
http://www.stdio.h.kyoto-u.ac.jp/~hioki/gairon-enshuu/SchemeNotes/continuation.html を見ながらRで同じことをやってみた。
まず
(+ (* 1 2) (call/cc (lambda (c) (* 3 4)))) ;==> 14 (+ (* 1 2) (call/cc (lambda (c) (* 3 (c 4))))) ;==> 6
をほとんどそのまま書いて、
> `+`(`*`(1,2), callCC(function(c) `*`(3, 4))) [1] 14 > `+`(`*`(1,2), callCC(function(c) `*`(3, c(4)))) [1] 6
関数を明示的に呼び出さないで、
> (1 * 2) + callCC(function(c) 3 * 4) [1] 14 > (1 * 2) + callCC(function(c) 3 * c(4)) [1] 6
うまくいったので、次はこれ。
(+ (* 1 2) (call/cc (lambda (c) (set! cont c) (* 3 4)))) (cont 2) ;==> 2
> (1 * 2) + (callCC( function(c){assign("cont",c,envir=.GlobalEnv); 3 * 4})) [1] 14 > cont(2) 以下にエラー cont(2) : 戻るための関数がありません,トップレベルへジャンプします
・・・だめだ。
よくわからないのでヘルプを見直すと
「A downward-only version of Scheme's call with current continuation.」
最初は下向きってのがよく分からなかったけど、どうやら callCC を呼びたしたとこより上では継続を呼び出せないみたい。(わけが分からない文だ)
けど、それなら大域脱出はできるよね、ってことで
(define (mul-cont x) (call/cc (lambda (escape) (letrec ((mul-aux (lambda (y) (display y) (newline) (let ((result (cond ((null? y) 1) ((= (car y) 0) (escape 0)) (#t (* (car y) (mul-aux (cdr y))))))) (display (list y result)) (newline) result) ))) (mul-aux x))))) (mul-cont '(1 2 3 4)) ;(1 2 3 4) ;(2 3 4) ;(3 4) ;(4) ;() ;(() 1) ;((4) 4) ;((3 4) 12) ;((2 3 4) 24) ;((1 2 3 4) 24) ;24 (mul-cont '(1 0 3 4)) ;(1 0 3 4) ;(0 3 4) ;; carが0のときに継続を呼び出して大域脱出する. ;0
をやってみた。
mulcont <- function(x){ callCC( function(escape){ mulaux <- function(y){ cat(y, "\n"); result <- if(length(y)==0){1} else if(y[1]==0){escape(0)} else{ y[1] * mulaux(y[-1])} cat(c(y, result), "\n") result } mulaux(x) }) } > mulcont(c(1,2,3,4)) 1 2 3 4 2 3 4 3 4 4 1 4 4 3 4 12 2 3 4 24 1 2 3 4 24 [1] 24 > mulcont(c(1,0,3,4)) 1 0 3 4 0 3 4 [1] 0
よし、うまく動いた。
まだ継続自体を理解しきれてないから callCC の定義を見てもよく分からない。
> callCC function (fun) { value <- NULL delayedAssign("throw", return(value)) fun(function(v) { value <<- v throw }) } <environment: namespace:base>
いろいろ動かしながら勉強してみよ。