Scheme:なんでも再帰
http://practical-scheme.net/docs/tailcall-j.html
こんな感じだったりしません?
--- tailcall-j.html.orig Sat May 7 17:50:20 2005 +++ tailcall-j.html Sat May 7 17:54:10 2005 @@ -272,7 +272,7 @@ (define (in-space c count) (cond ((eof-object? c) count) ((char-whitespace? c) (in-space (read-char) count)) - ((char=? c #\") (in-quote (read-char) (+ count 1)) + ((char=? c #\") (in-quote (read-char) (+ count 1))) (else (in-word (read-char) (+ count 1))))) (define (in-quote c count) (cond ((eof-object? c) (error "EOF in quoted word")) @@ -359,6 +359,8 @@ <pre> (define (count-words user-char user-proc) + (count-words-sub user-char user-proc 0)) + (define (count-words-sub user-char user-proc count) (define (in-word c count) (cond ((eof-object? c) count) ((char-whitespace? c) (in-space (read-char) count)) @@ -367,17 +369,18 @@ (define (in-space c count) (cond ((eof-object? c) count) ((char-whitespace? c) (in-space (read-char) count)) - ((char=? c user-char) (user-proc (read-char) (+ count 1)) + ((char=? c user-char) (user-proc (read-char) (+ count 1))) (else (in-word (read-char) (+ count 1))))) - (in-space (read-char) 0))</pre> + (in-space (read-char) count))</pre> <p>この関数を次のように呼び出せば、例10と同じ動作をする。 <pre> (define (in-quote c count) (cond ((eof-object? c) (error "EOF in quoted word")) - ((char=? c #\") (in-quote (read-char) count)) - (else (count-words (read-char) count)))) + ((char=? c #\") (count-words-sub #\" in-quote count)) + ((char=? c #\\) (read-char) (in-quote (read-char) count)) + (else (in-quote (read-char) count)))) (count-words #\" in-quote)</pre> @@ -411,12 +414,13 @@ </p> <pre> - (define count-words-with-quote quoter) + (define (count-words-with-quote quoter) (define (in-quote c count) (cond ((eof-object? c) (error "EOF in quoted word")) - ((char=? c quoter) (in-quote (read-char) count)) - (else (count-words (read-char) count)))) - (count-words quoter in-quote)</pre> + ((char=? c quoter) (count-words-sub quoter in-quote count)) + ((char=? c #\\) (read-char) (in-quote (read-char) count)) + (else (in-quote (read-char) count)))) + (count-words quoter in-quote))</pre> <p>Schemeプログラマが再帰を好んで使う理由は、こんな柔軟性なんだ。 </p>
2008/08/05 19:20:54 PDT
上の人と同じ部分に引っかかって、自分で直して、多分報告したほうがいいんだろうけどどうするかなーメールでいったほうがいいのかなーと思いつつwilikiに適当なページがないか探してみたらこのページを発見したので、自分で直したバージョンもここに張ってみる。
(define (count-words user-char user-proc) (define (in-word c count) (cond ((eof-object? c) count) ((char-whitespace? c) (in-space (read-char) count)) ((char=? c user-char) (user-proc (read-char) (+ count 1) in-space)) (else (in-word (read-char) count)))) (define (in-space c count) (cond ((eof-object? c) count) ((char-whitespace? c) (in-space (read-char) count)) ((char=? c user-char) (user-proc (read-char) (+ count 1) in-space)) (else (in-word (read-char) (+ count 1))))) (in-space (read-char) 0)) (define (in-quote c count ret-proc) (cond ((eof-object? c) (error "EOF in quoted word")) ((char=? c #\") (ret-proc (read-char) count)) ((char=? c #\\) (begin (read-char) (in-quote (read-char) count ret-proc))) (else (in-quote (read-char) count ret-proc))))
問題はユーザ関数からどうやって本体の関数に制御を戻すか。
上の人は count-words-sub というのを作ってそれに制御を戻している。
僕はユーザ関数に引数をもう一つ、制御の戻り先になる関数をとるようにした。