digitalmars.D - Named arguments
- Andrey (2/6) Oct 24 2017
- Jonathan M Davis (23/32) Oct 24 2017 Named arguments are not something that C-based languages typically have,...
- jmh530 (7/23) Oct 24 2017 Some good points. I realized that most of the languages that have
- H. S. Teoh (78/92) Oct 24 2017 If a function has too many parameters, or only a small subset of
- jmh530 (12/16) Oct 24 2017 What about something that's a little uglier, but could be done
- Andrey (3/38) Oct 25 2017 good alternative, I already forgot about the power of structs
- Andrea Fontana (27/29) Oct 25 2017 It would be a very good solution if we can init a struct using
- Cym13 (4/9) Oct 25 2017 In case you're not already aware of it there's a DIP in
- Jacob Carlborg (6/39) Oct 25 2017 For this, it would be nice if static initialization [1] work without
- Jonathan M Davis (14/27) Oct 24 2017 Except that things get a bit interesting with regards to stuff like .di
- bauss (19/53) Oct 24 2017 Pardon me, but I don't understand how named arguments can break
- Jonathan M Davis (35/93) Oct 24 2017 The issue I'm talking about is that if we had named arguments, and the n...
- bauss (6/14) Oct 25 2017 If you change function definitions you should provide fall-backs
- Jonathan M Davis (5/22) Oct 25 2017 Sure, but you don't have to provide fallbacks if you're just changing th...
- Gary Willoughby (5/12) Oct 25 2017 This has been discussed to death:
- Bastiaan Veelo (41/54) Oct 25 2017 Thanks for that link. Unaware of CyberShadow's work (which
- jmh530 (4/17) Oct 25 2017 You're passing the function arguments as template parameters.
- bauss (4/22) Oct 25 2017 That depends. It's a common pattern in D to pass them as template
- jmh530 (10/13) Oct 25 2017 std.algorithm has a lot of passing lambdas as template
- bauss (2/16) Oct 25 2017 Oh yeah of course not like that
- Bastiaan Veelo (2/20) Oct 25 2017 Oops!
- Jacob Carlborg (17/19) Oct 26 2017 No problem:
- jmh530 (13/30) Oct 27 2017 Color me surprised. Even the below compiles and runs without error
- codephantom (9/10) Oct 26 2017 Named arguments for functions:
Hello, why there are no named arguments for functions like, for example, in kotlin i.e.:int sum(in int a, in int b) { return a + b; } sum(a = 1, b = 2);
Oct 24 2017
On Tuesday, October 24, 2017 17:30:27 Andrey via Digitalmars-d wrote:Hello, why there are no named arguments for functions like, for example, in kotlin i.e.:Named arguments are not something that C-based languages typically have, and D has a very strong C/C++ heritage. There are some folks who would like to see them added to the language, but a DIP would have to be created and approved by Walter and Andrei for that to happen. IIRC, in the past, Walter didn't think that they interacted well with how D does function overloading, but I don't know what he thinks now. Some folks have managed to implement them using a library solution, and if you go digging in the newsgroup/forum/mailing list history for "named parameters" or "named arguments," you should be able to find discussions on that. Personally, I don't want them in D. If you have enough arguments that it matters, then the function probably has too many parameters or too many similar parameters. And as a library writer, I don't want to have the parameter names be part of the API. There are already enough problems getting the type and function names right without having to worry about bikeshedding over parameter names as well, and if we had named arguments, then you couldn't change parameter names without breaking code. It also wouldn't play well with separate compilation unless the parameter names were mangled into the function names, and symbol names in D are already too often too long due to idioms like Voldemort types creating really long symbol names. Recent work on the compiler has reduced that problem, but adding more information to mangled names would definitely not help. - Jonathan M Davisint sum(in int a, in int b) { return a + b; } sum(a = 1, b = 2);
Oct 24 2017
On Tuesday, 24 October 2017 at 19:22:41 UTC, Jonathan M Davis wrote:Personally, I don't want them in D. If you have enough arguments that it matters, then the function probably has too many parameters or too many similar parameters. And as a library writer, I don't want to have the parameter names be part of the API. There are already enough problems getting the type and function names right without having to worry about bikeshedding over parameter names as well, and if we had named arguments, then you couldn't change parameter names without breaking code. It also wouldn't play well with separate compilation unless the parameter names were mangled into the function names, and symbol names in D are already too often too long due to idioms like Voldemort types creating really long symbol names. Recent work on the compiler has reduced that problem, but adding more information to mangled names would definitely not help. - Jonathan M DavisSome good points. I realized that most of the languages that have named parameters are dynamically typed ones (Python/R) or ones overloading, but I think it's a little quirky and not like C++ and D as far as I can tell.
Oct 24 2017
On Tue, Oct 24, 2017 at 01:22:41PM -0600, Jonathan M Davis via Digitalmars-d wrote: [...]Personally, I don't want them in D. If you have enough arguments that it matters, then the function probably has too many parameters or too many similar parameters.If a function has too many parameters, or only a small subset of parameters need to be something other than some default value, or the set of parameters may change frequently, then my default approach is to abstract the parameters into a struct: struct OutputArgs { string filename; int width = 300; int height = 300; string fontDir = "/usr/share/local/fonts/arial.ttf"; int fontSize = 12; Color background = Color.black; Color foreground = Color.white; bool antiAlias = true; } void generateOutput(OutputArgs args) { ... } void main() { // Setup function arguments. // N.B.: only .filename needs to be explicitly set. OutputArgs args; args.filename = "/tmp/output.png"; // Call function with mostly default arguments. generateOutput(args); } This approach means that if you ever need to add more parameters to OutputArgs, as long as the default value is compatible with previous behaviour, you won't have to change existing code. Also, the caller can set the arguments in any order without needing to memorize which parameter is in which position.And as a library writer, I don't want to have the parameter names be part of the API. There are already enough problems getting the type and function names right without having to worry about bikeshedding over parameter names as well, and if we had named arguments, then you couldn't change parameter names without breaking code.There are times, however, when named parameters might be desirable. Self-documenting code is one. Rather than: auto x = foo(1, 2, 3); it would be more self-documenting if written as: // (Hypothetical syntax) auto x = foo(width: 1, height: 2, userId: 3); There are ways around this, of course. Here's a somewhat klunky, but workable solution: struct Width { int value; alias value this; } struct Height { int value; alias value this; } struct UserId { int value; alias value this; } int foo(Width w, Height h, UserId id) { ... } auto x = foo(Width(1), Height(2), UserId(3)); Inside the body of foo, you can freely assign w, h, and id to int variables, because of the `alias this`. But the declared parameter types of foo demands the user to use self-documenting syntax. And presumably, if your code already has values of the requisite types, you can pass them directly without needing to repeat the constructor name: int bar(Width w, Height h) { UserId id = getUserId(); foo(w, h, id); // no need to type Width(w), etc. } But of course, this scheme only works well if you have a common set of parameters that are used in many places. Otherwise you'll end up having to declare tons of structs that are only ever used to call 1 or 2 functions, which would be a lot of typing for little benefit. You could, of course, write a mixin template to factor out the boilerplate (somewhat), but even that doesn't necessarily cover all possible use cases.It also wouldn't play well with separate compilation unless the parameter names were mangled into the function names, and symbol names in D are already too often too long due to idioms like Voldemort types creating really long symbol names. Recent work on the compiler has reduced that problem, but adding more information to mangled names would definitely not help.[...] Nah. Parameter names are a concept only necessary at compile-time. All you need is to import the function declaration with the right parameter names, and on the caller's side the compiler will always emit the arguments in the right order. So no need to mangle parameter names at all. T -- An imaginary friend squared is a real enemy.
Oct 24 2017
On Tuesday, 24 October 2017 at 20:36:00 UTC, H. S. Teoh wrote:[snip] it would be more self-documenting if written as: // (Hypothetical syntax) auto x = foo(width: 1, height: 2, userId: 3);What about something that's a little uglier, but could be done with D magic? For instance: auto x = foo!(["width", "height", "userId"])(1, 2, 3) So for instance, you could have some original function, like below namedParam("width", "height", "userId") auto x = _foo(int width, int height, UserId userId) { } and then some D magic inserts a new function that is like auto foo(string[] names)(...) { } and then processes names, mixing in the correct named/typed variables and then returning a call to _foo with those variables.
Oct 24 2017
On Tuesday, 24 October 2017 at 20:36:00 UTC, H. S. Teoh wrote:On Tue, Oct 24, 2017 at 01:22:41PM -0600, Jonathan M Davis via Digitalmars-d wrote: [...]good alternative, I already forgot about the power of structs after Java.Personally, I don't want them in D. If you have enough arguments that it matters, then the function probably has too many parameters or too many similar parameters.If a function has too many parameters, or only a small subset of parameters need to be something other than some default value, or the set of parameters may change frequently, then my default approach is to abstract the parameters into a struct: struct OutputArgs { string filename; int width = 300; int height = 300; string fontDir = "/usr/share/local/fonts/arial.ttf"; int fontSize = 12; Color background = Color.black; Color foreground = Color.white; bool antiAlias = true; } void generateOutput(OutputArgs args) { ... } void main() { // Setup function arguments. // N.B.: only .filename needs to be explicitly set. OutputArgs args; args.filename = "/tmp/output.png"; // Call function with mostly default arguments. generateOutput(args); } This approach means that if you ever need to add more parameters to OutputArgs, as long as the default value is compatible with previous behaviour, you won't have to change existing code. Also, the caller can set the arguments in any order without needing to memorize which parameter is in which position. ...
Oct 25 2017
On Wednesday, 25 October 2017 at 07:46:49 UTC, Andrey wrote:good alternative, I already forgot about the power of structs after Java.It would be a very good solution if we can init a struct using its named field. Something like: struct S { int a; int b; int c; } S test = { a:1, b:4; }; So: void myFunc(S param); => myFunc({a:1, b:3}); I know: you say that this has trouble with overloading: void myFunc(S param); void myFunc(T param); But the same goes for this: void f(float i) { writeln("float"); } void f(double i) { writeln("double"); } f(1); And simply it won't compile. (for template arguments too) You can solve this doing: f(1.0f); or f(1.0); In the same way you can solve first problem calling: myFunc({a:1, b:3}.to!S) or myFunc(S{a:1, b:3}) or myFunc(cast(S){a:1, b:3}) or some other exotic syntax you want add to language, if needed (rarely, i guess). And the same goes for: auto blah = {a:1, b:2};
Oct 25 2017
On Wednesday, 25 October 2017 at 10:32:19 UTC, Andrea Fontana wrote:On Wednesday, 25 October 2017 at 07:46:49 UTC, Andrey wrote:In case you're not already aware of it there's a DIP in preparation just for that: https://github.com/dlang/DIPs/pull/71[...]It would be a very good solution if we can init a struct using its named field. Something like: [...]
Oct 25 2017
On 2017-10-24 22:36, H. S. Teoh wrote:On Tue, Oct 24, 2017 at 01:22:41PM -0600, Jonathan M Davis via Digitalmars-d wrote: [...]For this, it would be nice if static initialization [1] work without temporary variables. Then it would be pretty close to named parameters. [1] https://dlang.org/spec/struct.html#static_struct_init -- /Jacob CarlborgPersonally, I don't want them in D. If you have enough arguments that it matters, then the function probably has too many parameters or too many similar parameters.If a function has too many parameters, or only a small subset of parameters need to be something other than some default value, or the set of parameters may change frequently, then my default approach is to abstract the parameters into a struct: struct OutputArgs { string filename; int width = 300; int height = 300; string fontDir = "/usr/share/local/fonts/arial.ttf"; int fontSize = 12; Color background = Color.black; Color foreground = Color.white; bool antiAlias = true; } void generateOutput(OutputArgs args) { ... } void main() { // Setup function arguments. // N.B.: only .filename needs to be explicitly set. OutputArgs args; args.filename = "/tmp/output.png"; // Call function with mostly default arguments. generateOutput(args); }
Oct 25 2017
On Tuesday, October 24, 2017 13:36:00 H. S. Teoh via Digitalmars-d wrote:On Tue, Oct 24, 2017 at 01:22:41PM -0600, Jonathan M Davis viaExcept that things get a bit interesting with regards to stuff like .di files. Without the parameter names being mangled in, it would be possible for the parameter names in the .di files to not match the ones in the .d files. It's possible for that now, but right now, it doesn't matter, whereas with named arguments, it would matter. To some extent, you could probably get away with it, because the code that compiles against the .di files wouldn't normally be compiled against the .d files or vice versa, but it means that switching whether you used the .di files or the .d files could break code, whereas now, it wouldn't. Now, .di files are kind of terrible to use anyway, but introducing named arguments would just make them even more fragile if the parameter names aren't part of the function's mangled name. - Jonathan M DavisIt also wouldn't play well with separate compilation unless the parameter names were mangled into the function names, and symbol names in D are already too often too long due to idioms like Voldemort types creating really long symbol names. Recent work on the compiler has reduced that problem, but adding more information to mangled names would definitely not help.[...] Nah. Parameter names are a concept only necessary at compile-time. All you need is to import the function declaration with the right parameter names, and on the caller's side the compiler will always emit the arguments in the right order. So no need to mangle parameter names at all.
Oct 24 2017
On Tuesday, 24 October 2017 at 22:08:57 UTC, Jonathan M Davis wrote:On Tuesday, October 24, 2017 13:36:00 H. S. Teoh via Digitalmars-d wrote:Pardon me, but I don't understand how named arguments can break anything by being added, as long as you don't add an additional syntax to the function declaration. void foo(int bar, int baz) { } in .di void foo(int bar, int baz); ... Can be called like: foo(1, 2); foo(bar: 1, baz: 2); becomes foo(1, 2); foo(baz: 2, bar: 1); becomes foo(1, 2); because it matches the argument index. int bar = 1; int baz = 2; foo(bar, baz);On Tue, Oct 24, 2017 at 01:22:41PM -0600, Jonathan M Davis viaExcept that things get a bit interesting with regards to stuff like .di files. Without the parameter names being mangled in, it would be possible for the parameter names in the .di files to not match the ones in the .d files. It's possible for that now, but right now, it doesn't matter, whereas with named arguments, it would matter. To some extent, you could probably get away with it, because the code that compiles against the .di files wouldn't normally be compiled against the .d files or vice versa, but it means that switching whether you used the .di files or the .d files could break code, whereas now, it wouldn't. Now, .di files are kind of terrible to use anyway, but introducing named arguments would just make them even more fragile if the parameter names aren't part of the function's mangled name. - Jonathan M DavisIt also wouldn't play well with separate compilation unless the parameter names were mangled into the function names, and symbol names in D are already too often too long due to idioms like Voldemort types creating really long symbol names. Recent work on the compiler has reduced that problem, but adding more information to mangled names would definitely not help.[...] Nah. Parameter names are a concept only necessary at compile-time. All you need is to import the function declaration with the right parameter names, and on the caller's side the compiler will always emit the arguments in the right order. So no need to mangle parameter names at all.
Oct 24 2017
On Wednesday, October 25, 2017 06:23:52 bauss via Digitalmars-d wrote:On Tuesday, 24 October 2017 at 22:08:57 UTC, Jonathan M Davis wrote:The issue I'm talking about is that if we had named arguments, and the names of the parameters in .di and .d files didn't match, and named arguments were used, then changing whether the .di file or .d file were used would break code. e.g. .di: void foo(int a, int b); .d: void foo(int c, int d); Then this code foo(a : 4, b : 7); would compile with the .di file but not the .d file. That's not the end of the world, but it makes .di files even more fragile than they already are. Adding named parameters would not break any existing code, but it would introduce more ways to break code. Right now, no code anywhere has to care about parameter names except the function that has those parameters. There is no dependency on those names. You don't even have to have parameter names in a .di file if you don't want to - all that matters is the types. A function's parameter names can be changed at any time without breaking _any_ code that calls that function. But as soon as we have named arguments, suddenly, you can't change parameter names anymore than you can change the name of a function, or you risk breaking code, and that's a _huge_ negative IMHO. It also means more bikeshedding over names, because suddenly the parameter names are part of the API. It's even worse when you consider that most parameter names in existing code were not chosen with the idea that they would be part of the function's API, because we don't currently have named arguments in D. IMHO, it's already annoying enough how locked down things are once you put them out in the wild for others to use (at least if you care about not breaking the code of anyone using any code you make available). I don't want to see yet more added to the list of things that you can't change, because it might break someone's code, and adding named arguments to D definitely would do that, because it would make the parameter names part of the API, which they're not right now. - Jonathan M DavisOn Tuesday, October 24, 2017 13:36:00 H. S. Teoh via Digitalmars-d wrote:Pardon me, but I don't understand how named arguments can break anything by being added, as long as you don't add an additional syntax to the function declaration. void foo(int bar, int baz) { } in .di void foo(int bar, int baz); ... Can be called like: foo(1, 2); foo(bar: 1, baz: 2); becomes foo(1, 2); foo(baz: 2, bar: 1); becomes foo(1, 2); because it matches the argument index. int bar = 1; int baz = 2; foo(bar, baz);On Tue, Oct 24, 2017 at 01:22:41PM -0600, Jonathan M Davis viaExcept that things get a bit interesting with regards to stuff like .di files. Without the parameter names being mangled in, it would be possible for the parameter names in the .di files to not match the ones in the .d files. It's possible for that now, but right now, it doesn't matter, whereas with named arguments, it would matter. To some extent, you could probably get away with it, because the code that compiles against the .di files wouldn't normally be compiled against the .d files or vice versa, but it means that switching whether you used the .di files or the .d files could break code, whereas now, it wouldn't. Now, .di files are kind of terrible to use anyway, but introducing named arguments would just make them even more fragile if the parameter names aren't part of the function's mangled name. - Jonathan M DavisIt also wouldn't play well with separate compilation unless the parameter names were mangled into the function names, and symbol names in D are already too often too long due to idioms like Voldemort types creating really long symbol names. Recent work on the compiler has reduced that problem, but adding more information to mangled names would definitely not help.[...] Nah. Parameter names are a concept only necessary at compile-time. All you need is to import the function declaration with the right parameter names, and on the caller's side the compiler will always emit the arguments in the right order. So no need to mangle parameter names at all.
Oct 24 2017
On Wednesday, 25 October 2017 at 06:48:26 UTC, Jonathan M Davis wrote:On Wednesday, October 25, 2017 06:23:52 bauss via Digitalmars-d wrote:If you change function definitions you should provide fall-backs IMO and then deprecate the old function definition. Of course that's a world full of rainbows and unicorns, where people actually care about such things.[...]The issue I'm talking about is that if we had named arguments, and the names of the parameters in .di and .d files didn't match, and named arguments were used, then changing whether the .di file or .d file were used would break code. e.g. [...]
Oct 25 2017
On Wednesday, October 25, 2017 13:56:51 bauss via Digitalmars-d wrote:On Wednesday, 25 October 2017 at 06:48:26 UTC, Jonathan M Davis wrote:Sure, but you don't have to provide fallbacks if you're just changing the implementation, and right now, the parameter names are part of the implementation, whereas with named arguments, they would be part of the API. - Jonathan M DavisOn Wednesday, October 25, 2017 06:23:52 bauss via Digitalmars-d wrote:If you change function definitions you should provide fall-backs IMO and then deprecate the old function definition. Of course that's a world full of rainbows and unicorns, where people actually care about such things.[...]The issue I'm talking about is that if we had named arguments, and the names of the parameters in .di and .d files didn't match, and named arguments were used, then changing whether the .di file or .d file were used would break code. e.g. [...]
Oct 25 2017
On Tuesday, 24 October 2017 at 17:30:27 UTC, Andrey wrote:Hello, why there are no named arguments for functions like, for example, in kotlin i.e.:This has been discussed to death: http://forum.dlang.org/post/n8024o$dlj$1 digitalmars.com and you can do it as a library so no need to go in the language: https://github.com/CyberShadow/ae/blob/master/utils/meta/args.dint sum(in int a, in int b) { return a + b; } sum(a = 1, b = 2);
Oct 25 2017
On Wednesday, 25 October 2017 at 08:09:52 UTC, Gary Willoughby wrote:On Tuesday, 24 October 2017 at 17:30:27 UTC, Andrey wrote:Thanks for that link. Unaware of CyberShadow's work (which probably is of better quality) I just had a go: ``` void foo(int one, int two, double three, string four) { import std.stdio; writeln("one=", one, "; two=", two, "; three=", three, "; four=", four); } int first = 1; void main() { // Ordinary: foo(first, 2, 3.0, "4"); // Prints one=1; two=2; three=3; four=4 // Named arguments: named!(foo, "four", "4", "two", 2, "one", first, "three", 3.0); // idem } import std.traits; auto named(alias F, args...)() if (isFunction!F) { import std.meta; alias names = Stride!(2, args[0..$]); alias values = Stride!(2, args[1..$]); bool cmp(alias valueA, alias valueB)() { import std.algorithm.searching; return countUntil([ParameterIdentifierTuple!F], names[staticIndexOf!(valueA, values)]) < countUntil([ParameterIdentifierTuple!F], names[staticIndexOf!(valueB, values)]); } return F(staticSort!(cmp, values)); } ``` Not battle tested, but it works here. There is a limitation that the variable "first" cannot be local, but people better at this stuff may be able to remove that. Bastiaan.Hello, why there are no named arguments for functions like, for example, in kotlin i.e.:This has been discussed to death: http://forum.dlang.org/post/n8024o$dlj$1 digitalmars.com and you can do it as a library so no need to go in the language: https://github.com/CyberShadow/ae/blob/master/utils/meta/args.dint sum(in int a, in int b) { return a + b; } sum(a = 1, b = 2);
Oct 25 2017
On Wednesday, 25 October 2017 at 12:40:47 UTC, Bastiaan Veelo wrote:[snip] int first = 1; void main() { // Ordinary: foo(first, 2, 3.0, "4"); // Prints one=1; two=2; three=3; four=4 // Named arguments: named!(foo, "four", "4", "two", 2, "one", first, "three", 3.0); // idem }You're passing the function arguments as template parameters. Usually you want them to be able to be passed at run-time.
Oct 25 2017
On Wednesday, 25 October 2017 at 14:58:50 UTC, jmh530 wrote:On Wednesday, 25 October 2017 at 12:40:47 UTC, Bastiaan Veelo wrote:That depends. It's a common pattern in D to pass them as template parameters, in fact most functionality in std.algorithm supports it.[snip] int first = 1; void main() { // Ordinary: foo(first, 2, 3.0, "4"); // Prints one=1; two=2; three=3; four=4 // Named arguments: named!(foo, "four", "4", "two", 2, "one", first, "three", 3.0); // idem }You're passing the function arguments as template parameters. Usually you want them to be able to be passed at run-time.
Oct 25 2017
On Wednesday, 25 October 2017 at 15:33:05 UTC, bauss wrote:That depends. It's a common pattern in D to pass them as template parameters, in fact most functionality in std.algorithm supports it.std.algorithm has a lot of passing lambdas as template parameters, but not so much for parameters you would expect to be run-time parameters. Consider count: size_t count(alias pred = "a == b", Range, E)(Range haystack, E needle) it's not size_t count(alias pred = "a == b", Range haystack, E needle, Range, E)()
Oct 25 2017
On Wednesday, 25 October 2017 at 16:40:52 UTC, jmh530 wrote:On Wednesday, 25 October 2017 at 15:33:05 UTC, bauss wrote:Oh yeah of course not like thatThat depends. It's a common pattern in D to pass them as template parameters, in fact most functionality in std.algorithm supports it.std.algorithm has a lot of passing lambdas as template parameters, but not so much for parameters you would expect to be run-time parameters. Consider count: size_t count(alias pred = "a == b", Range, E)(Range haystack, E needle) it's not size_t count(alias pred = "a == b", Range haystack, E needle, Range, E)()
Oct 25 2017
On Wednesday, 25 October 2017 at 14:58:50 UTC, jmh530 wrote:On Wednesday, 25 October 2017 at 12:40:47 UTC, Bastiaan Veelo wrote:Oops![snip] int first = 1; void main() { // Ordinary: foo(first, 2, 3.0, "4"); // Prints one=1; two=2; three=3; four=4 // Named arguments: named!(foo, "four", "4", "two", 2, "one", first, "three", 3.0); // idem }You're passing the function arguments as template parameters. Usually you want them to be able to be passed at run-time.
Oct 25 2017
On 2017-10-25 16:58, jmh530 wrote:You're passing the function arguments as template parameters. Usually you want them to be able to be passed at run-time.No problem: $ cat main.d import std.stdio; void foo(args...)() { writeln(args); } void main(string[] args) { foo!(args); } $ dmd main.d $ ./main foo bar ["./main", "foo", "bar"] -- /Jacob Carlborg
Oct 26 2017
On Friday, 27 October 2017 at 06:45:03 UTC, Jacob Carlborg wrote:On 2017-10-25 16:58, jmh530 wrote:Color me surprised. Even the below compiles and runs without error import std.stdio; void foo(args...)() { writeln(args); } void main() { int x1 = 1; int x2 = x1 + 1; foo!(x1, x2); }You're passing the function arguments as template parameters. Usually you want them to be able to be passed at run-time.No problem: $ cat main.d import std.stdio; void foo(args...)() { writeln(args); } void main(string[] args) { foo!(args); } $ dmd main.d $ ./main foo bar ["./main", "foo", "bar"]
Oct 27 2017
On Tuesday, 24 October 2017 at 17:30:27 UTC, Andrey wrote:Hello, why there are no named arguments for functions..Named arguments for functions: - is useful..perhaps. - is desirable..debatable. - can provide a significant service to real programmers...?? If a case is to be made, that last item is where it needs to focus its attention. Useful and desirable is just syntactic sugar...and too many languages focus on adding syntactic sugar...I don't like it.
Oct 26 2017