#!/bin/perl

# perl program that uses dynamic scoping

$x = 3;

sub f { $x + 1; }

local $x = 4;

print f 1, "\n";

# more complex example

sub makelocalfun 
{
    local $y = $_[0];  # $y is first arg
    sub { $y+1 }      # lambda x.y
}

my $g = makelocalfun 3;

local $y = 4;

print "\n", &$g(1), "\n";

# 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 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.


print "---------------\n";

{  my $x = 2;
   my $f = sub { $x };
   {  my $x = 3;
      print $f->(), "\n";
   }
}


{  local $x = 2;
   local $f = sub { $x };
   {  local $x = 3;
      print $f->(), "\n";
   }
}
