home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / lang / pop / 223 < prev    next >
Encoding:
Text File  |  1993-01-27  |  9.4 KB  |  233 lines

  1. Newsgroups: comp.lang.pop
  2. Path: sparky!uunet!inmos!fulcrum!bham!bhamcs!axs
  3. From: axs@cs.bham.ac.uk (Aaron Sloman)
  4. Subject: Re: dlocals etc. (and shallow binding)
  5. Message-ID: <C1IC6K.F2H@cs.bham.ac.uk>
  6. Sender: news@cs.bham.ac.uk
  7. Nntp-Posting-Host: emotsun
  8. Organization: School of Computer Science, University of Birmingham, UK
  9. References: <58946@dime.cs.umass.edu> <C1CAwq.8up@cs.bham.ac.uk> <1993Jan26.033934.12517@philmtl.philips.ca>
  10. Date: Wed, 27 Jan 1993 10:08:43 GMT
  11. Lines: 220
  12.  
  13. ray@philmtl.philips.ca (Ray Dunn) writes:
  14.  
  15. > Date: 26 Jan 93 03:39:34 GMT
  16. > Organization: Not Philips.
  17. >
  18. > In refd article, axs@cs.bham.ac.uk (Aaron Sloman) writes:
  19. [AS]
  20. > >A really "clean" implementation would have required all local
  21. > >variables to have their values initialised to some safe default on
  22. > >procedure entry, e.g. to "undef".
  23.  
  24. [RD]
  25. > ...and to take advantage of internal knowledge of the fact that it doesn't
  26. > raises the hackles of anyone concerned about "future release surprise" or
  27. > portability!
  28.  
  29. [AS]
  30. But note that this has been a dependable feature of every Pop
  31. implementation for at least 22 years. Suppose it were written into
  32. the manual, would you still object to its use?
  33.  
  34. In fact, I think that it is an essential part of the dlocal
  35. mechanism that you can access the previous value as well as being
  36. able to update it. E.g. you can do things like
  37.  
  38.     dlocal hd(list);
  39.  
  40.         hd(list) + 1 -> hd(list);
  41.  
  42. in a procedure, with a *guarantee* that on exit from that procedure,
  43. whether normal or abnormal, the previous value stored in the head of
  44. the list will be reset. It would be illogical to disallow the
  45. special case of a value stored in a variable.
  46.  
  47. Of course a defender of pure functional programming would disallow
  48. the updating of a datastructure in any case, and the argument would
  49. change (which is I think Robin's position, if I've understood it.)
  50.  
  51. Ray objected to my example use of this facility:
  52.  
  53. [AS]
  54. > >    define print_procedure( ..... );
  55. > >        dlocal printlevel = printlevel + 1;
  56. >
  57. [RD]
  58. > looks pretty bogus to me.  I've been trying to teach programmers to avoid
  59. > this sort of thing for years.  POP-2 was quite clear about it, even though
  60. > this code would "work".  The reference manual states that when the extent
  61. > of another variable is interrupted "its value is not altered but it cannot
  62. > be accessed or changed by assignment."
  63.  
  64. [AS]
  65. Well, what I am claiming (if I understand the terminology correctly)
  66. is that allowing the value from the previous context to be accessed,
  67. but not altered, before the first assignment in the new context, is
  68. a very useful extension to the expressive power of the language.
  69.  
  70. [AS]
  71. >The alternative to these dynamically scoped uses of printlevel and
  72. > >popmatchvars (and similar things, like interrupt, cucharout,
  73. > >prmishap, etc.) would have been to require all these values to be
  74. > >passed explicitly as extra arguments in any procedure that might
  75. > >call a procedure that used these values, ....
  76. > > .....
  77.  
  78. Which is what Ray recommends:
  79. [RD]
  80. > In 'C' the effect can often be achieved by using a _static_ variable, but
  81. > my own technique is to use a pair of functions - the outer function
  82. > presents a "clean" interface to the outside world and calls a second
  83. > function with all the required extra arguments - it is this second function
  84. > that recurses.
  85. >
  86. > So Aaron's example becomes (ha! I'll do it in POP-2ish)
  87. >
  88. >     vars max_printlevel;
  89. >     5 -> max_printlevel;
  90. >
  91. >     print_procedure(....)
  92. >         aux_print_proc(..... , 1);
  93. >     end
  94. >
  95. >     aux_print_proc(..... , printlevel)
  96. >
  97. >         if printlevel >= max_printlevel then
  98. >             ... print closing bracket and return ....
  99. >         else
  100. >             ... print suitable opening bracket ....
  101. >             aux_print_proc(whatever tail of structure, printlevel+1);
  102. >         close
  103. >     end
  104.  
  105. Note that this solution works if all printing is done via one
  106. procedure, which used to be the case in POP2, but is no longer the
  107. case in Pop-11, where different data-types have their own
  108. class_print procedures, a bit like an object oriented system where
  109. each class has its own methods (as is the case in Steve Knight's new
  110. objectclass extension to Pop-11) (advertisement).
  111.  
  112. Extracts from REF PRINT in the online manual follow:
  113.  
  114. -------------------------------------------------------------------
  115. The basic printing procedure in POPLOG is -sys_syspr-, which prints  any
  116. item in its  standard format. While  this can be  called directly if  so
  117. desired, the  system  additionally  provides  the  procedures  -pr-  and
  118. -syspr- as a  two-stage mechanism  for printing  objects in  a way  that
  119. allows dynamic redefinition of the actual printing procedures used.
  120.  
  121.     The mechanism  is based  on the  convention that  programs  normally
  122. print objects  using the  variable procedure  -pr-, which  in the  first
  123. place, can be redefined in any  desired way. However, the default  value
  124. of the variable -pr- is the procedure -syspr-, which prints an object by
  125. calling its -class_print- procedure with the object as argument (see REF
  126. *KEYS); thus in the second place, the printing of individual data  types
  127. can be altered by redefining their -class_print- procedures. Because the
  128. default -class_print- of any type is -sys_syspr-, (printing in  standard
  129. format), the normal sequence of events is therefore:
  130.  
  131.         pr(ITEM)
  132.                 ---> syspr(ITEM)
  133.                             ---> class_print(datakey(ITEM))(ITEM)
  134.                                         ---> sys_syspr(ITEM)
  135.  
  136.     It is important to note, however, that to enable the redefinition of
  137. printing procedures for given  data types to take  effect at any  level,
  138. -sys_syspr- always calls -pr-  to print the  sub-components of any  data
  139. structure (i.e. list,  vector and  record elements,  etc). (Thus  saying
  140. that -sys_syspr-  'prints  any  item  in its  standard  format'  is  not
  141. strictly correct, since  the printing of  sub-components will depend  on
  142. -pr-. A COMPLETELY standard printing procedure would be
  143.  
  144.         define pr_standard(ITEM)
  145.             lvars ITEM;
  146.             dlocal pr = sys_syspr;
  147.             sys_syspr(ITEM)
  148.         enddefine;
  149.  
  150. i.e. one that locally redefines -pr- to be -sys_syspr-.)
  151.  
  152. pr(ITEM)                                            [procedure variable]
  153.         This variable procedure is conventionally used by all procedures
  154.         in the  system  which  print something;  its  default  value  is
  155.         -syspr-.
  156.  
  157. syspr(ITEM)                                                  [procedure]
  158.         This procedure does
  159.  
  160.                 class_print(datakey(ITEM))(ITEM)
  161.  
  162.         i.e. apply the -class_print- of the  data type of ITEM to  ITEM.
  163.         The default -class_print- of every data type is -sys_syspr-, but
  164.         this can be redefined as desired -- see REF *KEYS.
  165. -------------------------------------------------------------------
  166.  
  167. This means that for Ray's mechanism to work, every class_print
  168. procedure would have to take an extra argument, namely the
  169. printlevel, and every other procedure that did any printing would
  170. have to be given a printlevel as part of its input, and then it
  171. would pass on the incremented value to the next printing function it
  172. called. So the above definitions would have to replaced with
  173. something like:
  174.  
  175. pr(ITEM,INTEGER)
  176.         This variable procedure is conventionally used by all procedures
  177.         in the  system  which  print something;  its  default  value  is
  178.         -syspr-.
  179.  
  180. syspr(ITEM,INTEGER)
  181.         This procedure does
  182.  
  183.                 class_print(datakey(ITEM))(ITEM,INTEGER)
  184.  
  185.         unless INTEGER exceeds max_printlevel
  186.  
  187. I.e. every class_print procedure would need an extra input.
  188.  
  189. (Incidentally, for printing one normally needs at least two control
  190. variables, one for depth of nesting and one for length of tails,
  191. and Poplog Pop-11 is wrong to have only one variable for nesting,
  192. namely pop_pr_level)
  193.  
  194. I suspect that Ray's type of solution would be acceptable for
  195. printing, simply because once you get into any printing procedure
  196. you stay within printing procedures which call other printing
  197. procedures explicitly or implicitly (e.g. via class_print), so
  198. there's no real difficulty in passing on the extra parameters.
  199.  
  200. More generally, however, there are cases where there's a context,
  201. e.g. a database of some kind that's extended by a hypothetical
  202. action, and various different procedures can get called which only
  203. *indirectly*, via several levels of procedure calling eventually
  204. invoke the procedure that further extends the context. For that
  205. situation the extra parameter would have to be supplied to lots of
  206. procedures that do nothing with it except pass it on. If you have
  207. lots of such parameters (cucharout, prmishap, database, interrupt,
  208. etc. etc.) it gets messy. Then Robin's solution of providing a
  209. single environment that's passed on by every procedure looks like
  210. the only attractive solution.
  211.  
  212. What that amounts to is abandoning global variables that can be
  213. changed locally. It's a consistent way to do things, and maybe has
  214. some nice properties. I suspect that for a large team of programmers
  215. developing a suite of interrelated programs that can call one
  216. another recursively it may be less convenient and less efficient
  217. than using global variables that are dynamically scoped using
  218. dlocal. But I don't know.
  219.  
  220. [RD]
  221. > Now who has a compiler I can syntax check this with!!
  222.  
  223. A nice project for a student learning to use Pop-11's compiler
  224. development tools?
  225.  
  226. Aaron
  227. --
  228. -- 
  229. Aaron Sloman,
  230. School of Computer Science, The University of Birmingham, B15 2TT, England
  231. EMAIL   A.Sloman@cs.bham.ac.uk  OR A.Sloman@bham.ac.uk
  232. Phone: +44-(0)21-414-3711       Fax:   +44-(0)21-414-4281
  233.