int width = 10;
char justification = 'L';
void print(string s)
{
int left, diff = width - s.length();
if (diff <= 0) { print(s); return; }
switch(justification) {
case 'L': left = diff; break;
case 'R': left = 0; break;
case 'C': left = diff/2; break;
}
for(int i = 0; i < left; ++i) print(' ');
print(s);
for(int i = 0; i < width - left; ++i) print(' ');
}
void foo(double z)
{
justification = 'R';
print("answer:");
print(toString(z));
}
void bar(double z)
{
char justification = 'R';
print("answer:");
print(toString(z));
}
3*x - 5/y + f(2.0)requires knowing the current bindings for x, y and f. The set of current bindings is called the "referencing environment".
int g(int x) { return x*x; }
int f(int y) { int x = 3 + g(y); return x; }
int main() { int n = 5; f(n); return 0; }
Discuss Fortan 77's lack of recursion and how this allows for
static allocation of activation records.
x = 10;
int foo(y) { x = x + y; return y; }
int main()
{
for(i = 0; i < 100; ++i)
{
x = rand() % 11;
print(x);
print(foo(x));
}
print(x);
}
If you think of this program as a sort of bank simulation,
where the balance x=10 is set at the start, and foo(y)
represents depositing y dollars into the bank, you'll see that
we have a problem. Inside the for loop we needed a temporary
variable. We choose x and ... we chose poorly, because x
refers to the same object everywhere in the program, and we're
overwriting the global that tracks the account balance. With
a single scope, this kind of error is easy to make. More
importantly, you can't have recursion with a single scope!
int f(int x) { int y = 0; y = y + x; return y; }
If I call f(4) I should get 4, but what if I subsequently call
f(5)? Whether I get 5 or 9 depends on a language design
decision about the lifetime of local variables. Do they die
when they go out of scope, or do they live on as they go in
and out of scope. In C they die when they go out of scope at
the end of their containing block, by default. However, by
prefixing the declaration with the keyword
static, you get the opposite semantics, and the
variable lives on until the end of the program. Fortran 77
had the same policy as C's default policy, but we talked about
a funny side effect of some implementations' use of statically
allocated activation records.
Yet another issue has to do with determining which bindings are active when we have non-local variable references. For example, consider the following piece of very familiar code:
int x = 10;
int foo(int y) { x = x + y; return y; }
int main()
{
for(int i = 0; i < 100; ++i)
{
int x = rand() % 11;
print(x);
print(foo(x));
}
print(x);
}
We'll assume that local variables die withthe end of their enclosing block, just like C and Fortran, but we allow any { }-delimited block to define a scope. The question is this: When I call foo inside of main, does the "x" inside of foo refer to the global "x" or the "x" that's local to the for loop? In other words, do non-local references (like the "x" inside the foo function) refer to the x that is in scope at the point of the defintion of the function, or the x that is in scope at the point of the call of the function. The first approach is called lexical scope (also static scope), and the second is called dynamic scope.