langley@bigbird.rtp.dg.com (Mark L Langley) (03/10/90)
Jonathon Shapiro (shap@delrey.sgi.com) bristles > >>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... > >This is a great example of why language design should be left to >people who know what they're doing. I'll just let that part ride. The problem however is that the dangerous aspects of this are legal now, depending on how declarations and definitions are broken across files. > >C already has a facility for doing this. It is called a macro. One problem in general with macros is that they aren't C and hence obey their own, more casual, scoping rules. But could you say a little more about how using macros helps default argument handling? Isn't one win of default arguments to avoid using a macro? > >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. > How does it violate modularity? And I don't understand what you are getting at with ``sites.'' 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. My suggestion would not involve any more work than is done now. For example consider what happens now if you have two declarations of a function, in different parts of a system that have mutually exclusive declarations, but call the same function at run time. 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(); } Namely, since the actual default argument is supplied staticaly at call time the language processor detects no conflict. I just think redeclaring the default argument is legitimate; and should not be canceled by the occurrence of two declarations of foo being processed in the same compilation. Admittedly the above is the down side of what I am proposing. But things are no safer now, and there are useful aspects of redefining a default on purpose. >Try proposing it to the BASIC committee. They love this sort of >stuff. > >Jonathan Shapiro > Mark Langley langley@dg-rtp.dg.com
shap@delrey.sgi.com (Jonathan Shapiro) (03/11/90)
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
patch@hpldola.HP.COM (Pat Chkoreff) (03/13/90)
/ hpldola:comp.lang.c++ / shap@delrey.sgi.com (Jonathan Shapiro) / 4:13 pm Mar 10, 1990 / > 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(); > } As Mark Langley has pointed out, the supplying of default arguments should be thought of as the responsibility of the caller, not part of the function definition. So perhaps the example above should be equivalent to the following, which is valid and comprehensible (albeit reprehensible): int i = 0; int j = 1; extern void bar(int); void bar() { return bar(i+j); } main() { int j = 2; bar(); } Of course, the definition of bar() can be inline'd and/or static'ed, and the "return" is not strictly needed in the body, but that's irrelevant. Perhaps if the last formal argument of a function has a default value, then the compiler should always generate a dummy (inline) function without that argument which simply calls the other function with the appropriate default value. Then the meaning of C++ would be as well-founded as that of C++ without default arguments. BTW, this is the standard way of modeling default arguments in languages which do not support them but do support overloading (esp. Prolog). My apologies if this proposal has already been discussed. Patrick Chkoreff 719-590-5983 {hpfcla,hplabs}!hpldola!patch
shap@delrey.sgi.com (Jonathan Shapiro) (03/15/90)
In article <11430020@hpldola.HP.COM> patch@hpldola.HP.COM (Pat Chkoreff) writes: >/ hpldola:comp.lang.c++ / shap@delrey.sgi.com (Jonathan Shapiro) / 4:13 pm Mar 10, 1990 / > >As Mark Langley has pointed out, the supplying of default arguments should >be thought of as the responsibility of the caller, not part of the function >definition. De facto, C++ says otherwise. If what you say were true, the following would be legal: extern foo(int = 5); ... extern foo(int = 10); in the same file. Note that C++ disallows this. Jon
patch@hpldola.HP.COM (Pat Chkoreff) (03/17/90)
/ hpldola:comp.lang.c++ / shap@delrey.sgi.com (Jonathan Shapiro) / 12:52 pm Mar 14, 1990 / >>In article <11430020@hpldola.HP.COM> patch@hpldola.HP.COM (Pat Chkoreff) writes: >/ hpldola:comp.lang.c++ / shap@delrey.sgi.com (Jonathan Shapiro) / 4:13 pm Mar 10, 1990 / > >> As Mark Langley has pointed out, the supplying of default arguments should >> be thought of as the responsibility of the caller, not part of the function >> definition. > > De facto, C++ says otherwise. If what you say were true, the > following would be legal: > > extern foo(int = 5); > > ... > > extern foo(int = 10); > > in the same file. Note that C++ disallows this. > > Jon According to Mark Langley's policy, the example above should NOT be legal, because the caller's responsibility is ambiguous. The implementation of his policy which I proposed would in fact correctly reject the example. Here's why. The compiler would generate the following: extern int foo(int); // extern foo(int = 5); static int foo() { return foo(5); } // ... extern int foo(int); // extern foo(int = 10); static int foo() // This is line "10". { return foo(10); } This itself is not legal, because foo() is declared twice: CC: "t.c", line 10: error 1034: two definitions of foo() I still do not see a problem with either Mark Langley's policy or my implementation of it. Patrick Chkoreff 719-590-5983 {hpfcla,hplabs}!hpldola!patch