www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Named arguments

reply Andrey <andrey kabylin.ru> writes:
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
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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.:
 int sum(in int a, in int b) {

     return a + b;

 }

 sum(a = 1, b = 2);
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 Davis
Oct 24
parent jmh530 <john.michael.hall gmail.com> writes:
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 Davis
Some good points. I realized that most of the languages that have named parameters are dynamically typed ones (Python/R) or ones with VMs (C#/Scala). Fortran has named parameters and function overloading, but I think it's a little quirky and not like C++ and D as far as I can tell.
Oct 24
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
next sibling parent jmh530 <john.michael.hall gmail.com> writes:
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
prev sibling next sibling parent reply Andrey <andrey kabylin.ru> writes:
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: [...]
 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. ...
good alternative, I already forgot about the power of structs after Java.
Oct 25
parent reply Andrea Fontana <nospam example.com> writes:
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
parent Cym13 <cpicard openmailbox.org> writes:
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:
 [...]
It would be a very good solution if we can init a struct using its named field. Something like: [...]
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
Oct 25
prev sibling parent Jacob Carlborg <doob me.com> writes:
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:
 [...]
 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); }
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 Carlborg
Oct 25
prev sibling next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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 via
 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.
Except 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 Davis
Oct 24
parent reply bauss <jj_1337 live.dk> writes:
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:
 On Tue, Oct 24, 2017 at 01:22:41PM -0600, Jonathan M Davis via
 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.
Except 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 Davis
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);
Oct 24
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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:
 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 via

 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.
Except 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 Davis
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);
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 Davis
Oct 24
parent reply bauss <jj_1337 live.dk> writes:
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:
 [...]
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. [...]
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.
Oct 25
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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:
 On Wednesday, October 25, 2017 06:23:52 bauss via Digitalmars-d

 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. [...]
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.
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 Davis
Oct 25
prev sibling next sibling parent reply Gary Willoughby <dev nomad.so> writes:
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.:

 int sum(in int a, in int b) {
     return a + b;
 }

 sum(a = 1, b = 2);
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.d
Oct 25
parent reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
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:
 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);
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.d
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.
Oct 25
parent reply jmh530 <john.michael.hall gmail.com> writes:
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
next sibling parent reply bauss <jj_1337 live.dk> writes:
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:
 [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.
That depends. It's a common pattern in D to pass them as template parameters, in fact most functionality in std.algorithm supports it.
Oct 25
parent reply jmh530 <john.michael.hall gmail.com> writes:
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
parent bauss <jj_1337 live.dk> writes:
On Wednesday, 25 October 2017 at 16:40:52 UTC, jmh530 wrote:
 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)()
Oh yeah of course not like that
Oct 25
prev sibling next sibling parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
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:
 [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.
Oops!
Oct 25
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
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
parent jmh530 <john.michael.hall gmail.com> writes:
On Friday, 27 October 2017 at 06:45:03 UTC, Jacob Carlborg wrote:
 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"]
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); }
Oct 27
prev sibling parent codephantom <me noyb.com> writes:
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