(Scheme:初心者の質問箱より移動)
named letでループを書くと、次のようなコードによくなります。
(let loop ((ch (read-char in))) (cond ((eof-object? ch) ...) (else ... (loop (read-char in)))))
ここで、read-charが2度現れているのがうれしくない。たいてい同じ引数で同じ手続きを呼んでいて、なんだか冗長です。たとえばread-charをread-byteに変更したくなったら2箇所変えないといけない。とはいえ、次のようにするのもそれはそれで普通ではない感じがするので、上のような書き方はしかたないんですかねえ。
(let loop () (let ((ch (read-char in))) (cond ((eof-object? ch) ...) (else ... (loop))))
(let1 proc (lambda () (read-char in)) (let loop ((ch (proc))) (cond ((eof-object? ch) ...) (else ... (loop (proc))))))
Shiro(2005/09/12 02:55:56 PDT): まあ、もっともな疑問です。私も普通は最初の方式で書きますが、 分岐の先で何度も(read-char)が出てきてちょっと危険な香りを感じると2番目の方法 (ループ内でletを使ってchを束縛)にすることもあります。
Cでforループを書く時も同じようなジレンマがありますよね。まあこの例に関しては while文の条件式の中でgetchar()とEOF判定が出来てしまうので普通はそっちを 使いますが、判定が単純でない場合なんかはちょっと迷うこともあります。
たまには日陰者のdoなど如何?さらに見た目が怪しい感じですが(笑
(do ((ch (read-char in) (read-char in))) ((eof-object? ch) ...) ...)
Shiro: 日陰者といえば、Gaucheにはずっとundocumentedな地位に甘んじていた while, untilというマクロがあったんですが、0.8.6から晴れて正式なマクロに 昇格します。アクションと条件が別々に書けるようになって、さらに束縛もできるように なったんで、上のパターンはこんなふうに書けます。お薦めするわけじゃありませんが…
(until (read-char in) eof-object? => ch ...)
CVS HEADのuntilの定義で`=>'がシンタックスルールになっていません。
Shiro: おっありがとう。直しました。
student:初学者ですが、schemeのおもしろさにはまっています。schemeレベル1というところでしょうか。さて、いま末尾再帰と名前付きletを勉強していますが、すべて末尾再帰だけで書くことは不可能なのでしょうか?なんとなく名前付きletは構文が複雑すぎてうさんくさく感じてしまい.. ちょっと場違いかもしれませんが、名前付きletの意義を教えていただけないでしょうか。