The scope of an identifier in a program is those parts of the program where the identifier refers to (or, is bound to) some particular thing. There are two primary types of scope in programming languages, lexical scope (a.k.a. static scope) and dynamic scope.

Lexical scope is the name for the situation in which the scope matches some static, identifiable part of the text of the source code. For example, in C, the lexical scope is usually between the '{' symbol just before the declaration if the identifier and the corresponding '}' symbol (except in sub-blocks in which the same identifier is redeclared). One can tell by examining the text whether a particular part of the code is within a particular lexical scope or not. In short, identifiers are linked with what they identify at compile-time. The proces of binding lexical-scope identifiers to objects is called lexical binding.

Dynamic scope is a different beast, old implementations of Lisp implement this dynamic (ariels tells me that newer implementations of Lisp all have lexical binding by default). In this case, identifiers are linked with what they identify at run-time; the scope begins when the identifier is declared and ends usually at the end of the smallest enclosing block. A function (A) in (old) Lisp, for example, may reference an identifier (x) which is not declared in that function. In that case, the value of the identifier is taken from the context from which the function was called - for example, if function B declares x and then calls A, the identifier x within that call to A will reference the x from B. Another function C may also declare a different x, and call A, in which case x within that call to A will reference the x from C. A programmer taking advantage of dynamic scope for some function or procedure should not only document parameters and return values, but also all the other relavent elements of the context from which it is called. The proces of binding dynamic-scope identifiers to objects is called dynamic binding

Dynamic scope can be implemented as a stack of (identifier, value) pairs, such that an entry is pushed onto the stack whenever an identifier is declared, popped off when the identifier reaches the end of it's scope, and whenever an identifier is referenced the stack is searched from the top down to find it's value.

An example will help make the concept clear; consider the following pseudo-code:


 1 : define A
 2 : {
 3 :   declare x as integer
 4 :   define A.A
 5 :   {
 6 :     ...
 7 :     output x
 8 :     ...
 9 :   }
10 :   define A.B
11 :   {
12 :     declare x as string
13 :     ...
14 :   }
15 :   ...
16 :   call A.A
17 :   call A.B
18 :   ...
19 : }
20 : define B
21 : {
22 :   declare x as real
23 :   ...
24 :   call A.A
25 :   ...
26 : }

The lexical scope of the x declared in line 3 is lines 3 to 18, excluding lines 12 to 13. The lexical scope of the x declared in line 12 is lines 12 to 13. The lexical scope of the x declared in line 22 is lines 22 to 25. If there were no 'call's, the dynamic scopes would be effectively the same. Lines 7, 16, and 24 illustrate the difference between the two types of scope. For lexical scoping, at compile-time, the x referenced in line 7 is associated with the static context of x declared in line 3 - therefore, line 7 will always output an integer. For dynamic scoping, at run-time, when executing line 16, the run-time context associates x with an integer, so line 7 will output an integer; but, when executing line 24, the run-time context associates x with a real, so line 7 will output a real. Therefore, with dynamic scoping, line 7 will not always output an integer - in fact, if it weren't for line 16, it may never output an integer.