#!/bin/perl # perl program that uses dynamic scoping: $x = 3; sub f { $x + 1; } local $x = 4; 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 } } { local $x = 2; local $f = sub { $x }; { local $x = 3; 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 pushing 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.