静的スコープとは? わかりやすく解説

静的スコープ

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/11/26 23:40 UTC 版)

ナビゲーションに移動 検索に移動

静的スコープ(せいてきスコープ、: static scope)とは、プログラミング言語におけるスコープの一種。字句のみから決定できるため、字句スコープまたはレキシカルスコープ (lexical scope) ともいう[1]

概要

まず、一般的なローカル変数のスコープについて考える。

ブロックなどの構造を持つプログラミング言語では、あるブロックの内側のローカル変数は、そのブロックの外側からは「見えない」というものが多い。ただし、以前のJavaScript (ECMAScript) のように、サポートされるのは関数内ローカルのみで、ブロックローカルというスコープは無いものもある[2]

疑似コードによる例を挙げる。

A {
    var x;
}

B {
    var x; // A内のxとは別物
    var f;

    C {
        var y; // Cの内側からしか見えない
        y = rand();
        f = function(z) { return y + z; };
    }
    x = f(42);
}

ブロックAで定義されている変数xとブロックBで定義されている変数xは同じ識別子を持つが、ブロックが異なるため実体は別である。また、ブロックBからは、さらに内側のブロックCで定義されている変数を参照することはできない。逆にブロックCからはブロックBで定義されている変数xとブロックCで定義されている変数yが参照可能である。

以上のようなスコープはローカル変数として一般的なものである。しかし、上記の疑似コード中にある f = function(z) { return y + z; }; のように、スコープ内にある手続きオブジェクトクロージャ)によって、そのスコープ内における束縛を外部に持ち出すといったような(ことが可能な言語の)場合に、「静的スコープか否か」といったようなことが議論になる。

次の節で述べるCommon Lispでのdefvarや、Perlにおいてmyではなくlocalで宣言した変数といった動的スコープの場合は、その名前解決が、そのソースコードにおいて見えるように解決される(静的スコープ)のではなく、実行時の関数呼び出しの経路(コールスタック)から、ひとつひとつ呼出元をたどるようにして行われる(詳細は「動的スコープ」の記事を参照)。

それに対し静的スコープの場合は、手続きオブジェクトがクロージャによって実装されているなどのようにして、そのスコープにおける束縛が手続きオブジェクトに「ひっ付いて」おり、コールスタックによってではなく、手続きオブジェクトが作られた場所のスコープで名前が解決される(「コールスタック」の記事中の「ルーチンの入れ子における静的スコープサポート」という記述も参照)。

Common Lispにおける例

Common Lispは、静的スコープを一般的なルールとし、動的スコープの名前については明示が必要である。

(defvar *a*)
;; *a* を動的スコープで値なしで宣言する。
;; アスタリスクは名前の一部である。
;; defvarは、以降のそれに対する束縛が静的なものでなく、
;; 動的なものである事を保証する。

(setf *a* 5)
;; 変数 *a* を整数 5 に設定する。

(let ((*a* 3)) *a*)
; --> 3 
;; 明示的にletの中で上書きされた場合、*a*は3

*a*
; --> 5
;; letの外に出るともとに戻る

(defvar func-lex)
(setf func-lex
	  (let ((a 3))
		(lambda () a)))
;; 現在、静的スコープ内の3がlambdaの中に残っている
;; したがって、

(let ((a 5))
  (funcall func-lex))
; --> 3
;; 外からaを書き換えて呼び出しても、
;; 保存された静的な束縛 a = 3 がまだ残っており、
;; それが有効になって答えは3となる

;; 一方、*a*について考えると、
(defvar func-dyn)
(setf func-dyn
	  (let ((*a* 3))
		(lambda () *a*)))
(funcall func-dyn)
; --> 5

;; *a*は動的スコープの変数として宣言されているため、
;; lambdaの中の *a* は常に
;; その時点での最も外側の変数を指すことになる。
;; 静的スコープに束縛された *a* = 3 はlambdaの中に保存されない

脚注

[脚注の使い方]
  1. ^ lexical は「字句の」「語彙の」といった意味を持つ英語の形容詞。
  2. ^ ECMAScript 6 からは、キーワードvarで宣言した関数内ローカルな変数の他に、letで宣言した変数はブロックローカルになる。

関連項目


静的スコープ

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/02/15 09:28 UTC 版)

Scheme」の記事における「静的スコープ」の解説

詳細は「静的スコープ」を参照動的スコープ」も参照 マッカーシーが後に回顧で、初期LISPLISP 1 および LISP 1.5に関して「In modern terminology, lexical scoping was wanted, and dynamic scoping was obtained.」と書いているように、計算理論的にも静的スコープが本来は「正当」であり、動的スコープは、言ってしまえばある種安易なインタプリタ実装手法が招く「バグ」である(有用なことも多いが)。 ガイ・スティールは、LISP 1.5 からの変更点として最初に静的スコープの採用実装挙げており、サスマンがAlgolに関して持っていた興味からによるもので、Algol直接影響だと述べている。 「FUNARG問題」(en:Funarg problem)としてLISP初期から既に認識され議論されていたことでもあり、必ずしもSchemeから始まったとは言えないが、Scheme以後LISP方言に静的スコープが広まったのはSchemeからの影響と言ってよく、殊にCommon Lisp特筆される

※この「静的スコープ」の解説は、「Scheme」の解説の一部です。
「静的スコープ」を含む「Scheme」の記事については、「Scheme」の概要を参照ください。

ウィキペディア小見出し辞書の「静的スコープ」の項目はプログラムで機械的に意味や本文を生成しているため、不適切な項目が含まれていることもあります。ご了承くださいませ。 お問い合わせ



固有名詞の分類


英和和英テキスト翻訳>> Weblio翻訳
英語⇒日本語日本語⇒英語
  

辞書ショートカット

すべての辞書の索引

「静的スコープ」の関連用語

静的スコープのお隣キーワード
検索ランキング

   

英語⇒日本語
日本語⇒英語
   



静的スコープのページの著作権
Weblio 辞書 情報提供元は 参加元一覧 にて確認できます。

   
ウィキペディアウィキペディア
All text is available under the terms of the GNU Free Documentation License.
この記事は、ウィキペディアの静的スコープ (改訂履歴)の記事を複製、再配布したものにあたり、GNU Free Documentation Licenseというライセンスの下で提供されています。 Weblio辞書に掲載されているウィキペディアの記事も、全てGNU Free Documentation Licenseの元に提供されております。
ウィキペディアウィキペディア
Text is available under GNU Free Documentation License (GFDL).
Weblio辞書に掲載されている「ウィキペディア小見出し辞書」の記事は、WikipediaのScheme (改訂履歴)、Common Lisp (改訂履歴)、スコープ (プログラミング) (改訂履歴)の記事を複製、再配布したものにあたり、GNU Free Documentation Licenseというライセンスの下で提供されています。

©2025 GRAS Group, Inc.RSS