digitalmars.D.learn - Default Argument Improvements?
- Brian Byrne (42/42) Jan 30 2007 Hello,
- Whyn Oop (20/21) Feb 01 2007 The reason might be as trivial as run time complexity: I assume that suc...
- Brian Byrne (13/16) Feb 01 2007 I can't imagine there being much added complexity considering the progra...
- Frits van Bommel (5/11) Feb 01 2007 Those assignments always set the variables to in_*.
- Brian Byrne (4/8) Feb 01 2007 Ah yes, good call! Forgot about that. :)
- Whyn Oop (6/7) Feb 02 2007 Please, just describe informally how a maintainer would have to
- Brian Byrne (6/17) Feb 04 2007 Well, I guess it largely depends on your coding style. It may be a good ...
Hello, One of the things that annoyed me in C++ was when I had a base class constructor with which I wanted to supply default argument(s) for, but then have a derived class with one or more extended parameters (no default value) on top of the base's parameters. It's impossible to append the derived class's new parameter(s) to the end of the base's while keeping the same order since the original default parameter is wrenched in there. Example: class A { this( int x, int y = 0 ) { ... } } class B : A { this( int x, int y, int z ) { // Same parameter order super( x, y ); ... } this( int x, int z ) { // Requires duplication of function super( x ); // to get default argument effect ... } } Of course this applies in the general case not limited to member constructors. Is there a reason that default arguments must be at the end of a function? Why not allow: void foo( int a, int b = 0, int c ) { ... } Which could be called by: foo( 5, , 10 ); // empty gap for default foo( 5, void, 10 ); // or more explicit foo( 5, ..., 10 ); // or can the ellipsis be unambiguously used? To extend it even further, what if I had foo overloaded: void foo( int a, real b = 1.5, int c ) { ... } Then the above calling methods would be problematic. Could inserting the type in the calling statement be used to disambiguate the functions? foo( 5, int, 10 ); // matches foo(int, int, int); a = 5, b = 0, c = 10 foo( 0, real, 20 ); // matches foo(int, real, int); a = 0, b = 1.5, c = 20 and likewise going back to just having the first foo function: foo( 5, auto, 10 ); // matches foo(int, int, int) From my starting example with classes A and B, I wouldn't be helped much in filling out parameter y in B's constructor. But maybe something along these lines could work?: class B : A { // This part is probably really, really broken,.. but the idea exists const int DEF_Y = ParameterTypeTuple!( super.this )[ 1 ].init; this( int x, int y = DEF_Y, int z ) { // Same parameter order super( x, y ); ... } } This needs a lot more thought than I put into it, but if anything I'd just like to know why mid-list default arguments aren't supported. I'm sure the reason is probably trivial and I overlooked it. :) Thanks, Brian Byrne
Jan 30 2007
Brian Byrne Wrote:I'm sure the reason is probably trivial and I overlooked it. :)The reason might be as trivial as run time complexity: I assume that such improvements would bring the compiler at least much closer to the class of problems, which are believed to not be solvable in polynomial runtime. This in turn would largely disable any maintainabilty. Please note, that currently every defaulted parameter actually is a shorthand, which frees the coder from the work of writing one more signature. Allowing defaulted parameters everywhere would free the coder from writing about half of the otherwise required signatures for each of those parameters. These further request can be forseen: - not beeing forced to assign to the i-th defaulted parameter by mentioning all previous defined deafulted parameters. I.e. something like: f( f.default[9]=2) instead of f( int, int ,int , int ,real, int,double, float, char, 2) - not being forced to know the exact position of a defaulted parameter by naming them explicitely. I.e. something like f( f.default.x=2) instead of f( f.default[9]=2) - ...
Feb 01 2007
Whyn Oop Wrote:The reason might be as trivial as run time complexity: I assume that such improvements would bring the compiler at least much closer to the class of problems, which are believed to not be solvable in polynomial runtime.I can't imagine there being much added complexity considering the programmer is explicitly stating when he wants a default argument to be used. All the compiler has to do is perform a function lookup, being wary of any ambiguity, and inserting that default argument's value in the function call. Another [trivial] example could be for some given Vector4f class, Vector4f set( float in_x = float.nan, float in_y = float.nan, float in_z = float.nan, float in_w = float.nan ) { x = ( in_x == float.nan ) ? x : in_x; y = ( in_y == float.nan ) ? y : in_y; z = ( in_z == float.nan ) ? z : in_z; w = ( in_w == float.nan ) ? w : in_w; } Vector4f vec = Vector4f( 1.0, 2.0, 3.0, 4.0 ); vec.set( 100.0, , 300.0, 400.0 ); // vec == Vector4f( 100.0, 2.0, 300.0, 400.0 ) Handy, no? Brian Byrne
Feb 01 2007
Brian Byrne wrote:Vector4f set( float in_x = float.nan, float in_y = float.nan, float in_z = float.nan, float in_w = float.nan ) { x = ( in_x == float.nan ) ? x : in_x; y = ( in_y == float.nan ) ? y : in_y; z = ( in_z == float.nan ) ? z : in_z; w = ( in_w == float.nan ) ? w : in_w; }Those assignments always set the variables to in_*. The funny thing about NaNs: all normal comparisons return false. Use std.math.isnan(in_x) instead of (in_x == float.nan) if you prefer code that works ;).
Feb 01 2007
Frits van Bommel Wrote:Those assignments always set the variables to in_*. The funny thing about NaNs: all normal comparisons return false. Use std.math.isnan(in_x) instead of (in_x == float.nan) if you prefer code that works ;).Ah yes, good call! Forgot about that. :) Thanks for the heads up, Brian Byrne
Feb 01 2007
Brian Byrne Wrote:Handy, no?Please, just describe informally how a maintainer would have to evaluate the meaning of such codelines: f(,,,4,2); f(,,4.2);
Feb 02 2007
Whyn Oop Wrote:Brian Byrne Wrote:Well, I guess it largely depends on your coding style. It may be a good idea to explicitly state it in your code that you are going to use default parameters in this case. f( auto, auto, auto, 4, 2 ); f( auto, auto, 4.2 ); Similarity still exists, but the goal is much more explicit now. Brian ByrneHandy, no?Please, just describe informally how a maintainer would have to evaluate the meaning of such codelines: f(,,,4,2); f(,,4.2);
Feb 04 2007