yasuy****@javao*****
yasuy****@javao*****
2003年 11月 25日 (火) 15:40:03 JST
えんどうです。 > そもそも、dbd-make-driver自身はポリモルフィックに振る舞う > 必要が無いので、generic functionではなく普通の手続きで > 良いです。 それはそうですね。 > > モジュール名を文字列で指定して use や require や import する > > 方法はあるのでしょうか...? > > 今のところは、evalを使うしかないですね。 > 最も手っ取り早いのはこんな感じでしょうか (説明の簡略化のため、 > エラーチェック等は省いてあります)。 > > (define (dbi-make-driver driver-name) > (let ((module-name (string->symbol #`"dbd.,driver-name")) > (class-name (string->symbol #`"<,|driver-name|-driver>"))) > (eval `(use ,module-name) (current-module)) > (let ((driver-class (eval class-name (current-module)))) > (make driver-class :driver-name driver-name)))) これでうまくいきました。 > このコードだとdbi-make-driverが定義されているモジュール(dbi)に > どんどん新しいモジュールがインポートされてしまうのがちょっと気持ち > 悪いので、requireだけしておいて、直接dbd.*内の定義を覗く方法もあります。 dbiを利用する側からみたとき、dbi-make-driver で作られた <pg-driver> を使ってコネクションオブジェクトを作る際に、 dbi-make-connection が 基底クラスである <connection> 型ではなく、 引数のドライバーの型でディスパッチして <pg-connection> 型のオブジェクトを 作って欲しいのですが、requireだけする方法だと、 このディスパッチを dbi-make-connection の中に記述することになる気がしています。 > loadを使うのは避けた方が良いでしょう。loadは実行するたびに > ファイルをロードしてしまうので、モジュール内のスタティックデータが > 毎回リセットされてしまうとか、複数のスレッドが同時にloadを発行した > 場合にシステム側では排他制御をしないといった問題があります。 > requireは複数スレッドが同時に実行しても、また複数回実行しても、 > 一度だけファイルを読み込むことが保証されています。 了解しました。 > なお、上で言った「もうひとつのアプローチ」とは、アプリケーション側に > モジュールのロードを任せて、ライブラリにはクラスオブジェクトを受け渡す > という方法です。(dbm.* 系がその方針で作ってあります) モジュールのロードを静的に書いてしまうとpluggableにならない気がして、 dbi側が裏でロードするという方法を思い付きました。 > ただ、(eval `(require ,...)) をやってしまうと、アプリがどの > ファイルを使うのかを静的に追跡することが不可能になります。 > ライブラリレベルでそれをやると、そのライブラリを使った全ての > ライブラリにその性質が伝播してしまいます。どうせやるなら、 > なるべくアプリに近い側(mainを含むファイル)でやるほうが良いんじゃ > ないかなあ、というのが、私が持っている印象です。 RDBからRDBへテーブルをコピーする簡易GUIツールを作るとします。 例えば PostgreSQLとMySQLのドライバーが組み込まれていて、 コピー元とコピー先のドライバーは自由に選べるとしたら、 どのRDBMSからどのRDBMSへコピーするかは実行時でないと分かりません。 このような応用を考えると、静的に追跡不可能な状況は避けられない気がしています。 > あるいは、実行時のrequire/importを行う共通APIをひとつ作って、 > 全てをそこに集約させるという手もあるかもしれません。 この方がevalを使うより良いのでしょうね。言語仕様がふくらみますが... -- ENDO Yasuyuki <yasuy****@javao*****> http://www.javaopen.org/~yasuyuki/ (Personal/Japanese Only) http://www.javaopen.org/jfriends/ (Japanese Only)