home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c
- Path: sparky!uunet!taumet!steve
- From: steve@taumet.com (Steve Clamage)
- Subject: Re: Functions Within Functions
- Message-ID: <1992Jul30.162755.7255@taumet.com>
- Organization: TauMetric Corporation
- References: <Bs5w39.5ox@news.larc.nasa.gov> <1992Jul29.194054.19035@CSD-NewsHost.Stanford.EDU> <1992Jul30.004828.3153@proxxi.se>
- Date: Thu, 30 Jul 1992 16:27:55 GMT
- Lines: 102
-
- elias@proxxi.se (Elias M}rtensson (proxxi)) writes:
-
- >amorgan@Xenon.Stanford.EDU (Crunchy Frog) writes:
-
- >>In article <Bs5w39.5ox@news.larc.nasa.gov>
- >> wjb@cscsun2.larc.nasa.gov (William J. Bene) writes:
-
- >>>Is there any way to declare functions within another function like in pascal?
-
- >>Not according to ANSI C. GCC 2.x allows you to do it so you can use
- >>that (beware, it is still fairly buggy). BTW - Why do you want to
- >>do this? Occasionally I imagine it might be useful for encapsulating
- >>code, but if a function is used in only one place I make it static
- >>and avoid the problem that way (and have portable code).
-
- >Well, there ARE occations one might want to have encapsulated functions.
- >If You make a library which uses lots of functions, there might be
- >function name collisions, since You can have several encapsulated
- >functions with the same name, You won't have these problems.
-
- But if you make those functions static, you should not have any problems
- with collisions. The names of the static functions are not visible
- outside the compilation unit (module) where they are defined, and you
- should not really have unrelated "encapsulations" in the same module.
-
- Pascal had nested functions in part because it did not have separate
- compilation. (Standard Pascal still does not, a factor which IMHO
- prevented it from becoming more popular.) This allowed source modules
- to have local functions, and minimize problems of name collision
- when combining modules.
-
- Static functions in C pretty much eliminate this need for nested functions.
-
- The other reason for nested functions is lexical closure, the ability
- to call a function in its own nested context. The compiler keeps
- track of the function's runtime context for you, and you don't need
- to have long parameter lists or pass around complicated structures.
-
- Simple example, assuming a Pascal which supports separate compilation:
-
- procedure process(function gc: char); external;
-
- procedure fmaster(var f: text);
-
- function getchar: char; {function with no parameters returning char}
- var c: char;
- begin
- { reads file 'f', the parameter to 'fmaster' }
- read(f, c);
- getchar := c;
- end;
-
- begin {fmaster}
- process(getchar);
- end; {fmaster}
-
- procedure smaster(var s: string);
-
- function getchar: char; {function with no parameters returning char}
- begin
- { reads string 's', the parameter to 'smaster' }
- getchar := s.data[s.next];
- s.next := s.next + 1;
- end;
-
- begin {smaster}
- process(getchar);
- end; {smaster}
-
- Here we have a separately-compiled module with procedures 'fmaster'
- and 'smaster', and another with procedure 'process'. 'process' takes
- a function as a parameter, and it is passed local function 'getchar'.
- All that 'process' knows is that it gets passed a function which
- somehow gets a character from somewhere.
-
- Note that 'fmaster' can be called with a different file parameter each
- time, and each time the current file (from the current invocation of
- 'fmaster') is used when 'getchar' is called back.
-
- Similarly, 'smaster' can be called with different strings, and each
- time 'getchar' is called back from 'process', the string from the
- current invocation of smaster is used.
-
- This is pretty hard to do in C. The 'getchar' functions would have
- to take a file or string parameter, meaning that the 'process' would
- have to know that and pass the right thing to the right function.
- Auxiliary variables would be needed to keep track of what was current.
- If you added a new kind of 'master' routine, with a different way of
- getting characters, 'process' and various interfaces would have to be
- updated as well. This is a maintenace nightmare. In the Pascal
- version, you could write an independent new version of a 'master' and
- link it in with no other changes.
-
- In C++, of course, you would write a hierarchy of classes with a
- virtual 'getchar' function. You add new classes with new versions
- of 'getchar' without touching (or even recompiling) other code.
- The need for lexical closure is less, but there are still examples
- which are hard to do even in C++.
- --
-
- Steve Clamage, TauMetric Corp, steve@taumet.com
- Vice Chair, ANSI C++ Committee, X3J16
-