February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On Monday, February 28, 2011 13:38:34 Don wrote:
> spir wrote:
> > On 02/28/2011 07:51 PM, Jonathan M Davis wrote:
> >> I'm not entirely against named arguments being in D, however I do
> >> think that any
> >> functions that actually need them should be refactored anyway.
>
> I agree.
> CreateFont() in the Windows API, I'm looking at you. (For Linux people,
> that function has about 12 parameters).
>
> > ???
> >
> >> In actuality, if I were to vote on whether named arguments should be
> >> in the
> >> language, I would definitely vote against it (I just plain don't want
> >> the code
> >> clutter, [...]
> >
> > Just don't use them!
>
> You don't have that option. At least, if you're a library developer, you don't. (I'm a bit sick of people saying "you don't have to use it if you don't want to" in language design. If it is in the language, you don't have a choice. You will encounter it).
>
> There are a couple of things that I really, really don't like about the
> names argument idea:
> 1. It makes parameter names part of the API.
> Providing no way for the function writer to control whether it is part
> of the API or not, and especially, doing it retrospectively, strikes me
> as extremely rude.
>
> 2. It introduces a different syntax for calling a function.
> foo(4, 5);
> foo(x: 4, y: 5);
> They look different, but they do exactly the same thing. I don't like
> that redundancy.
>
>
> Especially since, as far as I can tell, the named arguments are just
> comments (which the compiler can check).
> If so, a syntax like this would be possible, with no language change at
> all:
>
> pragma(namedarguments); // applies to whole module
>
> foo(/*x*/ 4, /*y*/ 5);
>
> ---> if a function parameter has a comment which forms a valid
> identifier, it's a named parameter.
>
> But I still don't see the need for this feature. Aren't people using
> IDEs where the function signature (with parameter names) pops up when
> you're entering the function, and when you move the mouse over the
> function call?
> And if you really want to see them all the time, why not build that
> feature into the IDE?
> ("hit ctrl-f9 to show all parameter names, hit it again to hide them").
I agree with pretty much everything said here. However, as I understand it, named parameters (at least as they work in Python) would allow for you to reorder parameters and give values for paramters which are normally default parameters without giving values for the default paramters before them, and those changes could not be dealt with by comments. However, I consider them to be a big _problem_, not a feature - _especially_ the ability to rearrange the function arguments. All of a sudden you could have
foo(4, 5);
foo(x : 4, y : 5);
foo(y : 5, X : 4);
all making _exactly_ the same function call. That seem _very_ bug-prone and confusing to me. foo(x : 4, y : 5) was bad enough, but allowing foo(y : 5, x : 4)? Not good. The amount of effort to understand the code becomes considerably higher. You could be very familiar with foo and know exactly what parameters it takes and totally mistake what it's really getting passed, because the arguments were flipped in comparison to the function parameters.
I agree with Don. I think that named parameters would cause far more intellectual overhead and problems than they'd solve.
- Jonathan M Davis
- Jonathan M Davis
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | Don: >You don't have that option. At least, if you're a library developer, you don't. (I'm a bit sick of people saying "you don't have to use it if you don't want to" in language design. If it is in the language, you don't have a choice. You will encounter it).< If you add named arguments to D, you are free to not use them when you call Phobos functions or functions from libraries not written by you. You have to see them only if you modify code written by other people that uses named arguments. > There are a couple of things that I really, really don't like about the > names argument idea: > 1. It makes parameter names part of the API. > Providing no way for the function writer to control whether it is part > of the API or not, Probably I am don't understand something here. Function arguments need to be well chosen, so I don't mind them becoming part of the API. (In theory an annotation may be used to disallow the usage of named arguments for a specific function, but I think this is not necessary). > and especially, doing it retrospectively, strikes me > as extremely rude. There is not much D2 code around, most D2 code is in the future, where this feature will hopefully be known to be present. > 2. It introduces a different syntax for calling a function. > foo(4, 5); > foo(x: 4, y: 5); > They look different, but they do exactly the same thing. I don't like > that redundancy. In SPARK (Ada) they avoid that redundancy because you must use named arguments :-) To me they look the same, but the second also tells me what I am assigning numbers to. > Especially since, as far as I can tell, the named arguments are just > comments (which the compiler can check). > If so, a syntax like this would be possible, with no language change at all: > > pragma(namedarguments); // applies to whole module > > foo(/*x*/ 4, /*y*/ 5); > > ---> if a function parameter has a comment which forms a valid > identifier, it's a named parameter. The two following are the same thing: foo(x: 4, y: 5); foo(y: 5, x: 4); While the following ones are not the same call: foo(/*x*/ 4, /*y*/ 5); foo(/*y*/ 5, /*x*/ 4); And if your function is: void foo(int x = 1, int y = 2) {} You are also able to write: foo(y: 5); That's not equivalent to: foo(/*y*/ 5); In Mathematica and Python there are plotting functions that have lot of parameters, all of them have a default argument. With named arguments you are able to choose to modify only one or few arguments, keeping your code readable and short and bug-free. > But I still don't see the need for this feature. Aren't people using IDEs where the function signature (with parameter names) pops up when you're entering the function, and when you move the mouse over the function call? If you print code on a book or you show code on the web, etc, you don't have an IDE to help you. D isn't designed to require an IDE. And C# devs have added named arguments even if most C# programmers use an IDE. Bye, bearophile |
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On Mon, 28 Feb 2011 16:38:34 -0500, Don <nospam@nospam.com> wrote: > spir wrote: >> Just don't use them! > > You don't have that option. At least, if you're a library developer, you don't. (I'm a bit sick of people saying "you don't have to use it if you don't want to" in language design. If it is in the language, you don't have a choice. You will encounter it). encounter *reading* it or encounter *using it*? You shouldn't ever have to use named parameters if you don't want to. Just like you can specify all defaulted parameters, or specify all template args when calling templated functions. I could live without named parameters (obviously!), but I certainly think reading a call with named parameters can be much easier with the parameter names than without, and I don't think you could ever say the opposite (that name-less parameters would be clearer). > There are a couple of things that I really, really don't like about the names argument idea: > 1. It makes parameter names part of the API. > Providing no way for the function writer to control whether it is part of the API or not, and especially, doing it retrospectively, strikes me as extremely rude. > > 2. It introduces a different syntax for calling a function. > foo(4, 5); > foo(x: 4, y: 5); > They look different, but they do exactly the same thing. I don't like that redundancy. I look at it similarly to IFTI: foo(T)(T t) {...} foo(1); foo!int(1); both mean the same, the int is optional. Note that the library developer of foo has no way to restrict you from using either form. One is simply a clearer way of saying the other. In essense, the parameter names are ALREADY an essential part of the API. If we didn't name the parameters (entirely possible with .di files!), how shitty would programming be? > Especially since, as far as I can tell, the named arguments are just comments (which the compiler can check). > If so, a syntax like this would be possible, with no language change at all: > > pragma(namedarguments); // applies to whole module > > foo(/*x*/ 4, /*y*/ 5); > > ---> if a function parameter has a comment which forms a valid identifier, it's a named parameter. There is a feature that isn't available via comments, parameter reordering: foo(y: 5, x: 4); Who in their right mind wants to do this, right? Well, consider you use two different libraries, and in one library the y is always the first parameter, and in another the x is always the first parameter (yes, I've seen shit like this). Calls to the separate libs might be a nightmare of continuous documentation referencing. But if you can just always say "x is first", then the calls are easy to read and write, and completely unambiguous. > But I still don't see the need for this feature. Aren't people using IDEs where the function signature (with parameter names) pops up when you're entering the function, and when you move the mouse over the function call? Dunno, vim doesn't do that for me currently. Also, if reviewing code on github, there is no ide. -Steve |
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | Jonathan M Davis:
> All of a sudden you could have
>
> foo(4, 5);
> foo(x : 4, y : 5);
> foo(y : 5, X : 4);
>
> all making _exactly_ the same function call. That seem _very_ bug-prone and confusing to me.
(You have used an upper case X, this bug will be caught by the compiler).
For me the #1 purpose of named arguments is to make code more explicit/readable and often less buggy.
If you swap all arguments in your program, using named arguments, you are probably making your program a little more bug-prone. So as most other features there's a way to misuse it. But in most cases you don't swap arguments, and you use names more semantically meaningful than just x and y, so swapped arguments sticks out more. And you also need to train yourself a bit, to see the arguments of function calls not in their of their order, but in term of their names, their semantics. If you use MatPlotLib (from Python) you learn to see the names of function arguments and mostly ignore the order you give them to functions (because the order is much less significant), so this feature needs a bit of training for the mind/attitude of the programmer too.
Bye,
bearophile
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On 2/28/11 1:38 PM, Don wrote: > spir wrote: >> On 02/28/2011 07:51 PM, Jonathan M Davis wrote: >>> I'm not entirely against named arguments being in D, however I do >>> think that any >>> functions that actually need them should be refactored anyway. > > I agree. > CreateFont() in the Windows API, I'm looking at you. (For Linux people, > that function has about 12 parameters). That's a great example of where named parameters can come in very handy. As a consumer of the API, you do not have the option of refactoring CreateFont(); you have to play the cards you're dealt. Named arguments allow you to annotate in a compiler-verified fashion. >> Just don't use them! > > You don't have that option. At least, if you're a library developer, you > don't. (I'm a bit sick of people saying "you don't have to use it if you > don't want to" in language design. If it is in the language, you don't > have a choice. You will encounter it). You may encounter it, but nothing says you ever have to write it. There is no way to write a function such that callers would have to use named arguments in the function call. (If there were, then I'd agree with you -- that would be bad.) > > There are a couple of things that I really, really don't like about the > names argument idea: > 1. It makes parameter names part of the API. > Providing no way for the function writer to control whether it is part > of the API or not, and especially, doing it retrospectively, strikes me > as extremely rude. > A valid point. I think I would already consider parameter names to be part of the API, though; generated documentation relies upon them, as do contracts. Admittedly, this would be the first place where they leak directly into caller code. > 2. It introduces a different syntax for calling a function. > foo(4, 5); > foo(x: 4, y: 5); > They look different, but they do exactly the same thing. I don't like > that redundancy. You're right, it is redundant. So is this: Declaration: void func(int a = 0); Use: func(); // ok func(0); // same as above Are you also against default arguments, then? > > Especially since, as far as I can tell, the named arguments are just > comments (which the compiler can check). Look again at my example from the first post: HRESULT hr = m_Device.Present(hDestWindowOverride: hOverride); In this usage, the named argument allows me to skip over the first two parameters, which receive their default arguments. This seems highly valuable to me. > But I still don't see the need for this feature. Aren't people using > IDEs where the function signature (with parameter names) pops up when > you're entering the function, and when you move the mouse over the > function call? The point (in the annotation use case) is less in the writing than in the reading. |
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 2/28/11 1:50 PM, Jonathan M Davis wrote:
> However, I consider them to
> be a big _problem_, not a feature - _especially_ the ability to rearrange the
> function arguments. All of a sudden you could have
>
> foo(4, 5);
> foo(x : 4, y : 5);
> foo(y : 5, X : 4);
>
> all making _exactly_ the same function call. That seem _very_ bug-prone and
> confusing to me.
Of those three calls, the highest potential for confusion exists with the first. Admittedly, the third is of uncertain value.
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen kjaeraas | On Mar 1, 11 05:04, Simen kjaeraas wrote:
> Adam Ruppe <destructionator@gmail.com> wrote:
>
>> Another alternative is to give each element their own struct...
>>
>> struct Width { int width; alias width this; }
>>
>> foo(Width(10), Height(20));
>
> Clearly this can be done better:
>
> struct _(string s) { int data; alias data this; }
>
> foo(_!"width"(10), _!"height"(20));
>
How are these better than
foo(/*width*/ 10, /*height*/ 20);
? One advantage of named parameter is the compiler can verify you've passed in the correct order, and all these alternatives cannot.
|
February 28, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to KennyTM~ | > ? One advantage of named parameter is the compiler can verify you've passed in the correct order, and all these alternatives cannot.
Separate structs would be checked because doing them out of order would be a type mistmatch.
|
March 01, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bekenn | On Monday, February 28, 2011 14:25:05 Bekenn wrote:
> On 2/28/11 1:38 PM, Don wrote:
> > spir wrote:
> >> On 02/28/2011 07:51 PM, Jonathan M Davis wrote:
> >>> I'm not entirely against named arguments being in D, however I do
> >>> think that any
> >>> functions that actually need them should be refactored anyway.
> >
> > I agree.
> > CreateFont() in the Windows API, I'm looking at you. (For Linux people,
> > that function has about 12 parameters).
>
> That's a great example of where named parameters can come in very handy.
> As a consumer of the API, you do not have the option of refactoring
> CreateFont(); you have to play the cards you're dealt. Named arguments
> allow you to annotate in a compiler-verified fashion.
>
> >> Just don't use them!
> >
> > You don't have that option. At least, if you're a library developer, you don't. (I'm a bit sick of people saying "you don't have to use it if you don't want to" in language design. If it is in the language, you don't have a choice. You will encounter it).
>
> You may encounter it, but nothing says you ever have to write it. There is no way to write a function such that callers would have to use named arguments in the function call. (If there were, then I'd agree with you -- that would be bad.)
>
> > There are a couple of things that I really, really don't like about the
> > names argument idea:
> > 1. It makes parameter names part of the API.
> > Providing no way for the function writer to control whether it is part
> > of the API or not, and especially, doing it retrospectively, strikes me
> > as extremely rude.
>
> A valid point. I think I would already consider parameter names to be part of the API, though; generated documentation relies upon them, as do contracts. Admittedly, this would be the first place where they leak directly into caller code.
And that's a _big_ problem. For instance, how many parameter names in Phobos were chosen with the idea that a caller would use them? _None_. And now, if named arguments are added, all of a sudden, you can't rename parameters without breaking code. I, for one, do not want to _increase_ the number of things that I can't change in code without breaking other people's code. And at least with functions, I could rename them and leave a deprecated alias. With parameters, I don't have that option. A poorly named parameter would be set in stone unless the whole function were renamed or we were willing to break other people's code. Named arguments _decrease_ flexibility as far as the API goes.
On top of that, we would then have to worry about having high consistency in parameter names instead of just in function names. From the perspective of the library writer, this causes _more_ problems at _no_ benefit. From the perspective of the library user, it does provide some benefit, but I honestly do not think that
func(x : 4, y : 5);
is easier to read than
func(4, 5);
Sure, you have to know what func's parameters are, but you have to know that anyway. Only now, with named arguments, you have to care about what their _names_ are in addition to what they're for. I do _not_ want to have to read code which uses named arguments. It's just more clutter and more intellectual overhead.
The sole type of case that I have seen where named arguments are of real benefit is where you're dealing with horribly written functions that have a ton of parameters, and I would _hope_ that that kind of nonsense would be restricted to old C APIs and the like. And if you have to deal with such C APIs from D, you can write a wrapper which uses a proper struct or whatnot to encapsulate that mess. Such horrendous functions shouldn't be the norm at all.
As a library user, I see little benefit to named arguments and a definite problem with them in terms the added code clutter and intellectual overhead. As a library writer, it gives me _no_ benefit and definitely makes my life harder. Parameter names have never been part of a function's signature, and I _don't_ want them to start being a part of it now.
The more I think about this, the more I'm against the idea of named arguments.
- Jonathan M Davis
|
March 01, 2011 Re: Pretty please: Named arguments | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | Jonathan M Davis Wrote:
> On Monday, February 28, 2011 14:25:05 Bekenn wrote:
> > On 2/28/11 1:38 PM, Don wrote:
> > > spir wrote:
> > >> On 02/28/2011 07:51 PM, Jonathan M Davis wrote:
> > >>> I'm not entirely against named arguments being in D, however I do
> > >>> think that any
> > >>> functions that actually need them should be refactored anyway.
> > >
> > > I agree.
> > > CreateFont() in the Windows API, I'm looking at you. (For Linux people,
> > > that function has about 12 parameters).
> >
> > That's a great example of where named parameters can come in very handy.
> > As a consumer of the API, you do not have the option of refactoring
> > CreateFont(); you have to play the cards you're dealt. Named arguments
> > allow you to annotate in a compiler-verified fashion.
> >
> > >> Just don't use them!
> > >
> > > You don't have that option. At least, if you're a library developer, you don't. (I'm a bit sick of people saying "you don't have to use it if you don't want to" in language design. If it is in the language, you don't have a choice. You will encounter it).
> >
> > You may encounter it, but nothing says you ever have to write it. There is no way to write a function such that callers would have to use named arguments in the function call. (If there were, then I'd agree with you -- that would be bad.)
> >
> > > There are a couple of things that I really, really don't like about the
> > > names argument idea:
> > > 1. It makes parameter names part of the API.
> > > Providing no way for the function writer to control whether it is part
> > > of the API or not, and especially, doing it retrospectively, strikes me
> > > as extremely rude.
> >
> > A valid point. I think I would already consider parameter names to be part of the API, though; generated documentation relies upon them, as do contracts. Admittedly, this would be the first place where they leak directly into caller code.
>
> And that's a _big_ problem. For instance, how many parameter names in Phobos were chosen with the idea that a caller would use them? _None_. And now, if named arguments are added, all of a sudden, you can't rename parameters without breaking code. I, for one, do not want to _increase_ the number of things that I can't change in code without breaking other people's code. And at least with functions, I could rename them and leave a deprecated alias. With parameters, I don't have that option. A poorly named parameter would be set in stone unless the whole function were renamed or we were willing to break other people's code. Named arguments _decrease_ flexibility as far as the API goes.
>
> On top of that, we would then have to worry about having high consistency in parameter names instead of just in function names. From the perspective of the library writer, this causes _more_ problems at _no_ benefit. From the perspective of the library user, it does provide some benefit, but I honestly do not think that
>
> func(x : 4, y : 5);
>
> is easier to read than
>
> func(4, 5);
>
> Sure, you have to know what func's parameters are, but you have to know that anyway. Only now, with named arguments, you have to care about what their _names_ are in addition to what they're for. I do _not_ want to have to read code which uses named arguments. It's just more clutter and more intellectual overhead.
>
> The sole type of case that I have seen where named arguments are of real benefit is where you're dealing with horribly written functions that have a ton of parameters, and I would _hope_ that that kind of nonsense would be restricted to old C APIs and the like. And if you have to deal with such C APIs from D, you can write a wrapper which uses a proper struct or whatnot to encapsulate that mess. Such horrendous functions shouldn't be the norm at all.
>
> As a library user, I see little benefit to named arguments and a definite problem with them in terms the added code clutter and intellectual overhead. As a library writer, it gives me _no_ benefit and definitely makes my life harder. Parameter names have never been part of a function's signature, and I _don't_ want them to start being a part of it now.
>
> The more I think about this, the more I'm against the idea of named arguments.
>
> - Jonathan M Davis
I think it could be a real boon for generic code:
class House(Roof = Clay, Door = Wood, Window = Glass)
{
Roof _roof;
Door[] _doors;
Window[] _windows;
}
auto home = new House(Roof: Gingerbread, Window: Sugar)();
You would probably parameterize as much as possible, like the container types for _doors and _windows -- i.e. anything that isn't limited by the algorithm of your choice. Everything being optional of course, and all the work is all done at compile time.
This would give you _rich_ generic types with plain interfaces. You only specify what's important to you. How's that for a template library where every part can be shifted and replaced?
|
Copyright © 1999-2021 by the D Language Foundation