digitalmars.D - Dream Feature Regarding Default Arguments
- Nick Sabalausky (38/38) Apr 05 2014 I realize this isn't the time for such a thing to be added to D, but I
- Nick Sabalausky (5/14) Apr 05 2014 Actually, that last line should be:
- Mason McGill (24/43) Apr 06 2014 I think D is actually one of the better languages around in terms
- JN (5/16) Apr 06 2014 Wouldn't it be better to have named parameters like in Python or
- Nick Sabalausky (5/9) Apr 06 2014 Named parameters would be a good compliment to this (and I have always
- Frustrated (6/20) Apr 06 2014 How bout
- Nick Sabalausky (7/9) Apr 06 2014 That isn't too bad (VB6 had it IIRC), but the caller still has to
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (2/4) Apr 07 2014 Reusing the keyword default here is clever :)
- w0rp (3/7) Apr 07 2014 Named parameters would be nice to have. I'm not sure how you
- Frustrated (19/29) Apr 07 2014 it would be relatively easy.
-
Meta
(9/28)
Apr 07 2014
C# uses
:, like the follow. - Colden Cullen (3/47) Apr 07 2014 I like this a lot more. It looks similar to the associative array
- Idan Arye (24/24) Apr 07 2014 While we're at it - I would also like to see the two forms of
- Byron (7/19) Apr 08 2014 static structs can be initialized by name, maybe that syntax could be
I realize this isn't the time for such a thing to be added to D, but I thought I'd put the idea out there, FWIW: I find myself frequently needing to design APIs that work like this: func( [optionalFoo], [optionalBar] ) Typically, that's not permitted in C-style languages, including D. They only allow this: func( [optionalFoo, [optionalBar]] ) This restriction is necessary because, if the params take compatible types (ex: func(int,int)) and the caller only provides one, then there's no other way to tell which parameter the caller was trying to provide. But when the params are different incompatible types, there's no ambiguity. This leads to the following awkward, noisy, hard-to-read idioms which I find myself using very frequently (I'm pretty sure I've seen it in Phobos, too): void func(Foo foo=defaultFoo, Bar bar=defaultBar) {...} void func(Bar bar) { func(defaultFoo, bar); } or: void func(Foo foo, Bar bar=defaultBar) {...} void func(Bar bar=defaultBar) { func(defaultFoo, bar); } Worse still, if there are other overloads, params, templates, etc, then this gets REALLY hairy, REALLY fast. It becomes very difficult to read, difficult to test, difficult to maintain, and difficult for users to grok the function's generated documentation. Such a big mess for such a trivially simple API: func( [optionalFoo], [optionalBar] ) It would be *fantastic* if D recognized the disambiguation of using incompatible types and permitted this: interface Foo {} interface Bar {} class FooBar : Foo, Bar {} void func(Foo foo=someFoo, Bar bar=someBar) {...} func(myFoo); // Unambiguous, OK func(myBar); // Unambiguous, OK func(myFooBar); // Ambiguous, ERROR
Apr 05 2014
On 4/5/2014 9:26 PM, Nick Sabalausky wrote:It would be *fantastic* if D recognized the disambiguation of using incompatible types and permitted this: interface Foo {} interface Bar {} class FooBar : Foo, Bar {} void func(Foo foo=someFoo, Bar bar=someBar) {...} func(myFoo); // Unambiguous, OK func(myBar); // Unambiguous, OK func(myFooBar); // Ambiguous, ERRORActually, that last line should be: func(myFooBar); // Unambiguous, this is still interpreted as the first parameter (with the second parameter left as default) just as it is right now.
Apr 05 2014
On Sunday, 6 April 2014 at 01:33:36 UTC, Nick Sabalausky wrote:On 4/5/2014 9:26 PM, Nick Sabalausky wrote:I think D is actually one of the better languages around in terms of factoring this sort of thing out. Here's an example argument parser that lets you define pairs of optional arguments: http://pastebin.com/RaNfwH6X. It can be extended to allow n-tuples of optional arguments. Argument parsing is encapsulated so writers only have to declare one function template, with a constraint that clearly expresses intent: void func(Args...)(Args args) if (Pattern!(bool, AnyOf!(int, string)).matches!Args) { alias Parser = Pattern!(bool, AnyOf!(int, string)); auto parsedArgs = Parser.parse(tuple(args), tuple(false, 0, "0")); writeln(parsedArgs); } void main() { func(true); // true, 0, "0" func(true, 1); // true, 1, "0" func(true, "1"); // true, 0, "1" func(true, 1, "1"); // true, 1, "1" }It would be *fantastic* if D recognized the disambiguation of using incompatible types and permitted this: interface Foo {} interface Bar {} class FooBar : Foo, Bar {} void func(Foo foo=someFoo, Bar bar=someBar) {...} func(myFoo); // Unambiguous, OK func(myBar); // Unambiguous, OK func(myFooBar); // Ambiguous, ERRORActually, that last line should be: func(myFooBar); // Unambiguous, this is still interpreted as the first parameter (with the second parameter left as default) just as it is right now.
Apr 06 2014
On Sunday, 6 April 2014 at 01:26:21 UTC, Nick Sabalausky wrote:Such a big mess for such a trivially simple API: func( [optionalFoo], [optionalBar] ) It would be *fantastic* if D recognized the disambiguation of using incompatible types and permitted this: interface Foo {} interface Bar {} class FooBar : Foo, Bar {} void func(Foo foo=someFoo, Bar bar=someBar) {...} func(myFoo); // Unambiguous, OK func(myBar); // Unambiguous, OK func(myFooBar); // Ambiguous, ERRORWouldn't it be better to have named parameters like in Python or func(foo=myFoo) or func(bar=myBar) or func(foo=myFoo, bar=myBar) and there would be no ambiguity.
Apr 06 2014
On 4/6/2014 10:47 AM, JN wrote:Wouldn't it be better to have named parameters like in Python or func(foo=myFoo) or func(bar=myBar) or func(foo=myFoo, bar=myBar) and there would be no ambiguity.Named parameters would be a good compliment to this (and I have always wanted named parameters in D), but even with them it would still be nice to be able have neat-n-tidy implementations of func([foo],[bar]) APIs that don't require the use of named params.
Apr 06 2014
On Sunday, 6 April 2014 at 21:06:44 UTC, Nick Sabalausky wrote:On 4/6/2014 10:47 AM, JN wrote:How bout func(,,x,,y) or func(default, default, x, default, default, y)? where default is a keyword that substitutes the default value.Wouldn't it be better to have named parameters like in Python or func(foo=myFoo) or func(bar=myBar) or func(foo=myFoo, bar=myBar) and there would be no ambiguity.Named parameters would be a good compliment to this (and I have always wanted named parameters in D), but even with them it would still be nice to be able have neat-n-tidy implementations of func([foo],[bar]) APIs that don't require the use of named params.
Apr 06 2014
On Sunday, 6 April 2014 at 23:08:10 UTC, Frustrated wrote:How bout func(,,x,,y)That isn't too bad (VB6 had it IIRC), but the caller still has to care about the order of the params they're ignoring. Ie if you have func([foo],[bar]) then you can't just pass in a one-param foo-only or bar-only without worrying about the unimportant detail of the arbitrary ordering (unlike with the overload approach).
Apr 06 2014
func(default, default, x, default, default, y)? where default is a keyword that substitutes the default value.Reusing the keyword default here is clever :) I like it.
Apr 07 2014
On Sunday, 6 April 2014 at 14:47:28 UTC, JN wrote:Wouldn't it be better to have named parameters like in Python or func(foo=myFoo) or func(bar=myBar) or func(foo=myFoo, bar=myBar) and there would be no ambiguity.Named parameters would be nice to have. I'm not sure how you would implement them in D, though.
Apr 07 2014
On Monday, 7 April 2014 at 17:46:44 UTC, w0rp wrote:On Sunday, 6 April 2014 at 14:47:28 UTC, JN wrote:it would be relatively easy. void myfunc(name = int x) { } instead of void myfunc(int x) { } then myfunc(name = 4); or one could simply use the variable name void myfunc(int x) { } myfunc(x = 3); Of course assignments may not be valid, one could use := instead. myfunc(x := 3); One could build a template to do it how were but it would require calling the function as a string, e.g., template is passed the call as a string. The template gets the name of the function, looks up the parameter names, parses the arguments and generates the proper call string which is then mixed in. e.g., Named(q{myfunc(x := 3)}); => myfunc(3);Wouldn't it be better to have named parameters like in Python or func(foo=myFoo) or func(bar=myBar) or func(foo=myFoo, bar=myBar) and there would be no ambiguity.Named parameters would be nice to have. I'm not sure how you would implement them in D, though.
Apr 07 2014
On Monday, 7 April 2014 at 19:47:24 UTC, Frustrated wrote:it would be relatively easy. void myfunc(name = int x) { } instead of void myfunc(int x) { } then myfunc(name = 4); or one could simply use the variable name void myfunc(int x) { } myfunc(x = 3); Of course assignments may not be valid, one could use := instead. myfunc(x := 3); One could build a template to do it how were but it would require calling the function as a string, e.g., template is passed the call as a string. The template gets the name of the function, looks up the parameter names, parses the arguments and generates the proper call string which is then mixed in. e.g., Named(q{myfunc(x := 3)}); => myfunc(3);void TestFun(int i, string s = "", bool b) { //... } TestFun(i: 1, b: false); Is there any reason not to use this syntax? It doesn't *seem* to conflict with anything else.
Apr 07 2014
On Monday, 7 April 2014 at 20:00:39 UTC, Meta wrote:On Monday, 7 April 2014 at 19:47:24 UTC, Frustrated wrote:I like this a lot more. It looks similar to the associative array literal syntax, which is fitting.it would be relatively easy. void myfunc(name = int x) { } instead of void myfunc(int x) { } then myfunc(name = 4); or one could simply use the variable name void myfunc(int x) { } myfunc(x = 3); Of course assignments may not be valid, one could use := instead. myfunc(x := 3); One could build a template to do it how were but it would require calling the function as a string, e.g., template is passed the call as a string. The template gets the name of the function, looks up the parameter names, parses the arguments and generates the proper call string which is then mixed in. e.g., Named(q{myfunc(x := 3)}); => myfunc(3);void TestFun(int i, string s = "", bool b) { //... } TestFun(i: 1, b: false); Is there any reason not to use this syntax? It doesn't *seem* to conflict with anything else.
Apr 07 2014
While we're at it - I would also like to see the two forms of "variadic" named arguments: 1) Implicit Associative Array Version: works similar to Ruby void foo(string[string] args...){ foreach(k,v;args){ writeln("%s = %s",k,v); } } foo("a":"b","c":"d"); prints: a = b c = d 2) Templated Version: not sure about the declaration syntax. Maybe: void foo(T[...])(T args){ foreach(field;__traits(allMembers,T)){ writeln("%s(%s) = %s",field,typeof(__traits(getMember,args,field)).stringof,__traits(getMember,args,field)); } } foo(a:1,b:"2"); prints: a(int) = 1 b(string) = 2
Apr 07 2014
On Sat, 05 Apr 2014 21:26:17 -0400, Nick Sabalausky wrote:I realize this isn't the time for such a thing to be added to D, but I thought I'd put the idea out there, FWIW: I find myself frequently needing to design APIs that work like this: func( [optionalFoo], [optionalBar] ) Typically, that's not permitted in C-style languages, including D. They only allow this: func( [optionalFoo, [optionalBar]] )static structs can be initialized by name, maybe that syntax could be expanded upon? void foo( struct{ int a = 1; double b = 3.14; } ) { .. } ... foo( {b: 2} ); that or named tuples with an init value set?
Apr 08 2014