#!/bin/perl
# perl program that uses dynamic scoping:
$x = 3;
sub f { $x + 1; }
print f
1, "\n"; # prints 5, taking the $x in the dynamic scope.
# To implement dynamic scoping, Perl uses an extra stack just for
# the purpose. The old value of a local var is pushed on the
# special stack, and this stack is used when free vars that are
# declared local are looked up.
# if "my" is used instead of "local", then perl will use static scoping
# how are my vars different from local vars? A definition of a
# function that contains free vars must be more complicated - it
# constitutes a "closure": a pairing of a lambda term and the
# static environment in which it was defined. This idea of a closure
# will turn out to be the key to object-orientation. But for now,
# you need to understand the difference between the static,
# and the runtime stack. When we compile or interpret a program,
# a stack (or symbol table) is also needed to keep track of the
# scopes of variable declarations. If, when looking up the binding
# of free variables, it uses the static stack, then it's static
# scoping.
# The following fragments contrast directly static (my) and dynamic (local)
# scoping:
print "---------------\n";
{ my $x = 2;
my $f = sub { $x };
{ my $x = 3;
print $f->(), "\n"; # prints 2, taking $x from static scope }
}
print $f->(), "\n"; # prints 3, taking $x from dynamic scope }
}
# Static scoping is the commonly accepted standard. Consider the following
# example:
my $x = 2;
sub f { $_[0] + $x } # lambda y. y+x
sub g
{
my $x = $_[0];
f(1);
}
# In the subroutine g, since $x is a "local" variable, IT SHOULD NOT MATTER
# THAT IT'S CALLED x (alpha conversion). That is, if that line in g read
# instead "my $y = $_[0]", then surely g should remain the same function.
# However, under dynamic scoping it would not. The behavior, and thus
# MEANING of f cannot be determined until runtime. Thus when writing f
# (and g), I cannot just choose any variable names I wish, but must
# become concerned with how variables are named elsewhere in the program!
# This contradicts the whole idea of "locality" and abstraction. Dynamic
# scoping is only useful in temporarily replacing the values of variables
# that are GLOBAL ANYWAY. In fact, as the standard Perl references will
# tell you, the only time you should use local instead of my is to replace
# the values of built-in global variables such as @ARGV (the command-line
# arguments), or STDOUT, the standard output stream.
######### Simulating dynamic scoping with static scoping.
# Dynamic scoping may be occasionally useful as explained, so is a language
# missing something by not supporting it? Not really. We can simulate it
# by saving the previous value of a variable on the runtime stack, and
# recover it after we exit the "dynamic scope".
# int x = 1;
# int f(int y) { return x+y; }
# int main()
# {
# int savex = x; // simulates start of dynamic scope
# x = 2; // x is "local" because the saved value will be recovered.
#
# printf("%d\n", f(1)); // f will take x from "dynamic" scope
#
# x = savex; // simulates end of dynamic scope.
# }
## In this program we are using the runtime stack to simulate dynamic scoping.
# int savex = x has the effect of pusing x onto the stack. x = savex recovers
# the original value. Any value given to x in between is "local" because it
# will be erased once the original value is recovered.