Shiro Kawai
shiro****@lava*****
2003年 11月 25日 (火) 16:25:59 JST
From: yasuy****@javao***** Subject: [Gauche-devel-jp] Re: module名を文字列で指定してロードしたい Date: Tue, 25 Nov 2003 15:40:03 +0900 > > このコードだとdbi-make-driverが定義されているモジュール(dbi)に > > どんどん新しいモジュールがインポートされてしまうのがちょっと気持ち > > 悪いので、requireだけしておいて、直接dbd.*内の定義を覗く方法もあります。 > > dbiを利用する側からみたとき、dbi-make-driver で作られた > <pg-driver> を使ってコネクションオブジェクトを作る際に、 > dbi-make-connection が > 基底クラスである <connection> 型ではなく、 > 引数のドライバーの型でディスパッチして <pg-connection> 型のオブジェクトを > 作って欲しいのですが、requireだけする方法だと、 > このディスパッチを dbi-make-connection の中に記述することになる気がしています。 いや、ジェネリックファンクションdbi-make-connectionが共通の dbdモジュールに定義されてさえいれば、dbd.pg等の各dbd実装 モジュールがdefine-methodしたメソッドはそのジェネリックファンクションに くっつくので、dbiモジュールの中で明示的にディスパッチを書く 必要はないです。importするというのは単なる名前の可視性だけの 問題ですから。 モジュールdbi ---------------------- (define-method dbi-make-connection (top) .. デフォルトの動作 (エラーとか) ...) モジュールdbd.pg ------------------- (use dbi) (define-method dbi-make-connection ((driver <pg-driver>)) ... (make <pg-connection> ....)) ユーザ ----------------------------- (use dbi) ;; dbd.pg が見える必要はない。 (let* ((driver (dbi-make-driver ...)) (connection (dbi-make-connection driver))) ;; ちゃんとディスパッチされる ...) > RDBからRDBへテーブルをコピーする簡易GUIツールを作るとします。 > 例えば PostgreSQLとMySQLのドライバーが組み込まれていて、 > コピー元とコピー先のドライバーは自由に選べるとしたら、 > どのRDBMSからどのRDBMSへコピーするかは実行時でないと分かりません。 > > このような応用を考えると、静的に追跡不可能な状況は避けられない気がしています。 ええ、ですから、どこかのレベルで実行時ロードは必要なのです。 が、それをアプリケーションレベルで行えば、少なくともライブラリに 関しては静的解析が可能になります。 ライブラリレベルで行ってしまうと、そのライブラリを使う全ての ライブラリが静的解析不可能になります。 (それに、この例ですとGUIツールのメニューか何かでドライバーを 選ばせるかなんかするんですよね? そしたらどっちにせよアプリケーション レベルでドライバのリストを作っておく必要がありますね) まあ、どこまで静的解析にこだわる必要があるか、なんですが。 直観でしかないんですが、(eval '(require ...)) は 「スジが悪く」見えるんですね。 ただ、Perl方式の文字列指定も捨て難くはあるので、例えばこんな 低レベルAPIを用意しておいて: [function] dbd-search-driver-modules システムにインストールされているドライバモジュールを 検索し、(ドライバ名 . モジュール名) のリストを返す。 (("pg" . dbd.pg) ("mysql" . dbd.mysql) ...) みたいな。 library-foldあたりを使えばできそう。 [function] dbd-search-driver-module driver-name システムにインストールされているドライバモジュールの うち、ドライバ名driver-nameを実装しているものを 見付けてそのモジュール名を返す。無ければ#f。 [function] dbd-load-driver-class driver-name ドライバ名 ("pg" 等) を受けて、そのモジュールを ロードし、ドライバクラスを返す。 (ここでevalが必要) dbi-make-driverはこの上に構築すると。 これだと、動的ロードの基本機能はdbd-load-driver-classに 集中しているので、後でこういう動的ロードAPIをシステムでサポート した時にはそこだけ置き換えれば済みます。 --shiro