Scheme:なんでも再帰

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 というのを作ってそれに制御を戻している。

僕はユーザ関数に引数をもう一つ、制御の戻り先になる関数をとるようにした。

More ...