SRFI-42の拡張
SRFI-42では、ファイルの各行を扱う:lines-of-fileジェネレータが提案されているので実装してみた。
これにより、SRFI-42のsome-ec手続きでファイルを直ぐに読めるようになる。
(import (rnrs) (srfi :42) (yuni ec)) (do-ec (:lines-of-file str (index i) "check.scm") (begin (display (list i str)) (newline)))
地味に問題なのは、portの代わりに文字列でファイルを指定出来る点で、たしかにこれは便利だけど作ったportをいつ閉じるべきかといった問題がある。あとR6RSはtranscoderとしてテキストファイルのcodecを抽象化する仕組みがあるのでそれをどうにかサポートする必要がある。。多分、リストの形でオプションを追加できるようにするのが良いだろう。
SRFI-42のジェネレータを追加するためには、:doを使って新しい構文を作れば良い。
(define-syntax :port/%maybe-close (syntax-rules () ((_ cc var port finalizer readproc) (:do cc (let ((p port) (proc readproc) (step (lambda (p) (with-finalizer readproc finalizer p))))) ((var (step p))) (not (eof-object? var)) (let ()) #t ((step p))))))
port/%maybe-closeは、portがeof-objectを返したらfinalizer手続きを呼ぶ以外はsrfi-42の:portと同様。
doに入っている2つのletはScheme的なletではなくて、:do専用の構文になっている。あと、構文としてジェネレータを定義するときは、引数が一つ増えてccが追加されることに注意する。一種の継続渡しスタイルで書かれている。
ファイル/ディレクトリの列挙やglobに相当するオペレーションは標準で装備しても良いかもなぁ。
(do-ec (:files f (attribute executable writable) (glob "*/*/*.ss") "./") ...)
のように書けると便利そう。