For Gauche 0.9.5


Next: , Previous: , Up: ライブラリモジュール - R7RS統合   [Contents][Index]

10.1 二つの世界を往き来する

Gaucheを起動した直後は、それがREPLであってもスクリプトファイルの実行であっても、 トップレベルはuserモジュールになっています。userモジュールは gaucheモジュールを継承しています。 また、ライブラリを読み込む際にも、(select-moduleが呼ばれるまでは) トップレベルはgaucheを継承したモジュールになっています。 これが、(use something)等といちいち書かないでも Gaucheの組み込み手続きを使える理由です。 (モジュールの継承についてはモジュールの継承を参照してください)。

一方、R7RSではimportフォームによってどの名前空間を利用するか明示することが 求められています(例: (import (scheme base)))。 また、R7RSライブラリはそれぞれdefine-libraryフォームで囲う必要があります。 プログラムの最初のimportより前、あるいはライブラリのdefine-libraryの 外側は、R7RSの世界の外であり、標準では何も規定していません。

Gaucheはこれを利用して、適切な「世界」を設定し、R7RSコードと既存のGaucheコードを 透過的に混ぜるられるようにしています。

註:3つのimport形式で説明しますが、 R7RSのimportはGaucheのimportと異なります。この節では 区別が必要な時は前者をr7rs#import、後者をgauche#importと 表記しますが、実際のコードではr7rs#gauche#といったプレフィクスを つけずに、単にimportと書いてください。

R7RSライブラリをロードする

define-libraryフォーム自身は、gaucheモジュール内のマクロとして 定義されていて、R7RS環境を設定してその中身を評価するコードに展開されます。 (Gaucheコードからuseを使うか、 R7RSコードからr7rs#importフォームを使うかして)R7RSライブラリをロードすると、 Gaucheはファイルの評価をgaucheモジュール内で始めますが、すぐに define-libraryフォームに当たるので、その中身はR7RS環境で処理されることになります。

以下のコードを持つ、R7RSライブラリ(mylib foo)があるとしましょう。

(define-library (mylib foo)
  (import (scheme base))
  (export snoc)
  (begin
    (define (snoc x y) (cons y x))))

このファイルは*load-path*にあるディレクトリのどれかの下に、 mylib/foo.scmという名前で保存されなければなりません。

R7RSコードからは、このライブラリはr7rs#importフォームでロードできます。

(import (mylib foo))

(snoc 1 2) ⇒ (2 . 1)

Gaucheコードからこのライブラリを使うには、ライブラリ名の各要素を.で つなげたものをモジュール名として、useします。

(use mylib.foo)

(snoc 1 2) ⇒ (2 . 1)

Gaucheライブラリのロード

Gaucheライブラリのfoo.barをR7RSコードから使うには、 モジュール名を.で区切った名前のリストをライブラリ名として使います。 例えばgauche.lazyモジュールは次のとおりR7RSから使えます。

(import (gauche lazy))

SRFIモジュールについては、R7RSでは慣習的に(srfi n)という 名前を使うので、Gaucheもそれに合わせています。R7RSコードから srfi-1とsrfi-13を使うには、次のようにします。

(import (srfi 1) (srfi 13))

(これが動くのは、Gaucheがsrfiという名前を特別扱いしているのではなく、 Gaucheをインストールした時にsrfi/1.scm等のアダプタライブラリが作られているからです)

ヒント: Gaucheの組み込みの機能 (Gaucheコードでは最初から使える束縛) を R7RSコードから使いたい場合は、(gauche base)ライブラリをimportしてください (Gauche組み込み関数のインポート参照)。

(import (gauche base))

filter ⇒ #<closure filter>

R7RSスクリプトの実行

R7RSスクリプトは必ずimportフォームで始まります。 しかし、r7rs#importgauche#importと文法や意味が異なります。 そこで、ちょっとしたトリックを使っています。

goshがスクリプトファイルを読み込むのはuserモジュールです。 そこにはuser#importというマクロが用意してあり、 そのマクロは引数を調べて、それがR7RSのimportの構文であれば r7rs.userモジュールに切り替えてr7rs#importを実行し、 そうでなければgauche#importを実行します。 詳しくは3つのimport形式を参照してください。

R7RSスクリプトの例です:

(import (scheme base) (scheme write))
(display "Hello, world!\n")

Gaucheスクリプトを見慣れている人は、R7RSプログラムがmain手続きを 特別扱いしないことに気をつけてください。R7RSプログラムは、トップレベルフォームを 順に評価してゆくだけです。したがって次のスクリプトは何も表示しません:

(import (scheme base) (scheme write))
(define (main args)
  (display "Hello, world!\n")
  0)

R7RSスクリプトからコマンドライン引数を利用するには、 (scheme process-context)ライブラリのcommand-lineを使います (R7RSプロセスコンテキスト および コマンドライン引数参照)。

R7RS REPLを使う

gosh-r7オプションつきで起動され、スクリプトファイルが 与えられていなかった場合は、R7RS REPLモードになります。 使いやすいように、以下のモジュール (R7RS用語では「ライブラリ」)は 自動的にロードされます。

(scheme base) (scheme case-lambda) (scheme char)
(scheme complex) (scheme cxr) (scheme eval)
(scheme file) (scheme inexact) (scheme lazy)
(scheme load) (scheme process-context) (scheme read)
(scheme repl) (scheme time) (scheme write)

さらに、ヒストリ変数*1*2*3*1+*2+*3+*e および *historyも使えます (ヒストリ変数の詳細についてはREPLでの開発参照)。

R7RS REPLにいることはプロンプトを見ればわかります。 現在のモジュールがr7rs.userとなっているからです。

gosh[r7rs.user]> 

R7RS REPLからGauche REPLにスイッチするには、(gauche base)を インポートしてselect-moduleを使ってuserモジュールを選びます。

gosh[r7rs.user]> (import (gauche base))
#<undef>
gosh[r7rs.user]> (select-module user)
#<undef>
gosh> 

((select-module gauche)とする手もありますが、おすすめはしません。 gaucheモジュールの中を変えると思いがけない副作用が生じるかもしれませんから。)

R7RSコードをファイルに書きだし、R7RS REPLにそのファイルをロードしてインタラクティブに 開発を進めている場合 (例えばEmacsのSchemeモードなら、C-c C-lでファイルがロードできます)、 そのファイルがR7RSとして正しい形式になっていることを確認してください。 つまり、ファイルはimport宣言で始まるか、define-library形式 から構成されるものでなければなりません。それ以外の、単にSchemeコードが並べて 書いてあるだけのファイルをロードした場合、 それはREPLでの現在のモジュールが何であるかにかかわらずGaucheのuserモジュールに 読み込まれるので、r7rs.userモジュールからはデフォルトでは見えません。

Gauche REPLからのスイッチ

デフォルトでは、goshはスクリプトファイルが与えられなければGaucheのREPLに 入ります。REPLの説明はREPLでの開発を参照してください。

Gauche REPLからR7RS REPLにスイッチするには、 単にr7rsスタイルのimportを使うだけです。user#importは あなたが欲しいのがR7RSであることを察知して環境を切り替えます。

gosh> (import (scheme base))
#<undef>
gosh[r7rs.user]> 

ただし、gosh-r7オプションつきで起動していなければ、 この時点でロードされているのはuser#importで指定したライブラリだけです。

もし、「すっぴん」のR7RS環境、つまり(scheme base)でさえロードされていない 環境へと切り替えたければ、r7rsモジュールをuseして 直接r7rs.userモジュールを選択します。

gosh> (use r7rs)
gosh> (select-module r7rs.user)
gosh[r7rs.user]> 

こうして切り替えた場合、使えるフォームはimportdefine-library だけです (defineでさえ定義されていません!) この環境でSchemeを書くには、まず (import (scheme base)) 等として 束縛をインポートする必要があります。


Next: , Previous: , Up: ライブラリモジュール - R7RS統合   [Contents][Index]