Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!usc!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!ames!sgi!shinobu!odin!delrey!shap From: shap@delrey.sgi.com (Jonathan Shapiro) Newsgroups: comp.lang.c++ Subject: Re: default arg handling Message-ID: <5122@odin.SGI.COM> Date: 10 Mar 90 23:13:43 GMT References: <1116@xyzzy.UUCP> Sender: news@odin.SGI.COM Organization: Silicon Graphics, Inc., Mountain View, CA Lines: 137 Okay, Mark. I'll tey for a serious answer this time. I think your proposal, as I understand it, is a bad idea. In article <1116@xyzzy.UUCP> langley@bigbird.rtp.dg.com (Mark L Langley) writes: >Jonathon Shapiro (shap@delrey.sgi.com) bristles I like the way you put that - I don't recall seeing the word "bristle" used in this way on the net before. It fits. On the other hand, I would rather I hadn't "bristled in the first place". > >>langley@bigbird.rtp.dg.com (Mark L Langley) suggests... > >> > >> void bar(int x=i+j) { > >> printf("%d\n", x); > >> } > >> > >> main() { > >> int i=20, j=30; > >> bar(); > >> } > >> ...I intend to propose this as a change in ANSI C++, and have already > >> proposed it to AT&T in private correspondence... > > > >The problem with what you suggest is that the function definition site > >needs to know lots and lots of things about ALL function use sites. > >It also would be altogether impossible to implement this across files > >today. > > > >Functions should be isolated - they should not care who calls them, > >except to the extent that they specify requirements in the form of > >arguments. The above proposal violates this any number of ways. > > > >Now, as I clarified (I hope) in a later posting that you may not have >seen, I am just suggesting that the declaration of a default argument >to a function call, like the declaration of any other scoped object, >be shadowed by declarations at a more local scope. Well, yes and no. If we take this proposal on face value, it would seem to imply that one wishes to be able to say: extern void bar(int x=i+j); After all, the mechanism should work across files. The problem with your proposed interpretation is that it is contrary to other interpretations in the language, and that the types of the 'i' and 'j' cannot be known at the time the declaration is seen. This is what another poster probably meant when they complained that you wanted dynamic scoping, which is a LISP feature. You could think of dynamic scoping, for this discussion, as being call-by-name. In some cases, in the absence of the type, the expression is very difficult to parse, which imposes a practical consideration. Most important, however, is the fact that this runs contrary to the C convention that names must be defined (at least implicitly - even in older C's) before they are used. This declaration somehow promises that there will be an i and a j at the call site. The question then arises whether "there must be and i and a j at the call site" should be considered part of the "type" of the function. That is, does the declaration as written mean that we shouldn't allow you to call 'bar' unless the call site has an i and a j? Surely the implementation of bar doesn't care! Also, What should your proposal do when it sees: int i = 0; int j = 1; extern void bar(int x = i + j); main() { int j = 2; bar(); } Should we understand the j to mean the j that was in scope at the declaration (in a lexically scoped language, this would be the "expected" interpretation), or the 'j' in scope at the call site? [Since you seemed to express confusion about 'site', I mean the place where the function is called]. I take it that you wish the second. I suggest that the this interpretation opens a rats nest that even the LISP community is abandoning in newer dialects (consider Scheme, which is strictly lexically scoped). The former is interesting, and let me suggest that the following example might want to be considered analogous: int a = 5; int b = a; Note that in C/C++ this is not legal, even though the compiler can compile-time evaluate a according to the following rationale: 1. All declarations are "run" before any code 2. Therefore, 'a's value is known. 3. Therefore b = 5. But then what about extern int a; int b = a; Even a smart linker would have a hard time ensuring that there were no circular dependencies. Why should the *file* impact the syntactic correctness? > >I assume of course that you realize that an application (now) can be >broken across .c and .h files such that an intended default can be >canceled out by an errant declaration. > > // foo.c - definition of foo > extern "C" { extern printf(...); }; > void foo(int x=1024) { printf("%d\n", x); } > > // main.c - usage of foo > void foo(int x=100); > main() { foo(); } > This is a bug, not a feature - it means that the name mangling in the compiler isn't strong enough. It has always been my opinion that the determination of what should be the default value logically belongs with the definition of the function. Placing it in the declaration is an unfortunate artifact imposed on us by header files. In fact, at one point C++ allowed the declaration and the definition both to specify a default value, but it never required them to agree. I believe that it should be legal to specify the default in both places, so long as they agree. Does this make my concerns more clear? Jonathan Shapiro Silicon Graphics