Scope in Programming Languages
Scope in Programming Languages
Amruth N. Kumar Eric Fernandes, Steve Obringer Ramapo College of New Jersey [email protected]
Introduction
Scope is an important concept in programming languages one cannot read or write large programs without understanding the concept of scope. The scope of a variable in a program is the lines of code in the program whe be accessed.
Historically, two different types of scope have been used in programming languages: static scope and dynam modern programming languages such as Pascal, C++ and Java use static scope. Some languages such as APL, Sn versions of LISP use dynamic scope. As students of Programming Languages, we will study both these types.
The converse of scope is referencing environment. The referencing environment of a procedure is the set of whose scope extends to the procedure. It may be divided into local and non-local environments. The local refere environment of a procedure consists of all the variables declared within the procedure, and includes any formal procedure. The non-local referencing environment consists of all the variables not declared in the procedure, b extends to the procedure.
The concept of scope applies not only to variable names but also to the names of procedures. The scope of th procedure determines all the procedures/functions in a program that can call the procedure.
Scope Courseware
This courseware addresses all these aspects of scope. It comprises of five modules addressing the following t 1. Static Scope of variables 2. Static Referencing Environment of a procedure 3. Dynamic Scope of variables 4. Dynamic Referencing Environment of a procedure 5. Callability of procedures - Scope of procedure names
Pascal is popularly used to illustrate the intricacies of static scope since it allows procedure definitions to be nest you compare and contrast static scope with dynamic scope, and to reduce the burden of having to learn new synta will use Pascal-like programs to illustrate dynamic scope also.
Each of the five modules contains a tutorial and an applet. The applet is hyperlinked from the tutorial. The inform tutorial is organized under the following titles:
Definition: In this section, the definition of the concept is presented. Where applicable, the definition is clarified Pascal.
Example: This section includes the following items: 1. A sample program, and a problem based on the program; 2. Answer to the problem, along with explanation.
Pragmatics: In this section, additional questions are presented based on the earlier example. These questions are you consider other aspects of the problem, and extend what you have learned to other concepts.
Algorithms to determine Scope: Whereas the definition section describes the relevant theory, this section l that you may want to use to apply the theory to solve problems.
Test your understanding - Instructions: This section lists the following items: 1. Your options for solving problems using the applet; 2. The steps you must follow to solve each problem; 3. A screen shot illustrating these steps;
4. A hyperlink to the applet itself. Note that when you click on the hyperlink, the following two windows will be
a. A web page to record how many problems you have attempted and how many problems you have solve
b. The applet window that you will use to solve the problems. You may solve as many problems as you w
exiting the applet window. Please pay particular attention to the feedback provided by the applet for e
Once you exit the applet, you can re-launch it by clicking on the Create New Problem button on the acc page.
Acknowledgements
Partial support for this work was provided by the National Science Foundations Course, Curriculum and Labora Program under grant DUE-0088864, January 2001-December 2002.
print("in laurel -- n = ", n); hardy; end; m := 50; n := 100; print("in main program -- n = ", n); laurel(1); hardy; end;
Scoping in Lisp
The default scope rule in lisp is static scoping.
(setf m 50) (setf n 100) (defun hardy () (format t "~&in hardy -- n = ~a" n)) (defun laurel (n) (format t "~&in laurel -- m = ~a" m) (format t "~&in laurel -- n = ~a" n) (hardy)) (format t "~&in main program -- n = ~a" n) (laurel 1) (hardy)
Dynamic Scoping
Common Lisp also supports dynamic scoping. Using this scoping rule, we first look for a local definition of a variable. If it isn't found, we look up the calling stack for a definition. (See page 435 of the Lisp book.) Dynamic scoping was the norm in versions of Lisp before Common Lisp, and is also used in some older, interpreted languages such as SNOBOL and APL.
(defun hardy () (format t "~&in hardy -- n = ~a" n)) (defun laurel (n) (format t "~&in laurel -- m = ~a" m) (format t "~&in laurel -- n = ~a" n) (hardy)) (format t "~&in main program -- n = ~a" n) (laurel 1) (hardy)
Nesting procedures inside of other procedures interacts in interesting ways with recursion:
begin
integer global, n; procedure laurel(n: integer); begin procedure hardy; begin print(global); print(n); end; if n<4 then laurel(n+1); else hardy; end; global := 99; n := 100; laurel(1); end;
Note that when we finally call hardy, there are 5 different n's on the stack: the global one (with value 100), then 4 different invocations of laurel (with n=1, n=2, n=3, and n=4).
Procedures as Parameters
In Algol, Pascal, and Lisp, you can pass procedures or functions as parameters. To pass a procedure as a parameter, the system passes a closure: a reference to the procedure body along with a pointer to the environment of definition of the procedure.
begin procedure test(n: integer, p: procedure); begin procedure rose; begin print("in procedure rose -- n="); print(n); end; print("in procedure test -- n="); print(n); p; if n<10 then begin if n=3 then test(n+1,rose) else test(n+1,p) end end; procedure violet; begin print("in procedure violet"); end;
test(1,violet); end;
Output:
in procedure test -- n=1 in procedure violet in procedure test -- n=2 in procedure violet in procedure test -- n=3 in procedure violet in procedure test -- n=4 in procedure rose -- n=3 in procedure test -- n=5 in procedure rose -- n=3 in procedure test -- n=6 in procedure rose -- n=3 in procedure test -- n=7 in procedure rose -- n=3 in procedure test -- n=8 in procedure rose -- n=3 in procedure test -- n=9 in procedure rose -- n=3 in procedure test -- n=10 in procedure rose -- n=3
In Algol and Pascal, we can only pass procedures in as parameters -- we can't return a procedure or a function as a value from another function. We can do this in Lisp, however -- it means that Lisp can't always use a stack for storage allocation for local variables. Blocks in Smalltalk also are lexically scoped, and include their environment of definition. Blocks can be returned from methods, assigned to global variables, and so forth -- so that storage for local variables can't always be allocated on a stack in Smalltalk either. Example:
| a sum | a := Array new: 3. a at: 1 put: 10. a at: 2 put: 20. sum := 0. a do: [:n | sum := sum+n].
After we do this, the two global variables B1 and B2 are bound to blocks. The local variable k is no longer visible, but is still accessible and is shared by the two blocks. So B1 value will return 100. If we evaluate B2 value: 5, this will assign 7 to k. After that evaluating B1 value will return 7.
Paramerter transmission:
Exam-like questions
A.
Parameter transmission
Subprograms need mechanisms to exchange data. Arguments - data objects sent to a subprogram to be processed Obtained through o o parameters non-local references
Establishing a Correspondence Positional correspondence pairing actual and formal parameters based on their respective positions in the actual- and formal- parameter lists. Correspondence by explicit name the name is paired explicitly by the caller. 7.
parameter data object makes no difference and cannot be used by the subprogram. Note: Often "pass by" is used instead of "call by" . Examples:
Pass by name: After calling S(A[i],i), the effect is as if the procedure were i := 2; A[i] := 0; As a result A[2] becomes 0. On exit we have i = 2, A[1] = 1, A[2] = 0. Pass by reference: Since at the time of call i is 1, the formal parameter el is linked to the address of A(1). Thus it is A(1) that becomes 0. On exit we have: i = 2, A(1) = 0, A(2) = 1
8.
Transmission semantics
Types of parameters: input information output information (the result) both input and output The three types can be accomplished by copying or using pass-byreference Return results: Using parameters Using functions with a return value
9.
Thus the compiler has two main tasks in the implementation of parameter transmission 3. It must generate the correct executable code for transmission of parameters, return of results, and each reference to a formalparameter name. 4. It must perform the necessary static type checking to ensure that the type of each actual-parameter data object matches that declared for the corresponding formal parameter B.
Exam-like questions
1. Describe each method of parameter transmission (see A.2). 2. What is the difference between pass by name and pass by reference methods of parameter transmission? 3. What is the difference between pass by value and pass by reference methods of parameter transmission? 4. What is the difference between pass by value-result and pass by result methods of parameter transmission? 5. Consider the following code in some imaginary language : /* main program */ .... integer i = 1,j = 2; subprog(i,j); print(i,j); ..... subprog(integer k, integer m); begin k = k + 1; m = m + i; print (i,j,k,m); end;
What values would be printed in the three modes of parameter transmission? Fill in the table below: print(i,j,k,m) in subprog Print(i,j) in main program i j