www.digitalmars.com         C & C++   DMDScript  

D - Does D have function overloading?

reply satelliittipupu <satelliittipupu_member pathlink.com> writes:
I tried to port some C++ code to D, and did all kinds of little tests.
Then I ran into this problem:

Does D have function overloading? And if it doesn't and won't, then why is this?

I'm not sure if the term is correct, but the thing I mean is,
can I do this:

int somefunc(int a, bool is_it_so = true );

or

int longfunc(int a, char[] name = "untitled", int nro = 5, bool no_no = false );

and use them e.g.

somefunc(5);

longfunc(10, "justaname");

You propably know what I mean....

?
Mar 26 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
satelliittipupu wrote:

I tried to port some C++ code to D, and did all kinds of little tests.
Then I ran into this problem:

Does D have function overloading? And if it doesn't and won't, then why is this?

I'm not sure if the term is correct, but the thing I mean is,
can I do this:

int somefunc(int a, bool is_it_so = true );

or

int longfunc(int a, char[] name = "untitled", int nro = 5, bool no_no = false );

and use them e.g.

somefunc(5);

longfunc(10, "justaname");

You propably know what I mean....

?


  
Yes I understand. D has function overloading but not optional parameters (I wish it did). ie - the same thing can be done like: int somefunc(int a, bool is_it_so) {} int somefunc(int a) {somefunc(a, true);} somefunc(5); PS - Sorry for sending to your home address, clicked the wrong button. -- -Anderson: http://badmama.com.au/~anderson/
Mar 26 2004
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
J Anderson wrote:

 Yes I understand. D has function overloading but not optional parameters 
 (I wish it did).
[...] Why do you want optional parameters, I prefer the phrase "default valued parameters", to be restricted to basic types? And why should default valued parametsr be restricted to occur at the end of a formal parameter list? So long!
Mar 26 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Manfred Nowak wrote:

 J Anderson wrote:

  

 Yes I understand. D has function overloading but not optional 
 parameters (I wish it did).
   
[...] Why do you want optional parameters, I prefer the phrase "default valued parameters", to be restricted to basic types?
Sorry I don't quite understand (are you saying there is a difference between optional and default?) Because it's so much easier to: 1) type 2) interpret from the users perspective. I'd rather if you could make any value optional no matter where it is in the list. void foo(int a = 10, int b) foo(, 10);
 And why should default valued parametsr be restricted to occur at the end
 of a formal parameter list?
  
It could cause overloading problems but I still would like this.
 So long!
  
-- -Anderson: http://badmama.com.au/~anderson/
Mar 26 2004
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
J Anderson wrote:

Sorry I don't quite understand (are you saying there is a difference
between optional and default?)
Yes. Consider this overloads for `action': void action( time t){ /* create a human beeing at time t */ } void action() { /* destroy earth immediately */} The parameter `t' is clearly optional, but not default valued.
Because it's so much easier to:
1) type
Easier typing means loss of redundancy. Can you justify that time improvement one can achieve by easier typing is not lost during the lifetime of the source because of more necessary reading the source over and over again to understand its meaning and finding the subtle errors that were introduced because of the lack of redundancy?
2) interpret from the users perspective.
Are you sure? Consider a function `f' with 9 parameters `p1', `p2', ..., `p9'. Imagine, that there are three types of calls, because other than the default values have to be used: f( p1, p2, p5, p8) f( p2 p4, p6, p9) f( p3, p5, p7, p9) As you can see every parameter has to be made optional, because for every parameter exists a call for which that parameter is not needed. Now please explain why it is easier for a user, whatever that is, to interpret this three types of calls out of the 512 possible calls, that are introduced by making nine parameters optional instead of providing three types of calls. As far as you have managed that please explain why your arguments also hold, when applied to far more complex cases, than that which I am able to present to you within limited time and space.
I'd rather if you could make any value optional no matter where it is in
the list.
void foo(int a = 10, int b)
foo(, 10);
Maybe that for such simple cases the multiargument extension, which I just suggested, will be helpfull for the one that writes the call. Under my suggested multiargument extension this call would be written: foo( ; 10); Incredible more complex :-)
It could cause overloading problems but I still would like this.
Until that case, in which you were unable to detect why the compiler refuses to compile your code. Note: you did not explain, why default valued parameters should be restricted to basic types. Is there a reason to refuse a default value for a function or delegate variable? So long!
Mar 26 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Manfred Nowak wrote:

J Anderson wrote:

  

Sorry I don't quite understand (are you saying there is a difference
between optional and default?)
    
Yes. Consider this overloads for `action': void action( time t){ /* create a human beeing at time t */ } void action() { /* destroy earth immediately */} The parameter `t' is clearly optional, but not default valued.
Because it's so much easier to:
1) type
    
Easier typing means loss of redundancy. Can you justify that time improvement one can achieve by easier typing is not lost during the lifetime of the source because of more necessary reading the source over and over again to understand its meaning and finding the subtle errors that were introduced because of the lack of redundancy?
To me: void func(int a = 1, int b = 2, int c = 3, int d = 4, int e = 5) {} is much easier (and less error prone) then: void func() {func();} void func(int a) {func(a,2);} void func(int a, int b) {func(a,b,3);} void func(int a, int b, int c) {func(a,b,c,4);} void func(int a, int b, int c, int d) {func(a,b,c,d,5);} void func(int a, int b, int c, int d, int e) {}
2) interpret from the users perspective.
    
Are you sure? Consider a function `f' with 9 parameters `p1', `p2', ..., `p9'. Imagine, that there are three types of calls, because other than the default values have to be used: f( p1, p2, p5, p8) f( p2 p4, p6, p9) f( p3, p5, p7, p9) As you can see every parameter has to be made optional, because for every parameter exists a call for which that parameter is not needed. Now please explain why it is easier for a user, whatever that is, to interpret this three types of calls out of the 512 possible calls, that are introduced by making nine parameters optional instead of providing three types of calls.
By user, I mean the person using the class. Remembering 9 parameters is much worse then only needing to remember 4 or less. IMHO having more available ways of using a function is like being about to write an equation in different ways. ie a * b + c // is basicly the same as c + a * b Why should be limit the way functions can be called? In your example case it is a design issue not a language issue. Another advantage of optional parameters is that they help force the different calls to behave the same way.
As far as you have managed that please explain why your arguments also
hold, when applied to far more complex cases, than that which I am able to
present to you within limited time and space.
  
In the simple example I showed before, you only need to look at one line and know how to use it. You also only need to look at one bit of documentation. You don't need to look though pages of code to find out if a particular overload is provided.
I'd rather if you could make any value optional no matter where it is in
the list.
void foo(int a = 10, int b)
foo(, 10);
    
Maybe that for such simple cases the multiargument extension, which I just suggested, will be helpfull for the one that writes the call. Under my suggested multiargument extension this call would be written: foo( ; 10); Incredible more complex :-)
That would be ok also except is this runtime? On one hand you don't want optional parameters but then you want the ultimate dynamic optional parameters?
It could cause overloading problems but I still would like this.
    
Until that case, in which you were unable to detect why the compiler refuses to compile your code.
Again a design issue.
Note: you did not explain, why default valued parameters should be
restricted to basic types. Is there a reason to refuse a default value for
a function or delegate variable?
  
Did I say that? If I have it would have only been to make the job easier on Walter however optional everything I say.
So long!
  
-- -Anderson: http://badmama.com.au/~anderson/
Mar 26 2004
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
J Anderson wrote:

 To me:
 
 void func(int a = 1, int b = 2, int c = 3, int d = 4, int e = 5) {}
 
 is much easier (and less error prone) then:
 
 void func() {func();}
 void func(int a) {func(a,2);}
 void func(int a, int b) {func(a,b,3);}
 void func(int a, int b, int c) {func(a,b,c,4);}
 void func(int a, int b, int c, int d) {func(a,b,c,d,5);}
 void func(int a, int b, int c, int d, int e) {}
:-) Very convincing example. The error is in the first line. And now to the counter example. In which of the following lines of usage, i.e. calls, is the error? func( 1, 2, 3, 4, 6); func( 1, 2, 3, 4, 6); func( 1, 2, 3, 4, 6); func( 1, 2, 3, 4, 6); func( 1, 2, 3, 4, 6); Did you stop the time you have needed to find it? Then multiply it with the total number of lexical occurences of calls of `func', subtract 1, ... [some of the calculations intentionmally omitted] ..., finally multiply it with the appropriate hourly wage. Are you sure, that the resulting amount of money is less than your wage for writing five more lines of code? Note: I would have found your error, even without the commenting line above it. [...]
 Remembering 9 parameters is much worse then only needing to remember 4
 or less.
This is general wisdom, not related to the stated problem. Are you aware of the facts, 1) that the user must remember the default values of all nine default valued parameters to be able to decide, whether he is forced to overwrite it? 2) that he must remember and _type_ all preceding, up to eight, default values, if he detects that, the value of the ninth has to be overriden? 3) that any reviewer must _read_ up to eight values and compare them with remembered default values for only finding that they indeed are the default values, whereas the ninth has been overridden?
 IMHO having more available ways of using a function is like
 being about to write an equation in different ways. ie
 
 a * b + c // is basicly the same as
 c + a * b
:-) I am quite sure, that you know, that this sequences of character beeing the same depends strongly on the rules that are applied to them.
 Why should be limit the way functions can be called?
Again I am quite sure, that you know several limits. And one of them is, that a function call is not allowed to be ambiguous.
 In your example case it is a design issue not a language issue.
Why do you think so? At which point a design issue turns to be a language issue?
 Another advantage of optional parameters is that they help force the
 different calls to behave the same way.
I do not see any justification for this claim. Is this claim consistent with the implicit message issued by your question, why function calls should be limited?
As far as you have managed that please explain why your arguments also
hold, when applied to far more complex cases, than that which I am able
to present to you within limited time and space.
In the simple example I showed before, you only need to look at one line and know how to use it. You also only need to look at one bit of documentation. You don't need to look though pages of code to find out if a particular overload is provided.
??? I dont see a connection between my request and your reply.
 Incredible more complex :-)
That would be ok also except is this runtime?
I do not catch fully what you mean. There is no magic in my suggestion. The point/phase of execution will not be changed by my suggestion.
 On one hand you don't want optional parameters but then you want the
 ultimate dynamic optional parameters?
I do not want default valued parameters, as requested by the OP. I have not established a conviction on optional parameters. They are only a special case of the general possibilities of the D language. Because I had something totally different in mind, somebody could come up with the claim, that the usage of my suggested generalization for optional parametrs is an absue.
It could cause overloading problems but I still would like this.
Until that case, in which you were unable to detect why the compiler refuses to compile your code.
Again a design issue.
Agreed.
Note: you did not explain, why default valued parameters should be
restricted to basic types. Is there a reason to refuse a default value
for a function or delegate variable?
Did I say that?
No. And I only ask :-)
  If I have it would have only been to make the job
 easier on Walter however optional everything I say.
And with my suggestion also this is possible---by two or three minor changes to the language. So long!
Mar 27 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Manfred Nowak wrote:

J Anderson wrote:

  

To me:

void func(int a = 1, int b = 2, int c = 3, int d = 4, int e = 5) {}

is much easier (and less error prone) then:

void func() {func();} //should be {func(1);}
void func(int a) {func(a,2);}
void func(int a, int b) {func(a,b,3);}
void func(int a, int b, int c) {func(a,b,c,4);}
void func(int a, int b, int c, int d) {func(a,b,c,d,5);}
void func(int a, int b, int c, int d, int e) {}
    
:-) Very convincing example. The error is in the first line.
Just trying to make my point. I hoped you'd spot it :)
And now to the counter example. In which of the following lines of usage, 

i.e.
calls, is the error?

   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);

Did you stop the time you have needed to find it? Then multiply it with
the total number of lexical occurences of calls of `func', subtract
1, ... [some of the calculations intentionmally omitted] ..., finally
multiply it with the appropriate hourly wage. Are you sure, that
the resulting amount of money is less than your wage for writing five more
lines of code?
  
You could use this argument for making any line of code bigger in any language. Therefore why not omit every bit of syntax sugar? Also generally it's not five lines. One class could have many optional parameters. In fact every method could in some cases. More code is harder to read.
Note: I would have found your error, even without the commenting line
above it.

[...]
  

Remembering 9 parameters is much worse then only needing to remember 4
or less.
    
This is general wisdom, not related to the stated problem. Are you aware of the facts, 1) that the user must remember the default values of all nine default valued parameters to be able to decide, whether he is forced to overwrite it?
I see this differently. Optional characters are additions. The user shouldn't need to know them unless they require them. For example if decimal point was to be implemented with to string float it could be written as toString(float, int t = -1). Much of the time you wouldn't even care that t = -1 exists. If they need it there is only one place to look. On the design side if someone decided to change toString to toStringf (without optional parameters) then they'd need to go and find all the versions of toString that are used for floats and change them. Because there are also toString's for int this makes things more difficult. Ok that was only a simple example as things can get much more complex. It's not like you can set-up a constant name (well in C++ you could with macros) and just change things in one place. I like less redundant code because it is easier to maintain. -- -Anderson: http://badmama.com.au/~anderson/
Mar 27 2004
parent reply Ilya Minkov <minkov cs.tum.edu> writes:
It's not common nor good to have so many default arguments per method. I 
can't recall using them much. At most one or 2 and in not so many places 
per project. I would say that if one needs so many default arguments, 
there is something *really* wrong with their design!

It reminds me of someone having complained that if the module would have 
1000 imports, one would have to write out each of every one of them. :>

-eye

J Anderson schrieb:
 Manfred Nowak wrote:
 
 J Anderson wrote:

  

 To me:

 void func(int a = 1, int b = 2, int c = 3, int d = 4, int e = 5) {}

 is much easier (and less error prone) then:

 void func() {func();} //should be {func(1);}
 void func(int a) {func(a,2);}
 void func(int a, int b) {func(a,b,3);}
 void func(int a, int b, int c) {func(a,b,c,4);}
 void func(int a, int b, int c, int d) {func(a,b,c,d,5);}
 void func(int a, int b, int c, int d, int e) {}
   
:-) Very convincing example. The error is in the first line.
Just trying to make my point. I hoped you'd spot it :)
 And now to the counter example. In which of the following lines of usage,
 i.e.
 calls, is the error?

   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);

 Did you stop the time you have needed to find it? Then multiply it with
 the total number of lexical occurences of calls of `func', subtract
 1, ... [some of the calculations intentionmally omitted] ..., finally
 multiply it with the appropriate hourly wage. Are you sure, that
 the resulting amount of money is less than your wage for writing five 
 more
 lines of code?
  
You could use this argument for making any line of code bigger in any language. Therefore why not omit every bit of syntax sugar? Also generally it's not five lines. One class could have many optional parameters. In fact every method could in some cases. More code is harder to read.
 Note: I would have found your error, even without the commenting line
 above it.

 [...]
  

 Remembering 9 parameters is much worse then only needing to remember 4
 or less.
   
This is general wisdom, not related to the stated problem. Are you aware of the facts, 1) that the user must remember the default values of all nine default valued parameters to be able to decide, whether he is forced to overwrite it?
I see this differently. Optional characters are additions. The user shouldn't need to know them unless they require them. For example if decimal point was to be implemented with to string float it could be written as toString(float, int t = -1). Much of the time you wouldn't even care that t = -1 exists. If they need it there is only one place to look. On the design side if someone decided to change toString to toStringf (without optional parameters) then they'd need to go and find all the versions of toString that are used for floats and change them. Because there are also toString's for int this makes things more difficult. Ok that was only a simple example as things can get much more complex. It's not like you can set-up a constant name (well in C++ you could with macros) and just change things in one place. I like less redundant code because it is easier to maintain.
Mar 27 2004
next sibling parent Hauke Duden <H.NS.Duden gmx.net> writes:
Ilya Minkov wrote:
 It's not common nor good to have so many default arguments per method. I 
 can't recall using them much. At most one or 2 and in not so many places 
 per project. I would say that if one needs so many default arguments, 
 there is something *really* wrong with their design!
There is a big difference between writing applications and libraries. In applications you usually only implement the functionality that is actually needed, thus you have less need to hide unwanted functionality on the calling side. But as I wrote in another post, libraries are usually written to be used in many different applications. That means that they have to provide lots of functionality of which only a fraction will be used in most applications. So if you want your library to be easy to use you better think of a way to enable the application developer to just ignore any unnecessary complexities. Default values for function parameters are often a very convenient way to do this. Hauke
Mar 27 2004
prev sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
On Sat, 27 Mar 2004 16:05:02 +0100, Ilya Minkov <minkov cs.tum.edu>
wrote:

It's not common nor good to have so many default arguments per method. I 
can't recall using them much. At most one or 2 and in not so many places 
per project. I would say that if one needs so many default arguments, 
there is something *really* wrong with their design!
I agree with you. I use Java and C++ and I don't miss default arguments in Java. Sometimes I run into functions that take null or -1 or something as a placeholder. I haven't ever run into a case where this happens but if a function *really* wants to have alot of default arguments (like 10 or more) a struct can be used without too much hassle: // original function void test(int a, int b, int c, int d) { printf("%d %d %d %d\n",a,b,c,d); } // struct with defaults for b, c, d struct testOpt { int b = 10; int c = 20; int d = 30; } // overload to accept defaults void test(int a, testOpt x) { test(a, x.b, x.c, x.d); } int main() { test(1,2,3,4); testOpt opt; test(1,opt); // call with defaults static testOpt opt2 = {c : 200}; test(1,opt2); // call test with a=1 and c=200 return 0; }
Mar 27 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Ben Hinkle wrote:

I haven't ever run into a case where this happens but if a function
*really* wants to have alot of default arguments (like 10 or more)
a struct can be used without too much hassle:


// original function
void test(int a, int b, int c, int d)
{
   printf("%d %d %d %d\n",a,b,c,d);
}

// struct with defaults for b, c, d
struct testOpt {
   int b = 10;
   int c = 20;
   int d = 30;
}
// overload to accept defaults
void test(int a, testOpt x) { test(a, x.b, x.c, x.d); }

int
main()
{
   test(1,2,3,4);

   testOpt opt;
   test(1,opt);   // call with defaults

   static testOpt opt2 = {c : 200};
   test(1,opt2); // call test with a=1 and c=200
   return 0;
}
  
This is just as bad as the present solution. -- -Anderson: http://badmama.com.au/~anderson/
Mar 27 2004
parent reply "Ben Hinkle" <bhinkle4 juno.com> writes:
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:c44lu1$16ul$1 digitaldaemon.com...
 Ben Hinkle wrote:

I haven't ever run into a case where this happens but if a function
*really* wants to have alot of default arguments (like 10 or more)
a struct can be used without too much hassle:


// original function
void test(int a, int b, int c, int d)
{
   printf("%d %d %d %d\n",a,b,c,d);
}

// struct with defaults for b, c, d
struct testOpt {
   int b = 10;
   int c = 20;
   int d = 30;
}
// overload to accept defaults
void test(int a, testOpt x) { test(a, x.b, x.c, x.d); }

int
main()
{
   test(1,2,3,4);

   testOpt opt;
   test(1,opt);   // call with defaults

   static testOpt opt2 = {c : 200};
   test(1,opt2); // call test with a=1 and c=200
   return 0;
}
This is just as bad as the present solution.
With three I totally agree. With 10+ it might make sense. What would be even better would be if the struct initializer could be done on-the-fly like test(1,{c:200}) or if the implicit testOpt leads to lookup problems something like test(1,testOpt{c:200}) On-the-fly array construction and initialization has come up before. Java could be removed if we had a syntax as nice as the static initialization syntax.
Mar 27 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Ben Hinkle wrote:

With three I totally agree. With 10+ it might make sense. What would be even
better would be if the struct initializer could be done on-the-fly like
  test(1,{c:200})
or if the implicit testOpt leads to lookup problems something like
  test(1,testOpt{c:200})
  
Yes this would be good. However it's still not a solution to optional parameters, it is a solution to named parameters, like ada has (ada has optional and overload as well).
On-the-fly array construction and initialization has come up before. Java

could be removed if we had a syntax as nice as the static initialization
syntax.
-- -Anderson: http://badmama.com.au/~anderson/
Mar 27 2004
parent reply Ben Hinkle <bhinkle4 juno.com> writes:
On Sun, 28 Mar 2004 05:28:38 +0800, J Anderson
<REMOVEanderson badmama.com.au> wrote:

Ben Hinkle wrote:

With three I totally agree. With 10+ it might make sense. What would be even
better would be if the struct initializer could be done on-the-fly like
  test(1,{c:200})
or if the implicit testOpt leads to lookup problems something like
  test(1,testOpt{c:200})
  
Yes this would be good. However it's still not a solution to optional parameters, it is a solution to named parameters, like ada has (ada has optional and overload as well).
They are related. The other stuct initializer syntax test(1,testOpt{100,200}) that doesn't use names is more like the traditional optional parameters where you specify the values from the first one up until the last one you want and leave the rest as default. Keep in mind Walter's replies: http://www.prowiki.org/wiki4d/wiki.cgi?FeatureRequestList/DefaultArguments His theme is that the rules for overriding and overloading methods with optional parameter are complex. With my struct suggestion the problems are split in two and there isn't any conflict. The type of the struct tells the compiler which method signature to use in the overriding/overloading logic. If a subclass wants to define new defaults or optional parameters it can declare its own "options struct" and user code would have to explicity say which set of optional values it wants. Also I think it's ok that this struct solution is more work to define than C++ because for one or two optional parameters the wrapper approach is acceptable. So my general rule of thumb would be 1) for one or two compile-time optional parameters write a wrapper function 2) for large numbers of compile-time optional parameters use a struct (if on-the-fly struct initializers are implemented) 3) for run-time optional parameters use varargs style ... or an array And probably if I was using this in code I wouldn't even write a wrapper function with a struct. I'd just index the variables in the struct. ie: void test(int a, testOpt opt) { printf("%d %d %d %d\n", a, opt.b, opt.c, opt.d); } int main() { test(1,testOpt{2,3}); } -Ben
Mar 28 2004
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Congratulations for this idea!

Ben Hinkle wrote:

 3) for run-time optional parameters use varargs style ... or
    an array
That is the second time, that there ssems to be a difference between compile time and runtime optionality. What is meant by that? I do not catch the difference. Please explain. So long!
Mar 28 2004
parent reply Ben Hinkle <bhinkle4 juno.com> writes:
On Sun, 28 Mar 2004 17:53:16 +0200, Manfred Nowak
<svv1999 hotmail.com> wrote:

Congratulations for this idea!

Ben Hinkle wrote:

 3) for run-time optional parameters use varargs style ... or
    an array
That is the second time, that there ssems to be a difference between compile time and runtime optionality. What is meant by that? I do not catch the difference. Please explain.
by "compile-time" I mean that the number of default arguments, their types and their values are known when the code is compiled. Every call to that function - even if the function is overridden at run-time - will use those defaults and only those defaults. That's why defaults and overriding is so confusing - the defaults are determined at compile-time but the actual function called is determined at run-time. Wrapper functions actually are more flexible than C++ style defaults since a subclass can override the wrapper (unless it is marked "final") and specify a new default value. by "run-time" I mean "not compile-time". :-) -Ben
Mar 28 2004
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Ben Hinkle wrote:

 by "compile-time" I mean that the number of default arguments,
 their types and their values are known when the code is
 compiled. Every call to that function - even if the function
 is overridden at run-time - will use those defaults and only
 those defaults. That's why defaults and overriding is so 
 confusing - the defaults are determined at compile-time but
 the actual function called is determined at run-time.
 Wrapper functions actually are more flexible than C++ style
 defaults since a subclass can override the wrapper (unless it
 is marked "final") and specify a new default value.
 
 by "run-time" I mean "not compile-time". :-) 
Thanks for this try of an explanation, but I still miss the point. The end user, that who uses the final executable, and that is the only stage in which no compilation takes place, has influence only on the functions called by the input he provides. But that is typed input, so he has no influence on the function called, because he cannot change the type of his input. Do you mean with "runtime" that time, when another programmer writes down some calls to a given function/struct/class? If so, then again all parameters are known at "compile-time", except he does never compile them. But then they are of no problem :-) So do you mean with "compile-time" that time, when you introduce the functionality of your code to the compiler, knowing that it will be used by another programmer and do you call that usage "runtime"? If so, then I assume, that my `(,,;;,)'- suggestion should replace your suggestion to use the unsafe varargs/... thingy. So long!
Mar 28 2004
parent Ben Hinkle <bhinkle4 juno.com> writes:
On Mon, 29 Mar 2004 01:57:42 +0200, Manfred Nowak
<svv1999 hotmail.com> wrote:

Ben Hinkle wrote:

 by "compile-time" I mean that the number of default arguments,
 their types and their values are known when the code is
 compiled. Every call to that function - even if the function
 is overridden at run-time - will use those defaults and only
 those defaults. That's why defaults and overriding is so 
 confusing - the defaults are determined at compile-time but
 the actual function called is determined at run-time.
 Wrapper functions actually are more flexible than C++ style
 defaults since a subclass can override the wrapper (unless it
 is marked "final") and specify a new default value.
 
 by "run-time" I mean "not compile-time". :-) 
Thanks for this try of an explanation, but I still miss the point.
re-reading what I wrote I was being too vague. sorry for the confusion!
The end user, that who uses the final executable, and that is the only
stage in which no compilation takes place, has influence only on the
functions called by the input he provides. But that is typed input, so he
has no influence on the function called, because he cannot change the type
of his input.
yeah - that's run-time.
Do you mean with "runtime" that time, when another programmer writes down
some calls to a given function/struct/class? If so, then again all
parameters are known at "compile-time", except he does never compile
them. But then they are of no problem :-)
Let me give an example of what I meant. Suppose there was a function "fcn" with signature void fcn(...) Suppose the variable "user" has a 0 or 1 depending on something the user typed. Then the code if (user) fcn(0,"hello",33.3,"some random types"); else fcn("some", "totally different", "data"); then the actual number and types of the inputs passed to fcn is determined at run-time. You are right that we could enumerate all the possible combinations at compile time through some static analysis of the code, but I was just referring to the fact that you can't tell from looking at the signature of fcn. I was being vague in how I was using those terms. That vagueness comes out also in my explanation about wrappers since subclasses can override the wrapper and redefine the defaults. I just added the "compile time" and "run time" to distinguish what the function knows when about what is on the stack (sounds like Watergate: what did the function know and when did it know it?)
So do you mean with "compile-time" that time, when you introduce the
functionality of your code to the compiler, knowing that it will be used
by another programmer and do you call that usage "runtime"?

If so, then I assume, that my `(,,;;,)'- suggestion should replace your
suggestion to use the unsafe varargs/... thingy. 
I admit I was confused by your proposal. I'll look at it again.
So long!
Mar 28 2004
prev sibling next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Manfred Nowak wrote:
  > This is general wisdom, not related to the stated problem. Are you aware
 of the facts,
 
 1) that the user must remember the default values of all nine
 default valued parameters to be able to decide, whether he is forced
 to overwrite it?
Not if the function was well written. If the function developer is even moderately sane then the defaults will be chosen so that the function will work as intended if you just ignore the corresponding parameters. After all, a default value usually indicates that the function has a feature that you CAN use, but don't have to use.
 2) that he must remember and _type_ all preceding, up to eight, default
 values, if he detects that, the value of the ninth has to be overriden?
Depends on the syntax. That is one of the weak points in C++, but there have already been some good suggestions on how to avoid that. In any case, this issue also applies to the workaround of writing n dummy functions to emulate default parameters (at least if the parameters have the same type).
 3) that any reviewer must _read_ up to eight values and compare
 them with remembered default values for only finding that they indeed are
 the default values, whereas the ninth has been overridden?   
See 2. Default values are very important if you want to write good software libraries. A good library provides lots of functionality but is also easy to use. And to be easy to use one needs some mechanism to be able to hide/ignore unwanted functionality. In the case of functions that usually means that you need default values. These can be either implemented with a hack (like writing several dummy functions) or cleanly by supporting this directly in the language. To give an example: most people agree that the standard libraries of Python are well designed and exceptionally easy to use. Why is that? If you read the documentation you will see that many function parameters have useful default values. The functions CAN do powerful and complicated things, but if you just want to use a simple subset of this functionality you can simply leave out the parameters that you don't need. And you don't even have to know how these WOULD be used either, since you can depend on the defaults to be the right ones. Hauke
Mar 27 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Hauke Duden wrote:

 Default values are very important if you want to write good software 
 libraries. A good library provides lots of functionality but is also 
 easy to use. And to be easy to use one needs some mechanism to be able 
 to hide/ignore unwanted functionality. 
Exactly. In C++ I would hate to have to always supply the allocator when creating a vector (this applies to the work-around as well). You would need to know the exact allocator to use with the right container, let alone a simple change of a vector to a linked-list.
 In the case of functions that usually means that you need default 
 values. These can be either implemented with a hack (like writing 
 several dummy functions) or cleanly by supporting this directly in the 
 language.
Right, if optional parameters are provided, parhaps some of this mess Manfred is talking about could be avoided. -- -Anderson: http://badmama.com.au/~anderson/
Mar 27 2004
prev sibling next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Manfred Nowak wrote:

   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);
   func( 1, 2, 3, 4, 6);

Did you stop the time you have needed to find it? Then multiply it with
the total number of lexical occurences of calls of `func', subtract
1, ... [some of the calculations intentionmally omitted] ..., finally
multiply it with the appropriate hourly wage. Are you sure, that
the resulting amount of money is less than your wage for writing five more
lines of code?
  
Another thing I don't like about this solution is that if default values change you your function would stay the same. The vendor can't go into your code to fix these things. You would need to write (assuming u used 5 instead of 6): func( DefaultParam1, DefaultParam2, DefaultParam3, DefaultParam4, DefaultParam5); func( DefaultParam1, DefaultParam2, DefaultParam3, DefaultParam4, DefaultParam5); func( DefaultParam1, DefaultParam2, DefaultParam3, DefaultParam4, DefaultParam5); func( DefaultParam1, DefaultParam2, DefaultParam3, DefaultParam4, DefaultParam5); func( DefaultParam1, DefaultParam2, DefaultParam3, DefaultParam4, DefaultParam5); -- Anderson: http://badmama.com.au/~anderson/
Mar 27 2004
parent Manfred Nowak <svv1999 hotmail.com> writes:
J Anderson wrote:

 Another thing I don't like about this solution is that if default values
 change you your function would stay the same.   The vendor can't go into
 your code to fix these things.  You would need to write (assuming u used
 5 instead of 6):
 
    func( DefaultParam1, DefaultParam2, DefaultParam3, DefaultParam4,
    DefaultParam5);
[...] I do not understand why you have changed the fifth parameter to default. Now all parameters are the defaults? So the call could have an empty parameter list. However, thanks for this argument. Let me reason on it: if a value for an optional parameter, that is a default valued parameter, is not supplied with the actuall call, then the current default value is imposed on that parameter. Because there is no further information, it stays unknown, whether 1) the writer of the call was simply not aware of the existence of that optional paramter xor 2) the writer of the call intentionally has not provided a value to that parameter, because he knew and was happy with the current default value, that would be imposed by omitting any value. Now let us assume, that the default value to be imposed on that optional parameter changes with some reason. Above case 1) would cause no harm. But, arghhh, because of above case 2) every lexical occurence of that call must be checked and it must be decided whether case 1 or case 2 holds. In latter case, the old default value must be inserted into the code. Now the other way round: if a value for an optional parameter, that is a default valued parameter, is supplied with the actuall call and is identical with the current default value, then, because there is no further information, it stays unknown, whether 3) the writer of the call was simply not aware of the precise value of the current default value of that optional paramter but wanted exactly this current default value (Note: this unawareness could have also resulted from the fact, that a previous change to the default value, established the value provided by the writer of the call to be the new default value by pure chance, xor 4) the writer of the call was only forced to provide the current default value because his intent was to provide an explicite value to an optional default valued parameter further to the right in the sequence of optional default valued parameters. Now let us assume, that the default value to be imposed on that optional parameter changes with some reason. Above case 3) would not cause any harm. But, arghhh, because of case 4) every lexical occurrence of that call must be checked and it must be decided whether case 3) or case 4) holds. In latter case, the new default value must replace the old default value. Solutions: To avoid case 4: a) sequences of optional parameters that are default valued must be forbidden xor b) introduction of a keyword "forced" that accompanies the provided current default value. In fact this keyword can replace the value at all, and therefore may be better expressed by "currentDefaultEvenIfChangedByANewVersion". More? To avoid case 2: c) Ummm. Differentiating between two empty cases? I see no other solution than that to make one nonempty. What about the version dependent keyword "IAmHappyWithTheDefaultOfVersionXX_YY_ZZ"? d) forbid optional default valued parameters to have no value, which is a contradiction. qed. More? Preliminary conclusion: Optional default valued parameters cause some problems, when it cannot be guaranteed that the default value is unchangeable over time. So long!
Mar 28 2004
prev sibling parent "C. Sauls" <ibisbasenji yahoo.com> writes:
Consider this actual code from a Python project using a port of the C++ 
library, wxWidgets.

The wxFrame class constructor has this prototype:
wxFrame.__init__(self,
   parent,
   id,
   title,
   pos   = wxDefaultPosition,
   size  = wxDefaultSize,
   style = wxDEFAULT_FRAME_STYLE,
   name  = "frame"
)

Leaving this as the typical call:
wxFrame.__init__(self, None, -1, "MyApp")

But making it easier for me to write this one from the project:
wxFrame.__init__(self,
   parent = wxGetApp().GetTopLevelWindow(),
   id     = myMEDIA_WINDOW,
   title  = wxGetApp().GetSubTitle(),
   size   = wxSize(800, 600),
   style  = wxCAPTION | wxMINIMIZE_BOX | wxSYSTEM_MENU | wxFRAME_SHAPED
)

I consider it an immense help, and with the proper documentation its no 
hassle at all.  (Actually the wxPython docs could use major work, and 
yet its still no hassle.)

-C. Sauls
-Invironz
Mar 27 2004