fork download
  1. #!/bin/perl
  2.  
  3. # perl program that uses dynamic scoping:
  4.  
  5. $x = 3;
  6.  
  7. sub f { $x + 1; }
  8.  
  9. local $x = 4;
  10.  
  11. print f 1, "\n"; # prints 5, taking the $x in the dynamic scope.
  12.  
  13. # To implement dynamic scoping, Perl uses an extra stack just for
  14. # the purpose. The old value of a local var is pushed on the
  15. # special stack, and this stack is used when free vars that are
  16. # declared local are looked up.
  17.  
  18. # if "my" is used instead of "local", then perl will use static scoping
  19.  
  20. # how are my vars different from local vars? A definition of a
  21. # function that contains free vars must be more complicated - it
  22. # constitutes a "closure": a pairing of a lambda term and the
  23. # static environment in which it was defined. This idea of a closure
  24. # will turn out to be the key to object-orientation. But for now,
  25. # you need to understand the difference between the static,
  26. # and the runtime stack. When we compile or interpret a program,
  27. # a stack (or symbol table) is also needed to keep track of the
  28. # scopes of variable declarations. If, when looking up the binding
  29. # of free variables, it uses the static stack, then it's static
  30. # scoping.
  31.  
  32. # The following fragments contrast directly static (my) and dynamic (local)
  33. # scoping:
  34.  
  35. print "---------------\n";
  36.  
  37. { my $x = 2;
  38. my $f = sub { $x };
  39. { my $x = 3;
  40. print $f->(), "\n"; # prints 2, taking $x from static scope
  41. }
  42. }
  43.  
  44.  
  45. { local $x = 2;
  46. local $f = sub { $x };
  47. { local $x = 3;
  48. print $f->(), "\n"; # prints 3, taking $x from dynamic scope
  49. }
  50. }
  51.  
  52.  
  53. # Static scoping is the commonly accepted standard. Consider the following
  54. # example:
  55.  
  56. my $x = 2;
  57.  
  58. sub f { $_[0] + $x } # lambda y. y+x
  59.  
  60. sub g
  61. {
  62. my $x = $_[0];
  63. f(1);
  64. }
  65.  
  66. # In the subroutine g, since $x is a "local" variable, IT SHOULD NOT MATTER
  67. # THAT IT'S CALLED x (alpha conversion). That is, if that line in g read
  68. # instead "my $y = $_[0]", then surely g should remain the same function.
  69. # However, under dynamic scoping it would not. The behavior, and thus
  70. # MEANING of f cannot be determined until runtime. Thus when writing f
  71. # (and g), I cannot just choose any variable names I wish, but must
  72. # become concerned with how variables are named elsewhere in the program!
  73. # This contradicts the whole idea of "locality" and abstraction. Dynamic
  74. # scoping is only useful in temporarily replacing the values of variables
  75. # that are GLOBAL ANYWAY. In fact, as the standard Perl references will
  76. # tell you, the only time you should use local instead of my is to replace
  77. # the values of built-in global variables such as @ARGV (the command-line
  78. # arguments), or STDOUT, the standard output stream.
  79.  
  80.  
  81. ######### Simulating dynamic scoping with static scoping.
  82.  
  83. # Dynamic scoping may be occasionally useful as explained, so is a language
  84. # missing something by not supporting it? Not really. We can simulate it
  85. # by saving the previous value of a variable on the runtime stack, and
  86. # recover it after we exit the "dynamic scope".
  87.  
  88. # int x = 1;
  89. # int f(int y) { return x+y; }
  90. # int main()
  91. # {
  92. # int savex = x; // simulates start of dynamic scope
  93. # x = 2; // x is "local" because the saved value will be recovered.
  94. #
  95. # printf("%d\n", f(1)); // f will take x from "dynamic" scope
  96. #
  97. # x = savex; // simulates end of dynamic scope.
  98. # }
  99.  
  100. ## In this program we are using the runtime stack to simulate dynamic scoping.
  101. # int savex = x has the effect of pusing x onto the stack. x = savex recovers
  102. # the original value. Any value given to x in between is "local" because it
  103. # will be erased once the original value is recovered.
Success #stdin #stdout 0.01s 5308KB
stdin
Choose(49,5)
stdout
1---------------
2
3