digitalmars.D - Template default arguments
- Bill Baxter (37/37) May 04 2005 Howdy D folks.
- Uwe Salomon (5/14) May 05 2005 No. In "The C++ Programming Language" from Stroustrup he says that he di...
- Bill Baxter (31/34) May 05 2005 Interesting. So you mean Stroustrup says the method calls would be hard...
- Jan-Eric Duden (5/51) May 06 2005 If I were Stoustroup I would blame the designers of the library.
- Bill Baxter (46/62) May 08 2005 Yeh, I'm not particularly wild about the design of the widget constructo...
- Walter (7/14) May 09 2005 they
- Walter (10/19) May 09 2005 rummage
- Bill Baxter (10/12) May 05 2005 Unless I missed something in the doc, it looks like D handles default te...
- Matthias Becker (20/26) May 10 2005 In the 21st century you just don't have things with many paramters. So y...
- Eugene Pelekhay (9/67) May 06 2005 Hi
- Bill Baxter (8/21) May 06 2005 That is interesting. Yeh, it is very analogous to the structure initial...
Howdy D folks. I've been looking over D a bit, just reading through docs and such at this point. So far it looks very interesting, but I haven't had time to do any actual programming with it yet. Nevertheless, I haven't yet seen mention of the two things that I would most like to see improved in C++, so I thought I would post a couple of messages to the list to see if either this is already supported by D, or could be supported in a future version of D. My first C++ annoyance is template default arguments. This is the easy one to fix. I once had the misfortune of having to define a non-default allocator for all of my STL containers that would do allocation using special shared memory alloc commands on IRIX. It's great that STL makes it possible to do such a thing, but it was a royal pain because the allocator is generally the very last template argument. So that meant everywhere I was using an STL container I had to specify EVERY template argument, even ones where I was happy with the default. For instance take the STL map: map<Key, Data, Compare=someDefault, Alloc=someDefault> In order to define the Alloc parameter, you have to specify the Compare parameter too. That's just a silly syntactical limitation with no real reason for existing. I should be able to specify any of the default arguments I want and leave the others out. Two ways to do this I can think of are: 1) Like many scripting languages, support a keyword style syntax for default arguments. So I could make my map by typing map<MyKey, MyData, Alloc=MyAlloc> 2) Allow a special symbol to be used as an argument that just means "use the default", like: map<MyKey, MyData, :default:, MyAlloc> Actually thinking about it more, the above applies to method calls really too. I always assumed that C++'s inflexible rules for default arguments on methods were justified because of some sort of performance concerns, but I don't see why either of the above couldn't be handled completely at compile time for method calls as well. I'm no compiler writer, though. Maybe there's something I'm missing? I guess C++'s crazy Koenig lookup rules make compiler writer's heads explode quick enough as it is without throwing that into the mix. So how about it? Can D already do this? Could it in the future? Bill Baxter
May 04 2005
Actually thinking about it more, the above applies to method calls really too. I always assumed that C++'s inflexible rules for default arguments on methods were justified because of some sort of performance concerns, but I don't see why either of the above couldn't be handled completely at compile time for method calls as well.No. In "The C++ Programming Language" from Stroustrup he says that he did not want something like that to be possible: someFunc(what, , , does, it, , , mean, , 2); Ciao uwe
May 05 2005
In article <op.sqakdrtq6yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...No. In "The C++ Programming Language" from Stroustrup he says that he did not want something like that to be possible: someFunc(what, , , does, it, , , mean, , 2);Interesting. So you mean Stroustrup says the method calls would be hard to understand if default arguments could specified out of order? Unless there's more to it than you're quoting there, that's a very weak argument. Basically the current default parameter syntax is equivalent to saying: someFunc(what,are,the,rest,of,them,set,to, , , , , ,); except it gets written as someFunc(what,are,the,rest,of,them,set,to); which in my opinion is harder to fully comprehend than your example, because the person who sees the code at the bottom doesn't even have a clue that there *are* a bunch of other hidden parameters being silently tacked on the end. At least the extra commas in your example clue the reader in that there *are* some default values being used. The thing that drives me crazy about using GUI toolkits like wxWidgets or FOX for example, is all the default arguments I have to specify just to modify that one I really want to set. Here's an example widget of a constructor from FOX: FXListBox(FXComposite *p,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=FRAME_SUNKEN|FRAME_THICK|LISTBOX_NORMAL,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=DEFAULT_PAD,FXint pr=DEFAULT_PAD,FXint pt=DEFAULT_PAD,FXint pb=DEFAULT_PAD); Is Bjorn really going to tell me that it's better and more readable if I rummage through the header to dig up all the default values, and type them all in: FXListBox(p,NULL,0,FRAME_SUNKEN|FRAME_THICK|LISTBOX_NORMAL,0,0,0,0,DEFAULT_PAD,DEFAULT_PAD,DEFAULT_PAD,DEFAULT_PAD+1); instead of just doing this: FXListBox(p,,,,,,,,,,,DEFAULT_PAD+1); just so I can change the value of the last default parameter? Personally if I have to read someone else's source code, I'd rather see the latter code than the former. I also don't want to have to be the one that maintains the former and has to keep all those default parameters up to date with the default values as they're specified in the library. --bb
May 05 2005
Bill Baxter wrote:In article <op.sqakdrtq6yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...If I were Stoustroup I would blame the designers of the library. If you need to pass that many parameters a parameter class would certainly help. I'm not sure whats better - a paramter class or named parameters.No. In "The C++ Programming Language" from Stroustrup he says that he did not want something like that to be possible: someFunc(what, , , does, it, , , mean, , 2);Interesting. So you mean Stroustrup says the method calls would be hard to understand if default arguments could specified out of order? Unless there's more to it than you're quoting there, that's a very weak argument. Basically the current default parameter syntax is equivalent to saying: someFunc(what,are,the,rest,of,them,set,to, , , , , ,); except it gets written as someFunc(what,are,the,rest,of,them,set,to); which in my opinion is harder to fully comprehend than your example, because the person who sees the code at the bottom doesn't even have a clue that there *are* a bunch of other hidden parameters being silently tacked on the end. At least the extra commas in your example clue the reader in that there *are* some default values being used. The thing that drives me crazy about using GUI toolkits like wxWidgets or FOX for example, is all the default arguments I have to specify just to modify that one I really want to set. Here's an example widget of a constructor from FOX: FXListBox(FXComposite *p,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=FRAME_SUNKEN|FRAME_THICK|LISTBOX_NORMAL,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=DEFAULT_PAD,FXint pr=DEFAULT_PAD,FXint pt=DEFAULT_PAD,FXint pb=DEFAULT_PAD); Is Bjorn really going to tell me that it's better and more readable if I rummage through the header to dig up all the default values, and type them all in: FXListBox(p,NULL,0,FRAME_SUNKEN|FRAME_THICK|LISTBOX_NORMAL,0,0,0,0,DEFAULT_PAD,DEFAULT_PAD,DEFAULT_PAD,DEFAULT_PAD+1); instead of just doing this: FXListBox(p,,,,,,,,,,,DEFAULT_PAD+1); just so I can change the value of the last default parameter? Personally if I have to read someone else's source code, I'd rather see the latter code than the former. I also don't want to have to be the one that maintains the former and has to keep all those default parameters up to date with the default values as they're specified in the library.
May 06 2005
In article <427B4FA9.5000003 whisset.com>, Jan-Eric Duden says...Bill Baxter wrote:Here's an example widget of a constructor from FOX: FXListBox(FXComposite *p,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=FRAME_SUNKEN|FRAME_THICK|LISTBOX_NORMAL,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=DEFAULT_PAD,FXint pr=DEFAULT_PAD,FXint pt=DEFAULT_PAD,FXint pb=DEFAULT_PAD); Is Bjorn really going to tell me that it's better and more readable if I rummage through the header to dig up all the default values, and type them all in:If I were Stoustroup I would blame the designers of the library. If you need to pass that many parameters a parameter class would certainly help. I'm not sure whats better - a paramter class or named parameters.Yeh, I'm not particularly wild about the design of the widget constructors in FOX either, but I understand the designer's reasoning. It is nice in some ways to be able to have 1 line of code <=> one widget. That way when you go shuffling your UI around moving a widget from here to there is just a matter of moving one line of code. A parameter class would require extra lines of code to set up the parameters and just generally introduce extra superfluous classes. Of course in D you could use a static array initializer and still have one line of code (or are those not implemented yet?). If the D sig was: : FXListBox(FXComposite parent, FXListBoxOptions opts); Then you could call it like: : new FXListBox(parent, [pb:DEFAULT_PAD+1]); Assuming FXListBoxOptions is a struct that has a pb member. That's why I think Eugene's suggestion was so great. Why bother with the struct at all in the above example? FXListBoxOptions is just a placeholder that doesn't really need to be a named entity. It serves no purpose outside of calling this constructor, so why not just do away with it? : new FXListBox(parent, pb:DEFAULT_PAD+1); And use the original signature with all those default values. It acknowledges the fact that both argument lists and structs are lists of type-identifier pairs. (Although structs can contain other structs, whereas argument lists can't contain argument lists.) If you can initialize a struct with identifier-value pairs in D, why not argument lists, too? There is one other small difference, in that argument list generally has some elements that must be 'initialized' (i.e. no default value), whereas structs don't have that. But I don't see why it couldn't work, and work just as well for template argument lists as for method argument lists. Does it make the compiler's job too hard to match calls with the method they invoke when overloading is in the mix? It does mean that these two methods could no longer coexist: real fun(int a=5,string b="hello"); real fun(string b="hello", int a=5); In current C,C++,D those are different methods but a call like fun(a:2,b:"no good") would now be ambiguous. Although I suppose if you just changed the argument names in the second example it wouldn't be ambiguous: real fun(int a=5,string b="hello"); real fun(string c="hello", int d=5); So that's only going to be a problem if you write code that has the exact same types and argument names in different orders, which is probably something you shouldn't be doing anyway. One potential downside is that it would mean that the name of arguments suddenly has significance, unlike in C where you can leave them out entirely. That means user code can break if a library maintainer just renames an argument. Is this one of those cases like the switch statement where Walter doesn't want it to look just like C but act differently? --bb
May 08 2005
"Bill Baxter" <Bill_member pathlink.com> wrote in message news:d5m8a3$2mc6$1 digitaldaemon.com...Does it make the compiler's job too hard to match calls with the methodtheyinvoke when overloading is in the mix? It does mean that these twomethodscould no longer coexist: real fun(int a=5,string b="hello"); real fun(string b="hello", int a=5); In current C,C++,D those are different methods but a call like fun(a:2,b:"no good") would now be ambiguous.I hadn't thought of that, but you're right. It's not an insoluble problem, but it does make the compiler's job of disambiguating overloaded functions significantly harder.
May 09 2005
"Bill Baxter" <Bill_member pathlink.com> wrote in message news:d5d3dc$12jv$1 digitaldaemon.com...Is Bjorn really going to tell me that it's better and more readable if Irummagethrough the header to dig up all the default values, and type them all in:FXListBox(p,NULL,0,FRAME_SUNKEN|FRAME_THICK|LISTBOX_NORMAL,0,0,0,0,DEFAULT_P AD,DEFAULT_PAD,DEFAULT_PAD,DEFAULT_PAD+1);instead of just doing this: FXListBox(p,,,,,,,,,,,DEFAULT_PAD+1); just so I can change the value of the last default parameter? Personally if I have to read someone else's source code, I'd rather seethelatter code than the former. I also don't want to have to be the one that maintains the former and has to keep all those default parameters up todatewith the default values as they're specified in the library.I agree that stinks, but I also put the blame on the design of FXListBox. It should provide a few overloads of that functions that minimize the number of default parameters.
May 09 2005
Unless I missed something in the doc, it looks like D handles default template arguments just like C++. I.e. you can't specify the Nth without specifying all the ones before it too. So c'mon people, I can't be the only one who finds having to manually specify lots of default parameters to be irksome and a completely unnecessary practice in the 21st century. Can I? Can I get at least an 'amen' from the audience? Anyone? Or failing that, at least a compelling argument as to why I'm an idiot. Uwe's appeal-to-authority argument didn't really convince me. --bb In article <d5bt8k$3bd$1 digitaldaemon.com>, Bill Baxter says...My first C++ annoyance is template default arguments. This is the easy one to fix.
May 05 2005
Unless I missed something in the doc, it looks like D handles default template arguments just like C++. I.e. you can't specify the Nth without specifying all the ones before it too.Right.So c'mon people, I can't be the only one who finds having to manually specify lots of default parameters to be irksome and a completely unnecessary practice in the 21st century. Can I?In the 21st century you just don't have things with many paramters. So you can't have things with many default paramters. e.g. group some of the parameters to structs and pass them. A function like gets and is called like: This way you can do things like this: But perhaps you should rething your design in general if you have functions with many arguments. -- Matthias Becker
May 10 2005
Hi On Thu, 05 May 2005 04:35:16 +0300, Bill Baxter <Bill_member pathlink.com> wrote:Howdy D folks. I've been looking over D a bit, just reading through docs and such at this point. So far it looks very interesting, but I haven't had time to do any actual programming with it yet. Nevertheless, I haven't yet seen mention of the two things that I would most like to see improved in C++, so I thought I would post a couple of messages to the list to see if either this is already supported by D, or could be supported in a future version of D. My first C++ annoyance is template default arguments. This is the easy one to fix. I once had the misfortune of having to define a non-default allocator for all of my STL containers that would do allocation using special shared memory alloc commands on IRIX. It's great that STL makes it possible to do such a thing, but it was a royal pain because the allocator is generally the very last template argument. So that meant everywhere I was using an STL container I had to specify EVERY template argument, even ones where I was happy with the default. For instance take the STL map: map<Key, Data, Compare=someDefault, Alloc=someDefault> In order to define the Alloc parameter, you have to specify the Compare parameter too. That's just a silly syntactical limitation with no real reason for existing. I should be able to specify any of the default arguments I want and leave the others out. Two ways to do this I can think of are: 1) Like many scripting languages, support a keyword style syntax for default arguments. So I could make my map by typing map<MyKey, MyData, Alloc=MyAlloc> 2) Allow a special symbol to be used as an argument that just means "use the default", like: map<MyKey, MyData, :default:, MyAlloc>I think first is more preferrable, but with some minor changes to make it more similar to structure initialization syntax. Something like that: : template TFoo(T1 : int, T2 : long, T3 : SomeClass ) {} : TFoo(T2:float) foo; : void func(int a = 0, float b = 3.14) {} : func(b:4);Actually thinking about it more, the above applies to method calls really too. I always assumed that C++'s inflexible rules for default arguments on methods were justified because of some sort of performance concerns, but I don't see why either of the above couldn't be handled completely at compile time for method calls as well. I'm no compiler writer, though. Maybe there's something I'm missing? I guess C++'s crazy Koenig lookup rules make compiler writer's heads explode quick enough as it is without throwing that into the mix. So how about it? Can D already do this? Could it in the future? Bill Baxter
May 06 2005
In article <op.sqclqqox5ljmzl thrash>, Eugene Pelekhay says...That is interesting. Yeh, it is very analogous to the structure initialization situation. There's a list of things, and you want to spefiy some but not others. Is that proper D syntax though? Wouldn't it be: : template TFoo(T1 = int, T2 = long, T3 = SomeClass ) {} : TFoo!(T2:float) foo; --bbTwo ways to do this I can think of are: 1) Like many scripting languages, support a keyword style syntax for default arguments. So I could make my map by typing map<MyKey, MyData, Alloc=MyAlloc>I think first is more preferrable, but with some minor changes to make it more similar to structure initialization syntax. Something like that: : template TFoo(T1 : int, T2 : long, T3 : SomeClass ) {} : TFoo(T2:float) foo; : void func(int a = 0, float b = 3.14) {} : func(b:4);
May 06 2005