[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
6.20.1 Schemeファイルのロード | ||
6.20.2 ダイナミックライブラリのロード | ||
6.20.3 requireとprovide | ||
6.20.4 Autoload | ||
6.20.5 ライブラリの操作 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[R5RS+]
fileをロードします。すなわち、fileに書かれたScheme式を順次読み込んで
評価します。fileの拡張子 (“.scm
”) は省略できます。
fileが “/”, “./” または “../” で始まっていない場合は、
システムファイルサーチパス (変数*load-path*
に格納されています)
の中から該当ファイルが探されます。あるいは、キーワード引数pathsにディレクトリ名の
リストを渡すことによりサーチパスを指定することもできます。
ロードに成功した場合は#t
が返されます。
指定ファイルがみつからない場合はエラーとなりますが、もしキーワード引数
error-if-not-found
に#f
が与えられていれば単にload
から
#f
が返されます。
デフォルトでは、load
はコーディング認識ポート(コーディング認識ポート参照)を
使ってソースファイルを読み込むので、ファイル先頭の"coding:
" コメントによる
文字エンコーディング指定が有効になります。
(codingコメントについてはマルチバイトスクリプトを参照)。
但し、キーワード引数ignore-codingに真の値が渡された場合、
load
はcoding-aware portを作成せず、直接ファイルポートから
ソースを読み込みます。
キーワード引数environmentにモジュールが渡された場合は、
あたかもそのモジュールがファイルの先頭でselectされたかのように
load
されます。
カレントモジュールは保存されます。つまり、file中でselect-module
によって
カレントモジュールを変更しても、load
が終わったらload
を読んだ時点の
モジュールに戻ります。
ライブラリファイルをロードする場合は、`use
' (モジュールの定義と選択参照) を
使うか、下に説明する`require
' を使う方が良いでしょう。
load
とrequire
の違いについてはコンパイルを参照してください。
load
とrequire
がファイルを探すディレクトリのリストを保持しています。
もしサーチパスにディレクトリを追加したい場合は、この変数を直接変更せずに、下に説明する
add-load-path
を用いて下さい。
パスpathをライブラリロードパスのリストに加えます。 afterpに真の値が与えられていればpathは既存のリストの末尾に 追加されます。そうでなければpathは既存のリストの先頭に追加されます。
ロードパスを変更したい場合、*load-path*
を直接替えずにこのフォームを
使って下さい。このフォームはコンパイル時に解釈されるのに対し、*load-path*
を
書き換えるコードは実行時に解釈されます。“use
” や “require
” は
コンパイル時のロードパスを使うので、*load-path*
への変更は反映されないかもしれません。
更に、add-load-path
はpathの下にアーキテクチャ依存のディレクトリが
ないかどうかを探し、あればそれを内部の共有ライブラリサーチパスに追加します。
例えばあなたが自分のSchemeモジュールを/home/yours/lib
に入れていて、
それが共有ライブラリを必要としていたとします。手続きgauche-architecture
(環境の問い合わせ参照)が返す値をARCHとして、
共有ライブラリを/home/yours/lib/ARCH/
に置いておくと、
共有ライブラリはそこからロードされます。この方法を取ると、複数のプラットフォーム用に
別々にコンパイルされた共有ライブラリを管理することができます。
入力ポートportから、EOFを読むまで繰り返しScheme式を読み込み評価します。
portにコーディング認識ポートを渡さない限り、"coding:
"コメント
による文字コード変換は行われないことに注意して下さい。
これらの手続きによって、現在のロードのコンテクストを知ることができます。 ロードされているファイルの中でこれらの手続きを呼ぶと、次のような値が返されます。
current-load-port
現在のファイルがロードされている入力ポート。
current-load-history
入力ポートと行番号のペアのリストで、ロードのネスティングを示したもの。
例えばあなたが‘foo.scm’をロードし、そのファイルの7行目で
‘bar.scm’がロードされ、そのファイルの18行目で‘baz.scm’が
ロードされたとします。current-load-history
を‘baz.scm’中で
呼ぶと、それは次のような値を返します。
((#<port "foo.scm"> . 7) (#<port "bar.scm"> . 18)) |
current-load-next
現在のファイルがロードされた時点での、ファイルサーチパスの残りを返します。
例えば *load-path*
が
("." "../lib" "/home/gauche/lib" "/share/gauche/lib")
で、
あなたが‘foo.scm’をロードしたところ、それが‘../lib/’中に見つかったと
しましょう。このとき、‘foo.scm’中でcurrent-load-next
を呼べば
("/home/gauche/lib" "/share/gauche/lib") |
が返されます。
load
されていない状態で呼ばれた時は、これらの手続きはそれぞれ#f
、
()
、()
を返します。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ダイナミックローダブルライブラリ(共有ライブラリ)fileをロードしてリンクします。
fileにはサフィックス(“.so” 等) を含めないで下さい。システムによって
サフィックスは異なるため、dynamic-load
がそれを追加します。
キーワード引数init-functionは共有ライブラリ中の初期化関数の名前を 指定します。デフォルトでは、サフィックスを除くファイル名が “foo” の場合、 初期化関数名は “Scm_Init_foo” となります。
キーワード引数export-symbolsは、ロードされるライブラリ中の外部シンボルを
プロセスのシンボルテーブルに追加すべきかどうかを指定します。(註:ここでの「シンボル」
とはCの関数名や変数名のことで、Schemeのシンボルのことではありません)。
デフォルトでは共有ライブラリの外部シンボルはプロセスのシンボルテーブルに追加されず、
それぞれの共有ライブラリは他の共有ライブラリのシンボルを見ることができません。
export-symbolsに真の値を渡すと、フラグRTLD_GLOBAL
が
dlopen()
に渡されて、その共有ライブラリ中のシンボルがこれからロードされる
共有ライブラリからも見えるようになります。
通常、共有ライブラリはSchemeモジュール中でロードされるので、モジュールユーザが 直接この手続きを呼ぶ必要はほとんどないでしょう。
一度ロードされた共有ライブラリをアンロードすることはできません。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
require
とprovide
は、Lispでライブラリファイルを一度だけ
読み込むことを保証するための伝統的な方法です。
あるfeatureを最初にrequire
すると、その機能を提供する
ライブラリファイルがロードされ、その機能が提供されたということが記憶されます。
2回め以降のそのfeatureのリクエストではファイルはロードされません。
Gaucheではuse
構文 (モジュールの使用参照) が
requireのメカニズムをボンネットの下に隠してくれるので、
これらの式を直接目にする必要はほとんどありません。
もしあなたがちょっと変わった方式でライブラリを構成したくて、したがって
Gaucheの標準的なメカニズムをバイパスしたい場合に限り、使うようにしてください。
featureがまだロードされていなければロードします。featureは文字列で
なければなりません。それがそのまま(サフィックスを除く)ファイル名としてロードパスから
探されます。require
の解釈はコンパイル時に行われます。
SLIBモジュールをロードすると、require
が拡張されます。詳しくはslib
- SLIBインタフェースを
参照して下さい。
もしロードされたファイルがprovide
フォームを含んでいなかった場合、
あたかもファイルの最後に(provide feature)
があったかのように、
featureが自動的にprovideされます。これを
autoprovide機能と呼んでいます。
featureをシステムのprovideされたフィーチャーリストに加えます。
以降、featureがrequire
されてもファイルはふたたびロードされません。
require
が要求された機能を自動的にprovide
されたかのように
扱うAutoprovide機能があるために、provide
を明示的に呼ぶ必要は
ほとんど無いでしょう。provideを使いたいシチュエーションとしては
次のようなものが考えられます。
例えばfeature Xがfeature Yを置き換えるものだとします。
XはYのAPIを全て提供しますが、実装は異なります。この場合、
‘X.scm’が一度ロードされたら、‘Y.scm’をロードしてほしくないと思うでしょう。
‘X.scm’に (provide "X")
と (provide "Y")
の両方を
書いておくことで、‘X.scm’がfeature Yもprovideすると明示すれば、それが実現できます。
(注:provide
が呼ばれると、require
のautoprovide機能は
抑制されるため、‘X.scm’中で(provide "X")
も指定する必要があります。)
もちろんの方法では、ユーザが (require "Y")
を (require "X")
より先に書いてしまったら‘Y.scm’はロードされてしまいます。
この方法は、現場において、永久的な解決が高コストになるような場合のとりあえずの
回避処置と考えるべきでしょう。
provide
しない。
feature引数に#f
を渡すことで、何のfeatureもprovide
することなく
require
によるautoprovidingを抑制できます。
これもまた、何らかの一時的な解決と考えるべきです。たとえば開発中に、
‘X.scm’を頻繁に変更するために(require "X")
が常に
そのファイルをロードするようにさせたい、といった場合が考えられます。
‘X.scm’のリリースの前に (provide #f)
を消しておくことを
忘れないように。また、インタラクティブにリロードしたいならば
gauche.reload
(gauche.reload
- モジュールの再ロード参照) を使うことを
おすすめします。
featureが既にprovideされていれば#t
を返します。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
item … がオートロードされるように設定します。すなわち、 次にitemが参照された時、それが実際に評価される前にfile/moduleがロード されるようにします。これによって、必要とされる時までfile/moduleのロードを遅らせる ことができます。
引数file/moduleには、文字列かシンボルを指定できます。文字列の場合は
そのファイルがロードされます。シンボルの場合、その名のモジュールが(use
と
同じルールで)ロードされ、itemがfile/moduleから
オートロードを呼び出したモジュールへとインポートされます。
(モジュールのuse
の詳細についてはモジュールの定義と選択を参照して下さい)。
itemは変数名(シンボル)か、(:macro symbol)
というフォーム
でなければなりません。変数名の場合は、その変数が評価されようとした時に
指定のファイル/モジュールがロードされます。後者のフォームの場合は、
(symbol arg …)
というフォームがコンパイルされようとした
時に指定のファイル/モジュールがロードされます。後者はマクロのオートロードになります。
symbolはfile/moduleの中で定義されなければなりません。 そうでなければロード時にエラーが報告されます。
手続きのオートロードの例を示します。
(autoload "foo" foo0 foo1) (autoload "bar" bar0 bar1) (define (foobar x) (if (list? x) (map bar0 x) (foo0))) (foobar '(1 2)) ; この時点で "bar" がロードされる (foobar #f) ; この時点で "foo" がロードされる |
マクロのオートロードを設定した場合、指定のファイルまたはモジュールは、 そのマクロを使っているフォームが実行されるされないにかかわらず、 コンパイラがそのフォームを見た時点でロードされることに注意してください。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ある特定のライブラリおよび/あるいはモジュールがシステムにインストールされ ているかどうかをチェックするための手続きがいくつかあります。
以下の説明の中では、patternはシンボルまたは文字列です。シンボル
である場合にはモジュール名(たとえば、foo.bar
)を指定します。
文字列である場合にはライブラリの部分パス(たとえば、"foo/bar"
)を
指定します。これはライブラリサーチパス以下で検索されます。
ライブラリ/モジュールファイルに対する基本イテレータ。この手続きは
pattern にマッチする Scheme のプログラムファイルを検索します。
検索は paths (デフォルトは標準のファイルロードパス、
*load-path*
)にリストされたディレクトリ以下でおこなわれます。
マッチしたファイル毎に、proc が、そのマッチしたモジュール名あるいは
ライブラリ名、そのプログラムファイルのフルパス、状態値、の3つの引数を
ともなって呼びだされます。seedは、初期状態値として使われ、
proc が返す値は次の proc の呼出し時に状態値として使われます。
最後の proc から返された値は library-fold
の値として返ります。
pattern がシンボルでかつ、キーワード引数 strict? が
#t
(デフォルト値)であれば、この手続きは
あたえられたモジュール名のパターンにマッチするようにみえるファイル名に
たいして library-has-module?
を適用して、
本当にそのモジュールを実装しているファイルを見付けます。
大量のモジュールにマッチさせようとすると、時間がかる可能性があります。
#f
を strict? に渡すことで、余分なチェックを回避できます。
pattern が文字列だった場合、照合はファイル名に対してのみ行われ、
strict?は無視されます。
デフォルトでは、path 中の pattern にマッチする同じ名前をもつ
2つ以上のファイルがあるばあい、path に最初に出現したものだけが
採用されます。そのライブラリに対して、require
あるいは
use
を用いたをつかった場合に得られるのはこのファイルです。
すべてのマッチしたファイルについて反復したければ、allow-duplicates?
キーワード引数に #t
を渡します。
(library-fold 'srfi-1 acons '())
⇒ ((srfi-1 . "../lib/srfi-1.scm"))
(library-fold "srfi-1" acons '())
⇒ (("srfi-1" . "../lib/srfi-1.scm"))
;; |
マッチしたライブラリ/モジュール上のイテレータの map
版および
for-each
版。照合操作とキーワード引数の詳細については上述の
library-fold
を参照してください。
procは、マッチしたモジュール/ファイル名と、そのファイルの
フルパスの 2 つの引数をうけとります。library-for-each
は
結果を捨てます。
(library-map 'srfi-4 list :allow-duplicates? #t) ⇒ ((srfi-4 "../lib/srfi-4.scm") (srfi-4 "/usr/share/gauche/0.7.1/lib/srfi-4.scm")) (library-map 'dbm.* (lambda (m p) m)) ⇒ (dbm.odbm dbm.ndbm dbm.gdbm dbm.cdb) |
mod/path で指定されたライブラリあるいはモジュールを検索し、
もしあれば、真値を返します。キーワード引数 paths および
strict? は library-fold
のそれと同じ意味です。
上述のイテレータ手続きとはちがい、この手続きは呼び出しの過程で
最初に既にロードされているライブラリおよびモジュールをチェックします。
もしそのときに mod/path を見つけたら、真値を返し、ファイル
システムを見にいくことはありません。キーワード引数 force-search?
に #t
を渡せば、すでにロードされいるライブラリおよびモジュール
のチェックはスキップされます。
path で指定したファイルが存在し、かつ、module
で名指しされた
モジュールが実装されている場合でその場合に限り、#t
を返します。
path は実際のファイル名でなければなりません。
(library-has-module? "./test/foo/bar.scm" 'foo.bar)
⇒ #t ;; if ./test/foo/bar.scm implements module foo.bar.
|
この手続きは典型的なソースコードの配置を仮定して、与えられたファイルが
そのモジュールを実装しているかどうかを決定します。すなわち、
まずそのコードのフォームを読み、与えられたモジュールを定義している
define-module
フォームかどうかを見ます。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.