www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Key arguments

reply baleog <maccarka yahoo.com> writes:
How can i implement key arguments in D? I want something like this:
--
void f(int x, double y = 2.0, int z = 3);
...
f(1, z:10, y:5.1); // x=1, y=5.1, z=10
f(1, z:10); // x=1, y=2.0, z=10
--
I tried to do this with Variant type and explicit type checking. But it takes a
lot of routine actions. Maybe exists a better way?

Best regards
Jul 13 2008
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"baleog" <maccarka yahoo.com> wrote in message 
news:g5er1d$1p15$1 digitalmars.com...
 How can i implement key arguments in D? I want something like this:
 --
 void f(int x, double y = 2.0, int z = 3);
 ...
 f(1, z:10, y:5.1); // x=1, y=5.1, z=10
 f(1, z:10); // x=1, y=2.0, z=10
 --
 I tried to do this with Variant type and explicit type checking. But it 
 takes a lot of routine actions. Maybe exists a better way?

 Best regards
Downs will reply with a horrid hack involving overloading opAssign for some static instances of some structures and then getting their values in the function, but then you're severely limited since the "parameter" names are globals, and since that's so, you can't have two functions that use the same named parameters executing at the same time, either in a multithreaded fashion or with simple recursion. There's no general purpose way to do it, no.
Jul 14 2008
next sibling parent baleog <maccarka yahoo.com> writes:
Please look at the code where i tried to implement something like Keys
arguments:
---------
U K(T,U,V...)(T key, U default_value, V args) {
  foreach(i,h; args) 
    {
      try {
      	static if(!is(typeof(args[i]) == void[0u]))
	  static if (is(T == typeof(h.keys[0])) && is(U == typeof(h.values[0])))
	    return h[key];
      } catch (Exception e) {
	;
      }
    }
  return default_value;
}

void f(T...)(int x, T args)
{
  
  int y = K("y",0, args);
  double z = K("z", 10.0, args);
  writefln(y);
  writefln(z);

}

unittest
{
  f(1,["y":2], ["z":3.1]); // 2 3.1
  f(1); // 0 10
}
-----
What do you think about this attempt?
Jul 14 2008
prev sibling parent reply downs <default_357-line yahoo.de> writes:
Jarrett Billingsley wrote:
 "baleog" <maccarka yahoo.com> wrote in message
 news:g5er1d$1p15$1 digitalmars.com...
 How can i implement key arguments in D? I want something like this:
 --
 void f(int x, double y = 2.0, int z = 3);
 ...
 f(1, z:10, y:5.1); // x=1, y=5.1, z=10
 f(1, z:10); // x=1, y=2.0, z=10
 --
 I tried to do this with Variant type and explicit type checking. But it
 takes a lot of routine actions. Maybe exists a better way?

 Best regards
Downs will reply with a horrid hack involving overloading opAssign for some static instances of some structures and then getting their values in the function, but then you're severely limited since the "parameter" names are globals, and since that's so, you can't have two functions that use the same named parameters executing at the same time, either in a multithreaded fashion or with simple recursion.
Such abject nonsense. My hack is based on typesystem abuse, not global *variables*. It also doesn't use structs. Basically, the idea is that you typedef double y_parameter; then y_parameter y_p(double d) { return cast(y_parameter) d; } Then just make f a templated function, so that void f(T...)(int x, T t); and check for the presence of a y_parameter in T. Called like so: f(2, y_p = 5f);
Jul 14 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"downs" <default_357-line yahoo.de> wrote in message 
news:g5fsef$p0d$4 digitalmars.com...

 Such abject nonsense. My hack is based on typesystem abuse, not global 
 *variables*
Your face is abject nonsense!
 It also doesn't use structs.

 Basically, the idea is that you typedef double y_parameter; then 
 y_parameter y_p(double d) { return cast(y_parameter) d; }

 Then just make f a templated function, so that void f(T...)(int x, T t); 
 and check for the presence of a y_parameter in T.

 Called like so: f(2, y_p = 5f); 
Jul 14 2008
parent reply downs <default_357-line yahoo.de> writes:
Jarrett Billingsley wrote:
 "downs" <default_357-line yahoo.de> wrote in message 
 news:g5fsef$p0d$4 digitalmars.com...
 
 Such abject nonsense. My hack is based on typesystem abuse, not global 
 *variables*
Your face is abject nonsense!
Verily, I believe it is indeed your maternal parent who possesses this attribute! Ooooh, incinerate.
 It also doesn't use structs.

 Basically, the idea is that you typedef double y_parameter; then 
 y_parameter y_p(double d) { return cast(y_parameter) d; }

 Then just make f a templated function, so that void f(T...)(int x, T t); 
 and check for the presence of a y_parameter in T.

 Called like so: f(2, y_p = 5f); 
Jul 14 2008
next sibling parent reply BCS <ao pathlink.com> writes:
I really hope this is all Tung-in-cheek
Jul 14 2008
parent downs <default_357-line yahoo.de> writes:
BCS wrote:
 I really hope this is all Tung-in-cheek
 
 
Just a gentlemen's disagreement. The kind that sets off wars. :) "Was this the hack that launched a thousand flames / and burnt the threads of this NG?"
Jul 14 2008
prev sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"downs" <default_357-line yahoo.de> wrote in message 
news:g5g29h$146h$1 digitalmars.com...
 Jarrett Billingsley wrote:
 "downs" <default_357-line yahoo.de> wrote in message
 news:g5fsef$p0d$4 digitalmars.com...

 Such abject nonsense. My hack is based on typesystem abuse, not global
 *variables*
Your face is abject nonsense!
Verily, I believe it is indeed your maternal parent who possesses this attribute! Ooooh, incinerate.
GOD YOU BURNED ME SO BAD
Jul 14 2008
prev sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
baleog wrote:
 How can i implement key arguments in D? I want something like this:
 --
 void f(int x, double y = 2.0, int z = 3);
 ...
 f(1, z:10, y:5.1); // x=1, y=5.1, z=10
 f(1, z:10); // x=1, y=2.0, z=10
 --
 I tried to do this with Variant type and explicit type checking. But it takes
a lot of routine actions. Maybe exists a better way?
 
 Best regards
If you have a lot of arguments with various optional arguments that each have their own defaults, I think a struct is the most straightforward solution right now. struct FOptions { double y = 2.0; int z = 3; } void f(int x, FOptions opt) {...} {FOptions opt; opt.z = 10; opt.y = 5.1; f(1, opt); } {FOptions opt; opt.z = 10; f(1, opt); } It would be a lot nicer if static struct initializers worked for non-static structs too. Then you could do: Foptions opt = {z:10}; f(1,opt); Or even f(1,{z:10}); There have been proposals to make struct initializers more useful along these lines. The next step logical step in that evolution would be to recognize a trailing struct argument as a keyword set, and let you call f(1,z:10) as a shortcut for f(1,{z:10}) which would be a shortcut for something like f(1,cast(FOptions){z:10}) which would work if struct initializers didn't have to be static. Walter doesn't seem particularly interested, though. --bb
Jul 14 2008