www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Mixins don't quite cut it...

reply Hauke Duden <H.NS.Duden gmx.net> writes:
So here I was and though mixins were powerful enough to help me 
circumvent some of D's other shortcomings. More specifically, I thought 
it would be possible to make the missing default values for function 
arguments a little less painful.

It seems that I was wrong :(. Or maybe I just didn't use them in the 
right way (I fully admit that I don't completely understand the import 
mechanism that is used). Any hints would be appreciated.

I tried to use a mixin that implements the "dummy functions" you need if 
you want to have default values for function arguments. This would be 
especially useful for interfaces, since otherwise you'd have to write 
these dummies for each and every implementation of the interface. I also 
wanted to use a mixin to provide a default implementation for some of 
the "real" functions of the interface. But this combination seems to be 
explosive:

Here's the code I tried to compile:

interface IFoo
{
	void foo(int i);
	void foo(int i,int j);
}

template FooDefaults()
{
	void foo(int i)
	{
		this.foo(i,0);
	}	
}

template FooImpl()
{
	void foo(int i,int j)
	{
	}
}


class Foo : IFoo
{
	mixin FooDefaults;
	mixin FooImpl;	
}


Unfortunately this doesn't compile:

mixinbug.d(9): function foo conflicts with FooImpl!().foo at mixinbug.d(17)
mixinbug.d(11): function foo (int i) does not match argument types (int,int)
mixinbug.d(11): Error: expected 1 arguments, not 2


Why do the two mixins conflict? I sure hope that it is not because they 
have the same name, because obviously the signature is completely different.

This takes a lot of usefulness from the mixins for me. :(


Hauke
May 29 2004
parent reply "Walter" <newshound digitalmars.com> writes:
Think of mixins like imports. Functions imported from different modules do
not overload against each other, they conflict. This is what you're seeing
here. You can overload a function from one scope into another using an
alias:

interface IFoo
{
    void foo(int i);
    void foo(int i,int j);
}

template FooDefaults()
{
    void foo(int i)
    {
 this.foo(i,0);
    }
}

template FooImpl()
{
    void foo(int i,int j)
    {
    }
}


class Foo : IFoo
{
    mixin FooDefaults F1;
    alias F1.foo foo;

    mixin FooImpl F2;
    alias F2.foo foo;
}
May 29 2004
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Walter wrote:

 Think of mixins like imports. Functions imported from different modules do
 not overload against each other, they conflict. This is what you're seeing
 here. You can overload a function from one scope into another using an
 alias:
Hmmm. Ok, now I understand why this happens. I remember trying to persuade you to change this shortcoming for modules a while back ;). Unfortunately the alias workaround isn't much use to me since that would mean I'd still have to write one statement per dummy function :(. I don't know what it is with D and me. I like the overall concepts a lot but every time I think I should give it a new chance and try to implement something I end up running against another wall in the language design. And to make it worse, it is always a "small" design decision. For example, I like the idea of modules, but D becomes unusable for big projects because a module has to be in a single file. I also like mixins but you cannot use them to "mix" yourself an implementation for an interface. I like the fact that it has operator overloading, but oh, the operators for a class all have to be in the same module, making it impossible to add support for new "argument types" of stream classes. I like that it has a bool type but unfortunately and in contrast to one of the goals of this type the bool in D is actually slower than an int and it can be implicitly converted to integers. It seems that my way of programming (often library development with interfaces for abstraction from the implementation, plus lots of default function arguments) is just not compatible with D. At least not the D that we see now. You keep making it better, but I doubt that I'll switch before at least some of the remaining warts are removed. Right now C++ is still better for most of the things I do. Hauke
May 29 2004
next sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
 I also like mixins but you cannot use them to "mix" yourself an
 implementation for an interface. 
Can you explain this more? Is is the overloading? The following example seems to work fine: interface A { void a(); } template B() { void a(){printf("B.a\n");} } class C : A { mixin B; } int main() { C c = new C; c.a(); return 0;}
May 29 2004
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Ben Hinkle wrote:
I also like mixins but you cannot use them to "mix" yourself an
implementation for an interface. 
Can you explain this more? Is is the overloading? The following example seems to work fine: interface A { void a(); } template B() { void a(){printf("B.a\n");} } class C : A { mixin B; } int main() { C c = new C; c.a(); return 0;}
The problem I'm having is that I would like to have one mixin with dummy functions that emulate default values (because these dummies are always the same for all implementations) and another two or more mixins that provide different default implementations for the functions that provide the real functionality. But since the dummy functions have the same name (but a different signature) as the functions in the implementation mixins these two mixins cannot be mixed into the same class. Realworld use: I'd like to provide "building blocks" for interface implementations that allow the implementing class to select alternative partial implementations with different properties and mix them all together to form the full implementation. Here's an example: interface IFoo { void foo(int i); void foo(int i,int j); } template FooDefaults() { void foo(int i) { this.foo(i,0); //always the same for all impls } } template FooFastImpl() { void foo(int i,int j) { //fast implementation with high memory cost } } template FooSmallImpl() { void foo(int i,int j) { //slow implementation that needs little memory } } class MyFoo : IFoo { mixin FooDefaults; //always the same mixin FooFastImpl; //we want the fast alternative } 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. Hauke
May 29 2004
parent reply David L. Davis <SpottedTiger yahoo.com> writes:
In article <c9b26g$i5u$1 digitaldaemon.com>, Hauke Duden says...
Ben Hinkle wrote:
...

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.

Hauke
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?)
May 29 2004
parent reply J C Calvarese <jcc7 cox.net> writes:
David L. Davis wrote:
 In article <c9b26g$i5u$1 digitaldaemon.com>, Hauke Duden says...
 
Ben Hinkle wrote:
...

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.

Hauke
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?)
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/
May 30 2004
next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9d89g$f58$1 digitaldaemon.com>, J C Calvarese says...
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):
What I don't understand, is this. If it's "good" for the compiler to allow:
       void f() { f(0); }
       void f(int n) { /*stuff*/ }
and "bad" for the compiler to allow:
       void f(int n=0) { /*stuff*/ }
Then why can't the compiler simply rewrite the latter as the former before trying to figure out the rules? Just consider it more of that syntactic sugar. 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. Arcane Jill
May 30 2004
next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
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. Hauke
May 30 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
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/
May 31 2004
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
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
Jun 01 2004
parent Regan Heath <regan netwin.co.nz> writes:
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/
Jun 01 2004
prev sibling parent reply Andy Friesen <andy ikagames.com> writes:
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 would rather it be illegal to provide defaults on any method that is an override, including interface implementations. (by extension, then, interfaces would be allowed to provide defaults) -- andy
May 30 2004
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Andy Friesen 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 would rather it be illegal to provide defaults on any method that is an override, including interface implementations. (by extension, then, interfaces would be allowed to provide defaults)
Just to make sure I understand: you mean the override must not specify defaults because it will implicitly inherit the ones from the original defintion, correct? I would prefer that the defaults have to be explicit, but always the same as the original ones. That way they can be seen without having to look at any base classes. 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. If you require the overloads to have the same defaults then this case is automatically handled, because no overload can have the same defaults as both the methods it overrides. I.e. it is not possible to implement both interfaces in the same object, which is the only solution I can see. It would be the same as if the interfaces defined methods with the same parameter lists but different return values. Hauke
May 30 2004
parent reply Andy Friesen <andy ikagames.com> writes:
Hauke Duden wrote:
 Andy Friesen wrote:
 
 I would rather it be illegal to provide defaults on any method that is 
 an override, including interface implementations. (by extension, then, 
 interfaces would be allowed to provide defaults)
Just to make sure I understand: you mean the override must not specify defaults because it will implicitly inherit the ones from the original defintion, correct?
Exactly.
 I would prefer that the defaults have to be explicit, but always the 
 same as the original ones. That way they can be seen without having to 
 look at any base classes.
My first instinct is to agree that a bit of syntactic salt would be a good thing, but, on second thought, it means duplication, which is Very Bad.
 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. -- andy
May 30 2004
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Andy Friesen wrote:
  >> I would prefer that the defaults have to be explicit, but always the
 same as the original ones. That way they can be seen without having to 
 look at any base classes.
My first instinct is to agree that a bit of syntactic salt would be a good thing, but, on second thought, it means duplication, which is Very Bad.
No, duplication is good if the "other copy" is in a different class. Otherwise, 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.
 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()? And how'd you overload these two distinct functions without duplicating the default values? How do you indicate which one to overload? I don't think this can work. 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. Hauke
May 30 2004
parent reply Andy Friesen <andy ikagames.com> writes:
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. Hopefully, it would almost always be an interface or abstract class. (implementation inheritance is scary)
 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. 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 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. I think I see why Walter wanted to leave these out. :) -- andy
May 30 2004
parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
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 30 2004
parent Andy Friesen <andy ikagames.com> writes:
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
May 31 2004
prev sibling parent David L. Davis <SpottedTiger yahoo.com> writes:
*) 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 30 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:c9arki$8uh$1 digitaldaemon.com...
 Walter wrote:

 Think of mixins like imports. Functions imported from different modules
do
 not overload against each other, they conflict. This is what you're
seeing
 here. You can overload a function from one scope into another using an
 alias:
Hmmm. Ok, now I understand why this happens. I remember trying to persuade you to change this shortcoming for modules a while back ;). Unfortunately the alias workaround isn't much use to me since that would mean I'd still have to write one statement per dummy function :(.
The reason that mixins are in a separate scope is so that, for more complex mixins, declarations in it can be 'overridden' in the mixed in scope.
 I don't know what it is with D and me. I like the overall concepts a lot
 but every time I think I should give it a new chance and try to
 implement something I end up running against another wall in the
 language design. And to make it worse, it is always a "small" design
 decision. For example, I like the idea of modules, but D becomes
 unusable for big projects because a module has to be in a single file.
Why are large files a problem? And why can't sub-parts of a large module be put in other modules?
 I
 also like mixins but you cannot use them to "mix" yourself an
 implementation for an interface.
Actually, you can and it does work. (It didn't work in the original implementation because of a, now fixed, compiler bug.)
 I like the fact that it has operator
 overloading, but oh, the operators for a class all have to be in the
 same module, making it impossible to add support for new "argument
 types" of stream classes.
Here I'll argue that stream I/O should not use operator overloading.
 I like that it has a bool type but
 unfortunately and in contrast to one of the goals of this type the bool
 in D is actually slower than an int
I don't think it is slower.
 and it can be implicitly converted
 to integers.
So it can, too, in C++, so that's not a reason to prefer C++ <g>.
 It seems that my way of programming (often library development with
 interfaces for abstraction from the implementation, plus lots of default
 function arguments) is just not compatible with D.
I'll argue here that I think function overloading is greatly overused, but I know I'm in a minority on that.
 At least not the D that we see now. You keep making it better, but I
 doubt that I'll switch before at least some of the remaining warts are
 removed. Right now C++ is still better for most of the things I do.

 Hauke
May 29 2004
next sibling parent reply hellcatv hotmail.com writes:
Why are large files a problem? And why can't sub-parts of a large module be
put in other modules?
For one thing the dmd.exe linker will crash if too many symbols or functions are defined in the file... or too many template instantiations (or I presume mixin instantions) are created in a file
May 29 2004
parent reply "Walter" <newshound digitalmars.com> writes:
<hellcatv hotmail.com> wrote in message
news:c9bhcc$16m4$1 digitaldaemon.com...
 For one thing the dmd.exe linker will crash if too many symbols or
functions are
 defined in the file... or too many template instantiations (or I presume
mixin
 instantions) are created in a file
I suspect that something else is going on there...
May 29 2004
parent reply hellcatv hotmail.com writes:
In article <c9bldd$1bs0$1 digitaldaemon.com>, Walter says...
<hellcatv hotmail.com> wrote in message
news:c9bhcc$16m4$1 digitaldaemon.com...
 For one thing the dmd.exe linker will crash if too many symbols or
functions are
 defined in the file... or too many template instantiations (or I presume
mixin
 instantions) are created in a file
I suspect that something else is going on there...
well I've tested it with many simple and complex examples: it's not just templates...and they all work using gdc http://graphics.stanford.edu/~danielrh/vec.d http://graphics.stanford.edu/~danielrh/manyfuncs.d http://graphics.stanford.edu/~danielrh/close.d http://graphics.stanford.edu/~danielrh/sclass.d on most of these setting version=DontCrash will cause the linker to succeed by truncating some functions (they're all pretty well empty functions causing these crashes)
May 29 2004
parent "Walter" <newshound digitalmars.com> writes:
It happens with the linker when there are more than 16,000 fixups in a
single .obj file. Apparently, it's most likely an overflow of a short in the
linker.
May 30 2004
prev sibling next sibling parent DemmeGod <me demmegod.com> writes:
 Why are large files a problem? And why can't sub-parts of a large module
 be put in other modules?
Unless a package access level was added since I last checked, that would expose subparts that one wouldn't necessarily want exposed.
May 30 2004
prev sibling next sibling parent reply Helmut Leitner <helmut.leitner wikiservice.at> writes:
Walter wrote:
 
 "Hauke Duden" <H.NS.Duden gmx.net> wrote in message
 It seems that my way of programming (often library development with
 interfaces for abstraction from the implementation, plus lots of default
 function arguments) is just not compatible with D.
I'll argue here that I think function overloading is greatly overused, but I know I'm in a minority on that.
I share your opinion about overused function overloading, but I also share Haukes feelings of running against walls. -- Helmut Leitner leitner hls.via.at Graz, Austria www.hls-software.com
May 30 2004
parent "Walter" <newshound digitalmars.com> writes:
"Helmut Leitner" <helmut.leitner wikiservice.at> wrote in message
news:40B98DF6.FEBF47C5 wikiservice.at...
 Walter wrote:
 "Hauke Duden" <H.NS.Duden gmx.net> wrote in message
 It seems that my way of programming (often library development with
 interfaces for abstraction from the implementation, plus lots of
default
 function arguments) is just not compatible with D.
I'll argue here that I think function overloading is greatly overused,
but I
 know I'm in a minority on that.
I share your opinion about overused function overloading, but I also share Haukes feelings of running against walls.
Which walls are yours?
May 30 2004
prev sibling next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Walter wrote:
Think of mixins like imports. Functions imported from different modules
do
not overload against each other, they conflict. This is what you're
seeing
here. You can overload a function from one scope into another using an
alias:
Hmmm. Ok, now I understand why this happens. I remember trying to persuade you to change this shortcoming for modules a while back ;). Unfortunately the alias workaround isn't much use to me since that would mean I'd still have to write one statement per dummy function :(.
The reason that mixins are in a separate scope is so that, for more complex mixins, declarations in it can be 'overridden' in the mixed in scope.
Yes, that is a very important feature too. But that doesn't change the fact limits of the importing algorithm also limit the usefulness of mixins.
I don't know what it is with D and me. I like the overall concepts a lot
but every time I think I should give it a new chance and try to
implement something I end up running against another wall in the
language design. And to make it worse, it is always a "small" design
decision. For example, I like the idea of modules, but D becomes
unusable for big projects because a module has to be in a single file.
Why are large files a problem? And why can't sub-parts of a large module be put in other modules?
There was a big thread about this the other day called "Module with multiple files". The main problem is that when multiple classes need to collaborate with each other, i.e. if they need friend access, then you have to put them into the same file. With some kinds of class libraries that can mean huge files with tens of thousands of lines of code, which is impossible to manage efficiently when you have multiple programmers working on the classes at the same time. A "package" access level would help, as would the ability to split a module into multiple files (for example, the option to use a directory as a module). But the overloading problem also plays into it: if you want to break a module into sub-modules then all overloading functions must be in the same file. This can be counter-intuitive, as it is often more straightforward to put any global functions into the same file as the classes it takes as arguments.
I
also like mixins but you cannot use them to "mix" yourself an
implementation for an interface.
Actually, you can and it does work. (It didn't work in the original implementation because of a, now fixed, compiler bug.)
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
I like the fact that it has operator
overloading, but oh, the operators for a class all have to be in the
same module, making it impossible to add support for new "argument
types" of stream classes.
Here I'll argue that stream I/O should not use operator overloading.
It is the same if you use global functions, since they overload in the same way, so this kind of thing: class Stream; void store(Stream s,String x); <other file> void store(Stream s,MyClass c); doesn't work either. Because of this you cannot add support for, for example, storing new types to a stream class without using runtime polymorphy. And that is a problem because D also has structs which cannot implement interfaces, so you cannot add support for "being stored" to any struct whose base class you cannot control.
I like that it has a bool type but
unfortunately and in contrast to one of the goals of this type the bool
in D is actually slower than an int
I don't think it is slower.
You told me yourself. You said you use "int" as the return type for islower and isupper because having ==0, !=0 semantics usually takes two operations less than having ==0,==1 semantics (as you'd have with bool/bit).
and it can be implicitly converted
to integers.
So it can, too, in C++, so that's not a reason to prefer C++ <g>.
Yes, but C++ is my current language. Switching languages means a lot of work, so D has to offer compelling advantages. It fails to do so with the bool type.
It seems that my way of programming (often library development with
interfaces for abstraction from the implementation, plus lots of default
function arguments) is just not compatible with D.
I'll argue here that I think function overloading is greatly overused, but I know I'm in a minority on that.
Then you need to ask yourself whether you create the language just for yourself or also for the "majority". It is your decision of course, but if other people use lots of overloading and you want them to use your language ... I want to be honest here: most of the stuff I mentioned here is by itself not enough for me to "condemn" the language. Otherwise I wouldn't be posting here. But it adds up. One of the most important issues for me is still the lack of default values for function arguments. To give you an example, I recently wrote a String interface plus different implementations as a "tryout project" for D. That string interface has 48 "real" methods and 36 dummy methods to implement default values (almost all methods have one or two default arguments). So for each implementation you have to write almost twice as many methods as really necessary. My attempts to work around this limitation with mixins were the reason why I kept bumping into the mixin and overloading problems. Hauke
May 30 2004
parent reply "Walter" <newshound digitalmars.com> writes:
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:c9cguf$2hue$1 digitaldaemon.com...
 Why are large files a problem? And why can't sub-parts of a large module
be
 put in other modules?
There was a big thread about this the other day called "Module with multiple files". The main problem is that when multiple classes need to collaborate with each other, i.e. if they need friend access, then you have to put them into the same file. With some kinds of class libraries that can mean huge files with tens of thousands of lines of code, which is impossible to manage efficiently when you have multiple programmers working on the classes at the same time. A "package" access level would help, as would the ability to split a module into multiple files (for example, the option to use a directory as a module).
I'll go review the thread, but at the moment I have a hard time imagining why members should be private when they need to be accessed by tens of thousands of lines of other code. But the package level access sounds like a good feature to add.
 But the overloading problem also plays into it: if you want to break a
 module into sub-modules then all overloading functions must be in the
 same file. This can be counter-intuitive, as it is often more
 straightforward to put any global functions into the same file as the
 classes it takes as arguments.
One can overload functions from different import scopes using the 'alias' capability. I believe this explicit control over function overloading is better than C++ for handling very large programs - in C++ with its global overloading and ADL one can get really lost as to which functions are 'in play' for overloading.
I also like mixins but you cannot use them to "mix" yourself an
implementation for an interface.
Actually, you can and it does work. (It didn't work in the original implementation because of a, now fixed, compiler bug.)
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
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.
 It is the same if you use global functions, since they overload in the
 same way, so this kind of thing:

 class Stream;
 void store(Stream s,String x);

 <other file>
 void store(Stream s,MyClass c);

 doesn't work either. Because of this you cannot add support for, for
 example, storing new types to a stream class without using runtime
 polymorphy. And that is a problem because D also has structs which
 cannot implement interfaces, so you cannot add support for "being
 stored" to any struct whose base class you cannot control.
There's got to be a better way <g>.
I like that it has a bool type but
unfortunately and in contrast to one of the goals of this type the bool
in D is actually slower than an int
I don't think it is slower.
You told me yourself. You said you use "int" as the return type for islower and isupper because having ==0, !=0 semantics usually takes two operations less than having ==0,==1 semantics (as you'd have with
bool/bit). 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.
and it can be implicitly converted
to integers.
So it can, too, in C++, so that's not a reason to prefer C++ <g>.
Yes, but C++ is my current language. Switching languages means a lot of work, so D has to offer compelling advantages. It fails to do so with the bool type.
I have been surprised at the amount of controversy over a bool type (Matthew is solidly in your camp on this, too!). I recall many l-o-n-g threads in newsgroups over the semantics of bool to C years ago.
 I'll argue here that I think function overloading is greatly overused,
but I
 know I'm in a minority on that.
Then you need to ask yourself whether you create the language just for yourself or also for the "majority". It is your decision of course, but if other people use lots of overloading and you want them to use your language ...
A good point. But also consider that I wouldn't have created this newsgroup if I wasn't interested in other peoples' views. D has grown and improved a lot based on feedback from the members here. But the risk D runs in trying to please everyone is becoming a mish-mash of conflicting, overlapping features.
 I want to be honest here: most of the stuff I mentioned here is by
 itself not enough for me to "condemn" the language. Otherwise I wouldn't
 be posting here. But it adds up.
I appreciate you taking the time to post your thoughts on it here.
 One of the most important issues for me is still the lack of default
 values for function arguments. To give you an example, I recently wrote
 a String interface plus different implementations as a "tryout project"
 for D. That string interface has 48 "real" methods and 36 dummy methods
 to implement default values (almost all methods have one or two default
 arguments). So for each implementation you have to write almost twice as
 many methods as really necessary.

 My attempts to work around this limitation with mixins were the reason
 why I kept bumping into the mixin and overloading problems.

 Hauke
May 30 2004
next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Walter wrote:
There was a big thread about this the other day called "Module with
multiple files". The main problem is that when multiple classes need to
collaborate with each other, i.e. if they need friend access, then you
have to put them into the same file. With some kinds of class libraries
that can mean huge files with tens of thousands of lines of code, which
is impossible to manage efficiently when you have multiple programmers
working on the classes at the same time. A "package" access level would
help, as would the ability to split a module into multiple files (for
example, the option to use a directory as a module).
I'll go review the thread, but at the moment I have a hard time imagining why members should be private when they need to be accessed by tens of thousands of lines of other code. But the package level access sounds like a good feature to add.
The members are not really accessed by all the code, of course. Probably only in a couple of places. But the classes can each have a few thousand lines and if they need to access each other's private members then they all have to be in the same file. But if you really add package access this problem is solved. :)
But the overloading problem also plays into it: if you want to break a
module into sub-modules then all overloading functions must be in the
same file. This can be counter-intuitive, as it is often more
straightforward to put any global functions into the same file as the
classes it takes as arguments.
One can overload functions from different import scopes using the 'alias' capability. I believe this explicit control over function overloading is better than C++ for handling very large programs - in C++ with its global overloading and ADL one can get really lost as to which functions are 'in play' for overloading.
Well, when you use alias you always have to manually "prepare" the aliases for all overloaded functions you want to use. That makes it impossible to use two modules in combination by simply importing them both. Having said that, this really is one of the less important points for me. If the function overloading hadn't played into the mixin stuff I tried to pull off to implement default function arguments I wouldn't have mentioned it. As I said in another post, I usually use lots of interfaces, so runtime polymorphy works well enough for me in most situations.
I also like mixins but you cannot use them to "mix" yourself an
implementation for an interface.
Actually, you can and it does work. (It didn't work in the original implementation because of a, now fixed, compiler bug.)
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
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.
Yay! If you do that D will immediately climb a lot higher on my language ranking ladder ;).
I like that it has a bool type but
unfortunately and in contrast to one of the goals of this type the bool
in D is actually slower than an int
I don't think it is slower.
You told me yourself. You said you use "int" as the return type for islower and isupper because having ==0, !=0 semantics usually takes two operations less than having ==0,==1 semantics (as you'd have with
bool/bit). 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.
If a bool is simply a 32 bit value where 0 means false and !=0 means true then no conversion is necessary. Of course, there is some additional overhead when comparing two bool variables because they could both be true but have different values. But in my experience bool variables are very rarely compared to each other. Most of the time they are set to true or false or their true-ness is checked. There is no additional overhead for this. In fact, I believe such a bool allows the compiler to do additional optimizations, like the one you did manually with "islower". Only when the bool is explicitly converted to an int should the compiler perform the conversion !=0 => 1. I think such a bool as a distinct type without implicit conversions to and from integers would be the best possible way to do it.
and it can be implicitly converted
to integers.
So it can, too, in C++, so that's not a reason to prefer C++ <g>.
Yes, but C++ is my current language. Switching languages means a lot of work, so D has to offer compelling advantages. It fails to do so with the bool type.
I have been surprised at the amount of controversy over a bool type (Matthew is solidly in your camp on this, too!). I recall many l-o-n-g threads in newsgroups over the semantics of bool to C years ago.
So why are you surprised? :) I never encountered any situation where I needed to use a bool as an integer in pure C++ or JAVA code. The only thing that comes close is when interfacing with C code that expects an int instead of a bool. But that is mostly a problem of C++ because it is source code compatible with C. D has the opportunity to break with this, since it only needs binary compatibility with C.
I'll argue here that I think function overloading is greatly overused,
but I
know I'm in a minority on that.
Then you need to ask yourself whether you create the language just for yourself or also for the "majority". It is your decision of course, but if other people use lots of overloading and you want them to use your language ...
A good point. But also consider that I wouldn't have created this newsgroup if I wasn't interested in other peoples' views. D has grown and improved a lot based on feedback from the members here. But the risk D runs in trying to please everyone is becoming a mish-mash of conflicting, overlapping features.
I know and I am constantly surprised when you release a new DMD version and a lot of NG ideas are in there. I also realize that you need to try work through all the suggestions to see which features are REALLY needed by many people. But sometimes it seems that there are lots of people in the NG who all agree that something should be changed and there is no comment from you anywhere to be seen. Which doesn't mean that you don't listen, of course, because a month later this feature may very well be in the language. Or it may not because you have never had a problem with it yourself (see switch). Just to avoid misunderstandings: I believe every language should be designed by a single individual, since the compromises you get with design groups are often worse than the simple bad decisions a single person can make. I think your model of "eaves-dropping emperor" is really one of the better ones. But sometimes I wish you'd at least give some feedback when you have been convinced of something, so that we can stop and do something more productive :). A page of features that are on your todo list for a future version of DMD would be great. Hauke
May 30 2004
parent reply "Walter" <newshound digitalmars.com> writes:
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:c9d9v1$hdd$1 digitaldaemon.com...
 Walter wrote:
 One can overload functions from different import scopes using the
'alias'
 capability. I believe this explicit control over function overloading is
 better than C++ for handling very large programs - in C++ with its
global
 overloading and ADL one can get really lost as to which functions are
'in
 play' for overloading.
Well, when you use alias you always have to manually "prepare" the aliases for all overloaded functions you want to use. That makes it impossible to use two modules in combination by simply importing them
both. No, you just need to do one alias per imported name. Not one for each overload of each function. The alias pulls in all the functions of the same name.
 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.
If a bool is simply a 32 bit value where 0 means false and !=0 means true then no conversion is necessary.
Then just use an int. I just don't see what the problem is.
 But in my experience bool variables are very rarely compared to each
 other. Most of the time they are set to true or false or their true-ness
 is checked. There is no additional overhead for this.
And there is none in D.
 In fact, I believe such a bool allows the compiler to do additional
 optimizations, like the one you did manually with "islower". Only when
 the bool is explicitly converted to an int should the compiler perform
 the conversion !=0 => 1.

 I think such a bool as a distinct type without implicit conversions to
 and from integers would be the best possible way to do it.
It just doesn't set well with me that two values of a type can compare 'equal' yet contain entirely different bit patterns.
 I have been surprised at the amount of controversy over a bool type
(Matthew
 is solidly in your camp on this, too!). I recall many l-o-n-g threads in
 newsgroups over the semantics of bool to C years ago.
So why are you surprised? :)
I was surprised then, too. It's just much ado over next-to-nothing. (I argue about this with Matthew, too <g>.) One thing that is clear, though, is that there's no agreement at all.
 I never encountered any situation where I needed to use a bool as an
 integer in pure C++ or JAVA code. The only thing that comes close is
 when interfacing with C code that expects an int instead of a bool. But
 that is mostly a problem of C++ because it is source code compatible
 with C. D has the opportunity to break with this, since it only needs
 binary compatibility with C.
bool has been added to both C and C++, so if there was an obvious semantic meaning for it, such would have been chosen. But there was no consensus on what the 'obvious' semantics should be. People continue to fruitlessly argue about it. I'd rather move on <g>.
 A good point. But also consider that I wouldn't have created this
newsgroup
 if I wasn't interested in other peoples' views. D has grown and improved
a
 lot based on feedback from the members here. But the risk D runs in
trying
 to please everyone is becoming a mish-mash of conflicting, overlapping
 features.
I know and I am constantly surprised when you release a new DMD version and a lot of NG ideas are in there. I also realize that you need to try work through all the suggestions to see which features are REALLY needed by many people. But sometimes it seems that there are lots of people in the NG who all agree that something should be changed and there is no comment from you anywhere to be seen. Which doesn't mean that you don't listen, of course, because a month later this feature may very well be in the language. Or it may not because you have never had a problem with it yourself (see switch).
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!
 Just to avoid misunderstandings: I believe every language should be
 designed by a single individual, since the compromises you get with
 design groups are often worse than the simple bad decisions a single
 person can make.
Design-by-committee suffers from the "vote for my feature and I'll vote for yours" madness. And it still is no guarantee that wretched misfeatures won't get in the language, I submit C++'s 'export' as the canonical example <g>. That said, there is still a time and a place for a standards committee for a language, but that is after it is designed and all major features are in place.
 I think your model of "eaves-dropping emperor" is really one of the
 better ones. But sometimes I wish you'd at least give some feedback when
 you have been convinced of something, so that we can stop and do
 something more productive :). A page of features that are on your todo
 list for a future version of DMD would be great.
I keep thinking I'm done with 1.0 features <g>.
May 30 2004
next sibling parent reply =?iso-8859-1?q?Knud_S=F8rensen?= <knud NetRunner.all-technology.com> writes:
 A good point. But also consider that I wouldn't have created this
newsgroup
 if I wasn't interested in other peoples' views. D has grown and improved
a
 lot based on feedback from the members here. But the risk D runs in
trying
 to please everyone is becoming a mish-mash of conflicting, overlapping
 features.
I know and I am constantly surprised when you release a new DMD version and a lot of NG ideas are in there. I also realize that you need to try work through all the suggestions to see which features are REALLY needed by many people. But sometimes it seems that there are lots of people in the NG who all agree that something should be changed and there is no comment from you anywhere to be seen. Which doesn't mean that you don't listen, of course, because a month later this feature may very well be in the language. Or it may not because you have never had a problem with it yourself (see switch).
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!
 Just to avoid misunderstandings: I believe every language should be
 designed by a single individual, since the compromises you get with
 design groups are often worse than the simple bad decisions a single
 person can make.
Design-by-committee suffers from the "vote for my feature and I'll vote for yours" madness. And it still is no guarantee that wretched misfeatures won't get in the language, I submit C++'s 'export' as the canonical example <g>. That said, there is still a time and a place for a standards committee for a language, but that is after it is designed and all major features are in place.
If not special care at taken the intelligence of a group is often the average of its members. To solve this I have created what I call an eigenpoll. http://all-technology.com/eigenpolls/ If you like I will make one for D suggestions. Knud
May 30 2004
parent Hauke Duden <H.NS.Duden gmx.net> writes:
Knud Sørensen wrote:
 If not special care at taken the intelligence of a group 
 is often the average of its members.
One of my favorite authors (Terry Pratchett) wrote that "the IQ of a mob is the IQ of its dumbest member divided by the number of participants". It is not quite the same for academic working groups, but there is a similar tendency ;). Hauke
May 30 2004
prev sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Walter wrote:
If a bool is simply a 32 bit value where 0 means false and !=0 means
true then no conversion is necessary.
Then just use an int. I just don't see what the problem is.
Because int and bool are completely different types. True bools prevent errors, like the often seen newbie problem "while(x=7)". That would not be possible if "while" required a true boolean.
But in my experience bool variables are very rarely compared to each
other. Most of the time they are set to true or false or their true-ness
is checked. There is no additional overhead for this.
And there is none in D.
Well if there is none then why don't you use bool for islower? It clearly returns a boolean value (true or false), yet you use int because using bool/bit would be slower. If there was a real boolean type then the compiler would have the freedom of doing such optimizations implicitly by just considering any nonzero value as true.
 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? Hauke
May 30 2004
parent "Walter" <newshound digitalmars.com> writes:
"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 30 2004
prev sibling next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
This reply will make a lot of people really really happy!
Walter is thinking about package level acces and default
parameters!

:) :) :)

"Walter" <newshound digitalmars.com> wrote in message
news:c9d6pi$d0l$1 digitaldaemon.com...
 "Hauke Duden" <H.NS.Duden gmx.net> wrote in message
 news:c9cguf$2hue$1 digitaldaemon.com...
 Why are large files a problem? And why can't sub-parts of a large
module
 be
 put in other modules?
There was a big thread about this the other day called "Module with multiple files". The main problem is that when multiple classes need to collaborate with each other, i.e. if they need friend access, then you have to put them into the same file. With some kinds of class libraries that can mean huge files with tens of thousands of lines of code, which is impossible to manage efficiently when you have multiple programmers working on the classes at the same time. A "package" access level would help, as would the ability to split a module into multiple files (for example, the option to use a directory as a module).
I'll go review the thread, but at the moment I have a hard time imagining why members should be private when they need to be accessed by tens of thousands of lines of other code. But the package level access sounds like
a
 good feature to add.

 But the overloading problem also plays into it: if you want to break a
 module into sub-modules then all overloading functions must be in the
 same file. This can be counter-intuitive, as it is often more
 straightforward to put any global functions into the same file as the
 classes it takes as arguments.
One can overload functions from different import scopes using the 'alias' capability. I believe this explicit control over function overloading is better than C++ for handling very large programs - in C++ with its global overloading and ADL one can get really lost as to which functions are 'in play' for overloading.
I also like mixins but you cannot use them to "mix" yourself an
implementation for an interface.
Actually, you can and it does work. (It didn't work in the original implementation because of a, now fixed, compiler bug.)
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
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.
 It is the same if you use global functions, since they overload in the
 same way, so this kind of thing:

 class Stream;
 void store(Stream s,String x);

 <other file>
 void store(Stream s,MyClass c);

 doesn't work either. Because of this you cannot add support for, for
 example, storing new types to a stream class without using runtime
 polymorphy. And that is a problem because D also has structs which
 cannot implement interfaces, so you cannot add support for "being
 stored" to any struct whose base class you cannot control.
There's got to be a better way <g>.
I like that it has a bool type but
unfortunately and in contrast to one of the goals of this type the
bool
in D is actually slower than an int
I don't think it is slower.
You told me yourself. You said you use "int" as the return type for islower and isupper because having ==0, !=0 semantics usually takes two operations less than having ==0,==1 semantics (as you'd have with
bool/bit). 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.


and it can be implicitly converted
to integers.
So it can, too, in C++, so that's not a reason to prefer C++ <g>.
Yes, but C++ is my current language. Switching languages means a lot of work, so D has to offer compelling advantages. It fails to do so with the bool type.
I have been surprised at the amount of controversy over a bool type
(Matthew
 is solidly in your camp on this, too!). I recall many l-o-n-g threads in
 newsgroups over the semantics of bool to C years ago.


 I'll argue here that I think function overloading is greatly overused,
but I
 know I'm in a minority on that.
Then you need to ask yourself whether you create the language just for yourself or also for the "majority". It is your decision of course, but if other people use lots of overloading and you want them to use your language ...
A good point. But also consider that I wouldn't have created this
newsgroup
 if I wasn't interested in other peoples' views. D has grown and improved a
 lot based on feedback from the members here. But the risk D runs in trying
 to please everyone is becoming a mish-mash of conflicting, overlapping
 features.


 I want to be honest here: most of the stuff I mentioned here is by
 itself not enough for me to "condemn" the language. Otherwise I wouldn't
 be posting here. But it adds up.
I appreciate you taking the time to post your thoughts on it here.
 One of the most important issues for me is still the lack of default
 values for function arguments. To give you an example, I recently wrote
 a String interface plus different implementations as a "tryout project"
 for D. That string interface has 48 "real" methods and 36 dummy methods
 to implement default values (almost all methods have one or two default
 arguments). So for each implementation you have to write almost twice as
 many methods as really necessary.

 My attempts to work around this limitation with mixins were the reason
 why I kept bumping into the mixin and overloading problems.

 Hauke
May 30 2004
prev sibling parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
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
Jun 01 2004
next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"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>.
Jun 02 2004
parent Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c9lb8p$2tm2$2 digitaldaemon.com>, Walter says...
"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>.
Like I said, just a wild idea, not a feature request. But optional/default arguments would be really nice, and/or a type safe "va_args" replacement. Here's another wild idea: a typesafe "..." mechanism. I'm sure this needs some massaging for performance et al, but the following class is an example of a possible "va" syntax. Briefly, when a function X uses "...", the system looks for "X_opArg()" overloads to handle the "..." parts. Here it is with extended opCall(): class printf2 { void opCall(int x, ...) { printf("%d: ", x); opArg(...); printf("\n"); } void opCall_opArg(char[] x) { printf("%.*s", x); } void opCall_opArg(double x) { printf("%g", x); } void opCall_opArg(uint x) { printf("%d", x); } void print_two(...); void print_two_opCall(); // and so on } int main() { printf_two printf2 = new printf_two; double dd = 0.345; uint uu = 123; printf2("hello ", dd, " ", uu, "\n"); return 0; } I know, printf() is fast, cout slower, so why use seperate calls. In any case, it would be nice to have some sort of mechanism for this KIND of task, and the function call technique allows a kind of "translation to C object model", because the static type system can already overload in this way. An alternative would be to only allow this for "opCall" and use "opArg" without any special function name prefix. If you need more than one extended function, create inner classes, used as data members, to field the calls. Mostly, I think "..." is currently used for standalone functions anyway, so the hypothetical "printf" here would be a global object or implicit function returning a singleton, etc. But I think whatever mechanism would need to permit multiple such interfaces per class. .. Maybe for D v3.0 (cough)? Kevin
Jun 02 2004
prev sibling parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
Kevin Bealer wrote:

 Since you're thinking about the optionals, I'll mention a "wild idea" I've
 been thinking about. [...]  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)
Before thinking about that too deeply, I would rather go for the full solution of named arguments (like in Python). This certainly is a more intrusive language feature which will not be decided overnight, but in the long run, it just is far more powerful, useful and descriptive than such a hard-to-read extension.
Jun 02 2004
prev sibling parent Derek Parnell <derek psych.ward> writes:
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 30 2004