March 27, 2004
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
March 27, 2004
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/
March 27, 2004
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;
}

March 27, 2004
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/
March 27, 2004
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/
March 27, 2004
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
March 27, 2004
"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 has it. I don't know about C#. And I bet most struct opCall "constructors" could be removed if we had a syntax as nice as the static initialization syntax.



March 27, 2004
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
>has it. I don't know about C#. And I bet most struct opCall "constructors"
>could be removed if we had a syntax as nice as the static initialization
>syntax.
>

-- 
-Anderson: http://badmama.com.au/~anderson/
March 28, 2004
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

March 28, 2004
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!