Gauche:スクリプトとload-path
Shiro(2012/04/03 13:25:57 UTC): http://togetter.com/li/283057 からの考察。
現在のGaucheのファイルロードメカニズムは、あらかじめ設定されたload-pathからファイルを探すようになっている。add-load-path を使ってスクリプト内でload-pathに追加することもできるが、add-load-pathはリテラルしか取れないので、静的なメカニズムに近い (スクリプトが固定された時点でadd-load-pathに渡す引数も固定される)。
これは、私自身のUnixとの長い付き合いの中で、こういう想定に基づいた設計だった。
- ソフトウェアはconfigure + make + make installするもの
- スクリプトやモジュールファイルの置かれる位置はconfigure時に指定するもの
- だから、makeでパスを埋め込んじゃえばいい
- install前のテストはgosh -I.で起動すればいいよね
ただ、ちょっとしたスクリプトだとconfigureとかmake installは大げさだってのもわかる。 どっかにtarball展開するとか、いっそzipぽんと置いといて、そこから起動できたら便利、と (cf. https://github.com/SaitoAtsushi/gauche-zipload )
add-load-pathの引数を実行時に計算できるようにすれば色々ハックが可能になるけれど、 自由度が不必要に高くなりすぎるおそれがある。 コンパイル時にファイルの依存関係を把握出来ると何かと都合が良いのだ。 (cf. http://practical-scheme.net/wiliki/wiliki.cgi?Gauche%3aWishList#H-eg9li3 )
installに依存せず、実行時のカレントディレクトリにも依存しない方法として、「現在ロードしているファイルからの相対パス」でファイルを探せるようにする手がある。
いくつかのScheme処理系にはload-relativeという関数がある。じゃあuse-relativeとか作ろうか。スクリプトをmyscript.scm, そのスクリプト専用のモジュールをmymodule.scmとして、こんなふうに:
myscript.scm:
(use-relative mymodule) (define (main args) ...)
mymodule.scm:
(define-module mymodule (export ...)) ...
これなら、myscript.scmとmymodule.scmが同じディレクトリにさえあればいい
でも、スクリプト専用のモジュールがmymodule.scmとmymodule2.scmに分割されて、 mymodule.scmからもmymodule2.scmを読みたくなったら? mymodule.scmの中で(use-relative mymodule2) とすると、今度はmymoduleを 汎用化したい時に書き換えなくちゃならないのがいやんな感じだ。
むしろ、「現在ロード中のファイルからの相対パス」をload-pathに追加できればいいんじゃね。 例えば:
myscript.scm:
(add-load-path "." :relative) ; myscript.scmのあるディレクトリをload-pathに追加 (use mymodule) (define (main args) ...)
mymodule.scm:
(define-module mymodule (use mymodule2) (export ...))
mymodule2.scm:
(define-module mymodule2 ...)
これなら、3つのSchemeファイルを同一ディレクトリに置いとけばいい。
もうちょいモジュールファイルが増えて、
-+-- myscript.scm +-- lib +-- mymodule1.scm +-- mymodule2.scm +-- foo +-- myfoo.scm
みたいな構成になっても、myscript.scmの中で (add-load-path "lib" :relative) とするだけでいける。
追加しました https://github.com/shirok/Gauche/commit/5777fcaf02dbd9dc0eb943ab9b74490c18279d42
あ、これじゃcurrent-load-pathが取れない時にエラーになるや。修正。 https://github.com/shirok/Gauche/commit/053b064081e9c1bbdb87d3efcbfb427b7f3c1467