digitalmars.D - this is almost a workaround for the lack of named parameters
- J (31/31) Mar 21 2013 #!/usr/bin/rdmd
- J (4/4) Mar 21 2013 // CORRECTION:
- J (31/31) Mar 21 2013 /* Similarly but different (here I am instantiating a new
- J (6/6) Mar 22 2013 The bigger point here is more profound: it is trivial to
- J (76/82) Mar 22 2013 With credit for inspiration to David Medlock in this post--
- Jacob Carlborg (6/76) Mar 22 2013 Here's my proposal for anonymous structs that can be used as name
- foobar (3/92) Mar 22 2013 WTF? What do kwargs have to do with programming? Sounds more like
- John Colvin (4/118) Mar 22 2013 kwargs = keyword arguments
- foobar (7/13) Mar 22 2013 That was meant more as a rhetorical question rather than a real
- John Colvin (5/20) Mar 22 2013 Kwarg seems a reasonable name, consistent with a pre-existing
- foobar (7/29) Mar 23 2013 Your read it wrong. Not aggression but rather annoyment.
- bearophile (6/8) Mar 23 2013 Have you used a language where the usage of named arguments is
- John Colvin (7/15) Mar 23 2013 A simple example is matplotlib.pyplot.plot
- Jacob Carlborg (6/11) Mar 23 2013 I've heard it was a big boost for C# when it got support for default
- foobar (5/19) Mar 25 2013 AFAIK, this is only relevant or useful for COM (i.e. to support
- deadalnix (4/23) Mar 23 2013 Can't the monadic style thing do the trick ?
- J (10/35) Mar 23 2013 Good point, and I'm sure we all develop our personal sense of
- timotheecour (32/36) Mar 23 2013 I updated
- Philippe Sigaud (8/10) Mar 24 2013 The last time I tried this (maybe 2 years ago, so before
- Jacob Carlborg (4/8) Mar 24 2013 That would requires compile time values, i.e. no variables.
- Philippe Sigaud (2/7) Mar 24 2013 You're right.
- Jacob Carlborg (26/42) Mar 24 2013 What would be nice is to be able to do like this:
- Jacob Carlborg (4/8) Mar 24 2013 BTW, why was the constructor added to Proxy and the "dummy" argument?
- timotheecour (36/38) Mar 24 2013 because I wanted to simplify syntax from 'auto
- Jacob Carlborg (5/21) Mar 24 2013 I'm using Thunderbird and just using "Reply to the message".
- a a (2/3) Mar 24 2013 using gmail but doesn't work... (testing again via this message...) pls
- Jacob Carlborg (4/6) Mar 25 2013 I got this.
- foobar (16/24) Mar 25 2013 "idiomatic" is a relative term, tightly coupled to a specific
- bearophile (15/31) Mar 25 2013 Imperative/OOP languages are not totally different from each
- foobar (11/43) Mar 25 2013 C is a HORRIBLE language regarding naming conventions and is a
- deadalnix (9/15) Mar 22 2013 Question for specialists of the topic : are parameter name
- Dicebot (1/1) Mar 22 2013 http://dlang.org/phobos/std_traits.html#.ParameterIdentifierTuple
- deadalnix (2/3) Mar 22 2013 Seems to me like a solved problem.
- timotheecour (18/18) Mar 22 2013 so i hacked up a working solution yesterday.
- deadalnix (7/25) Mar 22 2013 Don't have time to look at the code now, but it seems awesome !
- Dmitry Olshansky (6/40) Mar 22 2013 Can opDispatch & chaining be leveraged to get the effect of:
- Jacob Carlborg (6/8) Mar 23 2013 Here you go:
- J (3/4) Mar 22 2013 Thanks, but this is a non-solution.
- Jacob Carlborg (5/5) Mar 21 2013 On 2013-03-21 19:35, J wrote:
- bearophile (9/11) Mar 21 2013 Maybe such two links should go in one page of the D wiki about
- Jacob Carlborg (6/11) Mar 21 2013 What do you think about my suggestion for anonymous structs as named
- bearophile (13/15) Mar 21 2013 You show code like:
- Jacob Carlborg (4/14) Mar 22 2013 This is not a tuple, it's an anonymous struct.
- J (22/25) Mar 21 2013 Intriguing, Jacob! I could learn alot about reflection by
- Jacob Carlborg (4/24) Mar 21 2013 It's been quite a while since I tested that code. I'll see what I can do...
- Jacob Carlborg (14/14) Mar 25 2013 On 2013-03-21 19:35, J wrote:
- J (3/15) Mar 25 2013 +1000
- J (64/86) Mar 26 2013 Wow. This is really nice! I added a method to Michel's nice
- renoX (8/13) Mar 26 2013 Interesting, the "doesn't not support passing the arguments out
- Jacob Carlborg (6/11) Mar 26 2013 I would guess it was easier. At least the change is very small. Smaller
- J (24/36) Mar 26 2013 Tested this. Seems to work fine with optional parameters.
- Timothee Cour (47/48) Mar 26 2013 Named parameters are only interesting if we can skip some optional param...
- J (7/9) Mar 26 2013 Another thing to check is whether there is enough information in
- J (4/14) Mar 26 2013 Or maybe there are no link time issues. If named parameters are
void main(string[] arg) { // Observation: I'd like to say: /* auto r = myfunc.call("named") with { z= 2; x = -123; y = 200; } */ // and have it turned into this: with(myfunc) { x = -123; y = 200; z = -20; } auto r = myfunc.call("named"); // Q: is there some way to achieve this? Maybe a variation on with? // Is there a macro facility lurking someplace? Or is there another way to do this? // Thanks! // - J } import std.stdio; struct myfunc_ { // named keyword or named parameters // --the call arguments and their defaults int x=0; int y=0; int z=0; string call(string non_keyword_arg) { writefln("%s: X %s, Y %s, Z %s", non_keyword_arg, x, y, z ); return "yo"; } } myfunc_ myfunc;
Mar 21 2013
// CORRECTION: // and have it turned into this: with(myfunc) { z =2; x = -123; y = 200; } auto r = myfunc.call("named");
Mar 21 2013
/* Similarly but different (here I am instantiating a new struct before the call, rather than re-using a global single struct each time), it would be lovely and elegant to say: */ void main(string[] arg) { /* Elegant: auto r = myfunc() with { z= 2; x = -123; y = 200; } */ // and have it lowered to: myfunc tmp; with(tmp) { z= 2; x = -123; y = 200; } auto r = tmp(); } import std.stdio; struct myfunc { // named keyword or named parameters // --the call arguments and their defaults int x=0; int y=0; int z=0; // opCall is sweet... improves upon previous example string opCall(string required_positional_arg = "default pos arg value") { writefln("%s: X %s, Y %s, Z %s", required_positional_arg, x, y, z ); return "yo"; } }
Mar 21 2013
The bigger point here is more profound: it is trivial to implement named parameters using structs + trivial lowerings, and this is no way conflicts with function overloading. D deserves to have named parameters to functions -- it makes for much more legible code, and obviates the need for slow builder patterns. Readable and speedable. It's win-win.
Mar 22 2013
With credit for inspiration to David Medlock in this post-- http://forum.dlang.org/thread/d9lnrr$26q3$1 digitaldaemon.com ... // Tongue firmly in cheek, I'd like to introduce // the NAPAPISS principle: (with apologies to SFINAE and RAII) // NAPAPISS = NAmed Parameters Are simply Passed in a Struct, Silly. // Yes, indeed, maybe this is what happens after drinking too much of // the fine wine products from the Napa valley... you start having // wild flights of fancy of how D might surprisingly soon have // named parameters.... import std.stdio; import std.c.stdlib; void main(string[] arg) { // this works today: but with the drawback that the // named params must be known at compile time... // Here is a named param call, // as compact as I could get it (see struct below for actual definition). auto a = myfunc!q{ z= 2; x = -123; y = 200 }(0)(); // calls opCall writeln("a=", a); // prints "a=yo", as returned from opCall // And here's the runtime version, unfortunately you have to // pre-declare g because otherwise it won't survive the scope, and // the return value from myfunc.opCall would become inaccessible. string g; with(myfunc!()(0)) { x=rand() % 40; y=x/2; z=y/2; g = call(); // as a side effect, prints 'X 7, Y 3, Z 1' } writeln("g=", g); // prints "g=yo", as returned from opCall /* // The bright future: this demonstrates that // it would be fairly trivial to make some kind of annotation // like kwarg or whaterver, to indicate that a function // was using this calling convention: kwarg string f(int a, string b) { body; } // so that kwarg function definitions are lowered to: struct f_kw { int a; string b; string f() { body; } } // and calls to kwarg functions are transformed // from this: auto r = f(a=5, b="good"); // into this: f_kw tmp34; tmp34.a = 5; tmp34.b = "good"; auto r = tmp34.f(); // the benefit: named parameters can be used in a natural way, // and they need be known only at runtime. */ } // how the 'works today' above examples were implemented: struct myfunc(string init_string="") { // named keyword or named parameters // --the call arguments and their defaults int x=0; int y=0; int z=0; this(int) {} string opCall() { mixin(init_string ~ ";"); writefln("X %s, Y %s, Z %s", x, y, z ); return "yo"; } alias opCall call; } On Friday, 22 March 2013 at 09:18:33 UTC, J wrote:The bigger point here is more profound: it is trivial to implement named parameters using structs + trivial lowerings, and this is no way conflicts with function overloading. D deserves to have named parameters to functions -- it makes for much more legible code, and obviates the need for slow builder patterns. Readable and speedable. It's win-win.
Mar 22 2013
On 2013-03-22 11:17, J wrote:With credit for inspiration to David Medlock in this post-- http://forum.dlang.org/thread/d9lnrr$26q3$1 digitaldaemon.com ... // Tongue firmly in cheek, I'd like to introduce // the NAPAPISS principle: (with apologies to SFINAE and RAII) // NAPAPISS = NAmed Parameters Are simply Passed in a Struct, Silly. // Yes, indeed, maybe this is what happens after drinking too much of // the fine wine products from the Napa valley... you start having // wild flights of fancy of how D might surprisingly soon have // named parameters.... import std.stdio; import std.c.stdlib; void main(string[] arg) { // this works today: but with the drawback that the // named params must be known at compile time... // Here is a named param call, // as compact as I could get it (see struct below for actual definition). auto a = myfunc!q{ z= 2; x = -123; y = 200 }(0)(); // calls opCall writeln("a=", a); // prints "a=yo", as returned from opCall // And here's the runtime version, unfortunately you have to // pre-declare g because otherwise it won't survive the scope, and // the return value from myfunc.opCall would become inaccessible. string g; with(myfunc!()(0)) { x=rand() % 40; y=x/2; z=y/2; g = call(); // as a side effect, prints 'X 7, Y 3, Z 1' } writeln("g=", g); // prints "g=yo", as returned from opCall /* // The bright future: this demonstrates that // it would be fairly trivial to make some kind of annotation // like kwarg or whaterver, to indicate that a function // was using this calling convention: kwarg string f(int a, string b) { body; } // so that kwarg function definitions are lowered to: struct f_kw { int a; string b; string f() { body; } } // and calls to kwarg functions are transformed // from this: auto r = f(a=5, b="good"); // into this: f_kw tmp34; tmp34.a = 5; tmp34.b = "good"; auto r = tmp34.f(); // the benefit: named parameters can be used in a natural way, // and they need be known only at runtime. */ } // how the 'works today' above examples were implemented: struct myfunc(string init_string="") { // named keyword or named parameters // --the call arguments and their defaults int x=0; int y=0; int z=0; this(int) {} string opCall() { mixin(init_string ~ ";"); writefln("X %s, Y %s, Z %s", x, y, z ); return "yo"; } alias opCall call; }Here's my proposal for anonymous structs that can be used as name parameters: http://forum.dlang.org/thread/kfbnuc$1cro$1 digitalmars.com?page=1 -- /Jacob Carlborg
Mar 22 2013
On Friday, 22 March 2013 at 10:17:02 UTC, J wrote:With credit for inspiration to David Medlock in this post-- http://forum.dlang.org/thread/d9lnrr$26q3$1 digitaldaemon.com ... // Tongue firmly in cheek, I'd like to introduce // the NAPAPISS principle: (with apologies to SFINAE and RAII) // NAPAPISS = NAmed Parameters Are simply Passed in a Struct, Silly. // Yes, indeed, maybe this is what happens after drinking too much of // the fine wine products from the Napa valley... you start having // wild flights of fancy of how D might surprisingly soon have // named parameters.... import std.stdio; import std.c.stdlib; void main(string[] arg) { // this works today: but with the drawback that the // named params must be known at compile time... // Here is a named param call, // as compact as I could get it (see struct below for actual definition). auto a = myfunc!q{ z= 2; x = -123; y = 200 }(0)(); // calls opCall writeln("a=", a); // prints "a=yo", as returned from opCall // And here's the runtime version, unfortunately you have to // pre-declare g because otherwise it won't survive the scope, and // the return value from myfunc.opCall would become inaccessible. string g; with(myfunc!()(0)) { x=rand() % 40; y=x/2; z=y/2; g = call(); // as a side effect, prints 'X 7, Y 3, Z 1' } writeln("g=", g); // prints "g=yo", as returned from opCall /* // The bright future: this demonstrates that // it would be fairly trivial to make some kind of annotation // like kwarg or whaterver, to indicate that a function // was using this calling convention: kwarg string f(int a, string b) { body; } // so that kwarg function definitions are lowered to: struct f_kw { int a; string b; string f() { body; } } // and calls to kwarg functions are transformed // from this: auto r = f(a=5, b="good"); // into this: f_kw tmp34; tmp34.a = 5; tmp34.b = "good"; auto r = tmp34.f(); // the benefit: named parameters can be used in a natural way, // and they need be known only at runtime. */ } // how the 'works today' above examples were implemented: struct myfunc(string init_string="") { // named keyword or named parameters // --the call arguments and their defaults int x=0; int y=0; int z=0; this(int) {} string opCall() { mixin(init_string ~ ";"); writefln("X %s, Y %s, Z %s", x, y, z ); return "yo"; } alias opCall call; } On Friday, 22 March 2013 at 09:18:33 UTC, J wrote:WTF? What do kwargs have to do with programming? Sounds more like a half-Klingon & half-Ferengi species to me.The bigger point here is more profound: it is trivial to implement named parameters using structs + trivial lowerings, and this is no way conflicts with function overloading. D deserves to have named parameters to functions -- it makes for much more legible code, and obviates the need for slow builder patterns. Readable and speedable. It's win-win.
Mar 22 2013
On Friday, 22 March 2013 at 20:04:14 UTC, foobar wrote:On Friday, 22 March 2013 at 10:17:02 UTC, J wrote:kwargs = keyword arguments It's a common naming convention in python, as exemplified in matplotlib.With credit for inspiration to David Medlock in this post-- http://forum.dlang.org/thread/d9lnrr$26q3$1 digitaldaemon.com ... // Tongue firmly in cheek, I'd like to introduce // the NAPAPISS principle: (with apologies to SFINAE and RAII) // NAPAPISS = NAmed Parameters Are simply Passed in a Struct, Silly. // Yes, indeed, maybe this is what happens after drinking too much of // the fine wine products from the Napa valley... you start having // wild flights of fancy of how D might surprisingly soon have // named parameters.... import std.stdio; import std.c.stdlib; void main(string[] arg) { // this works today: but with the drawback that the // named params must be known at compile time... // Here is a named param call, // as compact as I could get it (see struct below for actual definition). auto a = myfunc!q{ z= 2; x = -123; y = 200 }(0)(); // calls opCall writeln("a=", a); // prints "a=yo", as returned from opCall // And here's the runtime version, unfortunately you have to // pre-declare g because otherwise it won't survive the scope, and // the return value from myfunc.opCall would become inaccessible. string g; with(myfunc!()(0)) { x=rand() % 40; y=x/2; z=y/2; g = call(); // as a side effect, prints 'X 7, Y 3, Z 1' } writeln("g=", g); // prints "g=yo", as returned from opCall /* // The bright future: this demonstrates that // it would be fairly trivial to make some kind of annotation // like kwarg or whaterver, to indicate that a function // was using this calling convention: kwarg string f(int a, string b) { body; } // so that kwarg function definitions are lowered to: struct f_kw { int a; string b; string f() { body; } } // and calls to kwarg functions are transformed // from this: auto r = f(a=5, b="good"); // into this: f_kw tmp34; tmp34.a = 5; tmp34.b = "good"; auto r = tmp34.f(); // the benefit: named parameters can be used in a natural way, // and they need be known only at runtime. */ } // how the 'works today' above examples were implemented: struct myfunc(string init_string="") { // named keyword or named parameters // --the call arguments and their defaults int x=0; int y=0; int z=0; this(int) {} string opCall() { mixin(init_string ~ ";"); writefln("X %s, Y %s, Z %s", x, y, z ); return "yo"; } alias opCall call; } On Friday, 22 March 2013 at 09:18:33 UTC, J wrote:WTF? What do kwargs have to do with programming? Sounds more like a half-Klingon & half-Ferengi species to me.The bigger point here is more profound: it is trivial to implement named parameters using structs + trivial lowerings, and this is no way conflicts with function overloading. D deserves to have named parameters to functions -- it makes for much more legible code, and obviates the need for slow builder patterns. Readable and speedable. It's win-win.
Mar 22 2013
On Friday, 22 March 2013 at 21:10:27 UTC, John Colvin wrote:On Friday, 22 March 2013 at 20:04:14 UTC, foobar wrote:That was meant more as a rhetorical question rather than a real one. Yes, I guessed the meaning by the surrounding context but nevertheless it was a major WAT while skimming the post. Also, Who the fuck cares whats common in Python? I was reading and replying on the *D* NG, was I not?WTF? What do kwargs have to do with programming? Sounds more like a half-Klingon & half-Ferengi species to me.kwargs = keyword arguments It's a common naming convention in python, as exemplified in matplotlib.
Mar 22 2013
On Friday, 22 March 2013 at 21:29:46 UTC, foobar wrote:On Friday, 22 March 2013 at 21:10:27 UTC, John Colvin wrote:Kwarg seems a reasonable name, consistent with a pre-existing convention. Please suggest a better alternative if you have one. I must admit I'm bemused by your level of aggression over what appears to be a trivial matter.On Friday, 22 March 2013 at 20:04:14 UTC, foobar wrote:That was meant more as a rhetorical question rather than a real one. Yes, I guessed the meaning by the surrounding context but nevertheless it was a major WAT while skimming the post. Also, Who the fuck cares whats common in Python? I was reading and replying on the *D* NG, was I not?WTF? What do kwargs have to do with programming? Sounds more like a half-Klingon & half-Ferengi species to me.kwargs = keyword arguments It's a common naming convention in python, as exemplified in matplotlib.
Mar 22 2013
On Friday, 22 March 2013 at 21:41:46 UTC, John Colvin wrote:On Friday, 22 March 2013 at 21:29:46 UTC, foobar wrote:Your read it wrong. Not aggression but rather annoyment. Also, code readability is NOT a trivial matter and people who think that it is should have their keyboard chopped off. IMHO, I think the entire feature is a code smell and glad D does not support it. Code that needs named parameters to be more readable is poorly designed code in the first place.On Friday, 22 March 2013 at 21:10:27 UTC, John Colvin wrote:Kwarg seems a reasonable name, consistent with a pre-existing convention. Please suggest a better alternative if you have one. I must admit I'm bemused by your level of aggression over what appears to be a trivial matter.On Friday, 22 March 2013 at 20:04:14 UTC, foobar wrote:That was meant more as a rhetorical question rather than a real one. Yes, I guessed the meaning by the surrounding context but nevertheless it was a major WAT while skimming the post. Also, Who the fuck cares whats common in Python? I was reading and replying on the *D* NG, was I not?WTF? What do kwargs have to do with programming? Sounds more like a half-Klingon & half-Ferengi species to me.kwargs = keyword arguments It's a common naming convention in python, as exemplified in matplotlib.
Mar 23 2013
foobar:Code that needs named parameters to be more readable is poorly designed code in the first place.Have you used a language where the usage of named arguments is idiomatic, like Python, Scala or Ada? They are sometimes useful even for well designed code, like functions with two arguments. Bye, bearophile
Mar 23 2013
On Saturday, 23 March 2013 at 15:00:13 UTC, bearophile wrote:foobar:A simple example is matplotlib.pyplot.plot There are so many possible flags and parameters that can be passed in order to get the exact behaviour you want, but commonly you'll only want a few set for each call. You don't want to have to set all the other preceding parameters, you just want to go e.g. plot(data, linewidth=5)Code that needs named parameters to be more readable is poorly designed code in the first place.Have you used a language where the usage of named arguments is idiomatic, like Python, Scala or Ada? They are sometimes useful even for well designed code, like functions with two arguments. Bye, bearophile
Mar 23 2013
On 2013-03-23 16:55, John Colvin wrote:A simple example is matplotlib.pyplot.plot There are so many possible flags and parameters that can be passed in order to get the exact behaviour you want, but commonly you'll only want a few set for each call. You don't want to have to set all the other preceding parameters, you just want to go e.g. plot(data, linewidth=5)arguments and named parameters. It made it a lot easier to integrate with COM. -- /Jacob Carlborg
Mar 23 2013
On Saturday, 23 March 2013 at 15:59:12 UTC, Jacob Carlborg wrote:On 2013-03-23 16:55, John Colvin wrote:AFAIK, this is only relevant or useful for COM (i.e. to support legacy, not really OO code) and is not supported (compile error?) OO).A simple example is matplotlib.pyplot.plot There are so many possible flags and parameters that can be passed in order to get the exact behaviour you want, but commonly you'll only want a few set for each call. You don't want to have to set all the other preceding parameters, you just want to go e.g. plot(data, linewidth=5)default arguments and named parameters. It made it a lot easier to integrate with COM.
Mar 25 2013
On Saturday, 23 March 2013 at 15:55:36 UTC, John Colvin wrote:On Saturday, 23 March 2013 at 15:00:13 UTC, bearophile wrote:Can't the monadic style thing do the trick ? Named!plot.linewidth(5).call(data); This is doable with actual D using compile time reflection.foobar:A simple example is matplotlib.pyplot.plot There are so many possible flags and parameters that can be passed in order to get the exact behaviour you want, but commonly you'll only want a few set for each call. You don't want to have to set all the other preceding parameters, you just want to go e.g. plot(data, linewidth=5)Code that needs named parameters to be more readable is poorly designed code in the first place.Have you used a language where the usage of named arguments is idiomatic, like Python, Scala or Ada? They are sometimes useful even for well designed code, like functions with two arguments. Bye, bearophile
Mar 23 2013
On Saturday, 23 March 2013 at 19:56:17 UTC, deadalnix wrote:On Saturday, 23 March 2013 at 15:55:36 UTC, John Colvin wrote:Good point, and I'm sure we all develop our personal sense of 'code smell' based on our own past experience. I find adding lots of enums to be like doing RAII in C++: I find it a pain to have to pollute namespaces with extra enums (classes), just to get readability/safety. To me, the builder/monadic style is clunky and harder to read. I find plot(data, linewidth = 5) to be clean, clear, and more concise.On Saturday, 23 March 2013 at 15:00:13 UTC, bearophile wrote:Can't the monadic style thing do the trick ? Named!plot.linewidth(5).call(data); This is doable with actual D using compile time reflection.foobar:A simple example is matplotlib.pyplot.plot There are so many possible flags and parameters that can be passed in order to get the exact behaviour you want, but commonly you'll only want a few set for each call. You don't want to have to set all the other preceding parameters, you just want to go e.g. plot(data, linewidth=5)Code that needs named parameters to be more readable is poorly designed code in the first place.Have you used a language where the usage of named arguments is idiomatic, like Python, Scala or Ada? They are sometimes useful even for well designed code, like functions with two arguments. Bye, bearophile
Mar 23 2013
I updated https://github.com/timotheecour/dtools/blob/master/dtools/util/functional.d to incorporate Jacob Carlborg's idea (thanks for the working+clean code! let me know if attribution is ok) auto a=named!fun.z(3).x(4).call(); and then simplified it a bit to: auto a=named!fun.z(3).x(4)(); It's now looking pretty close to the ideal D syntax: auto a=fun(z:3,x:4); Notes: auto a=fun(z=3,x=4); doesn't seem like a good syntax compared to 'z:3,x:4', because z=3 could be ambiguous with an expression assigning 3 to z when z is in scope.I find it a pain to have to pollute namespaces with extra enums (classes), just to get readability/safety. plot(data, linewidth = 5) to be clean, clear, and more concise.I agree. In fact, I think we should push that named syntax 'named!fun.z(3).x(4)();' in std.functional once finalized, and start using it in phobos ASAP, it makes things more self documenting. If 'fun(z:3,x:4)' syntax later comes to D, it'd be trivial to write a tool that automatically changes the named!fun syntax in people's / phobos' source code to use the new cleaner syntax. main benefit IMO: prevent boilerplate code like this: struct Options{int x; int y=1; int z=2;} auto fun(Options options); Options options; options.x=4; options.z=3; auto a=fun(options); (or similar with param expansion: auto a=fun(options.x,options.y,options.z)) thanks for your comments!
Mar 23 2013
It's now looking pretty close to the ideal D syntax: auto a=fun(z:3,x:4);The last time I tried this (maybe 2 years ago, so before std.traits.ParameterNameTuple?), I used associative arrays: alias nfoo = named!foo; // nfoo is now a function admitting AA as arguments auto result = nfoo(["z":"Title"], ["x":1, "y":100]); Also, I see that at one time, you used a full string syntax: auto result = nfoo(q{z = "Title", x = 1, y = 100}); // nfoo will parse the input string I rather like this one. Why did you ditch it?
Mar 24 2013
On 2013-03-24 09:13, Philippe Sigaud wrote:Also, I see that at one time, you used a full string syntax: auto result = nfoo(q{z = "Title", x = 1, y = 100}); // nfoo will parse the input string I rather like this one. Why did you ditch it?That would requires compile time values, i.e. no variables. -- /Jacob Carlborg
Mar 24 2013
On Sun, Mar 24, 2013 at 11:15 AM, Jacob Carlborg <doob me.com> wrote:You're right.auto result = nfoo(q{z = "Title", x = 1, y = 100}); // nfoo will parse the input string I rather like this one. Why did you ditch it?That would requires compile time values, i.e. no variables.
Mar 24 2013
On 2013-03-24 03:05, timotheecour wrote:I updated https://github.com/timotheecour/dtools/blob/master/dtools/util/functional.d to incorporate Jacob Carlborg's idea (thanks for the working+clean code! let me know if attribution is ok)Absolutely.If 'fun(z:3,x:4)' syntax later comes to D, it'd be trivial to write a tool that automatically changes the named!fun syntax in people's / phobos' source code to use the new cleaner syntax. main benefit IMO: prevent boilerplate code like this: struct Options{int x; int y=1; int z=2;} auto fun(Options options); Options options; options.x=4; options.z=3; auto a=fun(options); (or similar with param expansion: auto a=fun(options.x,options.y,options.z))What would be nice is to be able to do like this: struct Options{int x; int y=1; int z=2;} auto fun(Options options); fun(y: 2, z: 45, x: 4); Then add opDispatch to Options to soak up any varialble not found in Options: struct Options { int x; int y = 1; int z = 2; private Variant[string] values; void opDispatch (string name, T) (T value) { values[name] = Variant(value); } ) fun(y: 2, foo: "asd", bar: 4.0, z: 45, x: 4); x, y, z are mapped to the variables in Options. foo and bar are handled by opDispatch. See my proposal for anonymous structs: http://forum.dlang.org/thread/kfbnuc$1cro$1 digitalmars.com -- /Jacob Carlborg
Mar 24 2013
On 2013-03-24 03:05, timotheecour wrote:I updated https://github.com/timotheecour/dtools/blob/master/dtools/util/functional.d to incorporate Jacob Carlborg's idea (thanks for the working+clean code! let me know if attribution is ok)BTW, why was the constructor added to Proxy and the "dummy" argument? -- /Jacob Carlborg
Mar 24 2013
BTW, why was the constructor added to Proxy and the "dummy" argument?because I wanted to simplify syntax from 'auto ret2=named!fun.z(3).x(4).call();' to 'auto ret2=named!fun.z(3).x(4)();' In doing that, I was having CT errors without it due to ambiguity between default unnamed constructor and opCall, so I added constructor. Then inside the named() function i needed to return a proxy object. Alternatives were: return Proxy!(func, null)(); //wrong: would call opCall return Proxy!(func, null).init; //not sure if it would incur overhead return Proxy!(func, null)(0); //introduces dummy arg, which should be optimized away. If you can find a better way (that doesn't incur runtime overhead), please do a pull request! Also, I'm wondering about: * how to put the unittest helper function "fun" inside main unittest block * whether the named!fun.z(3).x(4)(); call has any overhead over calling fun(4,2,3) directly. * how to support templated functions (here fun is not templated) * whether we should support this syntax: auto ret=named!fun.z(3)(4); //this would mean named!fun.z(3).x(4)(); ie all non-optional arguments go in the opCall(..) arguments, all optional arguments are called by name. So that would force API to freeze names only for optional arguments, not non-optional ones, cf in python: fun(4,z:3) Finally, how do I reply from my email client ? Right I'm using http://forum.dlang.org/ otherwise the message isn't delivered on the forum... Thanks!
Mar 24 2013
On 2013-03-24 20:59, timotheecour wrote:Aha, ok I see.BTW, why was the constructor added to Proxy and the "dummy" argument?because I wanted to simplify syntax from 'auto ret2=named!fun.z(3).x(4).call();' to 'auto ret2=named!fun.z(3).x(4)();' In doing that, I was having CT errors without it due to ambiguity between default unnamed constructor and opCall, so I added constructor. Then inside the named() function i needed to return a proxy object. Alternatives were: return Proxy!(func, null)(); //wrong: would call opCall return Proxy!(func, null).init; //not sure if it would incur overhead return Proxy!(func, null)(0); //introduces dummy arg, which should be optimized away.Finally, how do I reply from my email client ? Right I'm using http://forum.dlang.org/ otherwise the message isn't delivered on the forum... Thanks!I'm using Thunderbird and just using "Reply to the message". -- /Jacob Carlborg
Mar 24 2013
I'm using Thunderbird and just using "Reply to the message".using gmail but doesn't work... (testing again via this message...) pls ignore if this succeeds!
Mar 24 2013
On 2013-03-24 23:53, a a wrote:using gmail but doesn't work... (testing again via this message...) pls ignore if this succeeds!I got this. -- /Jacob Carlborg
Mar 25 2013
On Saturday, 23 March 2013 at 15:00:13 UTC, bearophile wrote:foobar:"idiomatic" is a relative term, tightly coupled to a specific language. Idiomatic D code for example is very different from idiomatic Haskell code. Idiomatic Python style in D would be very unidiomatic D code and vise versa. Each language has its own conventions, styles, set of distinct features, etc, etc and trying to use "language A" style while coding in "language B" is like trying to fit a square peg in a round hole. For instance, I would NOT use smalltalk naming conventions while writing say Java code. Both have very good and very consistent styles that are tightly coupled with their respective syntaxes and are very unsuitable to use in the other language. In short, if you want to discuss python features, style or specific math plotting libraries, please post to the python mailing list, not D's NG.Code that needs named parameters to be more readable is poorly designed code in the first place.Have you used a language where the usage of named arguments is idiomatic, like Python, Scala or Ada? They are sometimes useful even for well designed code, like functions with two arguments. Bye, bearophile
Mar 25 2013
foobar:"idiomatic" is a relative term, tightly coupled to a specific language. Idiomatic D code for example is very different from idiomatic Haskell code. Idiomatic Python style in D would be very unidiomatic D code and vise versa. Each language has its own conventions, styles, set of distinct features, etc, etc and trying to use "language A" style while coding in "language B" is like trying to fit a square peg in a round hole. For instance, I would NOT use smalltalk naming conventions while writing say Java code. Both have very good and very consistent styles that are tightly coupled with their respective syntaxes and are very unsuitable to use in the other language. In short, if you want to discuss python features, style or specific math plotting libraries, please post to the python mailing list, not D's NG.Imperative/OOP languages are not totally different from each other, both Python and D derive strongly from C that comes partially from Algol, and D copies several things from Python (string functions, part of the module system, part of the range design comes from itertools, and so on). So comparing languages and their features is very useful. If you have not used named arguments in languages that idiomatically use them, then it's not easy for you to see how and why they are sometimes useful and good. In Python function arguments don't have a type, so named arguments are more useful than in D. But from my experience in Python, I believe D could enjoy named arguments. Bye, bearophile
Mar 25 2013
On Monday, 25 March 2013 at 13:02:49 UTC, bearophile wrote:foobar:C is a HORRIBLE language regarding naming conventions and is a *very poor choice* to learn from in this regard. Python sets very high expectations regarding "beautiful code" and IMHO fails miserably (more so because of the starting higher expectations). I admit to being spoiled by actually beautifully designed languages that are far superior in that respect. I suggest to learn Smalltalk for a language that emphasizes code readability decades before Python became cool. I find Ruby which is based on Smalltalk's semantics and spirit to be more elegant and less pretentious compared to Python."idiomatic" is a relative term, tightly coupled to a specific language. Idiomatic D code for example is very different from idiomatic Haskell code. Idiomatic Python style in D would be very unidiomatic D code and vise versa. Each language has its own conventions, styles, set of distinct features, etc, etc and trying to use "language A" style while coding in "language B" is like trying to fit a square peg in a round hole. For instance, I would NOT use smalltalk naming conventions while writing say Java code. Both have very good and very consistent styles that are tightly coupled with their respective syntaxes and are very unsuitable to use in the other language. In short, if you want to discuss python features, style or specific math plotting libraries, please post to the python mailing list, not D's NG.Imperative/OOP languages are not totally different from each other, both Python and D derive strongly from C that comes partially from Algol, and D copies several things from Python (string functions, part of the module system, part of the range design comes from itertools, and so on). So comparing languages and their features is very useful. If you have not used named arguments in languages that idiomatically use them, then it's not easy for you to see how and why they are sometimes useful and good. In Python function arguments don't have a type, so named arguments are more useful than in D. But from my experience in Python, I believe D could enjoy named arguments. Bye, bearophile
Mar 25 2013
On Friday, 22 March 2013 at 09:18:33 UTC, J wrote:The bigger point here is more profound: it is trivial to implement named parameters using structs + trivial lowerings, and this is no way conflicts with function overloading. D deserves to have named parameters to functions -- it makes for much more legible code, and obviates the need for slow builder patterns. Readable and speedable. It's win-win.Question for specialists of the topic : are parameter name available using compile time reflection ? Because if they are, the problem boils down to perfect forwarding issue. And it seems solvable : NamedCall!( function, "foo", fooVal, "bar", barVal); // Booya !
Mar 22 2013
On Friday, 22 March 2013 at 15:50:38 UTC, Dicebot wrote:Seems to me like a solved problem.
Mar 22 2013
so i hacked up a working solution yesterday. advantages over https://github.com/jacob-carlborg/mambo/blob/master/mambo/util/Reflection.d#L135: no need to no arguments at CT (just names); allows optional and non optional ones; allows return value; also, mambo depends on tango and is hard to revive. More later. see: https://github.com/timotheecour/dtools/blob/master/dtools/util/functional.d nothing to install, just call: rdmd --main -unittest dtools/util/functional.d auto s=callNamed!(fun,`x,y`)(10,20); given a function: auto fun(int x,int y=2,double z=z_val, string z2="asdf"); Compile time errors will occur on duplicate param names, or ones that don't exist, or ones that are not optional and not provided (eg x, above) Feel free to contribute / comment
Mar 22 2013
On Friday, 22 March 2013 at 18:48:56 UTC, timotheecour wrote:so i hacked up a working solution yesterday. advantages over https://github.com/jacob-carlborg/mambo/blob/master/mambo/util/Reflection.d#L135: no need to no arguments at CT (just names); allows optional and non optional ones; allows return value; also, mambo depends on tango and is hard to revive. More later. see: https://github.com/timotheecour/dtools/blob/master/dtools/util/functional.d nothing to install, just call: rdmd --main -unittest dtools/util/functional.d auto s=callNamed!(fun,`x,y`)(10,20); given a function: auto fun(int x,int y=2,double z=z_val, string z2="asdf"); Compile time errors will occur on duplicate param names, or ones that don't exist, or ones that are not optional and not provided (eg x, above) Feel free to contribute / commentDon't have time to look at the code now, but it seems awesome ! Great leverage of language capabilities. Slightly different from my proposal, but I'm really not sure which interface fit best. I'm starting to think this should be : callNamed!(fun,`x`, `y`)(10,20); But I'm not sure of all the pro and cons.
Mar 22 2013
22-Mar-2013 23:03, deadalnix пишет:On Friday, 22 March 2013 at 18:48:56 UTC, timotheecour wrote:Can opDispatch & chaining be leveraged to get the effect of: named!(fun).x(10).y(20).call(); Or maybe even simpler?so i hacked up a working solution yesterday. advantages over https://github.com/jacob-carlborg/mambo/blob/master/mambo/util/Reflection.d#L135: no need to no arguments at CT (just names); allows optional and non optional ones; allows return value; also, mambo depends on tango and is hard to revive. More later. see: https://github.com/timotheecour/dtools/blob/master/dtools/util/functional.d nothing to install, just call: rdmd --main -unittest dtools/util/functional.d auto s=callNamed!(fun,`x,y`)(10,20); given a function: auto fun(int x,int y=2,double z=z_val, string z2="asdf"); Compile time errors will occur on duplicate param names, or ones that don't exist, or ones that are not optional and not provided (eg x, above) Feel free to contribute / commentDon't have time to look at the code now, but it seems awesome ! Great leverage of language capabilities. Slightly different from my proposal, but I'm really not sure which interface fit best. I'm starting to think this should be : callNamed!(fun,`x`, `y`)(10,20);But I'm not sure of all the pro and cons.-- Dmitry Olshansky
Mar 22 2013
On 2013-03-22 21:02, Dmitry Olshansky wrote:Can opDispatch & chaining be leveraged to get the effect of: named!(fun).x(10).y(20).call();Here you go: http://pastebin.com/ALaXLgt3 Use that together with "callNamed" from timotheecour. -- /Jacob Carlborg
Mar 23 2013
Thanks, but this is a non-solution. The name must be next to the value ( x=10, y=20), so they it will scale from 2 to 7 to 17 arguments and maintain readability.auto s=callNamed!(fun,`x,y`)(10,20);
Mar 22 2013
On Saturday, 23 March 2013 at 05:43:22 UTC, J wrote:For a use case, compare this call reflectAndTranslate(2, 4, 5, 6, 1, 2, false, true, 15, false, true, false); Quick, without looking at the docs, what does the false after 15 do? It's very hard to tell. Compare that to: reflectAndTranslate(x=2, y=4, z=5, offset=6, alpha=1, beta=2, invert=false, twist=true, colorBrush=15, stideReduce=false, bindMatrix=true, slow=false); It's self documenting.Thanks, but this is a non-solution. The name must be next to the value ( x=10, y=20), so they it will scale from 2 to 7 to 17 arguments and maintain readability.auto s=callNamed!(fun,`x,y`)(10,20);
Mar 23 2013
On Saturday, 23 March 2013 at 08:20:19 UTC, J wrote:On Saturday, 23 March 2013 at 05:43:22 UTC, J wrote:I'd argue that with or without named parameter, that code is ugly as hell. First, boolean can be replaced by enums for great benefice. Secondly, the usage of struct would also improve things quite a lot (x, y, z) is a point or a vector or something. At the end, it is about giving semantic to your code. BTW, monadic style named parameters have been proposed earlier, and I have to say this is really nice.For a use case, compare this call reflectAndTranslate(2, 4, 5, 6, 1, 2, false, true, 15, false, true, false); Quick, without looking at the docs, what does the false after 15 do? It's very hard to tell. Compare that to: reflectAndTranslate(x=2, y=4, z=5, offset=6, alpha=1, beta=2, invert=false, twist=true, colorBrush=15, stideReduce=false, bindMatrix=true, slow=false); It's self documenting.Thanks, but this is a non-solution. The name must be next to the value ( x=10, y=20), so they it will scale from 2 to 7 to 17 arguments and maintain readability.auto s=callNamed!(fun,`x,y`)(10,20);
Mar 23 2013
On 2013-03-21 19:35, J wrote: Here's another workaround: https://github.com/jacob-carlborg/mambo/blob/master/mambo/util/Reflection.d#L135 -- /Jacob Carlborg
Mar 21 2013
Jacob Carlborg:Here's another workaround: https://github.com/jacob-carlborg/mambo/blob/master/mambo/util/Reflection.d#L135Maybe such two links should go in one page of the D wiki about lack of named parameters workarounds. Eventually D should introduce a syntax for named arguments at the call point plus a syntax to deprecate argument names. It's not the most important thing that D currently lacks, but it's an improvement. Bye, bearophile
Mar 21 2013
On 2013-03-21 21:33, bearophile wrote:Maybe such two links should go in one page of the D wiki about lack of named parameters workarounds. Eventually D should introduce a syntax for named arguments at the call point plus a syntax to deprecate argument names. It's not the most important thing that D currently lacks, but it's an improvement.What do you think about my suggestion for anonymous structs as named parameters? http://forum.dlang.org/thread/kfbnuc$1cro$1 digitalmars.com?page=1 -- /Jacob Carlborg
Mar 21 2013
Jacob Carlborg:What do you think about my suggestion for anonymous structs as named parameters?You show code like: void foo ({ int x, int y } point) { } foo({ y: 5, x: 3 }); D already has two kinds of tuples so I don't want a "third kind" of tuple. What I want is D to manage better the Phobos Tuple we already have, adding an unpacking syntax (http://forum.dlang.org/thread/gridjorxqlpoytuxwpsg forum.dlang.org ). (This is not supposed to solve the named arguments problem). Bye, bearophile
Mar 21 2013
On 2013-03-21 22:18, bearophile wrote:You show code like: void foo ({ int x, int y } point) { } foo({ y: 5, x: 3 }); D already has two kinds of tuples so I don't want a "third kind" of tuple. What I want is D to manage better the Phobos Tuple we already have, adding an unpacking syntax (http://forum.dlang.org/thread/gridjorxqlpoytuxwpsg forum.dlang.org ). (This is not supposed to solve the named arguments problem).This is not a tuple, it's an anonymous struct. -- /Jacob Carlborg
Mar 22 2013
On Thursday, 21 March 2013 at 19:59:01 UTC, Jacob Carlborg wrote:On 2013-03-21 19:35, J wrote: Here's another workaround: https://github.com/jacob-carlborg/mambo/blob/master/mambo/util/Reflection.d#L135Intriguing, Jacob! I could learn alot about reflection by studying your code. How is it installed? I installing by downloading that single file, and with a quick hack to the Reflection.d top three lines (commenting out the module and imports at the top), I tried calling it with this, no luck: import Reflection; // with module and imports commented out... import std.stdio; string my(int a, int b) { writeln(a/b); return "howdy"; } void main(string[] arg) { auto s = callWithNamedArguments(my, `a=3, b=4`); } // yields: $ ./ref.d ./ref.d(13): Error: function ref.my (int a, int b) is not callable using argument types () ./ref.d(13): Error: expected 2 function arguments, not 0
Mar 21 2013
On 2013-03-21 21:42, J wrote:Intriguing, Jacob! I could learn alot about reflection by studying your code. How is it installed? I installing by downloading that single file, and with a quick hack to the Reflection.d top three lines (commenting out the module and imports at the top), I tried calling it with this, no luck: import Reflection; // with module and imports commented out... import std.stdio; string my(int a, int b) { writeln(a/b); return "howdy"; } void main(string[] arg) { auto s = callWithNamedArguments(my, `a=3, b=4`); } // yields: $ ./ref.d ./ref.d(13): Error: function ref.my (int a, int b) is not callable using argument types () ./ref.d(13): Error: expected 2 function arguments, not 0It's been quite a while since I tested that code. I'll see what I can do. -- /Jacob Carlborg
Mar 21 2013
On 2013-03-21 19:35, J wrote: [snip] I just noticed that Michel Fortin has implemented basic support for named parameters. I've updated his code to the latest DMD and pushed it to my fork: https://github.com/jacob-carlborg/dmd/commit/e363a093040c4b14e7e814027c3e199676c82820 From the commit message: Add basic support for named parameters. This will only allow to add the name of the parameter when calling a function. It doesn't not support passing the arguments out of order. All credit goes to Michel Fortin. -- /Jacob Carlborg
Mar 25 2013
On Monday, 25 March 2013 at 16:03:38 UTC, Jacob Carlborg wrote:On 2013-03-21 19:35, J wrote: [snip] I just noticed that Michel Fortin has implemented basic support for named parameters. I've updated his code to the latest DMD and pushed it to my fork: https://github.com/jacob-carlborg/dmd/commit/e363a093040c4b14e7e814027c3e199676c82820 From the commit message: Add basic support for named parameters. This will only allow to add the name of the parameter when calling a function. It doesn't not support passing the arguments out of order. All credit goes to Michel Fortin.+1000 Excellent!
Mar 25 2013
On Monday, 25 March 2013 at 18:11:54 UTC, J wrote:On Monday, 25 March 2013 at 16:03:38 UTC, Jacob Carlborg wrote:Wow. This is really nice! I added a method to Michel's nice work. You can get it in this branch. https://github.com/glycerine/dmd/tree/namedarg All the dmd test suite then passes. You can now do this: void test (double y, double z, int a, int b, int c, string d) { } void main () { test(y: 33.3, z: 44.4, a: 9999, b: 8888, 7777, // truly optional d:"Yehaw"); } I also tested the passing of named parameters through variadic templates, and there is a little work needed to make them 'named argument' aware. I added a failing test for that, if anyone wants to tackle it. It is dmd/test/compilable/namedarg_vararg.d in the branch above. $ cat namedarg_vararg.d cat namedarg_vararg.d import core.vararg; import std.stdio; void test(A...)(A a) { foreach(t; a) writeln(t); } void main () { test(x:33.3, z: 44.4, a: 9999, b: 8888, 7777, d:"Yehaw"); } $ dmd namedarg_vararg.d namedarg_vararg.d(12): Error: template namedarg_vararg.test(A...)(A a) cannot deduce template function from argument types !()(x:double,z:double,a:int,b:int,int,d:string) $ * * * Wierd and cool: Since the current version requires the exact same positions as names, it is almost like you get extra refined type safety for free. Say I have a function that takes two strings. The compiler can now help me if I mistakenly switch the two... Example: void find(string needle, string haystack) { } void main () { find(haystack: "abcdefg", needle: "def"); } dmd can now helpfully point out: namedarg_haystack.d(6): Error: function namedarg_haystack.find (string needle, string haystack) is not callable using argument types (haystack:string,needle:string) Nice. This has a different feel to it than where the compiler just 'makes it right' for you, but I still really like it. Super readable.On 2013-03-21 19:35, J wrote: [snip] I just noticed that Michel Fortin has implemented basic support for named parameters. I've updated his code to the latest DMD and pushed it to my fork: https://github.com/jacob-carlborg/dmd/commit/e363a093040c4b14e7e814027c3e199676c82820 From the commit message: Add basic support for named parameters. This will only allow to add the name of the parameter when calling a function. It doesn't not support passing the arguments out of order. All credit goes to Michel Fortin.+1000 Excellent!
Mar 26 2013
On Monday, 25 March 2013 at 16:03:38 UTC, Jacob Carlborg wrote: [cut]Add basic support for named parameters. This will only allow to add the name of the parameter when calling a function. It doesn't not support passing the arguments out of order. All credit goes to Michel Fortin.Interesting, the "doesn't not support passing the arguments out of order." can be seen either as a (temporary or not) implementation limitation OR as a feature. The things to check is how this feature would work with optional parameters.. renoX
Mar 26 2013
On 2013-03-26 10:31, renoX wrote:Interesting, the "doesn't not support passing the arguments out of order." can be seen either as a (temporary or not) implementation limitation OR as a feature.I would guess it was easier. At least the change is very small. Smaller that I would have imagined.The things to check is how this feature would work with optional parameters..Good point. -- /Jacob Carlborg
Mar 26 2013
On Tuesday, 26 March 2013 at 12:14:08 UTC, Jacob Carlborg wrote:On 2013-03-26 10:31, renoX wrote:Tested this. Seems to work fine with optional parameters. import std.stdio; void test (int a, int b = 24, int c = 12, int d = 6, int e = 3) { writeln(a); writeln(b); writeln(c); writeln(d); writeln(e); } void main () { test(a: 1, 2, c: 9999); } // output: $ ./namedarg_defaults 1 2 9999 6 3Interesting, the "doesn't not support passing the arguments out of order." can be seen either as a (temporary or not) implementation limitation OR as a feature.I would guess it was easier. At least the change is very small. Smaller that I would have imagined.The things to check is how this feature would work with optional parameters..Good point.
Mar 26 2013
Named parameters are only interesting if we can skip some optional parameters. This allows the python-like syntax of specifying only a subset of parameters; otherwise this isn't very interesting. This is used heavily in python and makes code * self-documenting * avoids DRY (don't specify unused params) * avoids boilerplate of introducing auxiliary option structs and fields to it Here are just 3 examples that hopefully will convince some that named params are useful and not ugly. ---- //inspired from python's matplotlib; many more options configurable, which are set to reasonable defaults plot(x=1,y=2,color='red',width=3); //here's another one (cf inspired by scons / waf build tools in python) compile(input=["foo.cpp"] , run=true, debug=true, ldflags="-lcurl", output_dir="build"); //other example: setting optional params in a classifier trainSVM(input=X, labels=Y, C=1000, crossValidate=true, loss=squareHingeLoss) ---- Additionally, we should be able to provide arguments out of order and check at compile time that there are no duplicates and no unexistant fields. The code i posted with support for named!plot.x(2).color("red").width(3) did that, and that wasn't hard. So hopefully it won't be easy to support as well skipping, reordering and CT checking with Michel Fortin's shiny syntax. Here are some design decisions to make: given a function void fun(int a,int b=1, int c=2); * whether to support mixing named and non-named arguments in 1 call (python does) fun(0,b=1) * whether to allow both calling conventions: fun(0,1) fun(0,b=1) * whether to allow both calling conventions: fun(0,1) fun(0,b=1) * whether to tag functions callable by named params via attribute (check is done at CT): that'll indicate clearly we want to freeze names in the API named void fun(int a,int b=1, int c=2); * alternatively to above, whether to use ':' instead of '=' in function declaration void fun(int a,int b:1, int c:2); //now it's only callable by name * whether to support skipping and reordering optional args ; I argued we need to for this to be useful enough Timothee CourInteresting, the "doesn't not support passing the arguments out of order." can be seen either as a (temporary or not) implementation >>limitation OR as a feature.
Mar 26 2013
On Wednesday, 27 March 2013 at 03:29:24 UTC, Timothee Cour wrote:Named parameters are only interesting if we can skip some optional parameters. This allows the python-like syntax of specifying only a subset of parameters; otherwise this isn't very interesting. This is used heavily in python and makes code * self-documenting * avoids DRY (don't specify unused params) * avoids boilerplate of introducing auxiliary option structs and fields to it Here are just 3 examples that hopefully will convince some that named params are useful and not ugly. ---- //inspired from python's matplotlib; many more options configurable, which are set to reasonable defaults plot(x=1,y=2,color='red',width=3); //here's another one (cf inspired by scons / waf build tools in python) compile(input=["foo.cpp"] , run=true, debug=true, ldflags="-lcurl", output_dir="build"); //other example: setting optional params in a classifier trainSVM(input=X, labels=Y, C=1000, crossValidate=true, loss=squareHingeLoss) ----How is that any better than the monadic solution proposed in the thread and that dn't require any language addition ?
Mar 26 2013
On Wednesday, 27 March 2013 at 03:29:24 UTC, Timothee Cour wrote:I'd say named parameters are *more* interesting with skipping and re-ordering, but still incredibly valuable even without. Let us get them in people's hands first (and start the addiction process going...bwahahaha!) Let people experience first hand how awesome they are in a quick, doable form. (Feel free to contribute code that implements those skipping and re-ordering features...) Status update: I fixed the only known bug, and added a feature. a. Named parameters now flow into variadic template arguments without a hitch. In other words, this compiles: void test(A...)(A a) {} void main () { test(b: 33.3 c: 44.4); } b. There is an name-matching escape mechanism now. It uses _underscores. If your function looks like: void f(int a, int _b) {} then you can call it like this: f(a:1, anyLabelYouWant: 3); (Actually this was necessitated by how dmd treats variadic actual arguments; it calls them _param_0, _param_1, ..., internally. I'm still going to call this escape-mechanism a feature, though.) Here's the latest (see the named_parameters branch specifically) https://github.com/glycerine/dmd/tree/named_parameters This passes all tests. Try it out. Try and break it.Named parameters are only interesting if we can skip some optional parameters.Interesting, the "doesn't not support passing the arguments out of order." can be seen either as a (temporary or not) implementation >>limitation OR as a feature.
Mar 26 2013
On Tuesday, 26 March 2013 at 09:31:53 UTC, renoX wrote:The things to check is how this feature would work with optional parameters..Another thing to check is whether there is enough information in the object files to link across separately compiled objects. Correct me if I'm wrong, but I don't think object files include the names of struct fields, nor the names of argument parameters. You might have to do what objective-C does, which is merge the parameter names into the name of the function.
Mar 26 2013
On Tuesday, 26 March 2013 at 20:28:39 UTC, J wrote:On Tuesday, 26 March 2013 at 09:31:53 UTC, renoX wrote:Or maybe there are no link time issues. If named parameters are only ever supplying additional type-check-time information, then there would be zero impact at link time. Correct?The things to check is how this feature would work with optional parameters..Another thing to check is whether there is enough information in the object files to link across separately compiled objects. Correct me if I'm wrong, but I don't think object files include the names of struct fields, nor the names of argument parameters. You might have to do what objective-C does, which is merge the parameter names into the name of the function.
Mar 26 2013