What does a name refer to? There are many situations where the same name is used for different things.
Each identifier is in a particular namespace . The same identifier
has different meanings in different name spaces - for example, in Java,
the class
class Foo {
Foo Foo (Foo Foo) {
Foo:
for (;;) {
if (Foo.Foo(Foo) == Foo)
break Foo;
}
return Foo;
}
}
Is this good style? Well, not really. Languages have different
name spaces - for example, the name spaces for functions and
variables are different in CommonLisp (and most other lisp dialects). This
is often criticized as a flaw in the language, since it means that
a different mechanism is needed to call the function
Within a name space, the same name can be used many times. Examples of
this include variable declarations, structure definitions, and class
extensions. For example the following C program has three distinct
variables
int x;
main(){
double x;
{
char* x;
}
}
In most languages, an identifier is associated with inner most declaration.
This is refered to as lexical scoping. The use of the same name of
a variable which hides other variables is generally bad style - although
many languages allow it because the alternative, insisting on distinct names
would require the programmer to know all the variables in use,
violating the principle of localizing information.
Some languages provide ways to access hidden variables - for example
PL1 has an EXTERNAL command for accessing hidden variables.
In Java hidden fields can be accessed using this.
class Planet {
String name;
void setName(String name){
this.name = name;
}
}
Object oriented languages provide facilities for accessing methods which
have been overridden. For example, super is used in Java for
this.
int x = 1;
void printx() {
printf("%d\n", x);
}
main()
{
printx();
{
int x = 2;
printf("%d\n", x);
printx();
{
int x = 3;
printf("%d\n", x);
printx();
}
printf("%d\n", x);
printx();
}
printx();
}
==============================
;; defvar declares and initializes a global variable
(defvar x 1)
(defun printx ()
(print x))
(defun main ()
(printx)
(let ((x 2))
(print x)
(printx)
(let ((x 3))
(print x)
(printx))
(print x)
(printx))
(printx)
nil)
The first program prints out
1 2 1 3 1 2 1 1and the second program prints out
1 2 2 3 3 2 2 1The difference is that the C function
printx() uses the
global variable x, while the LISP function binds
x at runtime to an instance of the variable x.
Most languages have abandoned the use of dynamical scope in favor of
lexical scope. The above commonlisp example uses a global
variable (via the defvar declaration). Global variables
are dynamically scoped in commonlisp, but other variables are lexically
scoped. Older dialects of lisp used dynamic scope. Scheme is strictly
lexically scoped.
Macro expansion can be viewed as using dynamic scope - for example, Swap will use the version of temp corresponding to where Swap is called.
#define Swap(A,B) {temp = (A); (A) = (B); (B)=temp;}