Gauche:evalと環境
R5RSのevalは、第二引数に「環境指定子(environment specifier)」を 取ると定義されている。
(eval form environment-specifier)
しかし、環境指定子の具体的な実装は処理系に任されている。
処理系によっては、レキシカルスコープを含めた環境を ファーストクラスオブジェクトとして取り出せるものがあるから、 そういう処理系独自の拡張を念頭に置いた仕様だろう。
Gaucheでも将来はそういう拡張をするかもしれないが、 現在のところは、単なるモジュールを環境指定子として使っている。 モジュールはトップレベルの名前空間を規定するものだ。 evalは、form内の自由変数を、第二引数に渡されたモジュール内で 解決する。
;; デフォルトではプログラムはuserモジュールで実行される。 ;; R5RSのinteraction-environmentは単にuserモジュールを返す。 gosh> (interaction-environment) #<module user> ;; userモジュール中で変数xを定義 gosh> (define x "I'm in the user module") x ;; userモジュール中でevalしてみる gosh> (eval 'x (interaction-environment)) "I'm in the user module" ;; evalはレキシカルな環境の影響を受けない。 gosh> (let ((x "local")) (eval 'x (interaction-environment))) "I'm in the user module" ;; 新たなモジュールを作る。 gosh> (define-module my-module) #<module my-module> ;; 新たなモジュール内で変数xを定義 gosh> (with-module my-module (define x "Hey, I'm in my-module.")) x ;; userモジュールのxには影響無し gosh> x "I'm in the user module" ;; my-module中でevalしてみる gosh> (eval 'x (find-module 'my-module)) "Hey, I'm in my-module." ;; evalを使ってmy-moduleに定義を追加 gosh> (eval '(define y "YYyyyy") (find-module 'my-module)) y ;; userモジュールからは見えない。 gosh> y *** ERROR: unbound variable: y Stack Trace: _______________________________________ ;; my-moduleからは見える gosh> (eval 'y (find-module 'my-module)) "YYyyyy"
define-moduleはモジュールに名前を付けるが、 Gaucheでは無名のモジュールを作ることもできる。
gosh> (define anon-module (make-module #f)) anon-module gosh> anon-module #<module #> gosh> (eval '(define x "I'm in anonymouns module.") anon-module) x gosh> (eval 'x anon-module) "I'm in anonymouns module."
無名のモジュールへの参照が無くなりガベージコレクトされると、 そのモジュール内の束縛も全てガベージコレクトされる。 一時的な評価環境を作るのに便利。