Monday, July 20, 2015

Scope และ Referencing Environment

Scope และ Referencing Environment

Scope การใช้งานตัวแปร คือ ขอบเขตที่สามารถใช้งานตัวแปรได้
การกำหนด Scope จำแนกได้ 2

ลักษณะ
1. Static Scoping  ตัวแปรจะมีขอบเขตสัมพันธ์กับ Unit ที่ครอบตัวแปร  การใช้งานตัวแปรสามารถทำได้หลังจากมีการประกาศ (declare) ตัวแปรแล้ว (สำหรับภาษาที่ต้องประกาศไทป์ก่อนใช้)
หรือในบางภาษาที่ไม่ต้องประกาศไทป์ก่อนใช้งาน ก็จะสามารถเรียกใช้ได้ทันทีตั้งแต่บรรทัดที่มีการใช้งานตัวแปร
เช่น ใน C มีการจัดการแบบ Static scoping
1.  |  #include <stdio.h>
2.  | int x;
3.  | void main( )
4.  | {
5.  |      void  myfunction(int a, int b);
6.  |      int y;
7.  |    ...
8.  | }
9.  | void myfunction (int m, int n)
10.| {
11.|      int o;
12.|     ...
13.| }

Unit หรือขอบเขต ในโปรแกรมสามารถพิจารณาได้ดังนี้
1. ขอบเขตครอบคลุมทั้งโปรแกรม
2. ขอบเขตภายในฟังก์ชั่น main
3. ขอบเขตภายในฟังก์ชั่น myfunction

ตัวแปร  x ในภาษา C จึงสามารถมองเห็นได้จากทุกๆส่วนของโปรแกรม  หรือเราจะรู้ตามกฎการเป็น Global variable ในภาษา C ที่อะไรประกาศเหนือฟังก์ชั่น main จะมองเห็นได้จากทุกส่วนของโปรแกรม main และ subfunction
ตัวแปร a และ b เป็นเพียงตัวแปรที่ประกาศตามข้อกำหนดของฟังก์ชั่นไม่สามารถใช้งานได้
ตัวแปร y ประกาศในฟังก์ชั่น main จึงสามารถเรียกใช้ได้ภายในฟังก์ชั่น main โดยนับตั้งแต่คำสั่งถัด (หรือบรรทัดถัดไป) หลังประกาศตัวแปรแล้ว แต่ตัวแปร y ไม่สามารถมองเห็นได้ในฟังก์ชั่น
ตัวแปร m, n  และ o ถือว่าเป็นตัวแปรที่ประกาศในฟังก์ชั่น ดังนั้นสามารถใช้งานได้ในเวลารันที่มีเรียกฟังก์ชั่นเท่านั้น และจะเรียกตัวแปร o ได้ในบรรทัดถัดไป (หลังบรรทัดที่ประกาศ)

ข้อสังเกต
1. การจัดการขอบเขตการใช้งานของตัวแปรในลักษณะนี้มักจะกำหนดให้ตัวแปรที่ประกาศใน Unit ที่ให,่กว่า สามารถมองเห็นได้ใน Unit ที่เล็กกว่า เช่น กรณีตัวแปร x เป็นต้น
2. เมื่อตัวแปรมีขอบเขตของตัวแปร  เราจะเรียกว่าเป็น Local variable ของ Unit นั้น  ส่วนตัวแปรอื่นๆที่อยู่นอกจาก Unit นั้น เราจะเรียกว่า Nonlocal variable   
3. บางภาษาการโปรแกรมกำหนดให้การประกาศตัวแปรต่างๆ ต้องทำก่อนคำสั่งอื่นๆ โดยไม่ยอมให้มีการประกาศในระหว่างโปรแกรม   แต่บางภาษาอนุญาตให้มีการประกาศได้ในตำแหน่งใดก็ได้ของโปรแกรม เพียงแค่กำหนดขอบเขต เช่นในภาษา C ใช้เครื่องหมาย {...} กำหนดขอบเขตของตัวแปร
    {
        int i;
        i = 88;
        j = 99;
        printf("(2) i: %d, j: %d\n", i, j);
    }


2. Dynamic Scoping
การจัดการขอบเขตการใช้งานของตัวแปรขึ้นกับลำดับการเรียกฟังก์ชั่น
สมมติภาษา Anynomous มีการจัดการแบบ Dynamic Scoping

1.  |int  b = 5;
2.  |int foo( )
3.  |{
4.  |    int a = b + 5;
5.  |    return a;
6.  |}
7.  |int bar( )
8.  |{
9.  |    int b = 2;
10.|    return foo( );
11.|}
12.|int main( )
13.|{
14.| foo( );
15.| bar( );
16.| return 0;
17.| }

บรรทัดที่ 12 เมื่อมีการรันโปรแกรมฟังก์ชั่น main( ) (สมมติ main ถูกเรียกก่อน) ถูกเรียกก่อน
ตัวแปร b จะถูกมองเห็นเป็นอันดับแรก
บรรทัดที่ 14 เมื่อเรียกฟังก์ชั่น foo จะมองเห็นตัวแปร a และ b ซึ่ง a = 10 และ b = 5 แล้วรีเทิร์นออกจากฟังก์ชั่นไปบรรทัดที่ 15
บรรทัดที่ 15 จะมองเห็นตัวแปร a และ b ดังนั้นเมื่อเรียกฟังก์ชั่น bar การประกาศ b ขึ้นมาใหม่จะเป็น b อีกตัวแปรหนึ่ง ซึ่งมีค่าเท่ากับ 12 และยังคงมี b = 5 ในสแตก แต่ไม่สามารถเรียกใช้ b = 5 ภายใน bar( บรรทัดที่ 9-11)  มีการเรียก  foo อีกครั้ง (จากการเรียก return ) จะเกิด a อีกตัว (บรรทัดที่ 4) ซึ่งตอนนี้ a มีค่าเท่ากับ 7 (จาก b = 2 ใน bar) ส่งค่ากลับคือ 7 แล้วในบรรทัดที่ 10 จะส่งค่ากลับคือ 7 แล้วรีเทิร์นไปทำงานที่บรรทัดที่ 16
 

ถ้าแก้ไขโค้ดใหม่ (ยังคงเป็นภาษา Anynomous ไม่ใช่ภาษา C!!)
12.|int main( )
13.|{
14.|  ...
15.| foo( );
16.| ......
17.| bar( );
18.| ......
19.| return 0;
20.| }

บรรทัดที่ 14 จะมองเห็นตัวแปร b 
บรรทัดที่ 16 เมื่อเรียก foo แล้วจะเห็นตัวแปร  b = 5 และ a = 10
บรรทัดที่ 18 เมื่อเรียก bar แล้วจะเห็นตัวแปร  b = 2 และ a = 7 
ขอบเขตของตัวแปรขึ้นกับลำดับการเรียกฟังก์ชั่น ไม่ใช่ขอบเขตของ Unit จากภาพด้านบน  ยังคงมี a = 10 และ b = 5 ในสแตก แต่การรันโปรแกรมจะไม่สามารถเรียกใช้ตัวแปรเหล่านี้ได้ เพราะถูกบดบังด้วยตัวแปร a และ b ที่เกิดขึ้นล่าสุดจากการประกาศในบรรทัดที่ 4 และ 9 ในการเรียก foo และเรียก bar (ซึ่งเรียก foo ต่อเพื่อรีเทิร์นค่า) 

ข้อสังเกต
ยังต้องพิจารณาจากขอบเขตของตัวแปรจาก Unit ที่ตัวแปรอยู่เช่นเดียวกับ Static scoping แต่พิจารณาเพิ่มเมื่อมีการเรียกฟังก์ชั่น


Referencing environment

Referencing environment หมายถึง ชื่อตัวแปรต่างๆที่มองเห็นได้จากบรรทัดที่กำลังประมวลผล
จากโค้ดที่ยกตัวอย่างบนสุด  สมมติรันโปรแกรมมาถึงบรรทัดที่ 6 ณ บรรทัดนั้นจะสามารถมองเห็นตัวแปร  y และตัวแปร x  ได้  ซึ่งทั้งสองตัวแปรคือ  Referencing environment ของการประมวลผล ณ ขณะนั้น
หากรันโค้ดมาถึงบรรทัดที่ 11 Referencing environment คือ ตัวแปร m, n, o และ x พารามิเตอร์ m และ n ถือว่าเป็น local variable ของฟังก์ชั่น

No comments:

Post a Comment