モジュールの話。
今更言うまでもなくモジュール化はコードの再利用に有効だが、Gaucheにもその機能は備わっている。…と言うか、実は全ての定義は何かしらのモジュールに属していて、基本的には同じモジュールに属するもの同士が互いに見える。今までグローバルな定義として扱ってきた
(define var 10)等は、厳密にはuserという名前のモジュールに属する。
モジュールの定義は
(define-module モジュール名 モジュール本体...)とする。
定義したからには当然使いたいところだが、モジュール使い方は大きく分けて2種類ある。1つはカレントモジュールの変更。もう1つは外部モジュールの参照。
カレントモジュールを変更する。すなわち、使いたいモジュールの中に入ってしまえば、これまで居たモジュールの内部が見えなくなる代わりに、新たに入るモジュールの内部が見えるようになる。
(select-module モジュール名)とすると、それ以降(からファイル終端まで)のフォームは指定したモジュール内で評価される。また、
(with-module モジュール名 フォーム...)とすると、カレントモジュールを一時的に変更して、指定したフォームを評価する。
カレントモジュールを変更することなく参照できる外部モジュールを参照する方法の1つにimportがある。
(define-module fooこのようにモジュールをimportすると、exportされているシンボルのみがカレントモジュールから見えるようになる。importにオプションを与えれば、細かい見え方の制御も可能。
(export visible1 visible2)
(define visible1 100)
(define visible2 200)
(define invisible 300)
)
(import foo)
(print visible1 visible2)
(print invisible) ; エラー
なお、モジュールの定義を同名のファイルに記述しておけば
(require “foo”)とする代わりに、useマクロを利用して
(import foo)
(use foo)と簡潔に記述できる。
exportを使うと、外部モジュールをより密接にカレントモジュールに取り込む。
(define-module bar例えば上記の例では、barをextendしたbazの中では、barのexportedとnot-exportedの両方が見える。またbazもexportedをexportしたことになる。しかし、not-exportedはexportされていないので、bazをimportしただけのカレントモジュールからは見えない。
(export exported)
(define exported 1000)
(define not-exported 2000)
)
(define-module baz
(extend bar)
(export disp)
(define disp (lambda () (print exported not-exported)))
)
(import baz)
(print exported)
(disp)
(print not-exported) ; エラー
exportするモジュールは複数指定可能。また、exportはuseと同様、指定したモジュールのファイルがまだロードされていなかったらロードする。
0 件のコメント:
コメントを投稿