May 30, 2004
Andy Friesen wrote:
> Hauke Duden wrote:
> 
>> ... when you see a method
>>
>> foo(int a,int b)
>>
>> in a class, how do you know how you can call it? Is there a default value for a or b? What is it?
>>
>> To find out you'd have to look in all base classes and see if they contain a function foo(int,int). That is what I consider bad.
> 
> 
> In almost all cases, this would be the direct parent, the uppermost base class, or an interface.  

How do you come to that conclusion? Inheritance hierarchies can be deep and new functions can be added at any level. Classes can also implement many interfaces. So you'd potentially have to look at many classes or interfaces!


>>>> Also, your system has another problem: what if two interfaces define the same function with different defaults? Then there are two "original" definitions, so this needs to be handled specifically.
>>>
>>>
>>> In such a case, the two functions are distinct, even if they happen to have the same name.  There is no conflict.
>>
>>
>> Urgh!!! So what happens if you have foo(int a=0) and foo(int a=5)? Which default value is chosen when someone calls foo()?
> 
> 
> Waaait a second.  I had no idea that two interfaces could 'overlap' in this way.

Sure. Otherwise you could never implement an interface that inherits from an interface a base class has already implemented.

> Since foo() is the same method for both interfaces, the defaults should necessarily coincide.  If they don't, it's probably a bug anyway. (even if it isn't, it sure looks like one)

I agree.


>> I think the only sensible solution is that different defaults are a conflict and that all overloads must specify the same defaults as the base class function they are overloading. It is easy to read, immediately understandable, typos are caught at compile time and function calling is unambiguous.
> 
> 
> It has real potential to be a maintenance nightmare if a default has to change, however.

Well, I think if you ever need to change a default then it IS already a maintenance nightmare. Because all the calling code will have been written with the old default you'd have to review every piece of code where the function is called to see if it still applies to the new one. Going through all base classes doesn't add much to that.

Anyway, in all my years of programming C++, I don't remember ever changing a default value. The default is not any arbitrary value, it is what you need to pass to the function if you don't really want to USE the parameter. That kind of value doesn't change as long as the function's task doesn't change.


Hauke
May 31, 2004
*) Ben Hinkle: ... The problem stems from the fact that FooDefaults defines dummies for almost all function names in IFoo. So this makes it impossible to use a mixin to implement the real functions. Of course, this problem wouldn't occur in this particular case if D would support default values for function arguments. It is a good example how the need to "hack" to get default arguments without copying huge chunks of code causes problems in other areas.
------------

*) David L. Davis [reply to Ben]: I agree, I too think that "D" should "support default values for function arguments." I use then all the time in Visual Basic 6.0, and I can't image not having them in a new modern programming langauge. Course when I program in "C" I don't have this functionally, but when I recently started taking a closer look at "D", I've been poking around in the "D" html help information looking for this...now I know why I haven't found it yet. :( (I haven't looked at C++ in a long while, but doesn't it have default values for function parameters?)
------------

*) J C Calvarese [reply to David]:
If you're talking about doing something like this...
void foo(int x, int y = 3) { ... }

You can emulate it with something like this...
void foo(int x, int y) { ... }
void foo(int x) { foo(x, 3); }

I'd prefer to do it directly, too, but Walter has some concerns. I've collected some previous threads here (in case you want to review the previous discussions):

http://www.wikiservice.at/d/wiki.cgi?FeatureRequestList/DefaultArguments

-- 
Justin (a/k/a jcc7)
http://jcc_7.tripod.com/d/
------------

J C Calvarese: Thanks for the reply. I'll keep a note of the above emulation approach in mind for current needs, but it does look like "D" will support "default function arguments" directly in some future build. Below is a potion of the thread, title: "Re: Mixins don't quite cut it..." dated: "Sun, 30 May 2004 10:45:08 -0700" where it looks like Walter has been listening to the forum about this issue, and it sounds like to me that he's going to add "default function arguments" to "D!" :)) If this is truly the case, then this is really "Great News!" <g>

-----------
<default function arguments portion>

Hauke Duden:"I'm talking about DMD 0.91 here. The problem appears when you try to have different mixins that provide functions with the same name but different signatures. Again, the importing algorithm is the culprit. And the reason I wanted to do this is to provide a mixin with the 'dummy' functions you need to write to get default values for function arguments. This is all described in more detail in my another of my posts: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/2456"

Walter [reply to Hauke]:"Seeing the lengths people go to try to emulate default function arguments makes it pretty obvious that I need to add it to the language, I'd underestimated it."

</default function arguments portion>
-------------


May 31, 2004
On Sat, 29 May 2004 16:58:52 -0700, Walter wrote:

[snip]

> Why are large files a problem?

The problem I have with large files is how to enable a group of developers to independantly and simultaneously modify sections of it without losing something. If only one coder can check-out the file at a time, I have others in the team waiting on that coder to check it in again. If I allow multiple checkouts, then there are issues about merging check ins without making mistakes. This can be quite a time-consuming manual effort.

A set of smaller files that together make a single 'module' is a much more practical solution for a team of coders.

Right now, I have a large file (33,400 lines) that I would *love* to split up so that I can have a team of coders simultaneously working on various parts.

-- 
Derek
31/May/04 11:53:10 AM
May 31, 2004
"Hauke Duden" <H.NS.Duden@gmx.net> wrote in message news:c9dm9m$120g$1@digitaldaemon.com...
> > The problem is I'm a thousand or two messages behind in reading the n.g. Even when I do post replies, that frequently inspires a whole ream of
new
> > postings. So the more I read and post, the further I get behind. I'm currently trying to wrap up reading the January postings. I'm not complaining, however, since the huge volume of messages is a wonderful
sign
> > of the health of the D community!
>
> Would it help if volunteers posted summaries of dead threads? Presenting all arguments and counter-arguments in a condensed manner?

I think you'll find that's more than a full time job <g>.


May 31, 2004
Hauke Duden wrote:
> Andy Friesen wrote:
> 
>> In almost all cases, this would be the direct parent, the uppermost base class, or an interface.  
> 
> 
> How do you come to that conclusion? Inheritance hierarchies can be deep and new functions can be added at any level. Classes can also implement many interfaces. So you'd potentially have to look at many classes or interfaces!

I meant that having such a heirarchy is a bad sign in and of itself, but I'm not so sure now.  I myself tend to avoid implementation inheritance like the plague, leading to relatively flat object heirarchies.  It's certainly the most effective way for *me* to think, but I shouldn't be so quick to assume it's the best approach for every problem.

> I think if you ever need to change a default then it IS already a maintenance nightmare. Because all the calling code will have been written with the old default you'd have to review every piece of code where the function is called to see if it still applies to the new one. Going through all base classes doesn't add much to that.

Come to think of it, it's no more or less of a hassle than any other change one might make to an interface.

blah.  All this thinking is leading me back to the conclusion that overloaded methods solve the problem better, if a tad more verbosely. :)

 -- andy
June 01, 2004
On Sun, 30 May 2004 20:54:10 +0200, Hauke Duden <H.NS.Duden@gmx.net> wrote:
> Arcane Jill wrote:
>> I also concur with the person on wiki who suggested that all functions with
>> default arguments be implicitly final. (Or even explicitly, if you really want
>> to make a point). Overloading is common, and default arguments are common, but
>> overloading and default arguments at the same time are rare enough that this is
>> unlikely to be much of a problem.
>
> I completely disagree! Default arguments are even more needed for interfaces than for normal classes, since without them EVERY implementation has to include all the dummy functions.
>
> A better rule would be that all overloads simply have to define the same default arguments. The default shouldn't change depending on the context in which the function is called anyway.

Why not say:

"Overloads must specify a default value for every parameter in the overloaded function(s) that have default value(s)."

So if you have foo(int a=0, int b) and foo(int a, int b=6) you must specify defaults for both a and b i.e. foo(int a=1, int b=2)

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
June 01, 2004
Regan Heath wrote:
> On Sun, 30 May 2004 20:54:10 +0200, Hauke Duden <H.NS.Duden@gmx.net> wrote:
> 
>> Arcane Jill wrote:
>>
>>> I also concur with the person on wiki who suggested that all functions with
>>> default arguments be implicitly final. (Or even explicitly, if you really want
>>> to make a point). Overloading is common, and default arguments are common, but
>>> overloading and default arguments at the same time are rare enough that this is
>>> unlikely to be much of a problem.
>>
>>
>> I completely disagree! Default arguments are even more needed for interfaces than for normal classes, since without them EVERY implementation has to include all the dummy functions.
>>
>> A better rule would be that all overloads simply have to define the same default arguments. The default shouldn't change depending on the context in which the function is called anyway.
> 
> 
> Why not say:
> 
> "Overloads must specify a default value for every parameter in the overloaded function(s) that have default value(s)."
> 
> So if you have foo(int a=0, int b) and foo(int a, int b=6) you must specify defaults for both a and b i.e. foo(int a=1, int b=2)


The overload must not change the default values, otherwise you get lots of weirdness, like the function call behaving differently depending on the type of the object reference (i.e. a call with a base class reference would have different defaults than the same call with a subclass reference). It is also useless because defaults are not arbitrary values, so they don't change.

I'm more and more convinced that the best solution is to have the simple rule:
All overloads must specify exactly the same defaults as the original method.

That way all cases are handled well, there is no ambiguity, it is easy to read and easy to understand.

Hauke

June 01, 2004
On Tue, 01 Jun 2004 11:01:23 +0200, Hauke Duden <H.NS.Duden@gmx.net> wrote:
> Regan Heath wrote:
>> On Sun, 30 May 2004 20:54:10 +0200, Hauke Duden <H.NS.Duden@gmx.net> wrote:
>>
>>> Arcane Jill wrote:
>>>
>>>> I also concur with the person on wiki who suggested that all functions with
>>>> default arguments be implicitly final. (Or even explicitly, if you really want
>>>> to make a point). Overloading is common, and default arguments are common, but
>>>> overloading and default arguments at the same time are rare enough that this is
>>>> unlikely to be much of a problem.
>>>
>>>
>>> I completely disagree! Default arguments are even more needed for interfaces than for normal classes, since without them EVERY implementation has to include all the dummy functions.
>>>
>>> A better rule would be that all overloads simply have to define the same default arguments. The default shouldn't change depending on the context in which the function is called anyway.
>>
>>
>> Why not say:
>>
>> "Overloads must specify a default value for every parameter in the overloaded function(s) that have default value(s)."
>>
>> So if you have foo(int a=0, int b) and foo(int a, int b=6) you must specify defaults for both a and b i.e. foo(int a=1, int b=2)
>
>
> The overload must not change the default values, otherwise you get lots of weirdness, like the function call behaving differently depending on the type of the object reference (i.e. a call with a base class reference would have different defaults than the same call with a subclass reference). It is also useless because defaults are not arbitrary values, so they don't change.

You're stating/assuming the default never changes, even in derived classes. Why does that have to be the case?

What is wrong with have a default initial size in a storage class, deriving a specialised version of that storage class from it and setting a different default initial size?

> I'm more and more convinced that the best solution is to have the simple rule:
> All overloads must specify exactly the same defaults as the original method.
>
> That way all cases are handled well, there is no ambiguity, it is easy to read and easy to understand.
>
> Hauke
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
June 02, 2004
In article <c9d6pi$d0l$1@digitaldaemon.com>, Walter says... .
>Seeing the lengths people go to try to emulate default function arguments makes it pretty obvious that I need to add it to the language, I'd underestimated it.

Argument Stanzas

Since you're thinking about the optionals, I'll mention a "wild idea" I've been thinking about.  Often it would be great to have optional parameters but there are multiple parameters that should be independantly optional.

foo(int x, int y, int z = 0, int p, int q, int r = 3);

In C++ this is impossible.  My suggestion is that argument lists could be broken up into "stanzas" using ";".  Maybe each set is grouped by function.

foo(int x, int y, int z = 0; int p, int q, int r = 3);

Called like this:

foo(1, 2, 3; 4, 5, 6)

Or:

foo(1, 2; 4, 5)

Each "stanza" can have however many optional parameters at the end.  So if the first stanza corresponds to coordinates, and the second to socket parameters, I can extend either independantly.  Conceptually, it's more like this:

<-> foo(int x, int y, int z = 0;
<->     int p, int q, int r = 3);

This could still be done during function argument matching and should be about the same implementation as regular optional parameters, (assuming the C++ idiom of inserting defaults in the calling function's argument list.)

As normal arguments are to a list, so stanzas are to several lists.

So naturally, if the last stanza contained ONLY optional parameters, it could be omitted, and so on.

My only reservation is that syntax may be ambiguous, although I can't see where it breaks.  Whaddaya think?

Kevin


>That's to create a bool from an int. This overhead isn't there once it is a bool. I don't know of any conceivable implementation of bool (and that includes C++'s bool) that doesn't have this overhead in converting to a bool.

There are equivalences in the math; if true means nonzero, you can use "|" for "||".  If false means "!= -1", you could use "&" for "&&".  Sadly, no middle ground, which suggests to me that there IS no mathematical solution.  Maybe use the high bit to indicate true and the low bit for false?  I'm kidding.

Kevin


June 02, 2004
"Kevin Bealer" <Kevin_member@pathlink.com> wrote in message news:c9jt8i$pfv$1@digitaldaemon.com...
> My only reservation is that syntax may be ambiguous, although I can't see
where
> it breaks.  Whaddaya think?

There's no technical problem with it, but I'd want to see more demand for it first <g>.