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") "./") ...)

のように書けると便利そう。