garry@ithaca.uucp (Garry Wiegand) (01/22/91)
When the C standards committee was meeting, did they discuss allowing the declaration of functions within functions? Ie, making: void outside(void) { static void inside(void) {} inside(); } count as legal C? Neither my quasi-Ansi C nor my g++ compiler will accept it. The name-space advantages should be obvious, and as far as I can see the syntax and semantics are clear and unambiguous, with no unfortunate side effects. (Except: I'm not sure if the word "static" would have any meaning in the context.) So I'm guessing that if they thought about it they must have decided not to break old compilers that were strongly "moded" inside. Or that there was some theological argument. Does anyone know? Put it on the list for next time. (The prohibition in C++ seems silly considering that a simple wrapper: void outside(void) { class wrapper {public: static void inside(void){} }; wrapper::inside(); } turns it into a legal program.) Garry Wiegand --- Ithaca Software, Alameda, California ...!uunet!ithaca!garry, garry%ithaca.uucp@uunet.uu.net
dave@cs.arizona.edu (Dave P. Schaumann) (01/22/91)
In article <1991Jan22.081057.8567@ithaca.uucp> garry@ithaca.uucp (Garry Wiegand) writes: |When the C standards committee was meeting, did they discuss allowing |the declaration of functions within functions? Ie, making: | | void outside(void) { | static void inside(void) {} | inside(); | } | |count as legal C? Neither my quasi-Ansi C nor my g++ compiler will |accept it. C has never allowed nested function definitions. I don't know for sure why, but I would guess (given that C is intended for generating clean, fast code) that they didn't want to get involved with closures. |Garry Wiegand --- Ithaca Software, Alameda, California |...!uunet!ithaca!garry, garry%ithaca.uucp@uunet.uu.net Dave Schaumann | And then -- what then? Then, future... dave@cs.arizona.edu | -Weather Report
gwyn@smoke.brl.mil (Doug Gwyn) (01/24/91)
In article <1991Jan22.081057.8567@ithaca.uucp> garry@ithaca.uucp (Garry Wiegand) writes: >When the C standards committee was meeting, did they discuss allowing >the declaration of functions within functions? It was proposed, but since X3J11 was not trying to invent lots of features, but rather just standardize existing practice, there was little support for the proposal.
lindsay@gandalf.cs.cmu.edu (Donald Lindsay) (01/27/91)
In article <1991Jan22.081057.8567@ithaca.uucp> garry@ithaca.uucp (Garry Wiegand) writes: >When the C standards committee was meeting, did they discuss allowing >the declaration of functions within functions? >The name-space advantages should be obvious,... Some of us have used languages that allowed this, and didn't like it. Personal opinion: the outer functions get unreadable. Software engineering opinion: the inner ones get undocumented or even unexpected side effects, because they modify global variables. (Global to them, that is.) Compiler writer's opinion: the calling convention now has to support uplevel addressing. This is typically done at a cost of at least one extra instruction per call. This distributed overhead is paid by all calls - not just the ones that plan to uplevel-address - unless your compiler does interprocedural optimization. -- Don D.C.Lindsay .. temporarily at Carnegie Mellon Robotics
sef@kithrup.COM (Sean Eric Fagan) (01/27/91)
In article <11681@pt.cs.cmu.edu> lindsay@gandalf.cs.cmu.edu (Donald Lindsay) writes: >Some of us have used languages that allowed this, and didn't like it. Somewhat agreed. It *can* be useful at time, but having static functions pretty much obliviates the needs, as far as I'm concerned. (With nested functions, you get lots and lots and *lots* of new scoping rules, which are a real bitch to deal with, both as a user and as a compiler writer. Ugh.) >Personal opinion: the outer functions get unreadable. Agreed. And where do you allow their declaration? Is void foo(int i) { int j; int strlen(int i) { return i/j; } int k; ... } legal, or do you only allow a window (a la pascal) for declaring functions? Pascal had the advantage that it is a bit more readable as a result of the restriction, but at the hindrance of the programmer's flow of thoughts. (And, of course, the same can be said about C's requirement on variable declaration; and I think the code is more readable, but disrupts flow-of-thought.) >Compiler writer's opinion: the calling convention now has to support >uplevel addressing. Actually, that's not a terrible problem. How to deal with nested call frames is very well understood, as are the optimisations you can do on them. But it's still a mess. Note, incidenlty, that Metaware's HighC allows nested functions, and gcc 2.0 will also allow them. Both compilers allow taking the address of a nested function, but HighC added to the syntax of the language to do so, whereas gcc just uses the same syntax (and notes what you're doing). As for the original question: the committee's job was to *standardize* C. Very few C compilers allowed nested functions, and none of the books describing the language "C" allowed for them. It was not in the language. My usual point for this type of thing is to bring up two things that ANSI introduced to C: prototypes, which most people agree are good, but still have problems with%, and trigraphs, which almost nobody likes, including the people who need them. ----- % Given: int foo(char); int foo(i) char i; { return i; } gcc (correctly) gives an error (unless -traditional is used, I believe); most other compilers accept it (maybe warning about it at a certain level), but not by default. ----- -- Sean Eric Fagan | "I made the universe, but please don't blame me for it; sef@kithrup.COM | I had a bellyache at the time." -----------------+ -- The Turtle (Stephen King, _It_) Any opinions expressed are my own, and generally unpopular with others.
dave@cs.arizona.edu (Dave P. Schaumann) (01/28/91)
This does bring up a problem that should be adressed: As it stands, C has two scopes where functions can be seen: 1. Static (ie, within a file) 2. Global (everywhere) It would be nice if there were a device that allowed user-definable scopes that function names would be visible in. Hmm. It occurs to me that C++'s class keyword allows just that... Maybe a simplified form of this mechanism should be considered for addition. Thus, you could type something like bar::foo( int baz ) { ... } bop::foo( char *glorp ) { ... } With no conflict. Of course, you would have to include the scope-space keyword to disambiguate a function call to foo(). Dave Schaumann | And then -- what then? Then, future... dave@cs.arizona.edu | -Weather Report
jimad@microsoft.UUCP (Jim ADCOCK) (01/29/91)
In article <1991Jan22.081057.8567@ithaca.uucp> garry@ithaca.uucp (Garry Wiegand) writes: |When the C standards committee was meeting, did they discuss allowing |the declaration of functions within functions? Ie, making: | | void outside(void) { | static void inside(void) {} | inside(); | } | |count as legal C? Neither my quasi-Ansi C nor my g++ compiler will |accept it. | |The name-space advantages should be obvious, and as far as I can |see the syntax and semantics are clear and unambiguous, with no |unfortunate side effects. (Except: I'm not sure if the word "static" |would have any meaning in the context.) | |So I'm guessing that if they thought about it they must have decided |not to break old compilers that were strongly "moded" inside. Or |that there was some theological argument. Does anyone know? | |Put it on the list for next time. | |(The prohibition in C++ seems silly considering that a simple wrapper: | | void outside(void) { | class wrapper {public: | static void inside(void){} | }; | wrapper::inside(); | } | |turns it into a legal program.) I don't think it would be too hard to remove the requirement for the wrapper class -- but, that still wouldn't give people the nested function capabilities they'd expect from playing with other languages. In C++, the nested class [and therefore the nested function] only is allowed access to the type names, static variables, extern variables and functions, and enumerations from the enclosing scope. Even if you didn't have to write the wrapper:: prefix on inside(), inside() still wouldn't be able to access the auto variables of outside(). So you still couldn't do the Pascal hack of declaring inner functions with implied parameters, for example. Seems to me the end result would come out half-Pas'cal'ed.
rjohnson@shell.com (Roy Johnson) (02/01/91)
In article <70282@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes: >In article <1991Jan22.081057.8567@ithaca.uucp> garry@ithaca.uucp (Garry Wiegand) writes: >|When the C standards committee was meeting, did they discuss allowing >|the declaration of functions within functions? Ie, making: >| >|> void outside(void) { >|> static void inside(void) {} >|>> inside(); >|> } >| >|count as legal C? Neither my quasi-Ansi C nor my g++ compiler will >|accept it. >| >|The name-space advantages should be obvious, and as far as I can >|see the syntax and semantics are clear and unambiguous, with no >|unfortunate side effects. (Except: I'm not sure if the word "static" >|would have any meaning in the context.) If you're worried about the namespace, just make different code modules, where the outside() is available to the other modules, and inside() is only available within outside()'s module. -- ======= !{sun,psuvax1,bcm,rice,decwrl,cs.utexas.edu}!shell!rjohnson ======= "If he exploded, all of Manhattan would be talking in high, squeaky voices for months!" "Cool." -- When I Was Short Roy Johnson, Shell Development Company
datangua@watmath.waterloo.edu (David Tanguay) (02/09/91)
One of the "problems" with adding nested functions to C is the addition of a display to access autos in outer scopes. The whole issue could be avoided by not having autos imported into functions. E.g.: int f( int a ) { static int b; auto int c; int g( int d ) { b = d+1; /* is okay */ c = 0; /* error: c is not in scope */ return d * b; } c = g( a + b ); return 3 * c + 2; } /* g is not visible here */ This results in scoping rules similar to Port (a cousin of C -- B->Zed->Port, I believe). Additional idea: an auto function is not visible to inner functions, static function is -- David Tanguay Software Development Group, University of Waterloo
rex@aussie.COM (Rex Jaeschke) (02/10/91)
> Re: functions within functions
MetaWare's High C has had nested functions now probably for 4-5 years.
(Interestingly, MetaWare is/was a big user of Pascal, and High C versions
earlier than the most recent one were actually written in their extended
Pascal.)
I documented their nested function extension (along with several other
extensions) in Vol 2, num 3 (Dec 1990) of The Journal of C Language
Translation on page 240. (Their very interesting iterator extension is
covered in Vol 2/4 in Mar '91.)
To add nested functions they use ! as a postfix punctuator in function
declarations. Late in 1990 Bjarne Stroustrup proposed using this notation
to solve a problem re alternate trigraphs at the ISO C level. As such, I
informed him this conflicted with MetaWare's prior art.
Rex
----------------------------------------------------------------------------
Rex Jaeschke | Journal of C Language Translation | C Users Journal
(703) 860-0091 | 2051 Swans Neck Way | DEC PROFESSIONAL
rex@aussie.COM | Reston, Virginia 22091, USA | Programmers Journal
----------------------------------------------------------------------------
Convener of the Numerical C Extensions Group (NCEG)
----------------------------------------------------------------------------
garry@ithaca.uucp (Garry Wiegand) (02/11/91)
In article <1991Feb8.232835.19022@watmath.waterloo.edu> datangua@watmath.waterloo.edu (David Tanguay) writes: >One of the "problems" with adding nested functions to C is the addition >of a display to access autos in outer scopes. The whole issue could be >avoided by not having autos imported into functions. >... > b = d+1; /* is okay */ > c = 0; /* error: c is not in scope */ Exactly! Doesn't hurt, gives people like me another level of function name-scoping, and if at some later time the community wants to add access to outer autos and parameters ("closure", as someone explained to me), that would be upward-compatible. I have seen the innards of compilers like the old 'pcc': they are really badly written, with lots of mode variables declared globally. *Not* structured/modular/defensive. In a well-written compiler you would probably have to make an extra check to *disallow* functions- in-functions. I wonder how many of the representatives on the standards committee have "well-written compilers"... >Additional idea: > an auto function is not visible to inner functions, static function is. Hmmmm... Garry Wiegand --- Ithaca Software, Alameda, California ...!uunet!ithaca!garry, garry%ithaca.uucp@uunet.uu.net
jfh@rpp386.cactus.org (John F Haugh II) (02/11/91)
In article <1991Feb11.090514.5736@ithaca.uucp> garry@ithaca.uucp (Garry Wiegand) writes: >I have seen the innards of compilers like the old 'pcc': they are >really badly written, with lots of mode variables declared globally. >*Not* structured/modular/defensive. In a well-written compiler you >would probably have to make an extra check to *disallow* functions- >in-functions. I would say a well written compiler would still have to add something to permit function definitions within a function. There are definitions which are not permitted inside of a function, such as definitions containing initialized aggregates, as well as ones which are forbade outside of functions, such as automatic variables (does anyone use "auto" anymore???) If the parser does not faithfully implement the syntax of the language, I'd say something is seriously wrong, even if the code is "structured", or whatever. The syntax elements <function-definition> and <automatic-variable-definition> had best not be lumped into the single syntax element <some-kind-of-definition>. -- John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 832-8832 Domain: jfh@rpp386.cactus.org "I've never written a device driver, but I have written a device driver manual" -- Robert Hartman, IDE Corp.