Gauche:evalと環境

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."

無名のモジュールへの参照が無くなりガベージコレクトされると、 そのモジュール内の束縛も全てガベージコレクトされる。 一時的な評価環境を作るのに便利。


Tags: eval, Module, 無名モジュール


Last modified : 2013/04/29 02:09:29 UTC