March 23, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | 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) I've heard it was a big boost for C# when it got support for default arguments and named parameters. It made it a lot easier to integrate with COM. -- /Jacob Carlborg |
March 23, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | 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: >> 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 > > 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) 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. |
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | 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:
>> On Saturday, 23 March 2013 at 15:00:13 UTC, bearophile wrote:
>>> 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
>>
>> 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)
>
> 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.
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.
|
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to J | 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! |
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to timotheecour | > 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? |
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to timotheecour | 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 |
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | 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 |
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Sun, Mar 24, 2013 at 11:15 AM, Jacob Carlborg <doob@me.com> wrote:
>> 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.
You're right.
|
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to timotheecour | 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 |
March 24, 2013 Re: this is almost a workaround for the lack of named parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | > 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! |
Copyright © 1999-2021 by the D Language Foundation