LISPUSER

LISPMEMOLisp is like a ball of mud - you can throw anything you want into it, and it's still Lisp. -- Anonymous

(top)  (memo)  (rss)

Common Lisp Hyper Spec CLHS 3.1.1 Introduction to Environments の翻訳

On Lisp 読んでる人からこのツッコミ (http://lispuser.net/memo/lisp/2007-03-31-23-26.html ) の意味がよくわかんないという反響や、 ちょっと非 Lisper の人との議論にでてきたので、ついでに CLHS 3.1.1 Introduction to Environments の翻訳をしてみました。 環境とスコープとエクステントをおさえればいいかなー (と、おもったんですが環境だけで力つきた)

3.1.1 環境の手引き

束縛とは名前とその意味するものとの間の関連である。束縛がレキシカル環境あるいは ダイナミック環境のどちらに確立されるかは、用いられたスペシャルオペレータによる。

環境とは束縛の集合と評価の過程で使用されるその他の情報(例:名前の意味付け)を合わせたものである。

環境における束縛は、いくつかの名前空間に分割されて格納されている。 ある環境における一つの名前は、同時に一つ以上の関連をもつことができる。 しかし、特定の名前空間においては、一つの束縛は一つの関連しか持つこができない。

3.1.1.1 グローバル環境

環境の一部分であるグローバル環境は、無限スコープかつ無限エクステントの束縛を含んでいる。 グローバル環境は特に以下のようなものを含む:

  • ダイナミック変数と定数変数の束縛
  • 関数、マクロ、スペシャルオペレータの束縛
  • コンパイラマクロの束縛
  • 型名とクラス名の束縛
  • 宣言に関数情報

3.1.1.2 ダイナミック環境

環境の一部である評価のためのダイナミック環境は、束縛を確立したフォームの実行中に 開始時点から廃止時点までの存続期間をもつような束縛を含む。 ダイナミック環境は特に以下のようなものを含む:

  • ダイナミック変数の束縛
  • アクティブな catch タグの情報
  • unwind-protect にって作られた脱出ポイントの情報
  • アクティブなエラー処理のための handler や restart 情報

実行プログラム中のある時点で任意の時点でのダイナミック環境は、 正確には 現在のダイナミック環境 としてする事ができるが、 単に ダイナミック環境 と呼ばれる事もある。

ある名前空間において、その名前との関連した束縛がダイナミック環境に存在した場合か、もしくは グローバル環境に束縛が存在する場合には「ダイナミック環境に束縛されている」と言われる。

3.1.1.3 レキシカル環境

レキシカル環境は実行中のプログラムのある時点における、その位置のフォー ムを含んだレキシカルスコープをもつ情報を含む環境である。レキカル環境は 特に以下のものを含む。

  • レキシカル変数やシンボルマクロの束縛
  • 関数やマクロの束縛 (これは暗黙的にコンパイラマクロがローカルに無効化される事に関する情報を含む)
  • block のタグ
  • go タグ
  • 宣言に関する情報

意味が処理されていく過程のプログラム中における任意の位置でのアクティブなレキシカル環境は、 正確には 現在のレキシカル環境 と参照されるが、単に レキシカル環境 と呼ばれることもある。

ある名前空間において、その名前と関連した束縛がレキシカル環境に存在した場合、もしくは グローバルな環境に束縛が存在する場合には「レキシカル環境に束縛されている」と言われる。

3.1.1.3.1 無レキシカル環境

無レキシカル環境 (null lexical environment) はグローバル環境と等価である。

一般的には環境オブジェクトの表現は実装依存であるが、環境オブジェクトが必要と されるどのような場所でも nil を使うことで無レキシカル環境を指定することができる。

3.1.1.4 環境オブジェクト

オペレータのなかには、環境オブジェクトと呼ばれるオブジェクトを利用する ものがある。それは与えられたレキシカル環境内でフォームの意味解析をする ために必要となるレキシカルな束縛の集合を表現している。環境オブジェクト 内の束縛の集合は、実際の評価時に必要とされる束縛のサブセットであるかも しれない 例えば、対応するレキシカル環境内における変数名や関数名の値 が環境オブジェクト中で利用可能でなかった場合など。

環境オブジェクトの型と性質は実装依存だ。 マクロ関数への環境パラメータの値は環境オブジェクトの一例である。

環境オブジェクトとして nil オブジェクトが使われた場合には無レキシカル環境を 意味する [ 3.1.1.3.1 節 (The Null Lexical Environment) を参照]。

補足説明

環境のポイントをおおまかに説明。

  • グローバル環境
    • defconstant 定数、defvar, defparameter によるダイナミック変数
    • defun による関数、defmacro によるマクロ、 if などのスペシャルオペレータ
    • define-compiler-macro によるコンパイラマクロ
    • deftype による型、 defclass によるクラス名
    • proclaim による宣言
  • ダイナミック環境
    • special 指定されたダイナミック変数
    • catch タグの情報
    • unwind-protect の情報
    • handler, restart などエラー関係の情報
  • レキシカル環境
    • let, let* によるレキシカル変数や define-symbol-macro シンボルマクロ
    • flet, labels 関数や macrolet マクロの束縛
    • block 情報
    • go タグ情報
    • declare による宣言

これだけの知識があればほぼおっけーだとおもいます。 あとは、サンプル。さんぷる。

グローバル環境

グローバル環境は簡単。いわゆる一つのグローバル変数とかのあれだから。 プログラム中どこからでも参照できる。

;; このへんにピンときたらグローバル
(defconstant ...)
(defvar ...)
(defparameter ...)
(defun ...)
(defmacro ...)
(define-compiler-macro ...)
(deftype ...)
(defclass ...)
(proclaim ...)

ダイナミック環境

;; ダイナミック環境をさわる
(let  ...) + (declare (special 変数名))
(let* ...) + (declare (special 変数名))
(catch ...)
(unwind-protect ...)
(handler-case ...)

レキシカル環境

;; レキシカル環境をさわる
(let ...)
(let* ...)
(flet ...)
(labels ...)
(block ...)
(go ...)
(declare ...)

なにが違うの?どう理解したらいいの?

;; 実例
(defvar *x* 100)
(defun dynamic-foo ()
  (let ((*x* 10))
    (dynamic-bar)))
(defun dynaimc-bar ()
  (print *x*))
(let ((x 100))
  (defun lexical-foo ()
    (let ((x 10))
      (lexical-bar)))
  (defun lexical-bar ()
    (print x)))
CL-USER> (dynamic-foo) ; *x* はダイナミック変数なので dynamic-foo 内のダイナミック環境で lexical-bar が呼び出される
10 
CL-USER> (dynamic-bar) ; dynamic-foo のダイナミック環境の生存期間は終わっているので、グローバル環境の値をみる
100
CL-USER> (lexical-foo) ; lexical-foo のレキシカル環境への束縛は lexical-bar のレキカル環境には影響しない。
100 
CL-USER> (lexical-bar) ; let のレキシカル環境の x の値を参照
100 

で、規格では define-symbol-macro はレキシカル環境に束縛をつくるので… ちなみに、シンボルマクロは普通のマクロと同様に展開されてしまうので、これだと setf ができません。 うーむスコープとエクステントの話をしないと正確じゃないですね。

(define-symbol-macro =x= 100)

(defun foo ()
  (let ((=x= 10))
    (bar)))

(defun bar ()
  (print =x=))

ねm

posted: 2007/04/19 23:31 | permanent link to this entry | Tags: LISP

(top)  (memo)  (rss)