www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Simple proposal: syntax for named function arguments

reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Hi there,

I know, the topic has been brought up before. Anyhow: I just realized that
there is a really simply, straightforward solution:

The idea is taken from Python, where function arguments can be given either
in order of declaration (as in C/C++/D) or, qualified with names, in any
order. This is especially useful for functions with many optional
arguments.

Imagine a function:

--------------
void myfunc(int onearg,
            int anotherarg,
            int oneopt = 0,
            int anotheropt = 0,
            int yetanotheropt = 0,
            int reallyneatopt = 0) {
        ...
}
--------------

Ways to call this:
--------------
myfunc(1,2);         // no options
myfunc(1,2,3,4);     // two options
myfunc(1,2,3,4,5,6); // all options
myfunc(1,2,0,0,0,1); // this is annoying!
--------------

consider the last case: you only want to set reallyneatopt, but you have to
remember that is is the fourth option, and you have to know and supply all
the other default values manually.

My proposal would be to allow:
--------------
myfunc(1,2,reallyneatopt: 0);
myfunc(1, anotherarg: 2, reallyneatopt: 0);
myfunc(1, reallyneatopt: 0, anotherarg: 2);
myfunc(reallyneatopt: 0, anotherarg: 2, onearg: 1);
--------------
... all having the same result.

=========================
In short:

* function argument names in a call are prepended to the supplied value with
a colon as separator, this gives a syntax very similar to struct
initializers, and I cannot see any conflicts with existing syntax.

* any function argument (optional or mandatory) can be given either in order
or named.

* all unnamed argument values have to be given before any named ones.

* when calling overloaded functions, enough arguments have to be given in
order to resolve any ambiguities

To clarify the last point, consider:
---------------
void myfunc(int val,char *str,bit opt = 0) { /* A */ } 
void myfunc(char *str,int val,bit opt = 0) { /* B */ } // perfectly legal

myfunc(opt: 1,val: 3,str: "abc"); // ambiguous -> error
myfunc(3,opt: 1,str: "abc");      // A is selected
myfunc(str: "abc",opt: 1,val: 3); // B is selected
---------------
(Practically, this rule should not be too important, but the possible
ambiguity has to be resolved somehow.)
=========================

The change should be straightforward. The compiler will have to consider
argument names as part of the interface of a function, which might need a
bit of coding in the compiler - effort depending on the details of the
current implementation. The algorithm for resolving a call should then be
trivial.

Greetings,
Nobbi
Jun 23 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
I think it's nice idea, but post 1.0

"Norbert Nemec" <Norbert.Nemec gmx.de> wrote in message
news:cbds4l$31b6$1 digitaldaemon.com...
 Hi there,

 I know, the topic has been brought up before. Anyhow: I just realized that
 there is a really simply, straightforward solution:

 The idea is taken from Python, where function arguments can be given either
 in order of declaration (as in C/C++/D) or, qualified with names, in any
 order. This is especially useful for functions with many optional
 arguments.

 Imagine a function:

 --------------
 void myfunc(int onearg,
             int anotherarg,
             int oneopt = 0,
             int anotheropt = 0,
             int yetanotheropt = 0,
             int reallyneatopt = 0) {
         ...
 }
 --------------

 Ways to call this:
 --------------
 myfunc(1,2);         // no options
 myfunc(1,2,3,4);     // two options
 myfunc(1,2,3,4,5,6); // all options
 myfunc(1,2,0,0,0,1); // this is annoying!
 --------------

 consider the last case: you only want to set reallyneatopt, but you have to
 remember that is is the fourth option, and you have to know and supply all
 the other default values manually.

 My proposal would be to allow:
 --------------
 myfunc(1,2,reallyneatopt: 0);
 myfunc(1, anotherarg: 2, reallyneatopt: 0);
 myfunc(1, reallyneatopt: 0, anotherarg: 2);
 myfunc(reallyneatopt: 0, anotherarg: 2, onearg: 1);
 --------------
 ... all having the same result.

 =========================
 In short:

 * function argument names in a call are prepended to the supplied value with
 a colon as separator, this gives a syntax very similar to struct
 initializers, and I cannot see any conflicts with existing syntax.

 * any function argument (optional or mandatory) can be given either in order
 or named.

 * all unnamed argument values have to be given before any named ones.

 * when calling overloaded functions, enough arguments have to be given in
 order to resolve any ambiguities

 To clarify the last point, consider:
 ---------------
 void myfunc(int val,char *str,bit opt = 0) { /* A */ }
 void myfunc(char *str,int val,bit opt = 0) { /* B */ } // perfectly legal

 myfunc(opt: 1,val: 3,str: "abc"); // ambiguous -> error
 myfunc(3,opt: 1,str: "abc");      // A is selected
 myfunc(str: "abc",opt: 1,val: 3); // B is selected
 ---------------
 (Practically, this rule should not be too important, but the possible
 ambiguity has to be resolved somehow.)
 =========================

 The change should be straightforward. The compiler will have to consider
 argument names as part of the interface of a function, which might need a
 bit of coding in the compiler - effort depending on the details of the
 current implementation. The algorithm for resolving a call should then be
 trivial.

 Greetings,
 Nobbi
Jun 24 2004
parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Matthew wrote:

 I think it's nice idea, but post 1.0
The reason why it might be considered for 1.0 already: It has some influence on the design of library functions. There is a number of functions that need plenty of options to be flexible. Without this proposed feature, you would have to find some way to pass them in in some reasonable way. If you have named function arguments, the design gets much simpler. If the standard library is to converge as soon as the language reaches 1.0, then there might be reason to consider features that might affect the design. Furthermore: the feature is simple enough to just throw it in without much effort. Anyway: I won't press the issue. I just got carried away when I realized how nice and clean the solution actually might be. Ciao, Nobbi
Jun 24 2004
parent "Dan Williams" <dnews ithium.NOSPAM.net> writes:
I think this would be a great feature to include for version 1.0, if
possible, for all the reasons Norbert has outlined :)




"Norbert Nemec" <Norbert.Nemec gmx.de> wrote in message
news:cbe37h$b34$1 digitaldaemon.com...
 Matthew wrote:

 I think it's nice idea, but post 1.0
The reason why it might be considered for 1.0 already: It has some influence on the design of library functions. There is a
number
 of functions that need plenty of options to be flexible. Without this
 proposed feature, you would have to find some way to pass them in in some
 reasonable way. If you have named function arguments, the design gets much
 simpler.

 If the standard library is to converge as soon as the language reaches
1.0,
 then there might be reason to consider features that might affect the
 design.

 Furthermore: the feature is simple enough to just throw it in without much
 effort.

 Anyway: I won't press the issue. I just got carried away when I realized
how
 nice and clean the solution actually might be.

 Ciao,
 Nobbi
Jun 29 2004