home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / c / 11763 < prev    next >
Encoding:
Text File  |  1992-07-30  |  4.5 KB  |  113 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!taumet!steve
  3. From: steve@taumet.com (Steve Clamage)
  4. Subject: Re: Functions Within Functions
  5. Message-ID: <1992Jul30.162755.7255@taumet.com>
  6. Organization: TauMetric Corporation
  7. References: <Bs5w39.5ox@news.larc.nasa.gov> <1992Jul29.194054.19035@CSD-NewsHost.Stanford.EDU> <1992Jul30.004828.3153@proxxi.se>
  8. Date: Thu, 30 Jul 1992 16:27:55 GMT
  9. Lines: 102
  10.  
  11. elias@proxxi.se (Elias M}rtensson (proxxi)) writes:
  12.  
  13. >amorgan@Xenon.Stanford.EDU (Crunchy Frog) writes:
  14.  
  15. >>In article <Bs5w39.5ox@news.larc.nasa.gov> 
  16. >>  wjb@cscsun2.larc.nasa.gov (William J. Bene) writes:
  17.  
  18. >>>Is there any way to declare functions within another function like in pascal?
  19.  
  20. >>Not according to ANSI C.  GCC 2.x allows you to do it so you can use
  21. >>that (beware, it is still fairly buggy).  BTW - Why do you want to
  22. >>do this?  Occasionally I imagine it might be useful for encapsulating
  23. >>code, but if a function is used in only one place I make it static
  24. >>and avoid the problem that way (and have portable code). 
  25.  
  26. >Well, there ARE occations one might want to have encapsulated functions.
  27. >If You make a library which uses lots of functions, there might be
  28. >function name collisions, since You can have several encapsulated
  29. >functions with the same name, You won't have these problems.
  30.  
  31. But if you make those functions static, you should not have any problems
  32. with collisions.  The names of the static functions are not visible
  33. outside the compilation unit (module) where they are defined, and you
  34. should not really have unrelated "encapsulations" in the same module.
  35.  
  36. Pascal had nested functions in part because it did not have separate
  37. compilation.  (Standard Pascal still does not, a factor which IMHO
  38. prevented it from becoming more popular.)  This allowed source modules
  39. to have local functions, and minimize problems of name collision
  40. when combining modules.
  41.  
  42. Static functions in C pretty much eliminate this need for nested functions.
  43.  
  44. The other reason for nested functions is lexical closure, the ability
  45. to call a function in its own nested context.  The compiler keeps
  46. track of the function's runtime context for you, and you don't need
  47. to have long parameter lists or pass around complicated structures.
  48.  
  49. Simple example, assuming a Pascal which supports separate compilation:
  50.  
  51.     procedure process(function gc: char); external;
  52.  
  53.     procedure fmaster(var f: text);
  54.  
  55.       function getchar: char; {function with no parameters returning char}
  56.       var c: char;
  57.       begin
  58.     { reads file 'f', the parameter to 'fmaster' }
  59.     read(f, c);
  60.     getchar := c;
  61.       end;
  62.  
  63.     begin {fmaster}
  64.       process(getchar);
  65.     end; {fmaster}
  66.  
  67.     procedure smaster(var s: string);
  68.  
  69.       function getchar: char; {function with no parameters returning char}
  70.       begin
  71.     { reads string 's', the parameter to 'smaster' }
  72.     getchar := s.data[s.next];
  73.     s.next := s.next + 1;
  74.       end;
  75.  
  76.     begin {smaster}
  77.       process(getchar);
  78.     end; {smaster}
  79.  
  80. Here we have a separately-compiled module with procedures 'fmaster'
  81. and 'smaster', and another with procedure 'process'.  'process' takes
  82. a function as a parameter, and it is passed local function 'getchar'.
  83. All that 'process' knows is that it gets passed a function which
  84. somehow gets a character from somewhere.
  85.  
  86. Note that 'fmaster' can be called with a different file parameter each
  87. time, and each time the current file (from the current invocation of
  88. 'fmaster') is used when 'getchar' is called back.
  89.  
  90. Similarly, 'smaster' can be called with different strings, and each
  91. time 'getchar' is called back from 'process', the string from the
  92. current invocation of smaster is used.
  93.  
  94. This is pretty hard to do in C.  The 'getchar' functions would have
  95. to take a file or string parameter, meaning that the 'process' would
  96. have to know that and pass the right thing to the right function.
  97. Auxiliary variables would be needed to keep track of what was current.
  98. If you added a new kind of 'master' routine, with a different way of
  99. getting characters, 'process' and various interfaces would have to be
  100. updated as well.  This is a maintenace nightmare.  In the Pascal
  101. version, you could write an independent new version of a 'master' and
  102. link it in with no other changes.
  103.  
  104. In C++, of course, you would write a hierarchy of classes with a
  105. virtual 'getchar' function.  You add new classes with new versions
  106. of 'getchar' without touching (or even recompiling) other code.
  107. The need for lexical closure is less, but there are still examples
  108. which are hard to do even in C++.
  109. -- 
  110.  
  111. Steve Clamage, TauMetric Corp, steve@taumet.com
  112. Vice Chair, ANSI C++ Committee, X3J16
  113.