[Gauche-devel-jp] Re: soft-port

アーカイブの一覧に戻る

Kimura Fuyuki fuyuk****@nigre*****
2004年 2月 22日 (日) 17:12:39 JST


At Sat, 21 Feb 2004 19:02:42 -1000 (HST),
Shiro Kawai <shiro****@lava*****> wrote:
> 
> もしよければ、SchemeレベルのAPIから「こんなのがあったらいい」
> みたいなアイディア出しとかしてみて下さい。OO的にやるなら<port>を
> 継承可にしてport-getcみたいなメソッドをオーバロードさせるのが
> 綺麗なんだろうけど、効率はおもいっきり落ちそうだ…

私には今のところたいした考えもないので、ほかの人が話に入りやすいように
簡単な解説をしてみます。

*

ここでやっているのは要するに、portをSchemeで書けるようにするための仕組
みを入れよう、じゃあどうしようかという話です。ちなみにこれは1 年以上前
から私のほしい二大機能のひとつになっています。(もうひとつはネイティブ
エンコーディングの動的切り替えのような何か)

ささださんのgreadlineや私のGauche-fastcgiではportを作るのにCを書かなけ
ればなりませんでしたが、こういうのはやっぱりSchemeで書けたほうが嬉しい
です。

また、備前さんの指摘にあった効率の悪い部分を見ると、

(define (read-base64)
 (let ((lines (port->list reader inp)))
   (with-output-to-port outp
     (lambda ()
       (with-input-from-string (string-concatenate lines)
         (lambda ()
           (with-port-locking (current-input-port)
             base64-decode)))))))

ここで必要とされているのは「inpからreaderで読んだものを順に渡してくれ
るようなポート」であることがわかります。ならそういうパイプ的な動作をす
るポートを定義して使ってやればいいわけです。

(define (read-base64)
  (define (pipe-port) readerとinpを使ってごにょごにょする)
  (with-output-to-port outp
    (lambda ()
      (with-input-from-port pipe-port
        (lambda ()
          (with-port-locking (current-input-port)
            base64-decode)))))))

SCMやGuileにはmake-soft-portという関数があって、いちおうは好きなように
動作するportを作ることができます。が、この機能はかなり限定的だし、効率
もあまり良くないのではないかと思います。それでもたとえば/dev/randomも
どきがこんなに簡単に書けるのはおもしろいですね。

(define random-port (make-soft-port
                     (vector
                      (lambda (c) #f)
                      (lambda (s) #f)
                      (lambda () #f)
                      (lambda () (integer->char (random 256)))
                      (lambda () #f))
                     "rw"))

もうちょっと高度な使い方は、Guileのreadlineサポートあたりを見るといい
でしょう。

実はGaucheにはこの機能を実現するための枠組みはすでにそなわっています。
port.cを覗けばScm_MakeVirtualPortとScm_MakeBufferedPortというのがある
と思いますが、それです。

virtual portは上のsoft portに似ていますが、はるかに強力です。soft port 
はほとんど文字(というよりはオクテット)単位でしか処理できませんが、
virtual portではオクテット/文字/バイト列などの読み書き方法をそれぞれ指
定できるし、別にこれらを全部用意しなくても、たとえば文字の読み出しさえ
定義しておけばオクテットの読み出しは勝手にシステム側で提供してくれると
いうすごいことになっています。(というか、予定)

buffered portはその名のとおりバッファ的な動作をします。obsoleteになっ
ているopen-input/output-buffered-portを強化したようなものと思えばいい
でしょう。細かいことはいらないただ大規模データを読み書きするだけという
場合には、virtual portよりこっちのほうが効率的なんじゃないかと思います。

ということで、史上最強のprocedural port実現の準備は着々とととのってい
るのですが、強力なのはいいとして、どうすれば使いやすくて柔軟性のある
API を提供できるかというのが前例がないだけに問題となっているわけです。

今ならまだ仕様が固まっていないので、希望を出しておけば好みの方向にねじ
まげることも可能かもしれません。ということで、出しましょう。:)

-- 
木村 冬樹



Gauche-devel-jp メーリングリストの案内
アーカイブの一覧に戻る