langley@bigbird.rtp.dg.com (Mark L Langley) (03/08/90)
jak@cs.brown.edu writes > >langley@bigbird.rtp.dg.com (Mark L Langley) suggests that the following >should be legal: >> >> 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 correspondance... > >Surely you can't be serious about this? You are proposing dynamic >scoping for C++. C and C++ have always been lexically scoped, and the >problems with dynamic scoping are so great that languages like Lisp, >which used to be dynamically scoped, are moving away from it. Yes I am serious, but no, I am not *proposing dynamic scoping*. I am just proposing that you delay evaluating the arguments until you evaluate the function call. Apparently I didn't make my point very clear; in retrospect I chose a poor example. Perhaps I am suggesting a slight mind shift. Namely, the default argument is not (I suggest) a property of the function definition. Rather it is a property of the caller. I think this is a better way of looking at it for two reasons. First, since the caller is the one that provides the arguments, shouldn't he have some say (if he wants it) in the arguments he *doesn't* provide? Second, I think that this is more compatible with the usual conventions of name-shadowing. Simply look at the declaration of the function as a scoped name, and more local declarations may shadow it. This imposes no new constraints on the user (he can just use the declaration from the include file unless he has something in mind). > >Consider: > >- How can you guarantee that any i and j will be in scope when bar is >called? You would have to look at the context of every call to bar to >decide this. If there is no i or j visible, then i and j are undeclared identifiers, and this should be reported as an error. > >- How do you decide which i and j should be used? You have to scan up >the stack at run-time -- a very expensive proposition. > >- How can you do any reasoning on your program when you have no idea >which i and j are going to be used? > No such mechanism is required. You take the most local copies of i and j at call time, the same as in any other expression. Now I wouldn't really expect someone to put foo(int x=i+j) {} in the function definition -- this would probably be a misuse. Rather, I would more expect some user of foo (a regular user at that) to supply some more appropriate value than the generic default. Consider this // foo.h void foo(int operation_type=0); ... // Delete.h #include foo.h enum MajorOptype { Noop, Insert=100, Delete=200 }; void foo(int operation_type=Delete); // application.c #include Delete.h enum MinorOptype { Paragraph, Word, Line, Column }; // big function bar with LOTS of calls to foo insert_from_deleted_buffer() { extern void foo(int operation_type=major_operation + minor_operation); const int major_operation=Insert; enum MinorOptype minor_operation; <code that sets minor_operation> foo(); } > Jak >~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >ARPA/BITNET : jak@cs.brown.edu Tel : (401) 863 7664 >Snail : 86 Benevolent St, Providence, 02906 RI. Tel : (401) 272 6149 Mark Langley langley@dg-rtp.dg.com -- Creative dissent always encouraged --
cs132093@cslab7f.cs.brown.edu (Dan Bornstein) (03/10/90)
In article <1006@xyzzy.UUCP>, langley@bigbird.rtp.dg.com (Mark L Langley) writes: > [lots-o-stuff deleted] > > Now I wouldn't really expect someone to put > foo(int x=i+j) {} > in the function definition -- this would probably be a misuse. Rather, I > would more expect some user of foo (a regular user at that) to supply some > more appropriate value than the generic default. Consider this > > // foo.h > void foo(int operation_type=0); > ... > // Delete.h > #include foo.h > enum MajorOptype { Noop, Insert=100, Delete=200 }; > void foo(int operation_type=Delete); > > // application.c > #include Delete.h > enum MinorOptype { Paragraph, Word, Line, Column }; > > // big function bar with LOTS of calls to foo > insert_from_deleted_buffer() { > extern void foo(int operation_type=major_operation + minor_operation); > const int major_operation=Insert; > enum MinorOptype minor_operation; > <code that sets minor_operation> > foo(); > } Whoah! This could lead to some strange bugs. Remember that many .h files have an #ifdef NAME and #endif surrounding their bodies. So, take this situation: // foo.h #ifndef FOO #define FOO void foo (int op=0); #endif // bar.h #ifndef BAR #define BAR #include "foo.h" const Bar = 100; void foo (int op=Bar); inline void bar (void) { // stuff foo (); // more stuff } #endif // baz.h #ifndef BAZ #define BAZ #include "foo.h" inline void baz (void) { // stuff foo (); // using foo()'s original default. // more stuff } #endif Now, foon wants to use bar() and baz(), so we have: // foon.c #include "bar.h" #include "baz.h" Now, the problem is that baz() will be defined incorrectly since after bar.h is included, the #defines keep the old foo() declaration from being encountered. This could be a real problem when bar and baz are not originally part of the same project and therefore the original author(s) didn't realize the ugly possibility. In other words, baz() behaves differently depending on whether or not bar.h has been included first. This seems to defeat modularity. -dan
shap@delrey.sgi.com (Jonathan Shapiro) (03/10/90)
>langley@bigbird.rtp.dg.com (Mark L Langley) suggests that the following >should be legal: > > 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 correspondance... > >Mark Langley >langley@dg-rtp.dg.com This is a great example of why language design should be left to people who know what they're doing. C already has a facility for doing this. It is called 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. Try proposing it to the BASIC committee. They love this sort of stuff. Jonathan Shapiro