Nice programing

정적 (어휘) 범위 지정 대 동적 범위 지정 (의사 코드)

nicepro 2020. 12. 13. 11:07
반응형

정적 (어휘) 범위 지정 대 동적 범위 지정 (의사 코드)


Program A()
{
    x, y, z: integer;

    procedure B()
    {
        y: integer;
        y=0;
        x=z+1;
        z=y+2;
    }

    procedure C()
    {
        z: integer;

        procedure D()
        {
            x: integer;
            x = z + 1;
            y = x + 1;
            call B();
        }

        z = 5;
        call D();
    }

    x = 10;
    y = 11;
    z = 12;
    call C();
    print x, y, z;
}

내 이해에서 정적 범위 지정을 사용하여 실행할 때이 프로그램의 결과는 x = 13, y = 7 및 z = 2입니다.

그러나 동적 범위 지정을 사용하여 실행 하면 결과는 x = 10, y = 7 및 z = 12입니다.

이 결과는 우리 교수님이 주신 결과입니다. 그러나 나는 그가 이러한 결과에 어떻게 도달했는지 내 삶을 이해할 수 없습니다. 누군가가 의사 코드를 살펴보고 두 가지 유형의 범위에서 값을 설명 할 수 있습니까?


으로 정적 (어휘) 범위 지정 , 프로그램 소스 코드의 구조는 당신이 언급하는 어떤 변수를 결정합니다. 동적 범위 지정을 사용 하면 프로그램 스택의 런타임 상태에 따라 참조하는 변수가 결정됩니다. 기본적으로 오늘날 널리 사용되는 모든 프로그래밍 언어 (아마도 emacs lisp 제외)는 어휘 범위 지정을 사용하기 때문에 이것은 매우 생소한 개념 일 가능성이 높습니다. 이는 인간과 분석 도구 모두가 추론하기 훨씬 더 쉽습니다.

이 훨씬 간단한 예제 프로그램 (의사 코드 구문으로 작성된)을 고려하십시오.

program a() {
  x: integer; // "x1" in discussions below
  x = 1;

  procedure b() {
    x = 2; // <-- which "x" do we write to?
  }

  procedure c() {
    x: integer; // "x2" in discussions below
    b();
  }

  c();
  print x;
}

프로그램 및 컴파일러는 두 변수를 참조 x하지만, 내가 그들을 표시했다 x1x2아래 토론을 완화 할 수 있습니다.

어휘 범위 지정을 사용하면 컴파일 타임 x에 프로그램 소스 코드의 정적 어휘 구조를 기반 으로 어떤 것을 참조 하는지 결정 합니다. 의 안쪽의 정의 x범위에 때 정의가 b 있다 x1, 그리고에 대한 질문 결의에 쓰기 때문에 x1, 그의 x = 2쓰기, 우리는 인쇄 할 수 있도록 2이 프로그램을 실행하기에.

동적 범위 지정을 사용하면 런타임에 추적되는 변수 정의 스택이 있습니다. 따라서 x작성하는 내용은 정확히 범위에있는 항목에 따라 다르며 런타임에 동적으로 정의되었습니다 . 실행 시작 a푸시 x => x1호출 스택에를 c밀어을 x => x2스택에, 우리가 얻을 때 다음 b, 스택의 상단은 x => x2우리로 쓰고, 그래서 x2. 이것은 x1그대로 유지되므로 1프로그램이 끝날 때 인쇄 합니다.

또한 약간 다른 프로그램을 고려하십시오.

program a() {
  x: integer; // "x1" in discussions below
  x = 1;

  procedure b() {
    x = 2; // <-- which "x" do we write to?
  }

  procedure c() {
    x: integer; // "x2" in discussions below
    b();
  }

  c();
  b();
}

Note b는 두 번 호출됩니다. 처음에는을 통해 c, 두 번째는 직접 호출 됩니다. 어휘 범위 지정을 사용하면 위의 설명이 변경되지 않고 x1두 번 모두 작성됩니다 . 그러나 동적 범위 지정에서는 x런타임에 바인딩되는 방식에 따라 다릅니다 . 처음으로를 호출 b하면 x2위에 설명 된대로 씁니다. 하지만 두 번째로를 씁니다. x1이것이 스택의 맨 위에 있기 때문입니다! ( 반납 x => x2시 팝업됩니다 c.)

자, 여기 교수님의 코드가 있는데, 어휘 범위를 사용하는 쓰기에 정확한 변수가 사용되는 주석이 달려 있습니다. 프로그램 끝에 인쇄되는 쓰기는 *다음 과 같이 표시됩니다 .

program A()
{
    x, y, z: integer; // x1, y1, z1

    procedure B()
    {
        y: integer; // y2
        y=0; // y2 = 0
        x=z+1; // x1 = z1 + 1 = 12 + 1 = 13*
        z=y+2; // z1 = y2 + 2 = 0 + 2 = 2*
    }

    procedure C()
    {
        z: integer; // z2

        procedure D()
        {
            x: integer;  // x2
            x = z + 1; // x2 = z2 + 1 = 5 + 1 = 6
            y = x + 1; // y1 = x2 + 1 = 6 + 1 = 7*
            call B();
        }

        z = 5; // z2 = 5
        call D();
    }

    x = 10; // x1 = 10
    y = 11; // y1 = 11
    z = 12; // z1 = 12
    call C();
    print x, y, z; // x1, y1, z1
}

그리고 여기에는 동적 범위 지정이 있습니다. 메모 만을 변경에 B, 그리고의 위치에 *태그 :

program A()
{
    x, y, z: integer; // x1, y1, z1

    procedure B()
    {
        y: integer; // y2
        y=0; // y2 = 0
        x=z+1; // x2 = z2 + 1 = 5 + 1 = 6
        z=y+2; // z2 = y2 + 2 = 0 + 2 = 2
    }

    procedure C()
    {
        z: integer; // z2

        procedure D()
        {
            x: integer;  // x2
            x = z + 1; // x2 = z2 + 1 = 5 + 1 = 6
            y = x + 1; // y1 = x2 + 1 = 6 + 1 = 7*
            call B();
        }

        z = 5; // z2 = 5
        call D();
    }

    x = 10; // x1 = 10*
    y = 11; // y1 = 11
    z = 12; // z1 = 12*
    call C();
    print x, y, z;
}

정적 범위 지정 및 동적 범위 지정은 모든 언어로 작성된 프로그램에서 특정 고유 이름을 가진 특정 변수를 찾는 다른 방법입니다.

인터프리터 또는 컴파일러가 변수를 찾는 방법과 위치를 결정하는 데 특히 유용합니다.

코드는 다음과 같습니다.

f2(){

   f1(){
   }

   f3(){
    f1()
   }

}

공전:

이것은 기본적으로 텍스트이며, 첫 번째 변수가 정의되거나 로컬 함수에서 확인되지 않습니다 (이름을 f1 ()로 지정), 로컬 함수 f1 ()에 없으면 함수를 포함 하는 함수 f2 ()에서 변수가 검색됩니다. ( 이것은 f1 ()을 의미합니다), ... 이것은 변수가 발견 될 때까지 계속됩니다.

동적:

This is different from static, in the sense, as it is more runtime or dynamic, first variable is defined or not will be checked in local function,if not in the local function f1(),then variable will be searched in function f3() that called this function(by this I mean f1() again), ...this continues...until variable is found.


The crux is that the lexical graph looks like this:

B <- A -> C -> D

whereas the call graph looks like this:

     A -> C -> D -> B

The only difference is what lineage B has. In the lexical picture, B is defined directly in the scope of A (the global scope). In the dynamic picture, the stack at B already has D on top of C and then A.

This difference amounts to how the keywords x and z are resolved in B. Lexically, they are identified with A.x and A.z, but dynamically, they are identified with D.x and (since no D.z exists) with C.z.

def B:
    B.y = 0
    x = z + 1
    z = y + 2
def C:
    def D:
        D.x = z + 1
        y = D.x + 1
        call B
    C.z = 5
    call D
A.x, A.y, A.z = 10, 11, 12
call C
print A.x, A.y, A.z

Above I've tried to represent your code more clearly. Note that D mutates A.y according to both methods of name resolution, whereas B only mutates A.x and A.z if lexical rather than dynamic scoping is chosen.

Note that while a function is only ever defined once*, it is common to call it from multiple places (and it may even call itself recursively). Thus, while it is fairly trivial to perform lexical scoping using the static code, the dynamic scoping is more complicated because the same keyword (in the same function) may resolve to different variables (from different name spaces) during different calls to that function (requiring you to step through the program and track how the call stack changes during execution).

*(Except in templating languages..)

참고URL : https://stackoverflow.com/questions/22394089/static-lexical-scoping-vs-dynamic-scoping-pseudocode

반응형