home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / lang / pop / 213 < prev    next >
Encoding:
Internet Message Format  |  1993-01-24  |  6.2 KB

  1. Path: sparky!uunet!pipex!warwick!uknet!bhamcs!axs
  2. From: axs@cs.bham.ac.uk (Aaron Sloman)
  3. Newsgroups: comp.lang.pop
  4. Subject: Re: dlocals etc. (and shallow binding)
  5. Message-ID: <C1CAwq.8up@cs.bham.ac.uk>
  6. Date: 24 Jan 93 03:55:37 GMT
  7. References: <58946@dime.cs.umass.edu>
  8. Sender: news@cs.bham.ac.uk
  9. Organization: School of Computer Science, University of Birmingham, UK
  10. Lines: 131
  11. Nntp-Posting-Host: emotsun
  12.  
  13. pop@cs.umass.edu ( Robin Popplestone ) writes:
  14.  
  15. > Date: 20 Jan 93 13:51:04 GMT
  16. > Organization: University of Massachusetts, Amherst
  17. >
  18. > Shallow binding of POP-2 variables arose because the 4130 only had one
  19. > index register which we needed to use as a stack pointer, since that
  20. > provided a general low-space-overhead way of calling functions in what was
  21. > a modified functional language. This always appeared as the wrong way of
  22. > doing things, since the lambda calculus calls for lexical binding, but was
  23. > justified on the grounds that existing lexical binding techniques (as
  24. > embodied in Algol) were also wrong, since they didn't provide the
  25. > possibility of returning a function as a result of a function. We were of
  26. > course aware of the debugging advantages of having part of the environment
  27. > available for very little cost.
  28.  
  29. It is interesting that Pop-2 and Maclisp both used incremental
  30. compilers rather than interpreters, and both used shallow binding
  31. for dynamically scoped identifiers rather than deep binding. By
  32. contrast Interlisp was interpreted and used deep binding, which
  33. required searching up a list of variable value pairs to get the
  34. value of a variable that was last declared local in some calling
  35. procedure.
  36.  
  37. It turned out that shallow binding, in which all occurrences of a
  38. particular variable pointed to the same memory location, whose value
  39. had to be saved somewhere on entry to a procedure in which the
  40. variable was local and then copied back on exit had a very nice
  41. property, and I believe this happened entirely by accident rather
  42. than by design.
  43.  
  44. A really "clean" implementation would have required all local
  45. variables to have their values initialised to some safe default on
  46. procedure entry, e.g. to "undef". Instead, for the sake of
  47. efficiency all the implementations of Pop that I have used employed
  48. shallow binding and always left the old value in the variable on
  49. procedure entry, which speeded up procedure entry, and could
  50. occasionally cause obscure bugs, when people forgot to assign to
  51. local variables and they inherited values from the preceding
  52. procedure activation.
  53.  
  54. But it also had a very nice side effect, namely that shallow-bound
  55. dynamic variables could be used to produce an "incremented context"
  56. mechanism that was automatically reset on procedure exit.
  57.  
  58. For example, the Pop-11 pattern matcher keeps a list of variables
  59. whose values have been set in the dynamic variable popmatchvars,
  60. which is local to the matcher and also has the empty list as its
  61. global value. This means that inside a recursive call of the
  62. matcher the previously bound variables are already available, and if
  63. new bindings are set, they can be "pushed" onto the front of the
  64. list, e.g. using
  65.  
  66.     [^word ^^popmatchvars] -> popmatchvars;
  67.  
  68. However on exit from the recursive call, popmatchvars will
  69. automatically be re-set to its original value, and this is
  70. guaranteed to happen whether the exit is normal or caused by an
  71. interrupt, or a use of "exitfrom", or suspension of a process, etc.
  72.  
  73. Similarly, printing routines often need to keep count of the level
  74. of recursion to prevent infinite printing. So it is quite common to
  75. use a variable like
  76.  
  77.     vars
  78.         printlevel = 0,
  79.         max_printlevel = 5;
  80.  
  81.  
  82.     define print_procedure( ..... );
  83.         dlocal printlevel = printlevel + 1;
  84.  
  85.         if printlevel >= max_printlevel then
  86.             ... print closing bracket and return ....
  87.         else
  88.             print suitable opening bracket
  89.             call print_procedure recursively on the components
  90.                 of the structure being printed.
  91.  
  92.         endif
  93.     enddefine;
  94.  
  95. Because of the way dynamic locals, declared using dlocal or vars,
  96. work, it is guaranteed that the top level value of the variable will
  97. always be reset when the procedure exits, normally or otherwise.
  98.  
  99. The alternative to these dynamically scoped uses of printlevel and
  100. popmatchvars (and similar things, like interrupt, cucharout,
  101. prmishap, etc.) would have been to require all these values to be
  102. passed explicitly as extra arguments in any procedure that might
  103. call a procedure that used these values, or else to do what Robin
  104. does, namely:
  105.  
  106. > My own practice these days is to avoid any dlocals in code I actually
  107. > write, by using an extra argument to any function (usually called "Env")
  108. > which is a data-structure that bundles up any kind of style switch.
  109.  
  110. But of course, you have to keep changing the definition of the
  111. structure Env for different purposes, which can makes reuse of code
  112. difficult. Also when the environment changes you either have to use
  113. dlocal anyway, to ensure that it is automatically reset whenever
  114. procedure exit occurs, or else you have to copy the structure on
  115. entry to any procedure that can change it.
  116.  
  117. I think dynamic local expressions, of which dynamic local variables
  118. are a special case, handle this rather elegantly, and I see no
  119. reason for avoiding them, provided that their use is disciplined.
  120.  
  121. It's interesting that these extra mechanisms to ensure automatic
  122. resetting of context are needed only because procedures can exit
  123. abormally. If a simpler control regime were used, and only ordinary
  124. procedure exit were available, then all tidying up and resetting of
  125. context could be done by explicit code at the end of a procedure
  126. definition, and there would be no need for dynamically scoped local
  127. variables.
  128.  
  129. In relation to some of the earlier discussion in this newsgroup, it
  130. is interesting to note that the dlocal mechanism in pop-11 can be
  131. used with global lexically scoped variables, i.e. file-local
  132. lexicals. This undermined the supposed contrast between dynamic and
  133. lexical scoping, and instead caused John Gibson to introduce the
  134. term "permanent" in contrast with "lexical".
  135.  
  136. I'll return to that topic in a later posting.
  137.  
  138. Aaron
  139. -- 
  140. Aaron Sloman,
  141. School of Computer Science, The University of Birmingham, B15 2TT, England
  142. EMAIL   A.Sloman@cs.bham.ac.uk  OR A.Sloman@bham.ac.uk
  143. Phone: +44-(0)21-414-3711       Fax:   +44-(0)21-414-4281
  144.