February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | On Mon, 28 Feb 2011 07:41:06 -0500, Michel Fortin <michel.fortin@michelf.com> wrote:
> On 2011-02-28 02:03:46 -0500, Bekenn <leaveme@alone.com> said:
>
>> Potential problems: The only problems I can foresee here are variations on the situation when there are two (or more) versions of a function with the same number, type, and names of parameters, but in non-matching order, like this:
>> void func(int a, char b);
>> void func(char b, int a);
>> In such a case, the compiler should diagnose an error if named arguments are employed.
>> Thoughts?
>
> Another problem is what happens if you override a function by using different parameter names. For instance:
>
> class A {
> void func(int foo);
> }
> class B : A {
> void func(int bar);
> }
>
> Currently, the above is allowed. Would it now become an error?
>
> I think it'd be much easier to support named arguments if we didn't allow reordering. I know I'm stripping the proposal from one of its main benefits, but I think the essence remains. This would make the rather common pattern of adding a comment for each argument compiler-verifiable without disrupting things too much:
>
> draw(null, // text
> null, // font
> 12, // size
> 0, // flags
> );
>
> draw(text: null,
> font: null,
> size: 12,
> flags: 0);
>
> It would be implemented as a check for equality of the argument names after overload resolution. No ABI change, no interaction with overloading, just an extra check that if an argument name is specified it must match the one in the declaration.
>
> There'd still be a funny interaction with overriding (see my first example), but you can always leave your argument unnamed if the definition keep changing the name in unpredictable ways.
>
All these 'what if' ambiguities are simple to resolve -- if you use positional arguments, it works. If you use named arguments, and it matches more than one overload, it fails.
In fact, the case you give is unambiguous -- if you have an A, you can use foo, if you have a B, you can use bar. Note that the confusion is all to the person, and is completely avoidable. It's like naming your arguments xy234m5 -- nobody knows what that means, so just choose a better name. But it's not illegal.
I would say this would be a huge improvement to D. But I would also say from my recollection, Walter is very against this. I think it would take a motivated developer creating a pull request to get it done...
-Steve
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
I prefer using the equals sign: foo(action = "dofoo", times = 100) This is how Python does it. |
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Mon, 28 Feb 2011 07:48:24 -0500, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> I prefer using the equals sign:
> foo(action = "dofoo", times = 100)
>
> This is how Python does it.
This syntax already means something in D:
string action;
int times;
foo(action = "dofoo", times = 100); // set action to "dofoo" and times to 100 and pass those to the function.
-Steve
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bekenn | On 2011-02-28 08:03, Bekenn wrote: > Consider the following line from a project I'm playing around with: > > HRESULT hr = m_Device.Present(null, null, null, null); > > Quick: What behavior does that third argument specify? If you said, > "Well, /obviously/, that's a handle to an alternative destination window > for the render operation; by passing null, you're choosing not to > provide an alternative render target." then... well, gee, I have no > answer to that. > > With named arguments, it becomes a bit easier to understand: > > HRESULT hr = m_Device.Present(pSourceRect: null, pDestRect: null, > hDestWindowOverride: null, pDirtyRegion: null); > > If I remember right, Python has this (optional) feature; I'm not aware > of anyone ever complaining about it. It also nicely provides a solution > to the bool argument problem: > http://blogs.msdn.com/b/oldnewthing/archive/2006/08/28/728349.aspx > > But wait, there's more! > > Named arguments get a +1 synergy bonus with default arguments. When > using parameter names to specify arguments, the order in which those > arguments are passed no longer matters. Imagine if the Present() method > above provided the default argument null for each parameter: > > interface IDirect3DDevice9 : IUnknown > { > ... > HRESULT Present(const(RECT)* pSourceRect = null, const(RECT)* pDestRect > = null, HWND hDestWindowOverride = null, const(RGNDATA)* pDirtyRegion = > null); > ... > } > > We can do this in the D binding without running afoul of any linkage > issues, and it simplifies the Present() call for its most common usage, > which I think is a good thing. Now, let's say I'm doing something > special; suppose I'm not worried about source and destination rectangles > or dirty regions, but I do want to supply a different render target. > With named arguments, that's easy to do without making things messy: > > HRESULT hr = m_Device.Present(hDestWindowOverride: hOverride); > > Named arguments should also play nicely with positional arguments: > > auto wrappedString = wrap(reallyLongString, colmuns: 120, tabsize: 4); > > Lastly, wouldn't be an entirely new feature; D already supports named > arguments for static struct initializers. I merely propose sharing the > love with normal functions and struct literals. > > Here are the rules I have in mind: > > 1) Named arguments are not a replacement for positional arguments. > Arguments fall into three categories: positional, named positional, and > named non-positional. An argument is positional if no name is supplied. > An argument is named positional if a name is supplied and its position > matches the parameter's position in the function declaration. An > argument is named non-positional if a name is supplied and either a) its > position does not match the parameter's position in the function > declaration, or b) it is immediately preceded by a named non-positional > argument. > > 2) No positional argument may appear after a named non-positional argument. > > 3) Named non-positional arguments may appear in any order. > > > Potential problems: The only problems I can foresee here are variations > on the situation when there are two (or more) versions of a function > with the same number, type, and names of parameters, but in non-matching > order, like this: > > void func(int a, char b); > void func(char b, int a); > > In such a case, the compiler should diagnose an error if named arguments > are employed. > > Thoughts? It's possible to implement this as a library: http://dsource.org/projects/orange/browser/orange/util/Reflection.d#L135 Not a complete solution but it works. -- /Jacob Carlborg |
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer: > I would say this would be a huge improvement to D. But I would also say > from my recollection, Walter is very against this. I think it would take > a motivated developer creating a pull request to get it done... Well implemented named arguments are my #1 enhancement request for D (my #2 request is the tuple unpacking syntax, another thing that's useful all the time). They are present in some languages as Python. Or in Ada language, where they are named "named arguments": http://en.wikibooks.org/wiki/Ada_Programming/Subprograms#Named_parameters In recent C# versions: http://msdn.microsoft.com/en-us/library/dd264739.aspx http://geekswithblogs.net/michelotti/archive/2009/01/22/c-4.0-named-parameters-for-better-code-quality.aspx ) If you use named arguments in Python, you learn how much useful they are, I use them often. They don't increase much the complexity of the language for the programmer, they make code less bug-prone, more handy to write, and more self-annotated with compiled-verified annotations. You have a function like: void drawRectangle(int height, int width) {...} You call it with: drawRectangle(640, 480); But you may be wrong, having inverted the two values: drawRectangle(480, 640); With good named argument you remove that bug source: drawRectangle(width: 640, height: 480); Named arguments are so useful that they justify little changes in the compiler too, if necessary. Bye, bearophile |
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 2/28/11, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> This syntax already means something in D:
>
> string action;
> int times;
> foo(action = "dofoo", times = 100); // set action to "dofoo" and times to
> 100 and pass those to the function.
>
> -Steve
>
Except that doesn't do what you'd expect it to do:
void foo(ref int time) { }
void main()
{
int times;
foo(times = 100); // set times to 100 and pass to the function.
}
Error: function test.foo (ref int time) is not callable using argument
types (int)
Error: times = 100 is not an lvalue
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Mon, 28 Feb 2011 08:15:02 -0500, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 2/28/11, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>> This syntax already means something in D:
>>
>> string action;
>> int times;
>> foo(action = "dofoo", times = 100); // set action to "dofoo" and times to
>> 100 and pass those to the function.
>>
>> -Steve
>>
>
> Except that doesn't do what you'd expect it to do:
> void foo(ref int time) { }
> void main()
> {
> int times;
> foo(times = 100); // set times to 100 and pass to the function.
> }
When I said "pass those" I meant "pass those values". I was not assuming ref arguments.
In any case, your syntax for named arguments is not possible. x = y is an expression, and can be used anywhere an expression can be used.
-Steve
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 2/28/11, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>
> In any case, your syntax for named arguments is not possible. x = y is an expression, and can be used anywhere an expression can be used.
>
I agree. I'm thinking there would be more ambiguity with the Python syntax:
void foo(int value = 50) { }
void main() {
int value = 20;
foo(value=40); // does main.value change?
}
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Would named arguments work with compile-time/template arguments as well? |
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russel Winder | On 2/28/11 1:32 AM, Russel Winder wrote: > The huge downside of any named parameter approach is that you have data > coupling between the source of the callee and the caller. This is fine > in a language such as Python where you distribute source and > documentation tools so you can always find out the names of parameters, > this is going to be a bit of a problem in languages where only the > compiled form may be the only distributed form. Programmers rely on > some other form of documentation other than the source and this leads to > error, It's not all that bad. Walter and I discussed a couple of times adding such a feature. As long as the function signature in the .d or .di file does specify a parameter name, that can be used. >> Potential problems: The only problems I can foresee here are variations >> on the situation when there are two (or more) versions of a function >> with the same number, type, and names of parameters, but in non-matching >> order, like this: >> >> void func(int a, char b); >> void func(char b, int a); >> >> In such a case, the compiler should diagnose an error if named arguments >> are employed. >> >> Thoughts? > > The Python mechanism relies on the fact that despatch is by name and not > by signature. Languages that dispatch by signature will have > significantly greater problems! A good subset of Python's approach to parameter passing sugar can be done without using maps or dispatch by name. Andrei |
Copyright © 1999-2021 by the D Language Foundation