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 というのを作ってそれに制御を戻している。
僕はユーザ関数に引数をもう一つ、制御の戻り先になる関数をとるようにした。