PL-2.3変数有効範囲(Scope)とその他

10264 ワード

Scope


Scope:任意の変数のビジュアルコード領域
Scope:任意の変数を参照できる領域、近接時にエラーが発生しないコード領域
  つまり、Scopeは空間概念です.

Static Scoping


  C言語のように、ほとんどの言語で採用されている方式で、変数の範囲は静的に定義されている方式です.by Compiler
Static Scoptingは「どこで発表されたのか」に注目している.

  • ローカル変数:もちろん、ローカル変数を宣言するデバイスでのみ使用できます.

  • Nonlocal Variable:独自のデバイスで使用できますが、宣言はデバイス上で行われる変数ではなく他の場所で行われる変数を意味します.

  • グローバル変数は非ローカル変数に含まれます.

  • あるいは、より大きな外部のユニット(関数)によって宣言される変数も含まれます.
  • int a;
    
    int main(void) {
    	int a, b;
        
        while(...) {
        	int a;				// 이 a는 while문 내에서 선언된 a를 가리킨다. (Local)
            a++;				// Static Scoping
            b = 3;				// Nonlocal Variable for while()
        }
     	return 0;
    }
    ~>,while文がaを宣言しない場合,Static Scoptingロジックはmainで宣言したaを指す.
    ~>でmainがaを宣言しない場合、Static Scoptingロジックはグローバル変数aを指す.
  • 静的および動的パラメータの概念
  • Static Parent:「宣言」自身(変数/関数など)のオブジェクト
  • 宣言は一度だけです.
  • 動的Parent:「呼び出し」自身(変数/関数など)のオブジェクト
  • は随時変更可能です.
  • このパラメータ分割基準は、静的/動的スキャンの分割基準と同じです.
      次のPascalコードを見てみましょう.
    procedure big ;
    	var x : integer ;
    
    	procedure sub1 ;			// Inner(Nested) Function : 로컬 변수처럼, 로컬 함수를 정의!
    		begin
    			... x ....			// 이때, 이 x는 어디의 x인가.
    		end ;
    
    	procedure sub2;
    		var x : integer ;
    		begin
    			sub1 ;
    		end ;
    
    	begin
    		sub2 ;
    	end 
    
    ~>bigというサブルーチンでは、変数x、ローカルサブルーチンsub 1、sub 2を宣言して定義する.
    ~>bigはsub 2を呼び出す.sub 2はsub 1を呼び出す.このとき、sub 1のxはどこのxなのでしょうか.
    ~>sub 1はbig,bigはstatic parentである.
    呼び出し~>sub 1はsub 2であるため、sub 2は動的パラメータである.
    ~>すなわちStatic Scopting言語の場合、xはbigで宣言されたxを指す.★
    Scoptingはコンパイラによって実行されます.
    ※Nested(Inner)Function機能:別の関数の機能を関数に宣言して定義できます.C言語はサポートされておらず、Ada、JavaScript、Python、FORTRAN 2003などがサポートしている.
    ※Block:ブロック単位でScopeを計算する言語もあります.(最近の傾向)
    ~>ローカル変数をコードブロック内で使用できる言語.ex)C言語
    ~>は、Static Scoptingに相当します.宣言が基準だからです.
    ex) if (a >= b) { int temp ; temp = a ; a = b ; b = temp; }
    CはInner Function機能がなく,Blockを基準としたStatic Scopting方式と考えられる.

  • 静的スキャンの欠点


  • 上の図の構造を使用してプログラムを作成する場合、Static Scopting言語では、コンパイラはエラーを検出せず、正常に通過します.

  • 実際、プログラマーが注意すれば、間違いはないと考えることもできます.
  • であるが、上記の構造は明らかに(論理的に)誤りリスクが高い.

  • 1)EでDを呼べますか?
  • はできません.DはA、EとAはScopeなので接点がありません.
  • EはDを発表しますか?No
  • BはDを発表しますか?No
  • MainはDを発表しますか?No ~> Nope!!

  • 2)EでBを呼べますか?
  • は驚くほどできます.E内部にB宣言がなくても.
  • EはBを発表しますか?No
  • BはBを発表しましたか?No
  • MainはBを発表しますか?Yes~>これでいいです

  • 3)D内でBを呼んでもいいですか.
  • でも驚くべきことができます.
  • DでBを発表しましたか?No
  • AはBを発表しましたか?No
  • MainはBを発表しますか?Yes~>これでいいです

  • 4)EでEを呼べますか?
  • も可能です.これは再帰呼び出しであり、フローは以下の通りです.
  • EはEを発表しますか?No
  • BはEを発表しますか?いいですよ.
  • すなわち,プログラマはAにC,D,BにEを宣言し,上記のようにプログラムを記述することで,不用意な呼び出し関係を実現できる.
    Static Scoptingは「宣言」だけに注目しているからだ.
    ※C/C++はInner(Nested)機能がなく、Block単位でStatic Scoptingを行う言語なので、このような問題は発生しません.
    ※一方、上記の図では、BのAのコールはDellableの場合でも可能であることに注意してください.これはTop-Down方式のインスタント言語だからです.
    ~>同様に、DからCを呼び出すことができる.逆に,CからDを呼び出すことは不可能である.Top-Down!

    Dynamic Scoping


    ダイナミックスキャンは「誰が発表したのか」ではなく、「誰が呼んだのか」です.
    Dynamic Scoping is based on the 'Calling Sequence' of subprograms!

  • つまり、Dynamic Parentについて行きます.

  • 従って、動的走査方式では、走査は実行時に行われる.
    これはCompilerの
  • 静的走査とは対照的である.
  • ダイナミックスキャンはInterpreterに適しています.

  • ダイナミックスキャンの利点
  • パラメータネストを行わなくても、磁気(サブルーチン)を呼び出す関数のローカル変数を使用することができます.便利です.

  • ダイナミックスキャンの欠点

  • Nonlocal変数にアクセスする場合、静的タイプチェックはできません.コールフローに従って、タイプを見つけることです.

  • 「テキストの近接性」を考慮せずに、任意のビジュアルサブルーチンのローカル変数にアクセスできます.
  • という言葉は、責任が下がったということです.★
  • 実際,上記の欠点は致命的すぎるため,現代では動的スキャンを用いる言語はほとんどない.
    ex)以前に動的スキャンを使用した言語:APL、SNOBL、LISPのいくつかの要約バージョン

    Pascal言語の例


      Pascal言語を例にとると、以下のようになります.プログラム内のローカル変数の内容.
    Pascalの
  • 範囲:
  • 、DeclarationからEnd保留語へ
  • Pascal Lifetime:開始から終了まで、
  • ~>PascalはStatic Scopting言語です.
    procedure example;
    	procedure increments;
    		begin
    			sum++;			// Static Scoping에선 에러, Dynamic Scoping에선 가능
    		end;				// Pascal은 Static Scoping이므로 에러이다!
    
    	procedure computes;
    		var sum : integer;
    		begin
    			increments;
    		end
    	begin
    		computes;
    	end;
    ~>状態スキャンを基準としてincrements関数のsumという変数は表示されません.
    しかし,Scopeは非可視であるがsumのLifetimeはincrementsで有効であることに注目すべきである.
    どうして.sumは計算中に宣言されるため、このプロセスはincrementsプロセスを囲んでいる.
    つまり、ScopeとLifetimeは別々にしなければなりません.ライフサイクルは「発表から終了まで」です.

    Referencing Environment


    Reference Environment:特定の状態で表示されるすべての名前の集合を指します.

  • Static Scopting言語では、環境を参照
  • は、この変数のLocal ScopeおよびScopeのすべての変数
  • を宣言する.

  • ダイナミックスキャン言語で、環境を参照
  • は、変数のローカル範囲を宣言し、呼び出しプロセス内のすべての変数
  • を宣言する.

  • この場合、両方のメソッドに同じ名前がある場合、Scopeに近い変数のみが処理され、遠い変数はHidden Variableとみなされます.★

  • ≪アクティブ・プロシージャ|Active Procedure|emdw≫:プロシージャは実行を開始しましたが、まだ終了していません.
  •   次のPascal言語の例です.
    procedure example ;
    	var a, b : integer ;
    	procedure sub1 ;
    		var x, y : integer ;
    		begin
    			....  		// 여기서는 sub1의 x, y, example의 a, b를 접근 가능 (Static Scoping)
    		end ;
    
    	procedure sub2
    		var x : integer;   		// ⓐ 지역 입장에선 sub2의 x가 Hidden Variable이다.
    		procedure sub3 ;
    			var x : integer ;
    			begin 
    				....       // ⓐ 지역. 여기서는 sub3의 x, example의 a, b 접근 가능 (Static)
    			end
    		begin
    			.... 		// 여기서는 sub2의 x, example의 a, b만 Reference 가능 (Static)
    		end
    	begin
    		....			// 여기서는 a, b만 접근 가능 (Static Scoping)
    	end ;
    ~>注釈を読むことで、流れを理解します.

    Named Constant


    Named Constant:Bindingが発生したときに発生したValue Bindingは1回のみ保存され、その後も値が変わらない変数
  • C言語のdefine前処理文はここにありません.
  • #define MAX_LEN		100000		// 얘는 변수가 아니다. 그냥 바꾸는거지.
  • C言語のconstキーワード宣言の変数がName Constantの例です.
  • const宣言時に、初期化後に値を変更しようとすると、コンパイラはコンパイルエラーをエクスポートします.
  • const float PI = 3.141592;
    PI += 3;					// Compile Error since it's Named Constant !
  • Named Constantsは、プログラムの信頼性と信頼性を向上させることを目的としています.★
  • Initialization


    初期化:ストレージBindingが発生したときにValue Binding、すなわち初期化を実行します.
      各種言語の初期化方法
    1) C
    int a = 3;
    const int a = 3; (Named Constant)
    2) FORTRAN
    REAL PI
    INTEGER SUM
    DATA SUM/0/, PI/3.14159/
    3) Ada
    SUM : INTEGER := 0 ;
    4) ALGOL ★
    int first := 10;
    int first = 10; (Named Constant)