www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Flag proposal

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
https://github.com/D-Programming-Language/phobos/pull/94

Discuss!

Andrei
Jun 10 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I like how your proposal is already a pull request.

I'm not too fond of this workaround:

bool state;
getopt(
    args,
    "state",      &state,
);
auto line = getLine(cast(Flag!"KeepTerminator")state);

Will getopt know how to use Flags? What about std.conv.to?

std.format/write will have to know how to print out a Flag too, or we
have to cast:
writeln(cast(bool)keepTerminator);

If the plan is to replace all boolean arguments in Phobos with Flags,
won't this break a lot of code? We'll have to switch to using this
template, and then if we finally get named arguments sometime down the
road we will have to convert everything back to bools again.
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 11:45 AM, Andrej Mitrovic wrote:
 I like how your proposal is already a pull request.

 I'm not too fond of this workaround:

 bool state;
 getopt(
      args,
      "state",&state,
 );
 auto line = getLine(cast(Flag!"KeepTerminator")state);

 Will getopt know how to use Flags? What about std.conv.to?
Yes, getopt should support any enum using bool as its base. std.conv already supports all enums.
 std.format/write will have to know how to print out a Flag too, or we
 have to cast:
 writeln(cast(bool)keepTerminator);
Without the cast, writeln prints "yes" or "no", which may be desirable. If you want to print the bool, you can say writeln(keepTerminator == Flag!"KeepTerminator".yes); or writeln(!!keepTerminator); etc. I find this array of options quite sensible.
 If the plan is to replace all boolean arguments in Phobos with Flags,
 won't this break a lot of code?
Migration can be done piecemeal with deprecation and all.
 We'll have to switch to using this
 template, and then if we finally get named arguments sometime down the
 road we will have to convert everything back to bools again.
If we convert back to bool the problem remains that people still can just pass "true" or whatever without specifying the name of the parameter. True, they could and should specify the name of the parameter, but by that argument they could and should insert a comment right now - and nobody does. Andrei
Jun 10 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/10/11, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 Without the cast, writeln prints "yes" or "no", which may be desirable.
 If you want to print the bool, you can say

 writeln(keepTerminator == Flag!"KeepTerminator".yes);

 or

 writeln(!!keepTerminator);
Oh, maybe this was already incorporated into format but I didn't nocie, I just did a blunt copy/paste of the template code so it didn't work for me: D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\format.d(1624): Error: template std.format.formatValue(Writer,T,Char) if (is(const(T) == const(void[]))) formatValue(Writer,T,Char) if (is(const(T) == const(void[]))) matches more than one template declaration, D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\format.d(895):formatValue(Writer,T,Char) if (is(T == enum)) and D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\format.d(1104):formatValue(Writer,T,Char) if (is(T : bool))
Jun 10 2011
parent KennyTM~ <kennytm gmail.com> writes:
On Jun 11, 11 01:41, Andrej Mitrovic wrote:
 On 6/10/11, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org>  wrote:
 Without the cast, writeln prints "yes" or "no", which may be desirable.
 If you want to print the bool, you can say

 writeln(keepTerminator == Flag!"KeepTerminator".yes);

 or

 writeln(!!keepTerminator);
Oh, maybe this was already incorporated into format but I didn't nocie, I just did a blunt copy/paste of the template code so it didn't work for me: D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\format.d(1624): Error: template std.format.formatValue(Writer,T,Char) if (is(const(T) == const(void[]))) formatValue(Writer,T,Char) if (is(const(T) == const(void[]))) matches more than one template declaration, D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\format.d(895):formatValue(Writer,T,Char) if (is(T == enum)) and D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\format.d(1104):formatValue(Writer,T,Char) if (is(T : bool))
Try to use the Phobos on git master. I have fixed this already (bug 5837) and the patch has been merged on June 3rd.
Jun 10 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
*notice
Jun 10 2011
prev sibling next sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around. -- Robert http://octarineparrot.com/
Jun 10 2011
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 11, 11 01:42, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
Well I agree it is ugly, but at least it's better than having the same enum 7 times in Phobos (std.stdio.KeepTerminator, std.string.CaseSensitive, std.algorithm.OpenRight, std.algorithm.SortOutput, std.datetime.AllowDayOverflow, std.datetime.PopFirst, std.datetime.AutoStart). If named parameter is supported, those Flag!"foo" parameters can be reverted back to bool without breaking the caller as the enum is based on bool.
Jun 10 2011
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-10 10:57, KennyTM~ wrote:
 On Jun 11, 11 01:42, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94
 
 Discuss!
 
 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
Well I agree it is ugly, but at least it's better than having the same enum 7 times in Phobos (std.stdio.KeepTerminator, std.string.CaseSensitive, std.algorithm.OpenRight, std.algorithm.SortOutput, std.datetime.AllowDayOverflow, std.datetime.PopFirst, std.datetime.AutoStart). If named parameter is supported, those Flag!"foo" parameters can be reverted back to bool without breaking the caller as the enum is based on bool.
And there are places in Phobos which _should_ be using enums like this but aren't (e.g. std.file.dirEntries' followSymlinks bool), so the number is only going to go up as such things are fixed, even without adding new code to Phobos. And of course, we're going to be adding new code, so the amount of duplication for this type of enum is only going to go up. - Jonathan M Davis
Jun 10 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 12:42 PM, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
This is not half-baked. It's pretty much it. Ugly is in the eye of the beholder, but I fail to see how the added punctuation makes Flag!"param".yes significantly more verbose than param : true. The problem that named parameters are still optional remains. Or we need to add one extra language feature to specify required named parameters. Andrei
Jun 10 2011
next sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 10/06/2011 19:06, Andrei Alexandrescu wrote:
 On 6/10/11 12:42 PM, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
This is not half-baked. It's pretty much it.
My choice of wording was poor, sorry.
 Ugly is in the eye of the beholder, but I fail to see how the added
 punctuation makes Flag!"param".yes significantly more verbose than param
 : true.
foo(param: true, otherParam: false); foo(Flag!"param".yes, Flag!"otherParam".no); I don't know about you, but I find the former is far more legible. I'd hate to see my code littered with Flag!"something".
 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
void foo(bool param, bool otherParam, bool thisOneIsntRequired = false); Call it with or without named parameters, two are required, one is not. foo(otherParam: true, param: false); foo(true, false); foo(otherParam: true, param: false, thisOneIsntRequired: true); Would all be valid.
 Andrei
-- Robert http://octarineparrot.com/
Jun 10 2011
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-10 14:52:53 -0400, Robert Clipsham <robert octarineparrot.com> said:

 On 10/06/2011 19:06, Andrei Alexandrescu wrote:
 Ugly is in the eye of the beholder, but I fail to see how the added
 punctuation makes Flag!"param".yes significantly more verbose than param
 : true.
foo(param: true, otherParam: false); foo(Flag!"param".yes, Flag!"otherParam".no); I don't know about you, but I find the former is far more legible. I'd hate to see my code littered with Flag!"something".
I have to say I totally agree with Robert. I agree with the need for a way to name parameters, but instantiating a pseudo-boolean type from a template for each function parameter is worse than the initial problem. Templates are already a difficult concept to grasp for most people (because they're so abstract), we really don't need to replace every boolean parameter with a template type.
 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
void foo(bool param, bool otherParam, bool thisOneIsntRequired = false); Call it with or without named parameters, two are required, one is not. foo(otherParam: true, param: false); foo(true, false); foo(otherParam: true, param: false, thisOneIsntRequired: true);
And just try to think of the signature for the function above if it was using Flag! void foo(Flag!"param" param, Flag!"otherParam" otherParam, Flag!"thisOneIsntRequired" thisOneIsntRequired = Flag!"thisOneIsntRequired".no); Do we really want to expose that in the documentation? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 10 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Michel Fortin" <michel.fortin michelf.com> wrote in message 
news:istqjn$2jld$1 digitalmars.com...
 On 2011-06-10 14:52:53 -0400, Robert Clipsham <robert octarineparrot.com> 
 said:

 On 10/06/2011 19:06, Andrei Alexandrescu wrote:
 Ugly is in the eye of the beholder, but I fail to see how the added
 punctuation makes Flag!"param".yes significantly more verbose than param
 : true.
foo(param: true, otherParam: false); foo(Flag!"param".yes, Flag!"otherParam".no); I don't know about you, but I find the former is far more legible. I'd hate to see my code littered with Flag!"something".
I have to say I totally agree with Robert. I agree with the need for a way to name parameters, but instantiating a pseudo-boolean type from a template for each function parameter is worse than the initial problem. Templates are already a difficult concept to grasp for most people (because they're so abstract), we really don't need to replace every boolean parameter with a template type.
 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
void foo(bool param, bool otherParam, bool thisOneIsntRequired = false); Call it with or without named parameters, two are required, one is not. foo(otherParam: true, param: false); foo(true, false); foo(otherParam: true, param: false, thisOneIsntRequired: true);
And just try to think of the signature for the function above if it was using Flag! void foo(Flag!"param" param, Flag!"otherParam" otherParam, Flag!"thisOneIsntRequired" thisOneIsntRequired = Flag!"thisOneIsntRequired".no); Do we really want to expose that in the documentation?
I completely agree with Robert and Michel on all the points they've raised. Flag is admittedly a great example of the power of D's templates. And it's admittedly a very clever hack to get around *some* of the limitations of not having named parameters...*But* it's *still* just that: a hack to get around some of the limitations of not having named parameters. And yes, it is comparatively ugly, as Robert and Michel's examples have very clearly shown. Also:
 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
If by that, you meant that the caller is allowed to call the function without naming the parameters, I really don't see that as a problem. Yea, *maybe* it would be better if the callee could optionally decide "caller must use named params", but even without that, it's a hell of a lot better than the current state, and it's also a lot better than Flag becase 1. It's *much* cleaner for both the caller and callee, and 2. It works for functions like foo(int, int, int, int), not just bools.
Jun 10 2011
parent David Nadlinger <see klickverbot.at> writes:
On 6/10/11 9:47 PM, Nick Sabalausky wrote:
 I completely agree with Robert and Michel on all the points they've raised.
 Flag is admittedly a great example of the power of D's templates. And it's
 admittedly a very clever hack to get around *some* of the limitations of not
 having named parameters...*But* it's *still* just that: a hack to get around
 some of the limitations of not having named parameters. And yes, it is
 comparatively ugly, as Robert and Michel's examples have very clearly shown.

 Also:

 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
If by that, you meant that the caller is allowed to call the function without naming the parameters, I really don't see that as a problem. Yea, *maybe* it would be better if the callee could optionally decide "caller must use named params", but even without that, it's a hell of a lot better than the current state, and it's also a lot better than Flag becase 1. It's *much* cleaner for both the caller and callee, and 2. It works for functions like foo(int, int, int, int), not just bools.
That quite accurately summarizes the reason for my short »I'm not really sure what to think about this – […] named parameters would be the better solution« comment on the pull request; full ack. David
Jun 10 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 2:12 PM, Michel Fortin wrote:
 On 2011-06-10 14:52:53 -0400, Robert Clipsham
 <robert octarineparrot.com> said:

 On 10/06/2011 19:06, Andrei Alexandrescu wrote:
 Ugly is in the eye of the beholder, but I fail to see how the added
 punctuation makes Flag!"param".yes significantly more verbose than param
 : true.
foo(param: true, otherParam: false); foo(Flag!"param".yes, Flag!"otherParam".no); I don't know about you, but I find the former is far more legible. I'd hate to see my code littered with Flag!"something".
I have to say I totally agree with Robert. I agree with the need for a way to name parameters, but instantiating a pseudo-boolean type from a template for each function parameter is worse than the initial problem. Templates are already a difficult concept to grasp for most people (because they're so abstract), we really don't need to replace every boolean parameter with a template type.
I disagree with the "templates are difficult" mantra. It is a meme from C++ much like "macros are evil" are one from C. It's a simple construct, you use it.
 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
void foo(bool param, bool otherParam, bool thisOneIsntRequired = false); Call it with or without named parameters, two are required, one is not. foo(otherParam: true, param: false); foo(true, false); foo(otherParam: true, param: false, thisOneIsntRequired: true);
And just try to think of the signature for the function above if it was using Flag! void foo(Flag!"param" param, Flag!"otherParam" otherParam, Flag!"thisOneIsntRequired" thisOneIsntRequired = Flag!"thisOneIsntRequired".no); Do we really want to expose that in the documentation?
Yes, that's the whole point, though I agree the hiccup in the default initializer is annoying. The documentation doesn't need the names anymore; the user would just say: void foo( Flag!"compressed", Flag!"encrypted", Flag!"buffered" = Flag!"buffered".no); Save for the "ehm" default parameter this looks palatable to me. Andrei
Jun 10 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-10 16:10:51 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 2:12 PM, Michel Fortin wrote:
 I have to say I totally agree with Robert.
 
 I agree with the need for a way to name parameters, but instantiating a
 pseudo-boolean type from a template for each function parameter is worse
 than the initial problem. Templates are already a difficult concept to
 grasp for most people (because they're so abstract), we really don't
 need to replace every boolean parameter with a template type.
I disagree with the "templates are difficult" mantra. It is a meme from C++ much like "macros are evil" are one from C. It's a simple construct, you use it.
Neither C macros nor C++ or D templates are very difficult by themselves. People trying to do unintuitive but clever things with them earned them this reputation. If you want something to be used everywhere and it is not an implementation detail, make it part of the language. Implementing what sounds should be a language feature through a template hack and putting it the standard library is not going to make people feel good about the language, it'll remind them of what the language is missing.
 And just try to think of the signature for the function above if it was
 using Flag!
 
 void foo(Flag!"param" param, Flag!"otherParam" otherParam,
 Flag!"thisOneIsntRequired" thisOneIsntRequired =
 Flag!"thisOneIsntRequired".no);
 
 Do we really want to expose that in the documentation?
Yes, that's the whole point, though I agree the hiccup in the default initializer is annoying.
I find it funny that you see a hiccup only in the default initializer when the name of all parameter is also duplicated in its type. Shouldn't that be 4 hiccups?
 The documentation doesn't need the names anymore; the user would just say:
 
 void foo(
    Flag!"compressed",
    Flag!"encrypted",
    Flag!"buffered" = Flag!"buffered".no);
 
 Save for the "ehm" default parameter this looks palatable to me.
Does that mean we now need a language feature to tell the documentation generator not to emit attribute names for parameters of type Flag!"" ? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 3:34 PM, Michel Fortin wrote:
 On 2011-06-10 16:10:51 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 2:12 PM, Michel Fortin wrote:
 I have to say I totally agree with Robert.

 I agree with the need for a way to name parameters, but instantiating a
 pseudo-boolean type from a template for each function parameter is worse
 than the initial problem. Templates are already a difficult concept to
 grasp for most people (because they're so abstract), we really don't
 need to replace every boolean parameter with a template type.
I disagree with the "templates are difficult" mantra. It is a meme from C++ much like "macros are evil" are one from C. It's a simple construct, you use it.
Neither C macros nor C++ or D templates are very difficult by themselves. People trying to do unintuitive but clever things with them earned them this reputation.
See, here you're simply wrong. C macros are heinously complicated in definition, and heinously complicated to implement. C++ templates are very bulky in definition too. It's not worth your time you argue this further.
 If you want something to be used everywhere and it is not an
 implementation detail, make it part of the language. Implementing what
 sounds should be a language feature through a template hack and putting
 it the standard library is not going to make people feel good about the
 language, it'll remind them of what the language is missing.
The problem with the "hack" label is that it instantly decreases the level of the conversation. It's the "N" word of programming. I don't want a universal thing, I want to solve a simple problem: there are 7 yes/no enums in Phobos, and probably some more to come. Flag solves that problem in a reasonable way. This is pretty much it.
 And just try to think of the signature for the function above if it was
 using Flag!

 void foo(Flag!"param" param, Flag!"otherParam" otherParam,
 Flag!"thisOneIsntRequired" thisOneIsntRequired =
 Flag!"thisOneIsntRequired".no);

 Do we really want to expose that in the documentation?
Yes, that's the whole point, though I agree the hiccup in the default initializer is annoying.
I find it funny that you see a hiccup only in the default initializer when the name of all parameter is also duplicated in its type. Shouldn't that be 4 hiccups?
I don't think so, but I understand how you can frame that as an argument that supports your viewpoint.
 The documentation doesn't need the names anymore; the user would just
 say:

 void foo(
 Flag!"compressed",
 Flag!"encrypted",
 Flag!"buffered" = Flag!"buffered".no);

 Save for the "ehm" default parameter this looks palatable to me.
Does that mean we now need a language feature to tell the documentation generator not to emit attribute names for parameters of type Flag!"" ?
No, just version(ddoc) for select functions if you want them to. You have the needed means within the language. Andrei
Jun 10 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 I don't want a universal thing, I want to solve a simple problem: there 
 are 7 yes/no enums in Phobos, and probably some more to come. Flag 
 solves that problem in a reasonable way. This is pretty much it.
I didn't understand this well at first. Thank you for explaining again. Bye, bearophile
Jun 10 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:isu15s$30as$1 digitalmars.com...
 On 6/10/11 3:34 PM, Michel Fortin wrote:
 If you want something to be used everywhere and it is not an
 implementation detail, make it part of the language. Implementing what
 sounds should be a language feature through a template hack and putting
 it the standard library is not going to make people feel good about the
 language, it'll remind them of what the language is missing.
The problem with the "hack" label is that it instantly decreases the level of the conversation. It's the "N" word of programming. I don't want a universal thing, I want to solve a simple problem: there are 7 yes/no enums in Phobos, and probably some more to come. Flag solves that problem in a reasonable way. This is pretty much it.
 And just try to think of the signature for the function above if it was
 using Flag!

 void foo(Flag!"param" param, Flag!"otherParam" otherParam,
 Flag!"thisOneIsntRequired" thisOneIsntRequired =
 Flag!"thisOneIsntRequired".no);

 Do we really want to expose that in the documentation?
Yes, that's the whole point, though I agree the hiccup in the default initializer is annoying.
I find it funny that you see a hiccup only in the default initializer when the name of all parameter is also duplicated in its type. Shouldn't that be 4 hiccups?
I don't think so, but I understand how you can frame that as an argument that supports your viewpoint.
 The documentation doesn't need the names anymore; the user would just
 say:

 void foo(
 Flag!"compressed",
 Flag!"encrypted",
 Flag!"buffered" = Flag!"buffered".no);

 Save for the "ehm" default parameter this looks palatable to me.
Does that mean we now need a language feature to tell the documentation generator not to emit attribute names for parameters of type Flag!"" ?
No, just version(ddoc) for select functions if you want them to. You have the needed means within the language. Andrei
Jun 10 2011
parent "Nick Sabalausky" <a a.a> writes:
Ignore this: I went to reply, hit the wrong key, and it sent before I got to 
type anything... The *real* reply in another post...

"Nick Sabalausky" <a a.a> wrote in message 
news:isu4gg$5ff$1 digitalmars.com...
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:isu15s$30as$1 digitalmars.com...
 On 6/10/11 3:34 PM, Michel Fortin wrote:
 If you want something to be used everywhere and it is not an
 implementation detail, make it part of the language. Implementing what
 sounds should be a language feature through a template hack and putting
 it the standard library is not going to make people feel good about the
 language, it'll remind them of what the language is missing.
The problem with the "hack" label is that it instantly decreases the level of the conversation. It's the "N" word of programming. I don't want a universal thing, I want to solve a simple problem: there are 7 yes/no enums in Phobos, and probably some more to come. Flag solves that problem in a reasonable way. This is pretty much it.
 And just try to think of the signature for the function above if it 
 was
 using Flag!

 void foo(Flag!"param" param, Flag!"otherParam" otherParam,
 Flag!"thisOneIsntRequired" thisOneIsntRequired =
 Flag!"thisOneIsntRequired".no);

 Do we really want to expose that in the documentation?
Yes, that's the whole point, though I agree the hiccup in the default initializer is annoying.
I find it funny that you see a hiccup only in the default initializer when the name of all parameter is also duplicated in its type. Shouldn't that be 4 hiccups?
I don't think so, but I understand how you can frame that as an argument that supports your viewpoint.
 The documentation doesn't need the names anymore; the user would just
 say:

 void foo(
 Flag!"compressed",
 Flag!"encrypted",
 Flag!"buffered" = Flag!"buffered".no);

 Save for the "ehm" default parameter this looks palatable to me.
Does that mean we now need a language feature to tell the documentation generator not to emit attribute names for parameters of type Flag!"" ?
No, just version(ddoc) for select functions if you want them to. You have the needed means within the language. Andrei
Jun 10 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:isu15s$30as$1 digitalmars.com...
 On 6/10/11 3:34 PM, Michel Fortin wrote:
 If you want something to be used everywhere and it is not an
 implementation detail, make it part of the language. Implementing what
 sounds should be a language feature through a template hack and putting
 it the standard library is not going to make people feel good about the
 language, it'll remind them of what the language is missing.
The problem with the "hack" label is that it instantly decreases the level of the conversation. It's the "N" word of programming.
You're assuming that we're choosing the word "hack" as an attempt to sway. Not so. We're calling it a hack because we genuinely see it as such. However, I can see how the accusation that our usage of "hack" was an attempt to sway with wordplay (or any other such resorting to meta-arguments) can be used to frame an argument that supports your viewpoint.
 I don't want a universal thing, I want to solve a simple problem: there 
 are 7 yes/no enums in Phobos, and probably some more to come. Flag solves 
 that problem in a reasonable way. This is pretty much it.
Others *do* want a more universal thing.
 And just try to think of the signature for the function above if it was
 using Flag!

 void foo(Flag!"param" param, Flag!"otherParam" otherParam,
 Flag!"thisOneIsntRequired" thisOneIsntRequired =
 Flag!"thisOneIsntRequired".no);

 Do we really want to expose that in the documentation?
Yes, that's the whole point, though I agree the hiccup in the default initializer is annoying.
I find it funny that you see a hiccup only in the default initializer when the name of all parameter is also duplicated in its type. Shouldn't that be 4 hiccups?
I don't think so, but I understand how you can frame that as an argument that supports your viewpoint.
Now who's digging their heels in and just being stubborn? You *really* don't see the problem with "Flag!"param" param"?
 The documentation doesn't need the names anymore; the user would just
 say:

 void foo(
 Flag!"compressed",
 Flag!"encrypted",
 Flag!"buffered" = Flag!"buffered".no);

 Save for the "ehm" default parameter this looks palatable to me.
Does that mean we now need a language feature to tell the documentation generator not to emit attribute names for parameters of type Flag!"" ?
No, just version(ddoc) for select functions if you want them to. You have the needed means within the language.
And with named arguments, you don't even need to bother with that. So, more verbosity (and likely an indentation increase) to support (minimally) "less" verbosity.
Jun 10 2011
parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:isu5aa$6t0$1 digitalmars.com...
 Now who's digging their heels in and just being stubborn? You *really* 
 don't see the problem with "Flag!"param" param"?
Erm, I mean "the hiccup with it".
Jun 10 2011
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-10 17:04:42 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 3:34 PM, Michel Fortin wrote:
 If you want something to be used everywhere and it is not an
 implementation detail, make it part of the language. Implementing what
 sounds should be a language feature through a template hack and putting
 it the standard library is not going to make people feel good about the
 language, it'll remind them of what the language is missing.
The problem with the "hack" label is that it instantly decreases the level of the conversation. It's the "N" word of programming.
A hack is something that works even though it's ugly and generally cause people to call for something better. I'm not opposed to using hacks as long as they're well-encapsulated and not too fragile, but in this case I find the encapsulation is leaky since you need to litter your code with Flag!"" everywhere.
 I don't want a universal thing, I want to solve a simple problem: there 
 are 7 yes/no enums in Phobos, and probably some more to come. Flag 
 solves that problem in a reasonable way. This is pretty much it.
I disagree that Flag is a reasonable solution. It works, but it's ugly and verbose. I understand it's tiresome to create an enum for every parameter, but asking all users to write Flag!"" everywhere is going to be tiresome everywhere else, which is hardly an improvement. I also think you are narrowing the problem a little too much. The problem exists everywhere there is a boolean parameter. This includes phobos, druntime, and potentially any other D library. Should Flag!"" become the recommended way to make boolean parameters in D? And should creating a separate Ddoc version of the function signature become the recommended way to document boolean parameters? If so, I think it'll reflect badly on the language. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 10 2011
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Michel Fortin" <michel.fortin michelf.com> wrote in message 
news:isu5tk$816$1 digitalmars.com...
 I understand it's tiresome to create an enum for every parameter, but 
 asking all users to write Flag!"" everywhere is going to be tiresome 
 everywhere else, which is hardly an improvement.
Excellent point.
 I also think you are narrowing the problem a little too much. The problem 
 exists everywhere there is a boolean parameter.
And not just bools, either. Graphics libraries typically have the same problem in spades, much more than Phobos. But with numbers, not bools. Even a Flag expanded to allow *any* enum is still insufficient for that. It seems like your design strategy here is (unintentionally, of course) focusing primarily on Phobos's own needs rather than really looking out much beyond Phobos.
 This includes phobos, druntime, and potentially any other D library. 
 Should Flag!"" become the recommended way to make boolean parameters in D? 
 And should creating a separate Ddoc version of the function signature 
 become the recommended way to document boolean parameters? If so, I think 
 it'll reflect badly on the language.
Jun 10 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 5:25 PM, Michel Fortin wrote:
 On 2011-06-10 17:04:42 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 3:34 PM, Michel Fortin wrote:
 If you want something to be used everywhere and it is not an
 implementation detail, make it part of the language. Implementing what
 sounds should be a language feature through a template hack and putting
 it the standard library is not going to make people feel good about the
 language, it'll remind them of what the language is missing.
The problem with the "hack" label is that it instantly decreases the level of the conversation. It's the "N" word of programming.
A hack is something that works even though it's ugly and generally cause people to call for something better. I'm not opposed to using hacks as long as they're well-encapsulated and not too fragile, but in this case I find the encapsulation is leaky since you need to litter your code with Flag!"" everywhere.
https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e744ab8e7 Andrei
Jun 10 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-10 18:57:20 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 5:25 PM, Michel Fortin wrote:
 A hack is something that works even though it's ugly and generally cause
 people to call for something better. I'm not opposed to using hacks as
 long as they're well-encapsulated and not too fragile, but in this case
 I find the encapsulation is leaky since you need to litter your code
 with Flag!"" everywhere.
https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e744ab8e7
It's
 
still a hack, but I'll agree it makes the encapsulation a little better if you use yes!"abc" at the function call point. However, I still think it's a deterioration from the user's point of view compared to the current situation with hand-crafted enums: it still requires a string, and the documentation will say func(Flag!"abc" abc), repeating the parameter's name unless you hand-craft a special Ddoc version of the function declaration. It's better than Flag!"abc".yes, but it's worse than Abc.yes. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 8:08 PM, Michel Fortin wrote:
 On 2011-06-10 18:57:20 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 5:25 PM, Michel Fortin wrote:
 A hack is something that works even though it's ugly and generally cause
 people to call for something better. I'm not opposed to using hacks as
 long as they're well-encapsulated and not too fragile, but in this case
 I find the encapsulation is leaky since you need to litter your code
 with Flag!"" everywhere.
https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e744ab8e7
It's

 still a hack, but I'll agree it makes the encapsulation a little better
 if you use yes!"abc" at the function call point.

 However, I still think it's a deterioration from the user's point of
 view compared to the current situation with hand-crafted enums: it still
 requires a string, and the documentation will say func(Flag!"abc" abc),
 repeating the parameter's name unless you hand-craft a special Ddoc
 version of the function declaration. It's better than Flag!"abc".yes,
 but it's worse than Abc.yes.
But the problem is the same today. enum Abc : bool { no, yes } void fun(Abc abc = Abc.no); No difference. In the function declaration, the word "abc" occurs three times. Andrei
Jun 10 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:isuivh$1a6v$1 digitalmars.com...
 On 6/10/11 8:08 PM, Michel Fortin wrote:
 On 2011-06-10 18:57:20 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 5:25 PM, Michel Fortin wrote:
 A hack is something that works even though it's ugly and generally 
 cause
 people to call for something better. I'm not opposed to using hacks as
 long as they're well-encapsulated and not too fragile, but in this case
 I find the encapsulation is leaky since you need to litter your code
 with Flag!"" everywhere.
https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e744ab8e7
It's

 still a hack, but I'll agree it makes the encapsulation a little better
 if you use yes!"abc" at the function call point.

 However, I still think it's a deterioration from the user's point of
 view compared to the current situation with hand-crafted enums: it still
 requires a string, and the documentation will say func(Flag!"abc" abc),
 repeating the parameter's name unless you hand-craft a special Ddoc
 version of the function declaration. It's better than Flag!"abc".yes,
 but it's worse than Abc.yes.
But the problem is the same today. enum Abc : bool { no, yes } void fun(Abc abc = Abc.no); No difference. In the function declaration, the word "abc" occurs three times.
Which makes Flag even less of an improvement.
Jun 10 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
We should rename Yes and No to Yay and Nay to make them alignable, and
even more importantly to make us appear as old Englishmen!

Kidding. I do welcome the proposal with the prefixed Yes/No template
though, it has my vote.
Jun 10 2011
parent reply Alix Pexton <alix.DOT.pexton gmail.DOT.com> writes:
On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable, and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Jun 11 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Alix Pexton" <alix.DOT.pexton gmail.DOT.com> wrote in message 
news:isvae3$2o51$1 digitalmars.com...
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable, and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :)
Dost thou, verily?
Jun 11 2011
parent Alix Pexton <alix.DOT.pexton gmail.DOT.com> writes:
On 11/06/2011 11:56, Nick Sabalausky wrote:
 "Alix Pexton"<alix.DOT.pexton gmail.DOT.com>  wrote in message
 news:isvae3$2o51$1 digitalmars.com...
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable, and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :)
Dost thou, verily?
Aye! A...
Jun 11 2011
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/11/11, Alix Pexton <alix.DOT.pexton gmail.dot.com> wrote:
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable, and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Oh damn, yay is what teenage girls would say, not old Englishmen. My bad, it really is "Aye". :p
Jun 11 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 11 Jun 2011 13:04:47 -0400, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 On 6/11/11, Alix Pexton <alix.DOT.pexton gmail.dot.com> wrote:
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable, and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Oh damn, yay is what teenage girls would say, not old Englishmen. My bad, it really is "Aye". :p
You were phonetically right :) It's yea or nay. http://dictionary.cambridge.org/dictionary/british/yea-or-nay My son's most recent birthday (3 years old) was a farm-themed birthday, and we asked people to RSVP yay or neigh :P So I guess there's all kinds of kooky fun you can have with flags... -Steve
Jun 11 2011
parent reply Alix Pexton <alix.DOT.pexton gmail.DOT.com> writes:
On 12/06/2011 02:40, Steven Schveighoffer wrote:
 On Sat, 11 Jun 2011 13:04:47 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:

 On 6/11/11, Alix Pexton <alix.DOT.pexton gmail.dot.com> wrote:
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable, and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Oh damn, yay is what teenage girls would say, not old Englishmen. My bad, it really is "Aye". :p
You were phonetically right :) It's yea or nay. http://dictionary.cambridge.org/dictionary/british/yea-or-nay My son's most recent birthday (3 years old) was a farm-themed birthday, and we asked people to RSVP yay or neigh :P So I guess there's all kinds of kooky fun you can have with flags... -Steve
Nope, its definitely Aye when used for voting, (at least it is round here) as in "all those in favour, say aye", "ayes to the right" and "the ayes have it". Maybe southerners say this "yea" word of which you speak, we don't hold with their strange customs in these parts ^^ A...
Jun 12 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 12 Jun 2011 04:36:55 -0400, Alix Pexton  
<alix.DOT.pexton gmail.dot.com> wrote:

 On 12/06/2011 02:40, Steven Schveighoffer wrote:
 On Sat, 11 Jun 2011 13:04:47 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:

 On 6/11/11, Alix Pexton <alix.DOT.pexton gmail.dot.com> wrote:
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable,  
 and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Oh damn, yay is what teenage girls would say, not old Englishmen. My bad, it really is "Aye". :p
You were phonetically right :) It's yea or nay. http://dictionary.cambridge.org/dictionary/british/yea-or-nay My son's most recent birthday (3 years old) was a farm-themed birthday, and we asked people to RSVP yay or neigh :P So I guess there's all kinds of kooky fun you can have with flags... -Steve
Nope, its definitely Aye when used for voting, (at least it is round here) as in "all those in favour, say aye", "ayes to the right" and "the ayes have it". Maybe southerners say this "yea" word of which you speak, we don't hold with their strange customs in these parts ^^
I don't deny that aye is used frequently for voting. All I was saying is, the correct expression is yea or nay, not yay or nay. Andrej thought it was actually aye or nay, which I've never heard as an expression. I'm not sure it's used anymore, but it's definitely an expression that was used for voting (see my dictionary reference). -Steve
Jun 12 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
TBH I've only ever heard it used in Ali G Indahouse, so what do I know.. :p
Jun 12 2011
prev sibling parent reply Alix Pexton <alix.DOT.pexton gmail.DOT.com> writes:
On 12/06/2011 16:11, Steven Schveighoffer wrote:
 On Sun, 12 Jun 2011 04:36:55 -0400, Alix Pexton
 <alix.DOT.pexton gmail.dot.com> wrote:

 On 12/06/2011 02:40, Steven Schveighoffer wrote:
 On Sat, 11 Jun 2011 13:04:47 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:

 On 6/11/11, Alix Pexton <alix.DOT.pexton gmail.dot.com> wrote:
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable,
 and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Oh damn, yay is what teenage girls would say, not old Englishmen. My bad, it really is "Aye". :p
You were phonetically right :) It's yea or nay. http://dictionary.cambridge.org/dictionary/british/yea-or-nay My son's most recent birthday (3 years old) was a farm-themed birthday, and we asked people to RSVP yay or neigh :P So I guess there's all kinds of kooky fun you can have with flags... -Steve
Nope, its definitely Aye when used for voting, (at least it is round here) as in "all those in favour, say aye", "ayes to the right" and "the ayes have it". Maybe southerners say this "yea" word of which you speak, we don't hold with their strange customs in these parts ^^
I don't deny that aye is used frequently for voting. All I was saying is, the correct expression is yea or nay, not yay or nay. Andrej thought it was actually aye or nay, which I've never heard as an expression. I'm not sure it's used anymore, but it's definitely an expression that was used for voting (see my dictionary reference). -Steve
True, "yea-or-nay" is quite a common, if old fashioned phrase, but "yea" on its own is exceptionally rare (to the point where I doubt ever hearing anyone make such a noise and mean it to indicate the affirmative). A...
Jun 12 2011
parent reply Paul D. Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
Alix Pexton Wrote:

 On 12/06/2011 16:11, Steven Schveighoffer wrote:
 On Sun, 12 Jun 2011 04:36:55 -0400, Alix Pexton
 <alix.DOT.pexton gmail.dot.com> wrote:

 On 12/06/2011 02:40, Steven Schveighoffer wrote:
 On Sat, 11 Jun 2011 13:04:47 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:

 On 6/11/11, Alix Pexton <alix.DOT.pexton gmail.dot.com> wrote:
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable,
 and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Oh damn, yay is what teenage girls would say, not old Englishmen. My bad, it really is "Aye". :p
You were phonetically right :) It's yea or nay. http://dictionary.cambridge.org/dictionary/british/yea-or-nay My son's most recent birthday (3 years old) was a farm-themed birthday, and we asked people to RSVP yay or neigh :P So I guess there's all kinds of kooky fun you can have with flags... -Steve
Nope, its definitely Aye when used for voting, (at least it is round here) as in "all those in favour, say aye", "ayes to the right" and "the ayes have it". Maybe southerners say this "yea" word of which you speak, we don't hold with their strange customs in these parts ^^
I don't deny that aye is used frequently for voting. All I was saying is, the correct expression is yea or nay, not yay or nay. Andrej thought it was actually aye or nay, which I've never heard as an expression. I'm not sure it's used anymore, but it's definitely an expression that was used for voting (see my dictionary reference). -Steve
True, "yea-or-nay" is quite a common, if old fashioned phrase, but "yea" on its own is exceptionally rare (to the point where I doubt ever hearing anyone make such a noise and mean it to indicate the affirmative). A...
Then you must not have heard the King James Version of the Bible read aloud, or been to a Shakespeare play. Admittedly the KJV and Shakespeare's works don't count as modern English, but I doubt you've never "heard such a noise"! :-) p.s. The word appears 209 times in Shakespeare's plays. There's a website for everything!
Jun 12 2011
parent Alix Pexton <alix.DOT.pexton gmail.DOT.com> writes:
On 13/06/2011 02:31, Paul D. Anderson wrote:
 Alix Pexton Wrote:

 On 12/06/2011 16:11, Steven Schveighoffer wrote:
 On Sun, 12 Jun 2011 04:36:55 -0400, Alix Pexton
 <alix.DOT.pexton gmail.dot.com>  wrote:

 On 12/06/2011 02:40, Steven Schveighoffer wrote:
 On Sat, 11 Jun 2011 13:04:47 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com>  wrote:

 On 6/11/11, Alix Pexton<alix.DOT.pexton gmail.dot.com>  wrote:
 On 11/06/2011 06:18, Andrej Mitrovic wrote:
 We should rename Yes and No to Yay and Nay to make them alignable,
 and
 even more importantly to make us appear as old Englishmen!
"Yay" and "Nay" are too similar looking, but luckily, "Yay" is not actually a old English word :) A more correct alternative would be "Aye" (pronounced the same as "eye"), which (along with "Nay") is still used for some voting actions (such as councillors deciding where to go for lunch). I myself say it al least 20 times a day :) A...
Oh damn, yay is what teenage girls would say, not old Englishmen. My bad, it really is "Aye". :p
You were phonetically right :) It's yea or nay. http://dictionary.cambridge.org/dictionary/british/yea-or-nay My son's most recent birthday (3 years old) was a farm-themed birthday, and we asked people to RSVP yay or neigh :P So I guess there's all kinds of kooky fun you can have with flags... -Steve
Nope, its definitely Aye when used for voting, (at least it is round here) as in "all those in favour, say aye", "ayes to the right" and "the ayes have it". Maybe southerners say this "yea" word of which you speak, we don't hold with their strange customs in these parts ^^
I don't deny that aye is used frequently for voting. All I was saying is, the correct expression is yea or nay, not yay or nay. Andrej thought it was actually aye or nay, which I've never heard as an expression. I'm not sure it's used anymore, but it's definitely an expression that was used for voting (see my dictionary reference). -Steve
True, "yea-or-nay" is quite a common, if old fashioned phrase, but "yea" on its own is exceptionally rare (to the point where I doubt ever hearing anyone make such a noise and mean it to indicate the affirmative). A...
Then you must not have heard the King James Version of the Bible read aloud, or been to a Shakespeare play. Admittedly the KJV and Shakespeare's works don't count as modern English, but I doubt you've never "heard such a noise"! :-) p.s. The word appears 209 times in Shakespeare's plays. There's a website for everything!
Aye, I did mean people using their own words and not someone else's. for such a prolific writer, 209 doesn't seem like a lot, and I can't help wondering how many times the bard used "aye". Mind you, he was a southerner! A...
Jun 13 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 11:55 PM, Nick Sabalausky wrote:
 However, I still think it's a deterioration from the user's point of
 view compared to the current situation with hand-crafted enums: it still
 requires a string, and the documentation will say func(Flag!"abc" abc),
 repeating the parameter's name unless you hand-craft a special Ddoc
 version of the function declaration. It's better than Flag!"abc".yes,
 but it's worse than Abc.yes.
But the problem is the same today. enum Abc : bool { no, yes } void fun(Abc abc = Abc.no); No difference. In the function declaration, the word "abc" occurs three times.
Which makes Flag even less of an improvement.
I'm not sure I figure the reasoning. You can't penalize twice for the same reason. This makes the existing situation less desirable, not Flag less of an improvement over it. Andrei
Jun 11 2011
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-10 22:08:31 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 6/10/11 8:08 PM, Michel Fortin wrote:
 On 2011-06-10 18:57:20 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:
 
 https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e744ab8e7
It's still
 
a hack, but I'll agree it makes the encapsulation a little better if you use yes!"abc" at the function call point. However, I still think it's a deterioration from the user's point of view compared to the current situation with hand-crafted enums: it still requires a string, and the documentation will say func(Flag!"abc" abc), repeating the parameter's name unless you hand-craft a special Ddoc version of the function declaration. It's better than Flag!"abc".yes, but it's worse than Abc.yes.
But the problem is the same today. enum Abc : bool { no, yes } void fun(Abc abc = Abc.no); No difference. In the function declaration, the word "abc" occurs three times.
I actually didn't meant to post the above. I wrote it, then thought I should sleep on it before deciding whether I'd post it or not since I was a little to tired. Then I hit a bad key combo and the message reached the server before I could unplug my network cable. I'm not surprised you could find some inconsistencies in it. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Michel Fortin" <michel.fortin michelf.com> wrote in message 
news:isvhkr$3s4$1 digitalmars.com...
 I actually didn't meant to post the above. I wrote it, then thought I 
 should sleep on it before deciding whether I'd post it or not since I was 
 a little to tired. Then I hit a bad key combo and the message reached the 
 server before I could unplug my network cable. I'm not surprised you could 
 find some inconsistencies in it.
That dang "Send Message" keyboard combo gets me now and then, too. In fact, last time was just yesterday. I'm all for keyboard accessability for everything, but I'd love to see the keyboard access for "Send Message" be a bit less easy. On my mail client, it's Ctrl-Enter, which of course is just begging for it to be accidentally hit while editing text.
Jun 11 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-11 07:01:13 -0400, "Nick Sabalausky" <a a.a> said:

 "Michel Fortin" <michel.fortin michelf.com> wrote in message
 news:isvhkr$3s4$1 digitalmars.com...
 
 I actually didn't meant to post the above. I wrote it, then thought I
 should sleep on it before deciding whether I'd post it or not since I was
 a little to tired. Then I hit a bad key combo and the message reached the
 server before I could unplug my network cable. I'm not surprised you could
 find some inconsistencies in it.
That dang "Send Message" keyboard combo gets me now and then, too. In fact, last time was just yesterday. I'm all for keyboard accessability for everything, but I'd love to see the keyboard access for "Send Message" be a bit less easy. On my mail client, it's Ctrl-Enter, which of course is just begging for it to be accidentally hit while editing text.
Just after sending this message, I changed the combo in my newsreader from command-option-D to command-option-control-shift-D, like I did for my mail client a while ago. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 11.06.2011 13:09, schrieb Michel Fortin:
 On 2011-06-11 07:01:13 -0400, "Nick Sabalausky" <a a.a> said:
 
 "Michel Fortin" <michel.fortin michelf.com> wrote in message
 news:isvhkr$3s4$1 digitalmars.com...
 I actually didn't meant to post the above. I wrote it, then thought I
 should sleep on it before deciding whether I'd post it or not since I
 was
 a little to tired. Then I hit a bad key combo and the message reached
 the
 server before I could unplug my network cable. I'm not surprised you
 could
 find some inconsistencies in it.
That dang "Send Message" keyboard combo gets me now and then, too. In fact, last time was just yesterday. I'm all for keyboard accessability for everything, but I'd love to see the keyboard access for "Send Message" be a bit less easy. On my mail client, it's Ctrl-Enter, which of course is just begging for it to be accidentally hit while editing text.
Just after sending this message, I changed the combo in my newsreader from command-option-D to command-option-control-shift-D, like I did for my mail client a while ago.
When using a newsreader you should be able to retract a message, at least in Thunderbird you can just delete your own message to remove it from the server.
Jun 11 2011
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-11 07:11:19 -0400, Daniel Gibson <metalcaedes gmail.com> said:

 When using a newsreader you should be able to retract a message, at
 least in Thunderbird you can just delete your own message to remove it
 from the server.
I know, but Unison doesn't have that option. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 1:52 PM, Robert Clipsham wrote:
 On 10/06/2011 19:06, Andrei Alexandrescu wrote:
 On 6/10/11 12:42 PM, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
This is not half-baked. It's pretty much it.
My choice of wording was poor, sorry.
 Ugly is in the eye of the beholder, but I fail to see how the added
 punctuation makes Flag!"param".yes significantly more verbose than param
 : true.
foo(param: true, otherParam: false); foo(Flag!"param".yes, Flag!"otherParam".no); I don't know about you, but I find the former is far more legible. I'd hate to see my code littered with Flag!"something".
I agree it's more legible. The crucial question is whether the added legibility warrants adding a new feature to the language.
 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
void foo(bool param, bool otherParam, bool thisOneIsntRequired = false); Call it with or without named parameters, two are required, one is not. foo(otherParam: true, param: false); foo(true, false); foo(otherParam: true, param: false, thisOneIsntRequired: true); Would all be valid.
The second call is problematic because it still allows bad style in calls. Andrei
Jun 10 2011
next sibling parent Torarin <torarind gmail.com> writes:
2011/6/10 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:
 On 6/10/11 1:52 PM, Robert Clipsham wrote:
 On 10/06/2011 19:06, Andrei Alexandrescu wrote:
 On 6/10/11 12:42 PM, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
This is not half-baked. It's pretty much it.
My choice of wording was poor, sorry.
 Ugly is in the eye of the beholder, but I fail to see how the added
 punctuation makes Flag!"param".yes significantly more verbose than param
 : true.
foo(param: true, otherParam: false); foo(Flag!"param".yes, Flag!"otherParam".no); I don't know about you, but I find the former is far more legible. I'd hate to see my code littered with Flag!"something".
I agree it's more legible. The crucial question is whether the added legibility warrants adding a new feature to the language.
 The problem that named parameters are still optional remains. Or we need
 to add one extra language feature to specify required named parameters.
void foo(bool param, bool otherParam, bool thisOneIsntRequired = false); Call it with or without named parameters, two are required, one is not. foo(otherParam: true, param: false); foo(true, false); foo(otherParam: true, param: false, thisOneIsntRequired: true); Would all be valid.
The second call is problematic because it still allows bad style in calls. Andrei
I agree, introducing a syntax for required named parameters sounds like it would entail baggage of similar weight. Torarin
Jun 10 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:isttf6$2oub$1 digitalmars.com...
 On 6/10/11 1:52 PM, Robert Clipsham wrote:
 On 10/06/2011 19:06, Andrei Alexandrescu wrote:
 On 6/10/11 12:42 PM, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
This is not half-baked. It's pretty much it.
My choice of wording was poor, sorry.
 Ugly is in the eye of the beholder, but I fail to see how the added
 punctuation makes Flag!"param".yes significantly more verbose than param
 : true.
foo(param: true, otherParam: false); foo(Flag!"param".yes, Flag!"otherParam".no); I don't know about you, but I find the former is far more legible. I'd hate to see my code littered with Flag!"something".
I agree it's more legible. The crucial question is whether the added legibility warrants adding a new feature to the language.
I really see Flag more as a way to try to rationalize avoiding adding named parameters to the language. And yes, the legibility of "foo(Flag!"param".yes, Flag!"otherParam".no);", combined with the frequency of need for such a thing, and the complete inability of Flag to address the problem for anything but bool, the inability to document it separately (as Jonathan Davis pointed out), is all definitely much much more than enough to warrant adding a tried-and-proven feature that's become standard in damn near every other modern language.
Jun 10 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:istv62$2skn$1 digitalmars.com...
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:isttf6$2oub$1 digitalmars.com...
 On 6/10/11 1:52 PM, Robert Clipsham wrote:
 foo(param: true, otherParam: false);
 foo(Flag!"param".yes, Flag!"otherParam".no);

 I don't know about you, but I find the former is far more legible. I'd
 hate to see my code littered with Flag!"something".
I agree it's more legible. The crucial question is whether the added legibility warrants adding a new feature to the language.
I really see Flag more as a way to try to rationalize avoiding adding named parameters to the language. And yes, the legibility of "foo(Flag!"param".yes, Flag!"otherParam".no);", combined with the frequency of need for such a thing, and the complete inability of Flag to address the problem for anything but bool, the inability to document it separately (as Jonathan Davis pointed out), is all definitely much much more than enough to warrant adding a tried-and-proven feature that's become standard in damn near every other modern language.
Regarding "the complete inability of Flag to address the problem for anything but bool", how are we going to wind up papering over that? Like: box(Int!"x"(3), Int!"y"(4), Int!"width"(100), Int!"height"(150), Int!"depth"(1), UInt!"color"(0xFFAA77)); ?
Jun 10 2011
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-10 13:36, Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message
 news:istv62$2skn$1 digitalmars.com...
 
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
 news:isttf6$2oub$1 digitalmars.com...
 
 On 6/10/11 1:52 PM, Robert Clipsham wrote:
 foo(param: true, otherParam: false);
 foo(Flag!"param".yes, Flag!"otherParam".no);
 
 I don't know about you, but I find the former is far more legible. I'd
 hate to see my code littered with Flag!"something".
I agree it's more legible. The crucial question is whether the added legibility warrants adding a new feature to the language.
I really see Flag more as a way to try to rationalize avoiding adding named parameters to the language. And yes, the legibility of "foo(Flag!"param".yes, Flag!"otherParam".no);", combined with the frequency of need for such a thing, and the complete inability of Flag to address the problem for anything but bool, the inability to document it separately (as Jonathan Davis pointed out), is all definitely much much more than enough to warrant adding a tried-and-proven feature that's become standard in damn near every other modern language.
Regarding "the complete inability of Flag to address the problem for anything but bool", how are we going to wind up papering over that? Like: box(Int!"x"(3), Int!"y"(4), Int!"width"(100), Int!"height"(150), Int!"depth"(1), UInt!"color"(0xFFAA77));
These yes/no enums _aren't_ named arguments. They're an attempt at creating new types where the values say what they are. The goal is primarily clarity, which named arguments arguably help with, but it's not quite the same thing. Without typedef (which is on its way out), you can't really do something like that with anything other than bool. Int!"y"(4) has to generate an int (unless you want to be forcing that all of these arguments be structs, which would be hideous), at which point it's purely documentation which the compiler has to optimize out. It's not doing the same thing as Flag at all. Andrei isn't trying to create general named arguments here. He's simply trying to create a cleaner way of generating enums with yes and no values and thus reduce boilerplate code. Having named arguments would create a similar effect, but the goal of this enum has nothing to do with named arguments beyond the fact that they have a similar effect. Its goal is to reduce boilerplate code. The net result of having the enums and Flag _is_ similar to named arguments for bool, but I don't believe that Andrei ever set down this path with the idea of creating named arguments. He effectively wanted a typedef for bool which was self-documenting. So, your suggestions of Int!"height(150) and the like are trying to do something very different (albeit somewhat related) to what Flag is trying to do. - Jonathan M Davis
Jun 10 2011
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 3:36 PM, Nick Sabalausky wrote:
 "Nick Sabalausky"<a a.a>  wrote in message
 news:istv62$2skn$1 digitalmars.com...
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:isttf6$2oub$1 digitalmars.com...
 On 6/10/11 1:52 PM, Robert Clipsham wrote:
 foo(param: true, otherParam: false);
 foo(Flag!"param".yes, Flag!"otherParam".no);

 I don't know about you, but I find the former is far more legible. I'd
 hate to see my code littered with Flag!"something".
I agree it's more legible. The crucial question is whether the added legibility warrants adding a new feature to the language.
I really see Flag more as a way to try to rationalize avoiding adding named parameters to the language. And yes, the legibility of "foo(Flag!"param".yes, Flag!"otherParam".no);", combined with the frequency of need for such a thing, and the complete inability of Flag to address the problem for anything but bool, the inability to document it separately (as Jonathan Davis pointed out), is all definitely much much more than enough to warrant adding a tried-and-proven feature that's become standard in damn near every other modern language.
Regarding "the complete inability of Flag to address the problem for anything but bool", how are we going to wind up papering over that? Like: box(Int!"x"(3), Int!"y"(4), Int!"width"(100), Int!"height"(150), Int!"depth"(1), UInt!"color"(0xFFAA77)); ?
I don't find it entirely fair to demean the suggestion as a tool to sustain your viewpoint. Flag supporting only yes and no is not a "complete inability" - it is its charter. The plan is not to have Flag be a replacement for named arguments, but instead to have it support good practices for Boolean settings and replace a number of awkward enum definitions in Phobos. As I mentioned, in the future it's possible to have Flag (or a related abstraction) support categorical features beyond yes and no, but it is not meant, and does not attempt, to cover named arguments. Andrei
Jun 10 2011
prev sibling parent reply Lutger Blijdestijn <lutger.blijdestijn gmail.com> writes:
Nick Sabalausky wrote:

 "Nick Sabalausky" <a a.a> wrote in message
 news:istv62$2skn$1 digitalmars.com...
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
 news:isttf6$2oub$1 digitalmars.com...
 On 6/10/11 1:52 PM, Robert Clipsham wrote:
 foo(param: true, otherParam: false);
 foo(Flag!"param".yes, Flag!"otherParam".no);

 I don't know about you, but I find the former is far more legible. I'd
 hate to see my code littered with Flag!"something".
I agree it's more legible. The crucial question is whether the added legibility warrants adding a new feature to the language.
I really see Flag more as a way to try to rationalize avoiding adding named parameters to the language.
I don't, even though I like named parameters. boolean parameters for binary options are kind of an exception imho, because they decrease readability at the call site much more often than other types do. Somebody one this newsgroup - maybe it was Don Clugston, also made a good point against named parameters: it introduces inflexibility because now the names of the parameters of a function become part of the public api. Changing a name will now break client code. I'd still probably welcome named parameters though.
 And yes, the legibility of "foo(Flag!"param".yes,
 Flag!"otherParam".no);", combined with the frequency of need for such a
 thing, and the complete inability of Flag to address the problem for
 anything but bool, the inability to document it separately (as Jonathan
 Davis pointed out), is all definitely much much more than enough to
 warrant adding a tried-and-proven feature that's become standard in damn
 near every other modern language.
Regarding "the complete inability of Flag to address the problem for anything but bool", how are we going to wind up papering over that? Like: box(Int!"x"(3), Int!"y"(4), Int!"width"(100), Int!"height"(150), Int!"depth"(1), UInt!"color"(0xFFAA77)); ?
Jun 10 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Jun 10 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 4:28 PM, Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn<lutger.blijdestijn gmail.com>  wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Actually, not. The name used with Flag is part of its type. Even in a separate compilation approach, the type names must match, which is not the case for parameter names. Andrei
Jun 10 2011
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 10 Jun 2011 17:34:34 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 6/10/11 4:28 PM, Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn<lutger.blijdestijn gmail.com>  wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Actually, not. The name used with Flag is part of its type. Even in a separate compilation approach, the type names must match, which is not the case for parameter names.
No, it's not the same, which actually can be viewed as a plus for named parameters. A named parameter call reduces to a normal call with boolean args, which is binary compatible, even if you change the name of the parameter. A Flag! requires a recompile as well as a source change. For things like fixing typos, the binary compatibility might be good. For example, if you have a typo in the name of a Flag parameter in library version 1, you can never change the name and be backwards compatible with someone who has an old version of the library they are compiling against. The Flag makes it *more* a part of the API than named parameters. -Steve
Jun 10 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/10/11, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 On 6/10/11 4:28 PM, Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn<lutger.blijdestijn gmail.com>  wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Actually, not. The name used with Flag is part of its type. Even in a separate compilation approach, the type names must match, which is not the case for parameter names. Andrei
I've either misread what Lutger said or I haven't stated my intentions more clearly. Most probably both.. :) By "breaking code", I'm referring to breaking compilation of existing code, not breaking the runtime semantics. You're doing this now: Flag!"KeepTerminator" keepTerminator You can change the variable name and the client code still compiles. But are you going to keep the name "KeepTerminator" in sync with the new variable name? It sure seems that's how this Flag template is used. If you do, that means client code has to change as well. Named arguments have the same problem. That's what I was referring to.
Jun 10 2011
prev sibling parent reply Lutger Blijdestijn <lutger.blijdestijn gmail.com> writes:
Andrej Mitrovic wrote:

 On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not strictly, but practically yes. It's also the point of them, exposing this name in the api. But its *only* for those parameters, which I understand are right now just 7 functions in the whole of phobos. With named parameters, the issue affects every function, including those already written without this dependency issue in mind.
Jun 10 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Lutger Blijdestijn" <lutger.blijdestijn gmail.com> wrote in message 
news:isu365$2ao$1 digitalmars.com...
 Andrej Mitrovic wrote:

 On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not strictly, but practically yes. It's also the point of them, exposing this name in the api. But its *only* for those parameters, which I understand are right now just 7 functions in the whole of phobos. With named parameters, the issue affects every function, including those already written without this dependency issue in mind.
That's hardly an issue though. Updating callers to use a changed function name is trivial. I see no reason why this would be any less trivial.
Jun 10 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-10 14:44, Nick Sabalausky wrote:
 "Lutger Blijdestijn" <lutger.blijdestijn gmail.com> wrote in message
 news:isu365$2ao$1 digitalmars.com...
 
 Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not strictly, but practically yes. It's also the point of them, exposing this name in the api. But its *only* for those parameters, which I understand are right now just 7 functions in the whole of phobos. With named parameters, the issue affects every function, including those already written without this dependency issue in mind.
That's hardly an issue though. Updating callers to use a changed function name is trivial. I see no reason why this would be any less trivial.
The problem is that there is no way to provide a deprecation path without renaming functions. When changing the types that a function takes or the number of its parameters, you can overload it. The old version gets scheduled for deprecation, then deprecated, and finally, it's removed. People have time to migrate their code. However, you _can't_ overload on parameter names. So, the only way that you can change a parameter's name without breaking any and all code that used it as a named argument is to create a _new_ function with a _new_ name. So, we'd have to rename entire functions just to be able to rename a single parameter. That's way worse than just having to deal with some parameter type changes or a changes in the number of arguments. Suddenly, you have a whole new function to remember. And currently, you can rename a parameter's name without breaking any code at all. So, named arguments _drastically_ increase the pain of renaming function parameters. - Jonathan M Davis
Jun 10 2011
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 10 Jun 2011 17:59:30 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-06-10 14:44, Nick Sabalausky wrote:
 "Lutger Blijdestijn" <lutger.blijdestijn gmail.com> wrote in message
 news:isu365$2ao$1 digitalmars.com...

 Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not strictly, but practically yes. It's also the point of them,
exposing
 this name in the api. But its *only* for those parameters, which I
 understand are right now just 7 functions in the whole of phobos.

 With named parameters, the issue affects every function, including  
those
 already written without this dependency issue in mind.
That's hardly an issue though. Updating callers to use a changed function name is trivial. I see no reason why this would be any less trivial.
The problem is that there is no way to provide a deprecation path without renaming functions. When changing the types that a function takes or the number of its parameters, you can overload it. The old version gets scheduled for deprecation, then deprecated, and finally, it's removed. People have time to migrate their code. However, you _can't_ overload on parameter names. So, the only way that you can change a parameter's name without breaking any and all code that used it as a named argument is to create a _new_ function with a _new_ name. So, we'd have to rename entire functions just to be able to rename a single parameter. That's way worse than just having to deal with some parameter type changes or a changes in the number of arguments. Suddenly, you have a whole new function to remember. And currently, you can rename a parameter's name without breaking any code at all. So, named arguments _drastically_ increase the pain of renaming function parameters.
This assumes everyone calls every function with named parameters. In reality the number of named parameter calls will be low. There are also possible ways to implement this properly: void foo(bool KeepTerminator) { } void foo(bool OldName); // mark as deprecated? Should be feasible. -Steve
Jun 10 2011
prev sibling next sibling parent KennyTM~ <kennytm gmail.com> writes:
On Jun 11, 11 05:59, Jonathan M Davis wrote:
 On 2011-06-10 14:44, Nick Sabalausky wrote:
 "Lutger Blijdestijn"<lutger.blijdestijn gmail.com>  wrote in message
 news:isu365$2ao$1 digitalmars.com...

 Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn<lutger.blijdestijn gmail.com>  wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not strictly, but practically yes. It's also the point of them, exposing this name in the api. But its *only* for those parameters, which I understand are right now just 7 functions in the whole of phobos. With named parameters, the issue affects every function, including those already written without this dependency issue in mind.
That's hardly an issue though. Updating callers to use a changed function name is trivial. I see no reason why this would be any less trivial.
The problem is that there is no way to provide a deprecation path without renaming functions. When changing the types that a function takes or the number of its parameters, you can overload it. The old version gets scheduled for deprecation, then deprecated, and finally, it's removed. People have time to migrate their code. However, you _can't_ overload on parameter names. So, the only way that you can change a parameter's name without breaking any and all code that used it as a named argument is to create a _new_ function with a _new_ name. So, we'd have to rename entire functions just to be able to rename a single parameter. That's way worse than just having to deal with some parameter type changes or a changes in the number of arguments. Suddenly, you have a whole new function to remember. And currently, you can rename a parameter's name without breaking any code at all. So, named arguments _drastically_ increase the pain of renaming function parameters. - Jonathan M Davis
Why do you need to rename parameter name of a stable API?
Jun 10 2011
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.793.1307743181.14074.digitalmars-d puremagic.com...
 On 2011-06-10 14:44, Nick Sabalausky wrote:
 "Lutger Blijdestijn" <lutger.blijdestijn gmail.com> wrote in message
 news:isu365$2ao$1 digitalmars.com...

 Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not strictly, but practically yes. It's also the point of them, exposing this name in the api. But its *only* for those parameters, which I understand are right now just 7 functions in the whole of phobos. With named parameters, the issue affects every function, including those already written without this dependency issue in mind.
That's hardly an issue though. Updating callers to use a changed function name is trivial. I see no reason why this would be any less trivial.
The problem is that there is no way to provide a deprecation path without renaming functions.
What I don't see is a compelling need to provide a deprecation path when the names change. What's so hard about "Recompiling...Oh, 'foo' doesn't work and the new name is 'bar', and it's on this file/line? Ok, done." And even that isn't needed much in a stable API anyway.
Jun 10 2011
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-10 14:28, Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not really. There's a big difference between changing the type name and changing the parameter name. You can freely change the parameter name without changing the type name. Also, you can overload on type names, allowing you to deprecate the old name and replace it with a new one gradually. You _can't_ overload on parameter names, so you _can't_ have a deprecation path with named arguments without renaming the function itself, which is _way_ worse. The difference between the two isn't even comparable. - Jonathan M Davis
Jun 10 2011
parent "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.791.1307742081.14074.digitalmars-d puremagic.com...
 On 2011-06-10 14:28, Andrej Mitrovic wrote:
 On 6/10/11, Lutger Blijdestijn <lutger.blijdestijn gmail.com> wrote:
 Changing a name will now break client code.
The flag template suffers from the same issue.
Not really. There's a big difference between changing the type name and changing the parameter name. You can freely change the parameter name without changing the type name. Also, you can overload on type names, allowing you to deprecate the old name and replace it with a new one gradually. You _can't_ overload on parameter names, so you _can't_ have a deprecation path with named arguments without renaming the function itself, which is _way_ worse. The difference between the two isn't even comparable. - Jonathan M Davis
I *really* think that whole issue is a complete triviality, but: 1. Maybe you *could* allow overloading on name, forcing at least that particular param to be named: void foo(int oldName); void foo(int newName); foo(oldName:7); // Ok foo(newName:7); // Ok foo(7); // Error void bar(int num); bar(num:7); // Ok bar(7); // Ok 2. This: void foo(int newName); deprecated void foo(int oldName); foo(oldName:7); // Error: Deprecated foo(newName:7); // Ok foo(7); // Ok
Jun 10 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 3:30 PM, Nick Sabalausky wrote:
 I really see Flag more as a way to try to rationalize avoiding adding named
 parameters to the language.
There are fights that I believe are important and others that I think are less so. I find name parameters nice to have but more in the second category. There's just so much stuff that's more important.
 And yes, the legibility of "foo(Flag!"param".yes, Flag!"otherParam".no);",
Fair point. I figured this should be easier: foo(yes!"param", no!"otherParam"); See https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e744ab8e7
 combined with the frequency of need for such a thing,
People have found 7 uses of the yes/no enum pattern in Phobos plus a couple others where it should - in 135KLoC.
 and the complete
 inability of Flag to address the problem for anything but bool,
Flag can be made to incorporate arbitrary categorical types, I just haven't done that yet so as to not complicate implementation too early.
 the
 inability to document it separately (as Jonathan Davis pointed out),
This is an issue shared by named parameters, and for such stuff the current enums work just fine. Now who is rationalizing? :o)
 is all
 definitely much much more than enough to warrant adding a tried-and-proven
 feature that's become standard in damn near every other modern language.
I'm actually less convinced than before having read your arguments. Andrei
Jun 10 2011
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 11.06.2011 0:58, Andrei Alexandrescu wrote:
 On 6/10/11 3:30 PM, Nick Sabalausky wrote:
 I really see Flag more as a way to try to rationalize avoiding adding 
 named
 parameters to the language.
There are fights that I believe are important and others that I think are less so. I find name parameters nice to have but more in the second category. There's just so much stuff that's more important.
 And yes, the legibility of "foo(Flag!"param".yes, 
 Flag!"otherParam".no);",
Fair point. I figured this should be easier: foo(yes!"param", no!"otherParam");
I think this looks not half bad and does not require change in the language. Still yes.param and no.param might be easier on the eyes, though IMO it should look more like just param and no.param. e.g. StopWatch(autoStart); StopWatch(no!autoStart); // or no.autoStart -- Dmitry Olshansky
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 6:03 PM, Dmitry Olshansky wrote:
 On 11.06.2011 0:58, Andrei Alexandrescu wrote:
 On 6/10/11 3:30 PM, Nick Sabalausky wrote:
 I really see Flag more as a way to try to rationalize avoiding adding
 named
 parameters to the language.
There are fights that I believe are important and others that I think are less so. I find name parameters nice to have but more in the second category. There's just so much stuff that's more important.
 And yes, the legibility of "foo(Flag!"param".yes,
 Flag!"otherParam".no);",
Fair point. I figured this should be easier: foo(yes!"param", no!"otherParam");
I think this looks not half bad and does not require change in the language. Still yes.param and no.param might be easier on the eyes, though IMO it should look more like just param and no.param. e.g. StopWatch(autoStart); StopWatch(no!autoStart); // or no.autoStart
Ask, and ye shall receive. https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330 Andrei
Jun 10 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/11/11, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 Ask, and ye shall receive.

 https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330
That's much more like it. This whole bikeshedding issue for me was avoiding the nasty bang quote string unquote shenanigans that look ugly in code. Keeping No and Yes at the beginning kind of goes in hand with the not operator. Now that I mention it, you can't negate a Flag variable: Flag!"KeepTerminator" state; auto line = getLine(!state); But maybe that's a good thing?
Jun 10 2011
prev sibling next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Fri, 10 Jun 2011 18:16:14 -0500, Andrei Alexandrescu wrote:

 On 6/10/11 6:03 PM, Dmitry Olshansky wrote:
 On 11.06.2011 0:58, Andrei Alexandrescu wrote:
 On 6/10/11 3:30 PM, Nick Sabalausky wrote:
 I really see Flag more as a way to try to rationalize avoiding adding
 named
 parameters to the language.
There are fights that I believe are important and others that I think are less so. I find name parameters nice to have but more in the second category. There's just so much stuff that's more important.
 And yes, the legibility of "foo(Flag!"param".yes,
 Flag!"otherParam".no);",
Fair point. I figured this should be easier: foo(yes!"param", no!"otherParam");
I think this looks not half bad and does not require change in the language. Still yes.param and no.param might be easier on the eyes, though IMO it should look more like just param and no.param. e.g. StopWatch(autoStart); StopWatch(no!autoStart); // or no.autoStart
Ask, and ye shall receive. https://github.com/andralex/phobos/
commit/801ccc96ce56827cd0d0b608895269bdccba4330 I'm sold. :) To add my 2 cents to the "named arguments" debate, I can't believe people are still asking for this. At this point in D's development, adding such would be a major language change, and there really shouldn't be any more of those. I mean, D2 supposedly went stable almost a year ago! If/when work starts on D3, we can get back to it. In the mean time, I think Flag!"param" with the new Yes/No types nicely solves a common case of code duplication in Phobos. It is not, nor do I think Andrei intended it to be, a general attempt to emulate named parameters. -Lars
Jun 10 2011
prev sibling next sibling parent reply Mafi <mafi example.org> writes:
Am 11.06.2011 01:16, schrieb Andrei Alexandrescu:
 Ask, and ye shall receive.

 https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330
I like this version much more but shouldn't it also be flag.KeepTerminator for consistency? Mafi
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 4:58 AM, Mafi wrote:
 Am 11.06.2011 01:16, schrieb Andrei Alexandrescu:
 Ask, and ye shall receive.

 https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330
I like this version much more but shouldn't it also be flag.KeepTerminator for consistency? Mafi
Not sure I understand. How do you mean that? Andrei
Jun 11 2011
parent Mafi <mafi example.org> writes:
Am 11.06.2011 14:07, schrieb Andrei Alexandrescu:
 On 6/11/11 4:58 AM, Mafi wrote:
 Am 11.06.2011 01:16, schrieb Andrei Alexandrescu:
 Ask, and ye shall receive.

 https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330
I like this version much more but shouldn't it also be flag.KeepTerminator for consistency? Mafi
Not sure I understand. How do you mean that? Andrei
I meant something like this: template FlagImpl(string name) { enum FlagImpl : bool { yes = true, no = false } } //usage Flag.xy as alias for FlagImpl!"xy" //to be consistent with yes.xy and no.xy struct Flag { template opDispatch(string name) { alias FlagImpl!name opDispatch; } } Now, opDispatch cannot currently be a type, can it.
Jun 11 2011
prev sibling next sibling parent Mike Parker <aldacron gmail.com> writes:
On 6/11/2011 8:16 AM, Andrei Alexandrescu wrote:
 On 6/10/11 6:03 PM, Dmitry Olshansky wrote:
 On 11.06.2011 0:58, Andrei Alexandrescu wrote:
 On 6/10/11 3:30 PM, Nick Sabalausky wrote:
 I really see Flag more as a way to try to rationalize avoiding adding
 named
 parameters to the language.
There are fights that I believe are important and others that I think are less so. I find name parameters nice to have but more in the second category. There's just so much stuff that's more important.
 And yes, the legibility of "foo(Flag!"param".yes,
 Flag!"otherParam".no);",
Fair point. I figured this should be easier: foo(yes!"param", no!"otherParam");
I think this looks not half bad and does not require change in the language. Still yes.param and no.param might be easier on the eyes, though IMO it should look more like just param and no.param. e.g. StopWatch(autoStart); StopWatch(no!autoStart); // or no.autoStart
Ask, and ye shall receive. https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330 Andrei
I was going to add my voice against this proposal until I saw this. Nice one!
Jun 11 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 10 Jun 2011 19:16:14 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 6/10/11 6:03 PM, Dmitry Olshansky wrote:
 On 11.06.2011 0:58, Andrei Alexandrescu wrote:
 On 6/10/11 3:30 PM, Nick Sabalausky wrote:
 I really see Flag more as a way to try to rationalize avoiding adding
 named
 parameters to the language.
There are fights that I believe are important and others that I think are less so. I find name parameters nice to have but more in the second category. There's just so much stuff that's more important.
 And yes, the legibility of "foo(Flag!"param".yes,
 Flag!"otherParam".no);",
Fair point. I figured this should be easier: foo(yes!"param", no!"otherParam");
I think this looks not half bad and does not require change in the language. Still yes.param and no.param might be easier on the eyes, though IMO it should look more like just param and no.param. e.g. StopWatch(autoStart); StopWatch(no!autoStart); // or no.autoStart
Ask, and ye shall receive. https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330
This is better. Does the definition of the function still require repetition? i.e. getLine(Flag!"KeepTerminator" keepTerminator = Yes.KeepTerminator). I suppose we can live with that. Still reads weird to me with the value coming before the category, but I suppose the names can be adjusted accordingly. As far as the negation, I think we need one more layer of type: struct FlagParam(string pname) { Flag!pname value; alias value this; this(Flag!pname x) { this.value = x } FlagParam op???() const { return FlagParam(cast(Flag!pname)!value); } } BTW, is there a way to hook "!"? Maybe this won't work... The idea is to have Yes.abc return FlagParam!"abc"(Flag!"abc".yes). -Steve
Jun 11 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-11 09:05:52 -0400, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 As far as the negation, I think we need one more layer of type:
 
 struct FlagParam(string pname)
 {
     Flag!pname value;
     alias value this;
     this(Flag!pname x) { this.value = x }
     FlagParam op???() const { return FlagParam(cast(Flag!pname)!value); }
 }
 
 BTW, is there a way to hook "!"?  Maybe this won't work...  The idea is 
 to  have Yes.abc return FlagParam!"abc"(Flag!"abc".yes).
If you need to convert a bool to a Flag!"abc", you can do any of these: func(expression ? Yes.abc : No.abc); or func(cast(Flag!"abc")expression); or, with your proposal: func(FlagParam!"abc"(expression)); None of this is very appealing, but I find the first is the most readable. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 8:25 AM, Michel Fortin wrote:
 On 2011-06-11 09:05:52 -0400, "Steven Schveighoffer"
 <schveiguy yahoo.com> said:

 As far as the negation, I think we need one more layer of type:

 struct FlagParam(string pname)
 {
 Flag!pname value;
 alias value this;
 this(Flag!pname x) { this.value = x }
 FlagParam op???() const { return FlagParam(cast(Flag!pname)!value); }
 }

 BTW, is there a way to hook "!"? Maybe this won't work... The idea is
 to have Yes.abc return FlagParam!"abc"(Flag!"abc".yes).
If you need to convert a bool to a Flag!"abc", you can do any of these: func(expression ? Yes.abc : No.abc); or func(cast(Flag!"abc")expression); or, with your proposal: func(FlagParam!"abc"(expression)); None of this is very appealing, but I find the first is the most readable.
Agreed. I'll venture to add that I find the first also more desirable than an implicit conversion from func(expression). Andrei
Jun 11 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 11 Jun 2011 09:25:19 -0400, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2011-06-11 09:05:52 -0400, "Steven Schveighoffer"  
 <schveiguy yahoo.com> said:

 As far as the negation, I think we need one more layer of type:
  struct FlagParam(string pname)
 {
     Flag!pname value;
     alias value this;
     this(Flag!pname x) { this.value = x }
     FlagParam op???() const { return FlagParam(cast(Flag!pname)!value);  
 }
 }
  BTW, is there a way to hook "!"?  Maybe this won't work...  The idea  
 is to  have Yes.abc return FlagParam!"abc"(Flag!"abc".yes).
If you need to convert a bool to a Flag!"abc", you can do any of these: func(expression ? Yes.abc : No.abc); or func(cast(Flag!"abc")expression); or, with your proposal: func(FlagParam!"abc"(expression)); None of this is very appealing, but I find the first is the most readable.
We need another struct besides Yes and No that allows creation with another opDispatch: Foo.abc(expression); The best name for Foo is Flag, but that's taken... But still, is there a way to override the type returned by !flag? I think there isn't... That's kind of sucky. Flipping of a flag is a very common feature, I would expect to be able to do it easily. Hm... what if opCast!bool() returns something other than bool? does that actually work? That *would* be a hack :) We could also possibly use unary - to denote flipping a flag. That's very hacky too, but I think it would work. -Steve
Jun 11 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 9:30 AM, Steven Schveighoffer wrote:
 On Sat, 11 Jun 2011 09:25:19 -0400, Michel Fortin
 <michel.fortin michelf.com> wrote:

 On 2011-06-11 09:05:52 -0400, "Steven Schveighoffer"
 <schveiguy yahoo.com> said:

 As far as the negation, I think we need one more layer of type:
 struct FlagParam(string pname)
 {
 Flag!pname value;
 alias value this;
 this(Flag!pname x) { this.value = x }
 FlagParam op???() const { return FlagParam(cast(Flag!pname)!value); }
 }
 BTW, is there a way to hook "!"? Maybe this won't work... The idea is
 to have Yes.abc return FlagParam!"abc"(Flag!"abc".yes).
If you need to convert a bool to a Flag!"abc", you can do any of these: func(expression ? Yes.abc : No.abc); or func(cast(Flag!"abc")expression); or, with your proposal: func(FlagParam!"abc"(expression)); None of this is very appealing, but I find the first is the most readable.
We need another struct besides Yes and No that allows creation with another opDispatch: Foo.abc(expression); The best name for Foo is Flag, but that's taken... But still, is there a way to override the type returned by !flag? I think there isn't... That's kind of sucky. Flipping of a flag is a very common feature, I would expect to be able to do it easily.
I agree that's a drawback. I couldn't find a reasonable workaround. Andrei
Jun 11 2011
prev sibling parent KennyTM~ <kennytm gmail.com> writes:
On Jun 11, 11 02:06, Andrei Alexandrescu wrote:
 On 6/10/11 12:42 PM, Robert Clipsham wrote:
 On 10/06/2011 17:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!

 Andrei
I really *really* don't like this. It's ugly and verbose, and a pathetic work around for the lack of named parameters. Either support named parameters or not, don't have an ugly half-baked work-around.
This is not half-baked. It's pretty much it. Ugly is in the eye of the beholder, but I fail to see how the added punctuation makes Flag!"param".yes significantly more verbose than param : true. The problem that named parameters are still optional remains. Or we need to add one extra language feature to specify required named parameters. Andrei
Making the compulsory enum name as a feature means http://www.digitalmars.com/d/archives/digitalmars/D/8524.html will never be addressed, I suppose.
Jun 10 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94
 
 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes. After thinking about it, I'd argue that it would be better to create a string mixin which created the enums for you instead of using the template as part of the arguments. e.g. mixin(YesNoEnum!"KeepTerminator")); Then all of the rest of the code is the same. You'd still use KeepTerminator.yes and KeepTerminator.no, but we avoided having to create duplicate enums by hand every time that we want this kind of variable. So, you still reduce the boilerplate code, but the usage is much less ugly. - Jonathan M Davis
Jun 10 2011
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 11, 11 03:30, Jonathan M Davis wrote:
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes. After thinking about it, I'd argue that it would be better to create a string mixin which created the enums for you instead of using the template as part of the arguments. e.g. mixin(YesNoEnum!"KeepTerminator")); Then all of the rest of the code is the same. You'd still use KeepTerminator.yes and KeepTerminator.no, but we avoided having to create duplicate enums by hand every time that we want this kind of variable. So, you still reduce the boilerplate code, but the usage is much less ugly. - Jonathan M Davis
The problem is the 'YesNoEnum!"KeepTerminator"' will not be shown along with the DDoc of 'getLine'.
Jun 10 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-10 12:33, KennyTM~ wrote:
 On Jun 11, 11 03:30, Jonathan M Davis wrote:
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94
 
 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes. After thinking about it, I'd argue that it would be better to create a string mixin which created the enums for you instead of using the template as part of the arguments. e.g. mixin(YesNoEnum!"KeepTerminator")); Then all of the rest of the code is the same. You'd still use KeepTerminator.yes and KeepTerminator.no, but we avoided having to create duplicate enums by hand every time that we want this kind of variable. So, you still reduce the boilerplate code, but the usage is much less ugly. - Jonathan M Davis
The problem is the 'YesNoEnum!"KeepTerminator"' will not be shown along with the DDoc of 'getLine'.
Why would it be? You generally want documentation specific to the enum anyway, so that isn't exactly boilerplate. You'd just stick the documentation above the mixin. And if you don't want to do that but want it in the documentation for the function that uses it (particularly if there's only one - though that's often not the case), then just put the documentation in the function's documentation. Andrei's current solution does nothing for documentation, and arguably makes it worse, because there's no place to put documentation on the enum directly if you need to. - Jonathan M Davis
Jun 10 2011
parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 11, 11 03:40, Jonathan M Davis wrote:
 On 2011-06-10 12:33, KennyTM~ wrote:
 On Jun 11, 11 03:30, Jonathan M Davis wrote:
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes. After thinking about it, I'd argue that it would be better to create a string mixin which created the enums for you instead of using the template as part of the arguments. e.g. mixin(YesNoEnum!"KeepTerminator")); Then all of the rest of the code is the same. You'd still use KeepTerminator.yes and KeepTerminator.no, but we avoided having to create duplicate enums by hand every time that we want this kind of variable. So, you still reduce the boilerplate code, but the usage is much less ugly. - Jonathan M Davis
The problem is the 'YesNoEnum!"KeepTerminator"' will not be shown along with the DDoc of 'getLine'.
Why would it be? You generally want documentation specific to the enum anyway, so that isn't exactly boilerplate. You'd just stick the documentation above the mixin. And if you don't want to do that but want it in the documentation for the function that uses it (particularly if there's only one - though that's often not the case), then just put the documentation in the function's documentation. Andrei's current solution does nothing for documentation, and arguably makes it worse, because there's no place to put documentation on the enum directly if you need to. - Jonathan M Davis
Please review the previous discussion of why Flag (was YesOrNo) was proposed. http://www.digitalmars.com/d/archives/digitalmars/D/YesOrNo_useful_idiom_helper_or_wanking_134392.html
Jun 10 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-10 12:47, KennyTM~ wrote:
 On Jun 11, 11 03:40, Jonathan M Davis wrote:
 On 2011-06-10 12:33, KennyTM~ wrote:
 On Jun 11, 11 03:30, Jonathan M Davis wrote:
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94
 
 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes. After thinking about it, I'd argue that it would be better to create a string mixin which created the enums for you instead of using the template as part of the arguments. e.g. mixin(YesNoEnum!"KeepTerminator")); Then all of the rest of the code is the same. You'd still use KeepTerminator.yes and KeepTerminator.no, but we avoided having to create duplicate enums by hand every time that we want this kind of variable. So, you still reduce the boilerplate code, but the usage is much less ugly. - Jonathan M Davis
The problem is the 'YesNoEnum!"KeepTerminator"' will not be shown along with the DDoc of 'getLine'.
Why would it be? You generally want documentation specific to the enum anyway, so that isn't exactly boilerplate. You'd just stick the documentation above the mixin. And if you don't want to do that but want it in the documentation for the function that uses it (particularly if there's only one - though that's often not the case), then just put the documentation in the function's documentation. Andrei's current solution does nothing for documentation, and arguably makes it worse, because there's no place to put documentation on the enum directly if you need to. - Jonathan M Davis
Please review the previous discussion of why Flag (was YesOrNo) was proposed. http://www.digitalmars.com/d/archives/digitalmars/D/YesOrNo_useful_idiom_he lper_or_wanking_134392.html
In many cases, I very much think that the documentation should be separate. A prime example would be std.datetime.AllowDayOverflow. It's use in several places in std.datetime, and having one place to read up on it is definitely beneficial. Not having a place where the enum is defined separately would definitely be worse in that case. The area where it's more debatable is when there's only _one_ function which uses the enum. Then Andrei's proposed solution is more reasonable. But worse comes to worst, you can _still_ put the documentation with the function in the current solution. Andrei's solution adds _nothing_ to that. It just makes it so that there isn't actually a separate enum somewhere which can be documented. It removes the possibility of documenting it. I'd rather have the one line mixin which you can either document directly or skip documenting and put its documentation with the function that uses it rather than one where you _can't_ document it separately. std.datetime will _not_ switch to this even if it gets checked in simply because it will make the documentation worse. And I'm not sure that we want to have some enums using this solution and some not, since that would be inconsistent. I'm not entirely against Andrei's solution (it does reduce boilerplate code), but I think that a string mixin solution makes more sense. It's less verbose, and you can choose where to put its documentation. - Jonathan M Davis
Jun 10 2011
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 2:30 PM, Jonathan M Davis wrote:
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes.
There is general agreement (which includes myself) that a language feature is nicer than Flag, and that Flag is nicer than the current state of affairs. This is no surprise because a specialized language feature will _always_ be better than one built from tools offered within the language. It's like God vs. human. So the crucial question is whether a language change is warranted. We should be much more restrained than this discussion suggests. Any and all programming languages have limitations. This, coupled with the former point, leads to the fact that at some point you MUST look into doing within the language something that could be done nicer if you got to play God. Doing the latter does not scale. So, does Flag work around a limitation in the language? Sure. Would a language-changing solution work better? Absolutely. Is the necessity of changing the language a foregone conclusion? I don't think so. Andrei
Jun 10 2011
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:istulq$2rjc$1 digitalmars.com...
 On 6/10/11 2:30 PM, Jonathan M Davis wrote:
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes.
There is general agreement (which includes myself) that a language feature is nicer than Flag,
Much
 and that Flag is nicer than the current state of affairs.
Only *barely*.
 This is no surprise because a specialized language feature will _always_ 
 be better than one built from tools offered within the language. It's like 
 God vs. human.

 So the crucial question is whether a language change is warranted. We 
 should be much more restrained than this discussion suggests. Any and all 
 programming languages have limitations. This, coupled with the former 
 point, leads to the fact that at some point you MUST look into doing 
 within the language something that could be done nicer if you got to play 
 God. Doing the latter does not scale.

 So, does Flag work around a limitation in the language? Sure. Would a 
 language-changing solution work better? Absolutely. Is the necessity of 
 changing the language a foregone conclusion? I don't think so.
In general, I would agree with this. I completely understand the desire, and even the need, to avoid extra language features when reasonable to do so. I really do. But the idea of using Flag over named parameters just stretches it to a rediculous extreme. This seriously reminds me of Sun's infamous whitepaper that desperately tried to rationalize Java's lack of delegates/anon-funcs ("But you can use functors!!!" Fuck functors.) Is adding the feature of named parameters worthwhile in light of Flag? *YES*, *ABSOLUTELY*, *CLEARLY*, *DEFINITELY*, *YES*, *YES*, *YES*.
Jun 10 2011
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 We should be much more restrained than this discussion suggests. Any and 
 all programming languages have limitations. This, coupled with the 
 former point, leads to the fact that at some point you MUST look into 
 doing within the language something that could be done nicer if you got 
 to play God. Doing the latter does not scale.
This use of word "scale" assumes there is a larger and larger group of basic features that we'll desire in the language. But I have experience both of "normal" languages and of languages with macros as Scheme, and I don't think this is true. In the next few years we will not want to add a large and growing number of basic features to D2/D3. And currently in D there are features much less generally useful than named arguments or tuple unpacking syntax sugar, as Delimited Strings, Lazy Variadic Functions and more.
 So, does Flag work around a limitation in the language? Sure. Would a 
 language-changing solution work better? Absolutely. Is the necessity of 
 changing the language a foregone conclusion? I don't think so.
Named arguments offer a more general solution than Flags, useful for all kinds of arguments, with a more readable syntax. I don't think you need a sub-feature to _require_ the argument name at the call point (on the other hand you may desire a sub-feature Scala has, to support deprecation of argument names. This helps solve a problem Don too has with named arguments). Bye, bearophile
Jun 10 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 10 Jun 2011 16:21:59 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 6/10/11 2:30 PM, Jonathan M Davis wrote:
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes.
There is general agreement (which includes myself) that a language feature is nicer than Flag,
Yes.
 and that Flag is nicer than the current state of affairs.
No. Flag!"KeepTerminator".yes is much worse than KeepTerminator.yes. And Flag!"KeepTerminator" keepTerminator is just, horrendous, in documentation *or* source. If the rote creation of boolean enums is a problem, why not a mixin? template Flag(string name) { mixin("enum " ~ name ~ " : bool { no = false, yes = true }"); } mixin Flag!"KeepTerminator";
 This is no surprise because a specialized language feature will _always_  
 be better than one built from tools offered within the language. It's  
 like God vs. human.
I think the debate is more about how this solution is a step in the wrong direction more than it's not as good as a real solution.
 So the crucial question is whether a language change is warranted.
If the options are Flag or a language solution, the answer is yes. I'd much rather keep things as they are than have Flag!string. -Steve
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 5:14 PM, Steven Schveighoffer wrote:
 On Fri, 10 Jun 2011 16:21:59 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 There is general agreement (which includes myself) that a language
 feature is nicer than Flag,
Yes.
 and that Flag is nicer than the current state of affairs.
No. Flag!"KeepTerminator".yes is much worse than KeepTerminator.yes. And Flag!"KeepTerminator" keepTerminator is just, horrendous, in documentation *or* source.
https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e744ab8e7
 If the rote creation of boolean enums is a problem, why not a mixin?

 template Flag(string name)
 {
 mixin("enum " ~ name ~ " : bool { no = false, yes = true }");
 }

 mixin Flag!"KeepTerminator";
Because you still need to define it separately from use.
 This is no surprise because a specialized language feature will
 _always_ be better than one built from tools offered within the
 language. It's like God vs. human.
I think the debate is more about how this solution is a step in the wrong direction more than it's not as good as a real solution.
 So the crucial question is whether a language change is warranted.
If the options are Flag or a language solution, the answer is yes. I'd much rather keep things as they are than have Flag!string.
Keeping things as they are fosters awkward duplication or coupling. Andrei
Jun 10 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-10 15:54, Andrei Alexandrescu wrote:
 On 6/10/11 5:14 PM, Steven Schveighoffer wrote:
 On Fri, 10 Jun 2011 16:21:59 -0400, Andrei Alexandrescu
 
 <SeeWebsiteForEmail erdani.org> wrote:
 There is general agreement (which includes myself) that a language
 feature is nicer than Flag,
Yes.
 and that Flag is nicer than the current state of affairs.
No. Flag!"KeepTerminator".yes is much worse than KeepTerminator.yes. And Flag!"KeepTerminator" keepTerminator is just, horrendous, in documentation *or* source.
https://github.com/andralex/phobos/commit/84c75336a4ef04b4c3b1924d7ac9329e7 44ab8e7
 If the rote creation of boolean enums is a problem, why not a mixin?
 
 template Flag(string name)
 {
 mixin("enum " ~ name ~ " : bool { no = false, yes = true }");
 }
 
 mixin Flag!"KeepTerminator";
Because you still need to define it separately from use.
What I want to know is what you want to do with such enums where it's actually _desirable_ that they be defined separately from use. A prime example of this is std.datetime's AllowDayOverflow. It's used by several functions, and by having it explicitly defined separately, it can be appropriately documented in one place rather than having to explain it for every function that uses it. I really think that it _should_ be defined separately. But if it is defined separately, then I don't see how it could work with the Flag template. Even if we go with the improved yes and no templates that you just added (which are definitely an improvement over naked Flag), they don't work with a yes/no enum which is defined separately. This means that you'll have AllowDayOverflow.yes and AllowDayOverflow.no instead of yes!"AllowDayOverflow" and no!"AllowDayOverflow". That's not necessarily a bad thing, since the enum _is_ defined differently, but if the common idiom is to use yes!"enumName" and no!"enumName", then the yes/no enums which are actually defined separately won't match. Is that acceptable, or is there actually a reasonable way to make the yes and no templates work with non-Flag enums (perhaps by having it first check whether enumName.yes compiles before trying Flag!"enumName")? - Jonathan M Davis
Jun 10 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 7:09 PM, Jonathan M Davis wrote:
 What I want to know is what you want to do with such enums where it's actually
 _desirable_ that they be defined separately from use.
I guess if you want such you either define the flag separately or make it an alias and document the alias. I mean there's nothing new here just because Flag came about. Andrei
Jun 10 2011
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.781.1307734245.14074.digitalmars-d puremagic.com...
 On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94

 Discuss!
I do have to admit that as much as I hate the idea of named parameters, this particular proposal certainly seems to be an argument in favor of adding them, which would tend to argue against making these changes. After thinking about it, I'd argue that it would be better to create a string mixin which created the enums for you instead of using the template as part of the arguments. e.g. mixin(YesNoEnum!"KeepTerminator")); Then all of the rest of the code is the same. You'd still use KeepTerminator.yes and KeepTerminator.no, but we avoided having to create duplicate enums by hand every time that we want this kind of variable. So, you still reduce the boilerplate code, but the usage is much less ugly.
I'd support this *as long as* it's existence didn't get used as rationalization for avoiding the inclusion of named arguments.
Jun 10 2011
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Lutger Blijdestijn:

 Somebody one this newsgroup - maybe it was Don Clugston, also made a good 
 point against named parameters: it introduces inflexibility because now the 
 names of the parameters of a function become part of the public api. 
 Changing a name will now break client code.
Scala faces this problem: http://www.digitalmars.com/d/archives/digitalmars/D/Deprecated_argument_names_131514.html Bye, bearophile
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 5:53 PM, bearophile wrote:
 Lutger Blijdestijn:

 Somebody one this newsgroup - maybe it was Don Clugston, also made a good
 point against named parameters: it introduces inflexibility because now the
 names of the parameters of a function become part of the public api.
 Changing a name will now break client code.
Scala faces this problem: http://www.digitalmars.com/d/archives/digitalmars/D/Deprecated_argument_names_131514.html Bye, bearophile
That's good evidence that introducing named parameters would be quite involved. Andrei
Jun 10 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 That's good evidence that introducing named parameters would be quite involved.
It's also good evidence that Martin Odersky, one of the most intelligent language designers alive today, is willing to do a lot to support named arguments in his language :-) Probably implementing tuple unpacking syntax sugar too needs some not small changes, but they are well worth it (of those two features I think tuple unpacking syntax sugar is more important than named arguments). Anyway, in Scala this sub-feature isn't a custom language feature, it uses a general feature, annotations, that's used for several other purposes too. Bye, bearophile
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 6:26 PM, bearophile wrote:
 Andrei:

 That's good evidence that introducing named parameters would be
 quite involved.
It's also good evidence that Martin Odersky, one of the most intelligent language designers alive today, is willing to do a lot to support named arguments in his language :-)
I have all respect for Odersky's competence, but that is beside the point. Design decisions are always taken in a context, and it's not impossible he would've had decided otherwise in a different context. D is a rich, powerful language _now_. It has classic features present in many languages, and a few features that are not present in many. Their full combination is not present in any other language, and creates a unique context. We've been historically trigger happy about discussing adding features in this group. This is not unique to D - all languages underwent the same process. But at this point it is a necessity that we start migrating our mindset from an endless wishlist - towards finding ingenious solutions within the language. Again, this is the case for every single language there is. Combining existing features towards new ends is in some ways more difficult than language design because you play within a confined ground, and I am a bit disappointed that a few posters have shown only contempt for such an effort.
 Probably implementing tuple unpacking syntax sugar too needs some not
 small changes, but they are well worth it (of those two features I
 think tuple unpacking syntax sugar is more important than named
 arguments).
What's wrong with myTuple.expand? Andrei
Jun 10 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 Design decisions are always taken in a context,
Right. But wasn't your comment about Scala named arguments complexity too out of context?
 But at this point it is a necessity that we start 
 migrating our mindset from an endless wishlist - towards finding 
 ingenious solutions within the language.
There are few basic features that are missing that are better as built-ins, even now. Tuple unpacking syntax sugar, named arguments, computed gotos, and few other smaller things. Do you want to freeze D language to D2 and not take a look at ideas for D3?
 and I am a bit disappointed that a few 
 posters have shown only contempt for such an effort.
You need to take a better look at the kind of people that are in this forum. People here are walking away from C++, Java (and even Python), looking for a feature-rich language that avoids some of the syntax kludges their former languages force them to use in their programs. So it's not so strange that people in this forum have on average a significantly lower tolerance to tricks like your Flag proposal. In a C++ forum your Flag idea probably is much more welcome, because compared to D programmers probably C++ programmers accept a higher level of noise and ugliness in their code :-)
 What's wrong with myTuple.expand?
It does nothing of what I need? Haven't we had this discussion already? I am having a huge deja-vu :-) I have discussed this topic several times already. Didn't you agree about the need of unpacking syntax sugar for tuples? I am confused now.................................. Bye, bearophile
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 7:04 PM, bearophile wrote:
 Andrei:

 Design decisions are always taken in a context,
Right. But wasn't your comment about Scala named arguments complexity too out of context?
What I did was to say that Don's and others' point, corroborated with the fact that Scala found it necessary to add that feature to the language, suggests that we need to worry about that.
 But at this point it is a necessity that we start migrating our
 mindset from an endless wishlist - towards finding ingenious
 solutions within the language.
There are few basic features that are missing that are better as built-ins, even now. Tuple unpacking syntax sugar, named arguments, computed gotos, and few other smaller things. Do you want to freeze D language to D2 and not take a look at ideas for D3?
Falling for either extreme would be a mistake.
 and I am a bit disappointed that a few posters have shown only
 contempt for such an effort.
You need to take a better look at the kind of people that are in this forum. People here are walking away from C++, Java (and even Python), looking for a feature-rich language that avoids some of the syntax kludges their former languages force them to use in their programs.
I'd love to see more evidence to this claim.
 So it's not so strange that people in this forum have on average a
 significantly lower tolerance to tricks like your Flag proposal. In a
 C++ forum your Flag idea probably is much more welcome, because
 compared to D programmers probably C++ programmers accept a higher
 level of noise and ugliness in their code :-)
I don't think that's the reason. You should have seen the C++ forums up until about 1997. They were brimming with enthusiastic proposals for language changes. Interesting work became possible after it became clear to everyone that the language is now given, so it's time to use what's there. D, too, is receiving an increasing amount of real work from the community since TDPL's publication.
 What's wrong with myTuple.expand?
It does nothing of what I need? Haven't we had this discussion already? I am having a huge deja-vu :-) I have discussed this topic several times already. Didn't you agree about the need of unpacking syntax sugar for tuples? I am confused now..................................
I must be the one confused, but at best we shouldn't spread ourselves too thin. Andrei
Jun 10 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 I'd love to see more evidence to this claim.
Right :-)
 Interesting work became possible after it became clear 
 to everyone that the language is now given, so it's time to use what's 
 there.
If you want to build stable large frameworks and libraries then having a "stable" (backwards compatible) language helps. But in this thread we are only several years. Python is just out of a design hiatus meant to help other Python implementations catch up, and now new design ideas are discussed again. In D syntax sugar for tuple unpacking is useful for library programmers too. Bye, bearophile
Jun 10 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 8:31 PM, bearophile wrote:
 Andrei:

 I'd love to see more evidence to this claim.
Right :-)
 Interesting work became possible after it became clear to everyone
 that the language is now given, so it's time to use what's there.
If you want to build stable large frameworks and libraries then having a "stable" (backwards compatible) language helps. But in this thread we are only talking about additive changes.
Don't kid yourself. Every additive change creates more precedent and more reason to refuse thinking creatively within the language. It also means the language and its fostered idioms are a moving target.



 things), and the same has happened to Python too, since several
 years. Python is just out of a design hiatus meant to help other
 Python implementations catch up, and now new design ideas are
 discussed again. In D syntax sugar for tuple unpacking is useful for
 library programmers too.
I think these languages are at a different point in their evolution than D. We still don't have a strong answer to "what are the largest apps written in D" and this is because many people with an interest in the language are paralyzed in analysis. I know the phenomenon: after you spend a lot discussing designs, it is downright frightening to commit to one. Andrei
Jun 10 2011
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-10 16:46, Andrei Alexandrescu wrote:
 On 6/10/11 6:26 PM, bearophile wrote:
 Andrei:
 That's good evidence that introducing named parameters would be
 quite involved.
It's also good evidence that Martin Odersky, one of the most intelligent language designers alive today, is willing to do a lot to support named arguments in his language :-)
I have all respect for Odersky's competence, but that is beside the point. Design decisions are always taken in a context, and it's not impossible he would've had decided otherwise in a different context. D is a rich, powerful language _now_. It has classic features present in many languages, and a few features that are not present in many. Their full combination is not present in any other language, and creates a unique context. We've been historically trigger happy about discussing adding features in this group. This is not unique to D - all languages underwent the same process. But at this point it is a necessity that we start migrating our mindset from an endless wishlist - towards finding ingenious solutions within the language. Again, this is the case for every single language there is. Combining existing features towards new ends is in some ways more difficult than language design because you play within a confined ground, and I am a bit disappointed that a few posters have shown only contempt for such an effort.
The Herb Sutter interview that you recently posted a link to has an interesting point of view on that. One of the reasons that lambdas were added to C++0x was because Boost had shown how close you could get there using the language as it was and that it just wasn't good enough. Lambdas were added to the language precisely because they couldn't be done reasonably without additional language supported. On the other hand, other stuff that they added which Boost had tried to do - such as shared_ptr - were added as library solutions, because they worked as library solutions. As you've said, we've reached the point that D is powerful enough and complicated enough that we should be first trying to see how well we can solve problems using the language itself rather than adding new features to it. As we do that, we should be able to see what is reasonably feasible within the language as it is and what just doesn't work. As we find things that just don't work but which we really want to be able to do, we can look at adding features to the language to deal with them, but we should definitely be looking at using the language as it is first. In this particular case, while named arguments might arguably be nice, they're "nice to have," not a necessity. The question is how close we can get to having reasonable yes/no enums like we've been trying to do but without excessive boilerplate code. We may decide to add named arguments later, but D is really at the point that its current features need to be completely ironed out before we look at adding additional features that we don't really need. I think that there _are_ features that we need to look at adding in some form or other (such as conditional attributes) in order to solve current problems in the language (such as the inability to use many attributes - such as pure and safe - with templates without excessive duplication of code). But if a feature does not solve a pressing problem and/or can be reasonably solved by improving Phobos, then we should be improving Phobos. - Jonathan M Davis
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 7:09 PM, Jonathan M Davis wrote:
 I think that there _are_ features that we need to look at adding in some form
 or other (such as conditional attributes) in order to solve current problems
 in the language (such as the inability to use many attributes - such as pure
 and  safe - with templates without excessive duplication of code). But if a
 feature does not solve a pressing problem and/or can be reasonably solved by
 improving Phobos, then we should be improving Phobos.
Good point. Walter and I agree that there are two categories of language change: adding new features, and removing undue limitations. At this point, we're planning on a lot more of the latter than the former kind. As an example, consider: module my_module; void fun() { import std.random; return uniform(0, 100); } int gun() { import std.stdio; writeln(fun()); } This module won't compile in today's D, but not for a matter of principles; it's just a random limitation of the language. (It does work if you import from within a class or struct.) You can insert most declarations in a scope, so the ones you can't insert are just awkward exceptions, unless there's a good reason to actively disable them. Any code should work if you just wrap another scope around it. Walter and I call the above a "turtle feature", in allusion to the "turtles all the way down" meme. Walter wants to fix this, and similar limitations that act "unturtly". Imports inside a scope won't be visible outside that scope, and importing the same module from several different functions will come at no cost in compilation time. This may as well lead to a different approach to defining good D modules, in which many imports don't come at the top unless they are of very general use. Functions that have special needs can always embed their own imports modularly without the symbols spilling out in everyone else's sight. As a perk - remember Adam Ruppe's trick to build the examples on the site? Some have top-level code so they don't compile as they are. With this change, code should work if the website simply adds a unittest { ... } around the code. Andrei
Jun 10 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Wait, Walter wants to fix this? IIRC just a few days ago he made a
post on how this would be a bad feature because it hides imports in
arbitrary places. I guess he changed his mind..
Jun 10 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/10/2011 6:15 PM, Andrej Mitrovic wrote:
 Wait, Walter wants to fix this? IIRC just a few days ago he made a
 post on how this would be a bad feature because it hides imports in
 arbitrary places.
I did?
Jun 10 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 I did?
I don't remember you talking about this topic. But I don't want this feature, overall I think it will not improve the code. An amoeba is often free to move in every direction in 2D or more, while an insect has a rigid exoskeleton that constricts it to move only in few ways. But such limits allow the insect to run fast :-) Bye, bearophile
Jun 10 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/11/11, bearophile <bearophileHUGS lycos.com> wrote:
 But I don't want this
 feature, overall I think it will not improve the code.
I've found someone that contradicts you: http://www.digitalmars.com/d/archives/digitalmars/D/Function-local_imports_109317.html
Jun 10 2011
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 8:51 PM, Andrej Mitrovic wrote:
 On 6/11/11, bearophile<bearophileHUGS lycos.com>  wrote:
 But I don't want this
 feature, overall I think it will not improve the code.
I've found someone that contradicts you: http://www.digitalmars.com/d/archives/digitalmars/D/Function-local_imports_109317.html
Wow. Andrei
Jun 10 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

 I've found someone that contradicts you:
 http://www.digitalmars.com/d/archives/digitalmars/D/Function-local_imports_109317.html
Thank you. That person didn't have enough experience yet, it seems. More experienced Python programmers use local imports only in very uncommon situations, you see it from the lot of Python code in the standard library. So I despite its little advantage of local reasoning improvements I think it's far from the top of the list of the important things to desire, I think that currently design improvement efforts are better spent toward more generally useful features instead :-) Bye, bearophile
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 4:38 AM, bearophile wrote:
 Andrej Mitrovic:

 I've found someone that contradicts you:
 http://www.digitalmars.com/d/archives/digitalmars/D/Function-local_imports_109317.html
Thank you. That person didn't have enough experience yet, it seems. More experienced Python programmers use local imports only in very uncommon situations, you see it from the lot of Python code in the standard library. So I despite its little advantage of local reasoning improvements I think it's far from the top of the list of the important things to desire, I think that currently design improvement efforts are better spent toward more generally useful features instead :-) Bye, bearophile
I'm not very familiar with Python's module system. Is it very similar to D's? Thanks, Andrei
Jun 11 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 I'm not very familiar with Python's module system. Is it very similar to 
 D's?
If you take a look at the Python module system, you copy the first half of it, its more evident characteristics, ignoring its care for details and corner cases, and you remove its dynamic characteristics, you produce a kind of D module system :-) Python doesn't have the anti-hijacking feature, and it's more dynamic. Its package system is more refined than the primitive D package system (and it seems it's not easy to design right, because even the last versions of Python have modified a the its semantics of packages). In Python when you do "import foo" you import only the name "foo". This is probably one of the first things I've asked in D, and I am for it still, but most D programmers have not appreciated this idea, so I have stopped asking for it since lot of time. (S)ML language has a WAY more complex module system, but despite its advantages, I think D/Python module system is good enough and it's easy to learn to use. In the end on the surface if you know the Python module system it's easy to learn to use the D one, and the opposite too is true. I think the D package system needs to be improved, using more brain. This is another example of why D design development can't be stopped yet. Bye, bearophile
Jun 11 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/11/11, Walter Bright <newshound2 digitalmars.com> wrote:
 On 6/10/2011 6:15 PM, Andrej Mitrovic wrote:
 Wait, Walter wants to fix this? IIRC just a few days ago he made a
 post on how this would be a bad feature because it hides imports in
 arbitrary places.
I did?
Hmm. It might have been a bug in the matrix, and I misplaced you for someone else. :]
Jun 10 2011
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 This module won't compile in today's D, but not for a matter of 
 principles; it's just a random limitation of the language. (It does work 
 if you import from within a class or struct.) You can insert most 
 declarations in a scope, so the ones you can't insert are just awkward 
 exceptions, unless there's a good reason to actively disable them. Any 
 code should work if you just wrap another scope around it.
 
 Walter and I call the above a "turtle feature", in allusion to the 
 "turtles all the way down" meme. Walter wants to fix this, and similar 
 limitations that act "unturtly". Imports inside a scope won't be visible 
 outside that scope, and importing the same module from several different 
 functions will come at no cost in compilation time.
You are allowed to import modules inside functions in Python too (there is a just a minor restriction), but I have never asked for this feature in D because this feature has a cost too. Putting all imports at the top of the module is more tidy, it allows the person that reads the code to find all the used imports very quickly. If they are spread in the module they become less easy to find, you need to use your editor/IDE to search for them. Bye, bearophile
Jun 10 2011
next sibling parent reply David Nadlinger <see klickverbot.at> writes:
On 6/11/11 3:21 AM, bearophile wrote:
 Andrei:

 This module won't compile in today's D, but not for a matter of
 principles; it's just a random limitation of the language. (It does work
 if you import from within a class or struct.) You can insert most
 declarations in a scope, so the ones you can't insert are just awkward
 exceptions, unless there's a good reason to actively disable them. Any
 code should work if you just wrap another scope around it.

 Walter and I call the above a "turtle feature", in allusion to the
 "turtles all the way down" meme. Walter wants to fix this, and similar
 limitations that act "unturtly". Imports inside a scope won't be visible
 outside that scope, and importing the same module from several different
 functions will come at no cost in compilation time.
You are allowed to import modules inside functions in Python too (there is a just a minor restriction), but I have never asked for this feature in D because this feature has a cost too. Putting all imports at the top of the module is more tidy, it allows the person that reads the code to find all the used imports very quickly. If they are spread in the module they become less easy to find, you need to use your editor/IDE to search for them. Bye, bearophile
At least allowing imports in unittests would be nice though – I frequently find myself writing »version (unittest) {}« blocks before the actual unit tests just to import some modules not needed during regular builds (yeah, I suppose I'm somewhat pedantic about that). David
Jun 10 2011
parent jdrewsen <jdrewsen nospam.com> writes:
Den 11-06-2011 03:26, David Nadlinger skrev:
 On 6/11/11 3:21 AM, bearophile wrote:
 Andrei:

 This module won't compile in today's D, but not for a matter of
 principles; it's just a random limitation of the language. (It does work
 if you import from within a class or struct.) You can insert most
 declarations in a scope, so the ones you can't insert are just awkward
 exceptions, unless there's a good reason to actively disable them. Any
 code should work if you just wrap another scope around it.

 Walter and I call the above a "turtle feature", in allusion to the
 "turtles all the way down" meme. Walter wants to fix this, and similar
 limitations that act "unturtly". Imports inside a scope won't be visible
 outside that scope, and importing the same module from several different
 functions will come at no cost in compilation time.
You are allowed to import modules inside functions in Python too (there is a just a minor restriction), but I have never asked for this feature in D because this feature has a cost too. Putting all imports at the top of the module is more tidy, it allows the person that reads the code to find all the used imports very quickly. If they are spread in the module they become less easy to find, you need to use your editor/IDE to search for them. Bye, bearophile
At least allowing imports in unittests would be nice though – I frequently find myself writing »version (unittest) {}« blocks before the actual unit tests just to import some modules not needed during regular builds (yeah, I suppose I'm somewhat pedantic about that).
+1
Jun 11 2011
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/10/2011 6:21 PM, bearophile wrote:
 You are allowed to import modules inside functions in Python too (there is a
 just a minor restriction), but I have never asked for this feature in D
 because this feature has a cost too. Putting all imports at the top of the
 module is more tidy, it allows the person that reads the code to find all the
 used imports very quickly. If they are spread in the module they become less
 easy to find, you need to use your editor/IDE to search for them.
What, there's a Python feature you don't like? :-) I suspect that way of thinking may go the way of the old C style of putting all your declarations at the top.
Jun 10 2011
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 8:21 PM, bearophile wrote:
 Andrei:

 This module won't compile in today's D, but not for a matter of
 principles; it's just a random limitation of the language. (It does work
 if you import from within a class or struct.) You can insert most
 declarations in a scope, so the ones you can't insert are just awkward
 exceptions, unless there's a good reason to actively disable them. Any
 code should work if you just wrap another scope around it.

 Walter and I call the above a "turtle feature", in allusion to the
 "turtles all the way down" meme. Walter wants to fix this, and similar
 limitations that act "unturtly". Imports inside a scope won't be visible
 outside that scope, and importing the same module from several different
 functions will come at no cost in compilation time.
You are allowed to import modules inside functions in Python too (there is a just a minor restriction), but I have never asked for this feature in D because this feature has a cost too. Putting all imports at the top of the module is more tidy, it allows the person that reads the code to find all the used imports very quickly. If they are spread in the module they become less easy to find, you need to use your editor/IDE to search for them. Bye, bearophile
Maybe you also care less about what you import. Similar arguments have been made for placing all variable declarations at the top of the function etc. It's unclear at this point how far local imports would go, but I see good advantages. Andrei
Jun 10 2011
prev sibling parent reply Lutger Blijdestijn <lutger.blijdestijn gmail.com> writes:
bearophile wrote:

 Andrei:
 
 This module won't compile in today's D, but not for a matter of
 principles; it's just a random limitation of the language. (It does work
 if you import from within a class or struct.) You can insert most
 declarations in a scope, so the ones you can't insert are just awkward
 exceptions, unless there's a good reason to actively disable them. Any
 code should work if you just wrap another scope around it.
 
 Walter and I call the above a "turtle feature", in allusion to the
 "turtles all the way down" meme. Walter wants to fix this, and similar
 limitations that act "unturtly". Imports inside a scope won't be visible
 outside that scope, and importing the same module from several different
 functions will come at no cost in compilation time.
You are allowed to import modules inside functions in Python too (there is a just a minor restriction), but I have never asked for this feature in D because this feature has a cost too. Putting all imports at the top of the module is more tidy, it allows the person that reads the code to find all the used imports very quickly. If they are spread in the module they become less easy to find, you need to use your editor/IDE to search for them. Bye, bearophile
Why would you have to find local imports? It's considered good practice to narrow scope of variables and put declarations as close as possible to point of use, yet you don't hunt for local variable declarations all the time. If an import is local, it is simply (supposedly) only of concern to that scope and relevant when doing work concerning whatever is in that scope. In effect this could as well lead to reducing to need to look for imports! Python is a bit different because there's an awful lot more going on when importing, with increased chances of bugs when not careful. Simply importing something more than once can introduce errors. Hopefully, that is less so with D. The only really tricky thing are module constructors (circular imports). But at this level, it's probably easier to use facilities of dmd to tell you what imports what.
Jun 11 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Lutger Blijdestijn:

It's considered good practice to narrow scope of variables and put declarations
as close as possible to point of use, yet you don't hunt for local variable
declarations all the time.<
I agree this turtle idea has some good sides too. But I want to stress that it's not among the first five things I think D has to change/improve. More important are tuple unpacking syntax sugar, named arguments, conditional attributes, better vector operations, etc. Bye, bearophile
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 7:20 AM, bearophile wrote:
 Lutger Blijdestijn:

 It's considered good practice to narrow scope of variables and put
 declarations as close as possible to point of use, yet you don't
 hunt for local variable declarations all the time.<
I agree this turtle idea has some good sides too. But I want to stress that it's not among the first five things I think D has to change/improve. More important are tuple unpacking syntax sugar, named arguments, conditional attributes, better vector operations, etc.
Again, there are two broad categories of changes: feature additions and removal of undue limitations. We favor doing the latter. Andrei
Jun 11 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Andrei:

 Again, there are two broad categories of changes: feature additions and 
 removal of undue limitations. We favor doing the latter.
I understand, but that's not always the best decision in this early stage of D life. There are also few little feature changes I have put in Bugzilla since lot of time. The more time passes, the less easy they are to apply. Bye, bearophile
Jun 11 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
Andrei Alexandrescu wrote:
 module my_module;

 void fun()
 {
      import std.random;
      return uniform(0, 100);
 }

 int gun()
 {
      import std.stdio;
      writeln(fun());
 }

 This module won't compile in today's D, but not for a matter of
 principles; it's just a random limitation of the language. (It does work
 if you import from within a class or struct.) You can insert most
 declarations in a scope, so the ones you can't insert are just awkward
 exceptions, unless there's a good reason to actively disable them. Any
 code should work if you just wrap another scope around it.
//void main(){ immutable a = b; immutable b = 1; int foo(int n){ if(n==1) return 1; return 1+bar(n); } int bar(int n){ if(n&1) return foo(3*n+1); return foo(n/2); } //} Will this be fixed too? Timon
Jun 13 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 Will this be fixed too?
Mutually recursive inner functions are not so common, and there is a workaround, making one of them a delegate defined before. But what about this? auto foo()() out(result) { } body { return 0; } void main() { foo(); } test.d(1): Error: function test.foo!().foo post conditions are not supported if the return type is inferred test.d(7): Error: template instance test.foo!() error instantiating test.d(7): Error: forward reference to inferred return type of function call foo This is a common problem for my code, is it possible to fix (support) this? (In functional-style code auto return values are sometimes almost necessary). Bye, bearophile
Jun 13 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:isualt$hf2$1 digitalmars.com...
 Combining existing features towards new ends is in some ways more 
 difficult than language design because you play within a confined ground, 
 and I am a bit disappointed that a few posters have shown only contempt 
 for such an effort.
That analysis of the situation hinges on the steadfast notion that Flag is a great thing. I absolutely appreciate doing things in library instead of language when reasonable to do so. You don't see me asking for map/reduce or ranges to be built into the language, do you? What a lot of people *don't* like is this seemingly frequent pattern: 1. Andrei comes up with something he feels is a great idea (And you do have a lot of genuinely great ideas, don't get me wrong. Probably more than most of us, certainly including me.) 2. The idea is posted to the NG ostensibly for discussion. 3. Andrei shoots down every objection as being wrong, failing to understand the idea's greatness, or some meta-argument trump card like "X is the N-word of the programming world" is pulled out. 4. The proposed idea can't possibly have any significant flaws, so everyone else on the board is obviously in contempt of something more fundamental, in this case, the strategy of preferring library solutions over language additions. Just because some of us feel this one particular thing doesn't work well in library, does *not* imply we think new features are generally preferable as language additions. So please stop leaping to that conclusion.
Jun 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 12:36 AM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:isualt$hf2$1 digitalmars.com...
 Combining existing features towards new ends is in some ways more
 difficult than language design because you play within a confined ground,
 and I am a bit disappointed that a few posters have shown only contempt
 for such an effort.
That analysis of the situation hinges on the steadfast notion that Flag is a great thing.
Actually my point there was that we should be coy at this point about changing the language. Flag doesn't have much to do with it. It is clear to me that a language change would obviate Flag and would have additional advantages. The point is it would also have disadvantages.
 I absolutely appreciate doing things in library instead of language
 when reasonable to do so. You don't see me asking for map/reduce or
 ranges to be built into the language, do you? What a lot of people
 *don't* like is this seemingly frequent pattern:

 1. Andrei comes up with something he feels is a great idea (And you
 do have a lot of genuinely great ideas, don't get me wrong. Probably
 more than most of us, certainly including me.)

 2. The idea is posted to the NG ostensibly for discussion.

 3. Andrei shoots down every objection as being wrong, failing to
 understand the idea's greatness, or some meta-argument trump card
 like "X is the N-word of the programming world" is pulled out.

 4. The proposed idea can't possibly have any significant flaws, so
 everyone else on the board is obviously in contempt of something more
 fundamental, in this case, the strategy of preferring library
 solutions over language additions.
I thought what I was doing was to rationally discuss the proposal. Clearly I am in favor of it since I'm proposing it. But that doesn't mean I need to resort to eliciting emotional response, demeaning the counter-arguments, or discussing the competence or ulterior motives of the opponents.
 Just because some of us feel this one particular thing doesn't work well in
 library, does *not* imply we think new features are generally preferable as
 language additions. So please stop leaping to that conclusion.
Consider two statements: 1. "I dislike Flag. It looks ugly to me." 2. "I dislike Flag. Instead I want named arguments." There is little retort to (1) - it simply counts as a vote against. For (2) the course of action is to point out the liabilities of changing the language. Andrei
Jun 11 2011
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-11 07:54:58 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Consider two statements:
 
 1. "I dislike Flag. It looks ugly to me."
 
 2. "I dislike Flag. Instead I want named arguments."
 
 There is little retort to (1) - it simply counts as a vote against. For 
 (2) the course of action is to point out the liabilities of changing 
 the language.
I'm actually not sure whether I want named arguments or not, but I'm quite sure I don't want to use Flag!"" in my code. I'd actually prefer a simple bool parameter to Flag!"". Currently, it looks like we have these possibilities: // definition // call with a constant void func(bool abc); -> func(true); enum Abc { no, yes } void func(Abc abc); -> func(Abc.yes); void func(Flag!"Abc" abc); -> func(Flag!"Abc".yes); -> func(yes!"Abc"); -> func(Yes.Abc); which then becomes this if you're using a boolean expression instead of a constant: // definition // call with an expression void func(bool abc); -> func(expression); enum Abc { no, yes } void func(Abc abc); -> func(expression ? Abc.yes : Abc.no); -> func(cast(Abc)expression); void func(Flag!"Abc" abc); -> func(expression ? Flag!"Abc".yes : Flag!"Abc".no); -> func(expression ? yes!"Abc" : no!"Abc"); -> func(expression ? Yes.Abc : No.Abc); -> func(cast(Flag!"Abc")expression); My take on this is that we shouldn't try to reinvent the boolean in the standard library. If you want to replace a bool with a two-option enum at some places for clarity, that's fine. But I wouldn't elevate that to a pattern meant to be used everywhere. And personally, I don't like the proliferation of yes/no enums: if you use an enum, value names should be more meaningful than a simple yes/no. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 8:16 AM, Michel Fortin wrote:
 On 2011-06-11 07:54:58 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 Consider two statements:

 1. "I dislike Flag. It looks ugly to me."

 2. "I dislike Flag. Instead I want named arguments."

 There is little retort to (1) - it simply counts as a vote against.
 For (2) the course of action is to point out the liabilities of
 changing the language.
I'm actually not sure whether I want named arguments or not, but I'm quite sure I don't want to use Flag!"" in my code. I'd actually prefer a simple bool parameter to Flag!"". Currently, it looks like we have these possibilities: // definition // call with a constant void func(bool abc); -> func(true);
The call entails simple data coupling as documented by Steve McConnell: you can pass any unstructured Boolean for any meaning of abc.
 enum Abc { no, yes }
 void func(Abc abc); -> func(Abc.yes);
To add the documentation effort: /** This is an argument for func. Refer to func below. */ enum Abc { no, /// you don't want func to do Abc yes /// you do want func to do Abc } /** This is func. Mind Abc defined above. */ void func(Abc abc); I think we agree this is rather awkward (I know because I wrote a fair amount of such). So we have the advantage of a nice call syntax and the disadvantage of verbose definition and documentation.
 void func(Flag!"Abc" abc); -> func(Flag!"Abc".yes);
 -> func(yes!"Abc");
 -> func(Yes.Abc);

 which then becomes this if you're using a boolean expression instead of
 a constant:
Aha! This reasoning is flawed as I'll explain below.
 // definition // call with an expression

 void func(bool abc); -> func(expression);

 enum Abc { no, yes }
 void func(Abc abc); -> func(expression ? Abc.yes : Abc.no);
 -> func(cast(Abc)expression);

 void func(Flag!"Abc" abc); -> func(expression ? Flag!"Abc".yes :
 Flag!"Abc".no);
 -> func(expression ? yes!"Abc" : no!"Abc");
 -> func(expression ? Yes.Abc : No.Abc);
 -> func(cast(Flag!"Abc")expression);

 My take on this is that we shouldn't try to reinvent the boolean in the
 standard library.
I think this characterization is wrong. Let me replace the meaningless Abc with an actual example, e.g. OpenRight in std.algorithm. OpenRight is not a Boolean. Its *representation* is Boolean. It is categorical data with two categories. You can represent it with an unstructured Boolean the same way you can represent an automaton state with an unstructured integer or temperature with an unstructured double, but then you'd have the disadvantages that dimensional analysis libraries are solving. For representing categorical data with small sets, programming languages use enumerated types. This is because in a small set you can actually give name each element. That way you have a separate type for the categorical data so you can enjoy good type checking. The mistake I believe you are making is the conflation of a categorical data with two categories with an unstructured Boolean. By making that conflation you lose the advantages of good typechecking in one fell swoop. (But not all categorical data is a small set, and consequently enumerated types are insufficient. Consider e.g. the notion of a user id. People routinely use integers for that, and suffer endless consequences because of bugs caused by unstructured integers posing as user IDs. I have seen instances of such bugs in several codebases in different languages.) As a direct consequence, it is *wrong* to desire to pass an unstructured Boolean expression in lieu of OpenRight. So it is *good* that you can't. What you *should* be doing is to define an OpenRight value in the first place and use it, or construct it in place with "expr ? OpenRight.yes : OpenRight.no", with the advantage that the conversion intent is explicit and visible.
 If you want to replace a bool with a two-option enum
 at some places for clarity, that's fine. But I wouldn't elevate that to
 a pattern meant to be used everywhere. And personally, I don't like the
 proliferation of yes/no enums: if you use an enum, value names should be
 more meaningful than a simple yes/no.
I think you'd be entirely wrong to make this distinction. There's zero, one, and many. Not zero, one, two, and many. Andrei
Jun 11 2011
next sibling parent David Nadlinger <see klickverbot.at> writes:
On 6/11/11 3:56 PM, Andrei Alexandrescu wrote:
 To add the documentation effort:

 /**
 This is an argument for func. Refer to func below.
 */
 enum Abc {
 no, /// you don't want func to do Abc
 yes /// you do want func to do Abc
 }

 /**
 This is func. Mind Abc defined above.
 */
 void func(Abc abc);

 I think we agree this is rather awkward (I know because I wrote a fair
 amount of such).

 So we have the advantage of a nice call syntax and the disadvantage of
 verbose definition and documentation.
So what? Library code is typically written once, and used often. Also, what's wrong with the followig (maybe there is really an issue with it, didn't run it through DDoc): --- /** * This is func. * * Params: * abc = Abc.yes to destroy the world, Abc.no to leave it intact. */ void func(Abc abc) {} /// Ditto. enum Abc : bool { no, yes } --- David
Jun 11 2011
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-11 09:56:28 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 6/11/11 8:16 AM, Michel Fortin wrote:
 On 2011-06-11 07:54:58 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:
 
 Consider two statements:
 
 1. "I dislike Flag. It looks ugly to me."
 
 2. "I dislike Flag. Instead I want named arguments."
 
 There is little retort to (1) - it simply counts as a vote against.
 For (2) the course of action is to point out the liabilities of
 changing the language.
I'm actually not sure whether I want named arguments or not, but I'm quite sure I don't want to use Flag!"" in my code. I'd actually prefer a simple bool parameter to Flag!"". Currently, it looks like we have these possibilities: // definition // call with a constant void func(bool abc); -> func(true);
The call entails simple data coupling as documented by Steve McConnell: you can pass any unstructured Boolean for any meaning of abc.
Which is often useful if the value is conditional to a boolean expression. The only lacking thing is the parameter name which would make things clear to the reader. Structured data is useful only if you pass it around; if you use it only once as a function parameter and nowhere else, then it just gets in the way. If your argument was that structured data is always preferred to unstructured data, I disagree.
 enum Abc { no, yes }
 void func(Abc abc); -> func(Abc.yes);
To add the documentation effort: /** This is an argument for func. Refer to func below. */ enum Abc { no, /// you don't want func to do Abc yes /// you do want func to do Abc } /** This is func. Mind Abc defined above. */ void func(Abc abc); I think we agree this is rather awkward (I know because I wrote a fair amount of such). So we have the advantage of a nice call syntax and the disadvantage of verbose definition and documentation.
Yes, and I think most of the time this should be a bool. Or to be precise: if it's not worth documenting separately, especially if it's used just once as a flag to a specific function, and if you don't expect it to extend to more than yes/no, then it should be a bool.
 void func(Flag!"Abc" abc); -> func(Flag!"Abc".yes);
 -> func(yes!"Abc");
 -> func(Yes.Abc);
 
 which then becomes this if you're using a boolean expression instead of
 a constant:
Aha! This reasoning is flawed as I'll explain below.
 // definition // call with an expression
 
 void func(bool abc); -> func(expression);
 
 enum Abc { no, yes }
 void func(Abc abc); -> func(expression ? Abc.yes : Abc.no);
 -> func(cast(Abc)expression);
 
 void func(Flag!"Abc" abc); -> func(expression ? Flag!"Abc".yes :
 Flag!"Abc".no);
 -> func(expression ? yes!"Abc" : no!"Abc");
 -> func(expression ? Yes.Abc : No.Abc);
 -> func(cast(Flag!"Abc")expression);
 
 My take on this is that we shouldn't try to reinvent the boolean in the
 standard library.
I think this characterization is wrong. Let me replace the meaningless Abc with an actual example, e.g. OpenRight in std.algorithm. OpenRight is not a Boolean. Its *representation* is Boolean. It is categorical data with two categories. You can represent it with an unstructured Boolean the same way you can represent an automaton state with an unstructured integer or temperature with an unstructured double, but then you'd have the disadvantages that dimensional analysis libraries are solving. For representing categorical data with small sets, programming languages use enumerated types. This is because in a small set you can actually give name each element. That way you have a separate type for the categorical data so you can enjoy good type checking. The mistake I believe you are making is the conflation of a categorical data with two categories with an unstructured Boolean. By making that conflation you lose the advantages of good typechecking in one fell swoop.
I think you're misinterpreting. I don't like yes/no enums because I don't find the value names meaningful, but I'm perfectly fine with two-element enums if they are properly named.
 (But not all categorical data is a small set, and consequently 
 enumerated types are insufficient. Consider e.g. the notion of a user 
 id. People routinely use integers for that, and suffer endless 
 consequences because of bugs caused by unstructured integers posing as 
 user IDs. I have seen instances of such bugs in several codebases in 
 different languages.)
I totally agree with making specific types to avoid mixing unrelated things, as long as it's reasonable. You wouldn't argue for a UserId type if values of this type weren't passed around.
 As a direct consequence, it is *wrong* to desire to pass an 
 unstructured Boolean expression in lieu of OpenRight. So it is *good* 
 that you can't. What you *should* be doing is to define an OpenRight 
 value in the first place and use it, or construct it in place with 
 "expr ? OpenRight.yes : OpenRight.no", with the advantage that the 
 conversion intent is explicit and visible.
But boundaries can be open or closed on the right, but also on the left. Unfortunately, because you choose to call the enum OpenRight, it can only be used on the right, and nowhere else. What you're doing with OpenRight, and more generally with Flag!"", is narrowing excessively the category to the point where it can be used at one place and one place only: as a specific parameter to a specific function. If you had another parameter for the left side, you'd create an OpenLeft enum with exactly the same choices. I doubt this kind of categorization has any advantage. Actually, I think the advantage you seek has nothing to do with categorization and much more to do with a desire to see those parameter names appear at the call site. You're actually using over-categorization to achieve that, and with Flag!"" you're going to make this systematic. Sorry, I can't approve.
 If you want to replace a bool with a two-option enum
 at some places for clarity, that's fine. But I wouldn't elevate that to
 a pattern meant to be used everywhere. And personally, I don't like the
 proliferation of yes/no enums: if you use an enum, value names should be
 more meaningful than a simple yes/no.
I think you'd be entirely wrong to make this distinction. There's zero, one, and many. Not zero, one, two, and many.
No idea what you mean there. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 10:40 AM, Michel Fortin wrote:
 On 2011-06-11 09:56:28 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:
 For representing categorical data with small sets, programming
 languages use enumerated types. This is because in a small set you can
 actually give name each element. That way you have a separate type for
 the categorical data so you can enjoy good type checking. The mistake
 I believe you are making is the conflation of a categorical data with
 two categories with an unstructured Boolean. By making that conflation
 you lose the advantages of good typechecking in one fell swoop.
I think you're misinterpreting. I don't like yes/no enums because I don't find the value names meaningful, but I'm perfectly fine with two-element enums if they are properly named.
What is meaningless about OpenRight.yes?
 (But not all categorical data is a small set, and consequently
 enumerated types are insufficient. Consider e.g. the notion of a user
 id. People routinely use integers for that, and suffer endless
 consequences because of bugs caused by unstructured integers posing as
 user IDs. I have seen instances of such bugs in several codebases in
 different languages.)
I totally agree with making specific types to avoid mixing unrelated things, as long as it's reasonable. You wouldn't argue for a UserId type if values of this type weren't passed around.
The problem is the definition of "reasonable" is loose. For all I can tell we agree, it's just we have different notions of what's reasonable.
 But boundaries can be open or closed on the right, but also on the left.
 Unfortunately, because you choose to call the enum OpenRight, it can
 only be used on the right, and nowhere else.
But this is intentional. If I wanted something more general, I would have used something more general! What are you saying here?
 What you're doing with OpenRight, and more generally with Flag!"", is
 narrowing excessively the category to the point where it can be used at
 one place and one place only: as a specific parameter to a specific
 function. If you had another parameter for the left side, you'd create
 an OpenLeft enum with exactly the same choices. I doubt this kind of
 categorization has any advantage.
In fact, no. The same Flag instantiation can be used with distinct functions. Its advantage is that you don't need to go out of your way and define it. It's a sort of a lambda, a literal for a categorical value.
 Actually, I think the advantage you seek has nothing to do with
 categorization and much more to do with a desire to see those parameter
 names appear at the call site. You're actually using over-categorization
 to achieve that, and with Flag!"" you're going to make this systematic.
 Sorry, I can't approve.
I think it's best to discuss the pros and cons of the proposal than the proposer's desires. Yes, clarifying the intent at the call site is a good thing. And yes, systematization can be good. Named parameters would be one way to go about it, and categorization would be another. If you characterize the approach as *over* categorization, I'm interested in your justification of that qualification.
 If you want to replace a bool with a two-option enum
 at some places for clarity, that's fine. But I wouldn't elevate that to
 a pattern meant to be used everywhere. And personally, I don't like the
 proliferation of yes/no enums: if you use an enum, value names should be
 more meaningful than a simple yes/no.
I think you'd be entirely wrong to make this distinction. There's zero, one, and many. Not zero, one, two, and many.
No idea what you mean there.
Sets with zero and one elements have distinctive properties compared to sets of more than one element. Sets with two elements don't. Andrei
Jun 11 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-11 12:01:33 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 6/11/11 10:40 AM, Michel Fortin wrote:
 On 2011-06-11 09:56:28 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:
 For representing categorical data with small sets, programming
 languages use enumerated types. This is because in a small set you can
 actually give name each element. That way you have a separate type for
 the categorical data so you can enjoy good type checking. The mistake
 I believe you are making is the conflation of a categorical data with
 two categories with an unstructured Boolean. By making that conflation
 you lose the advantages of good typechecking in one fell swoop.
I think you're misinterpreting. I don't like yes/no enums because I don't find the value names meaningful, but I'm perfectly fine with two-element enums if they are properly named.
What is meaningless about OpenRight.yes?
Choosing between "yes" and "no" is not meaningful. I'd rather choose between "open" and "closed". Of course you'd have to pick a more fitting name for the enum, preferably one that could work for all bounds, not just the right one to make the category more useful. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 11:56 AM, Michel Fortin wrote:
 On 2011-06-11 12:01:33 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 On 6/11/11 10:40 AM, Michel Fortin wrote:
 On 2011-06-11 09:56:28 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:
 For representing categorical data with small sets, programming
 languages use enumerated types. This is because in a small set you can
 actually give name each element. That way you have a separate type for
 the categorical data so you can enjoy good type checking. The mistake
 I believe you are making is the conflation of a categorical data with
 two categories with an unstructured Boolean. By making that conflation
 you lose the advantages of good typechecking in one fell swoop.
I think you're misinterpreting. I don't like yes/no enums because I don't find the value names meaningful, but I'm perfectly fine with two-element enums if they are properly named.
What is meaningless about OpenRight.yes?
Choosing between "yes" and "no" is not meaningful. I'd rather choose between "open" and "closed".
I don't see how "OpenRight.yes" is meaningless and "Openness.right" is meaningful.
 Of course you'd have to pick a more fitting
 name for the enum,
Name one.
 preferably one that could work for all bounds, not
 just the right one to make the category more useful.
Again, the charter of that particular category is only "open to the right". Anyway, that was the first thing "grep yes std/*" found. Let's see the next one: /** Specifies whether the output of certain algorithm is desired in sorted format. */ enum SortOutput { no, /// Don't sort output yes, /// Sort output } This already is very unpleasant because "certain" is as imprecise as it gets. Plus one for Flag, I hope you agree. Alright, so we have void topNIndex( alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range, RangeIndex)(Range r, RangeIndex index, SortOutput sorted = SortOutput.no); With Flag in tow, you'd delete SortOutput and you'd replace the definition with: void topNIndex( alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range, RangeIndex)(Range r, RangeIndex index, Flag!"sortOutput" sorted = No.sortOutput); Call: auto a = [ 1, 2, 3 ]; topNIndex(a, Yes.sortOutput); I understand you find the above meaningless and would advocate using a bool, which means: topNIndex(a, true); which would have even me running to the manual, and I wrote the darn thing. With named parameters, we'd have something along the lines of: topNIndex(a, sortOutput : true); which is nice, but not present in the language (and I can tell after talking to Walter it won't be anytime soon). With your choice of meaningful/less, you'd have something like: enum HowToOutput { unsorted, sorted } topNIndex(a, HowToOutput.sorted); which is pretty much the same thing as yes/no, just more convoluted and less systematic. I mean you can't impose to yourself to choose any names except "yes" and "no" on account of them being meaningless. Andrei
Jun 11 2011
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-11 13:08:48 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 With named parameters, we'd have something along the lines of:
 
 topNIndex(a, sortOutput : true);
 
 which is nice, but not present in the language (and I can tell after 
 talking to Walter it won't be anytime soon).
The funny thing is that named arguments are not that difficult to implement as long as you don't allow reordering. Much easier than const(Object)ref actually. <https://github.com/michelf/dmd/commit/673bae4982ff18a3d216bc1578f50d40f4d26d7a> Took me less time than what I took arguing about Flag!"". -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 1:59 PM, Michel Fortin wrote:
 On 2011-06-11 13:08:48 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 With named parameters, we'd have something along the lines of:

 topNIndex(a, sortOutput : true);

 which is nice, but not present in the language (and I can tell after
 talking to Walter it won't be anytime soon).
The funny thing is that named arguments are not that difficult to implement as long as you don't allow reordering. Much easier than const(Object)ref actually. <https://github.com/michelf/dmd/commit/673bae4982ff18a3d216bc1578f50d40f4d26d7a> Took me less time than what I took arguing about Flag!"".
Love the attitude!! Let's see what Don and Walter think. Andrei
Jun 11 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/11/2011 12:58 PM, Andrei Alexandrescu wrote:
 On 6/11/11 1:59 PM, Michel Fortin wrote:
 On 2011-06-11 13:08:48 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 With named parameters, we'd have something along the lines of:

 topNIndex(a, sortOutput : true);

 which is nice, but not present in the language (and I can tell after
 talking to Walter it won't be anytime soon).
The funny thing is that named arguments are not that difficult to implement as long as you don't allow reordering. Much easier than const(Object)ref actually. <https://github.com/michelf/dmd/commit/673bae4982ff18a3d216bc1578f50d40f4d26d7a> Took me less time than what I took arguing about Flag!"".
Love the attitude!! Let's see what Don and Walter think.
I think it's clever and insightful how Michel's solution is implemented. It does not allow, however, for named arguments to be not in the same positions as unnamed ones. In other words, unlike struct field initializations, named arguments cannot appear in any order. I think people will find it an odd difference.
Jun 11 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/11/2011 10:05 PM, Walter Bright wrote:
 On 6/11/2011 12:58 PM, Andrei Alexandrescu wrote:
 On 6/11/11 1:59 PM, Michel Fortin wrote:
 On 2011-06-11 13:08:48 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 With named parameters, we'd have something along the lines of:

 topNIndex(a, sortOutput : true);

 which is nice, but not present in the language (and I can tell after
 talking to Walter it won't be anytime soon).
The funny thing is that named arguments are not that difficult to implement as long as you don't allow reordering. Much easier than const(Object)ref actually. <https://github.com/michelf/dmd/commit/673bae4982ff18a3d216bc1578f50d40f4d26d7a> Took me less time than what I took arguing about Flag!"".
Love the attitude!! Let's see what Don and Walter think.
I think it's clever and insightful how Michel's solution is implemented. It does not allow, however, for named arguments to be not in the same positions as unnamed ones. In other words, unlike struct field initializations, named arguments cannot appear in any order. I think people will find it an odd difference.
If we all get convinced that named parameters are worth it, I'm convinced Michel would be sufficiently motivated to address this limitation. I personally am lukewarm regarding the feature but I think many people would find it quite convenient. Andrei
Jun 11 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:it07ni$1pvj$1 digitalmars.com...
 Anyway, that was the first thing "grep yes std/*" found. Let's see the 
 next one:

 /**
 Specifies whether the output of certain algorithm is desired in sorted
 format.
  */
 enum SortOutput {
     no,  /// Don't sort output
     yes, /// Sort output
 }

 This already is very unpleasant because "certain" is as imprecise as it 
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear. Also, since you're in favor of Flag, I think you'd agree with me that the doc comments on the "no" and "yes" values are unnecessary and can be ditched. Which makes the whole idiom this: enum SortOutput { no, yes } I hadn't noticed this before, but now that I'm actually looking directly at that, I don't see how that can be considered "boilerplate", or at least enough boilerplate to be worth having a utility template, adding Flag!"..." to function signatures in the code and documentation, and the inconsistency in changing the user's syntax away from how people expect to use an enum. And not only that, but all for the sake of a scenario that you've already argued is only rarely encountered. It's a clever use of templates, sure, but it's a little too clever for it's own good.
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/11/2011 03:52 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it07ni$1pvj$1 digitalmars.com...
 Anyway, that was the first thing "grep yes std/*" found. Let's see the
 next one:

 /**
 Specifies whether the output of certain algorithm is desired in sorted
 format.
   */
 enum SortOutput {
      no,  /// Don't sort output
      yes, /// Sort output
 }

 This already is very unpleasant because "certain" is as imprecise as it
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear.
Not at all. The typo in the original text must have confused you: it should be "certain algorithms" because SortOutput is used in four distinct algorithms (one of which has two overloads). Grep std/algorithm.d. Flag += 2
 Also, since you're in favor of Flag, I think you'd agree with me that the
 doc comments on the "no" and "yes" values are unnecessary and can be
 ditched. Which makes the whole idiom this:

 enum SortOutput { no, yes }
This exact kind of argument has been made in 1995 in favor of STL algorithms that require defining a struct outside the current context. The cost of adding one extra symbol turned out to be a fair amount more unpleasant than it was initially though. Assessing that the boilerplate in this case is one line would be missing that important aspect. Andrei
Jun 11 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-11 20:27, Andrei Alexandrescu wrote:
 On 06/11/2011 03:52 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it07ni$1pvj$1 digitalmars.com...
 
 Anyway, that was the first thing "grep yes std/*" found. Let's see the
 next one:
 
 /**
 Specifies whether the output of certain algorithm is desired in sorted
 format.
 
   */
 
 enum SortOutput {
 
      no,  /// Don't sort output
      yes, /// Sort output
 
 }
 
 This already is very unpleasant because "certain" is as imprecise as it
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear.
Not at all. The typo in the original text must have confused you: it should be "certain algorithms" because SortOutput is used in four distinct algorithms (one of which has two overloads). Grep std/algorithm.d. Flag += 2
 Also, since you're in favor of Flag, I think you'd agree with me that the
 doc comments on the "no" and "yes" values are unnecessary and can be
 ditched. Which makes the whole idiom this:
 
 enum SortOutput { no, yes }
This exact kind of argument has been made in 1995 in favor of STL algorithms that require defining a struct outside the current context. The cost of adding one extra symbol turned out to be a fair amount more unpleasant than it was initially though. Assessing that the boilerplate in this case is one line would be missing that important aspect.
Yes, though there is a distinct difference between having to create a functor elswhere to just to call an STL function and creating an extra enum next to your function definition for one of its parameters. The parameter issue is far smaller IMHO. It only comes up when defining functions, and particularly if we created a mixin for creating such an enum, the overhead would be fairly minimal - certainly far less than creating a functor for every call to an STL algorithm function (which pratically destroys the usefulness of the STL's algorithms for most people). So, I don't think that the cost involved is altogether comparable. However, you do bring up a very valid point. Flag definitely lowers the bar for the usage of such enums. Ultimately, my main concern with using Flag like this is the error messages. Given the templates involved, I'd expect them to be pretty bad. D's template error messages are certainly better than C++'s (primarily thanks to template constraints), but they're still pretty bad - especially for newbies - and this particular use case effectively is simplifying the library developer's life slightly at the cost of nastier error messages for everyone who mistypes one of these enums. So, we save pain in one area and move it over to another which arguably has a higher impact. And I'm just not sure whether that's worth it or not. The fact that you've gotten to Yes.EnumName and eliminated all of the obvious template stuff from the user's perspective makes the code much cleaner, and it's fine as long as they don't have any typos, but the difference between EnumName.yes and Yes.EnumName for the user is pretty much nonexistant except for the fact that Yes.EnumName will have worse error messages. So, from the user's perspective, the situation is worse. I don't know. I think that this proposal has reached the point where it might be reasonable to include it, but I just don't know if the gain in development is worth the pain for everyone who uses the functions which have Flag enums. If the error messages weren't worse, then it wouldn't be a problem, but as soon as you include templates, the error messages are pretty much always significantly worse. If there were a significant gain from this proposal, then I'd say that it would be worth it, but the gain seems pretty minor to me. So, I just don't know. - Jonathan M Davis
Jun 11 2011
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/11/2011 10:45 PM, Jonathan M Davis wrote:
 Yes, though there is a distinct difference between having to create a functor
 elswhere to just to call an STL function and creating an extra enum next to
 your function definition for one of its parameters. The parameter issue is far
 smaller IMHO.
Absolutely. The proposed solution is also much smaller than e.g. lambda libraries and ultimately the language feature. Andrei
Jun 11 2011
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.841.1307850316.14074.digitalmars-d puremagic.com...
 but the
 difference between EnumName.yes and Yes.EnumName for the user is pretty 
 much
 nonexistant except for the fact that Yes.EnumName will have worse error
 messages.
It also creates an awkward inconsistency. Most enums are X.Y, but then callint certain functions it's Y.X
Jun 12 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:it1c0f$1uup$1 digitalmars.com...
 On 06/11/2011 03:52 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it07ni$1pvj$1 digitalmars.com...
 Anyway, that was the first thing "grep yes std/*" found. Let's see the
 next one:

 /**
 Specifies whether the output of certain algorithm is desired in sorted
 format.
   */
 enum SortOutput {
      no,  /// Don't sort output
      yes, /// Sort output
 }

 This already is very unpleasant because "certain" is as imprecise as it
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear.
Not at all. The typo in the original text must have confused you: it should be "certain algorithms" because SortOutput is used in four distinct algorithms (one of which has two overloads). Grep std/algorithm.d. Flag += 2
Not that I consider quibbling over small English wording differences a major thing, but I fail to see how: "Specifies whether the output of an algorithm is desired in sorted format." is significantly different from: "Specifies whether the output of certain algorithms are desired in sorted format." In either case, I don't see anything problematically imprecise.
Jun 12 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/12/11 1:45 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it1c0f$1uup$1 digitalmars.com...
 On 06/11/2011 03:52 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>   wrote in message
 news:it07ni$1pvj$1 digitalmars.com...
 Anyway, that was the first thing "grep yes std/*" found. Let's see the
 next one:

 /**
 Specifies whether the output of certain algorithm is desired in sorted
 format.
    */
 enum SortOutput {
       no,  /// Don't sort output
       yes, /// Sort output
 }

 This already is very unpleasant because "certain" is as imprecise as it
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear.
Not at all. The typo in the original text must have confused you: it should be "certain algorithms" because SortOutput is used in four distinct algorithms (one of which has two overloads). Grep std/algorithm.d. Flag += 2
Not that I consider quibbling over small English wording differences a major thing, but I fail to see how: "Specifies whether the output of an algorithm is desired in sorted format." is significantly different from: "Specifies whether the output of certain algorithms are desired in sorted format." In either case, I don't see anything problematically imprecise.
Still means I need to jump back and forth in the documentation. Andrei
Jun 12 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:it32j8$2gfq$1 digitalmars.com...
 On 6/12/11 1:45 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it1c0f$1uup$1 digitalmars.com...
 On 06/11/2011 03:52 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>   wrote in message
 news:it07ni$1pvj$1 digitalmars.com...
 Anyway, that was the first thing "grep yes std/*" found. Let's see the
 next one:

 /**
 Specifies whether the output of certain algorithm is desired in sorted
 format.
    */
 enum SortOutput {
       no,  /// Don't sort output
       yes, /// Sort output
 }

 This already is very unpleasant because "certain" is as imprecise as 
 it
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear.
Not at all. The typo in the original text must have confused you: it should be "certain algorithms" because SortOutput is used in four distinct algorithms (one of which has two overloads). Grep std/algorithm.d. Flag += 2
Not that I consider quibbling over small English wording differences a major thing, but I fail to see how: "Specifies whether the output of an algorithm is desired in sorted format." is significantly different from: "Specifies whether the output of certain algorithms are desired in sorted format." In either case, I don't see anything problematically imprecise.
Still means I need to jump back and forth in the documentation.
And you don't like the "///ditto" suggestion for handling that?
Jun 12 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/12/11 2:19 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it32j8$2gfq$1 digitalmars.com...
 On 6/12/11 1:45 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>   wrote in message
 news:it1c0f$1uup$1 digitalmars.com...
 On 06/11/2011 03:52 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>    wrote in message
 news:it07ni$1pvj$1 digitalmars.com...
 Anyway, that was the first thing "grep yes std/*" found. Let's see the
 next one:

 /**
 Specifies whether the output of certain algorithm is desired in sorted
 format.
     */
 enum SortOutput {
        no,  /// Don't sort output
        yes, /// Sort output
 }

 This already is very unpleasant because "certain" is as imprecise as
 it
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear.
Not at all. The typo in the original text must have confused you: it should be "certain algorithms" because SortOutput is used in four distinct algorithms (one of which has two overloads). Grep std/algorithm.d. Flag += 2
Not that I consider quibbling over small English wording differences a major thing, but I fail to see how: "Specifies whether the output of an algorithm is desired in sorted format." is significantly different from: "Specifies whether the output of certain algorithms are desired in sorted format." In either case, I don't see anything problematically imprecise.
Still means I need to jump back and forth in the documentation.
And you don't like the "///ditto" suggestion for handling that?
That actually does help, but not for enums used by more than one function. The other issues remain too. Andrei
Jun 12 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:it3ne2$1g2f$1 digitalmars.com...
 On 6/12/11 2:19 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it32j8$2gfq$1 digitalmars.com...
 On 6/12/11 1:45 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>   wrote in message
 news:it1c0f$1uup$1 digitalmars.com...
 On 06/11/2011 03:52 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>    wrote in 
 message
 news:it07ni$1pvj$1 digitalmars.com...
 Anyway, that was the first thing "grep yes std/*" found. Let's see 
 the
 next one:

 /**
 Specifies whether the output of certain algorithm is desired in 
 sorted
 format.
     */
 enum SortOutput {
        no,  /// Don't sort output
        yes, /// Sort output
 }

 This already is very unpleasant because "certain" is as imprecise as
 it
 gets. Plus one for Flag, I hope you agree.
Flag -= 1 s/output of certain algorithm/output of an algorithm/ += 1 That one-word doc change makes it all perfectly clear.
Not at all. The typo in the original text must have confused you: it should be "certain algorithms" because SortOutput is used in four distinct algorithms (one of which has two overloads). Grep std/algorithm.d. Flag += 2
Not that I consider quibbling over small English wording differences a major thing, but I fail to see how: "Specifies whether the output of an algorithm is desired in sorted format." is significantly different from: "Specifies whether the output of certain algorithms are desired in sorted format." In either case, I don't see anything problematically imprecise.
Still means I need to jump back and forth in the documentation.
And you don't like the "///ditto" suggestion for handling that?
That actually does help, but not for enums used by more than one function. The other issues remain too.
I would think that an enum used by more than one function *should* be listed separately.
Jun 13 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/13/11 4:02 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it3ne2$1g2f$1 digitalmars.com...
 That actually does help, but not for enums used by more than one function.
 The other issues remain too.
I would think that an enum used by more than one function *should* be listed separately.
Actually, not necessarily, if the definition is self explanatory. By the same argument a named argument with the same name and meaning in several functions doesn't necessarily have to be defined separately. Andrei
Jun 13 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
 On 6/13/11 4:02 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it3ne2$1g2f$1 digitalmars.com...
 That actually does help, but not for enums used by more than one function.
 The other issues remain too.
I would think that an enum used by more than one function *should* be listed separately.
Actually, not necessarily, if the definition is self explanatory. By the same argument a named argument with the same name and meaning in several functions doesn't necessarily have to be defined separately. Andrei
What about just not documenting the enum itself? This elegantly resolves the 'certain' vs. 'an' debate too :o). Timon
Jun 13 2011
prev sibling parent reply so <so so.so> writes:
 My take on this is that we shouldn't try to reinvent the boolean in the
 standard library.
I think this characterization is wrong. Let me replace the meaningless Abc with an actual example, e.g. OpenRight in std.algorithm. OpenRight is not a Boolean. Its *representation* is Boolean. It is categorical data with two categories. You can represent it with an unstructured Boolean the same way you can represent an automaton state with an unstructured integer or temperature with an unstructured double, but then you'd have the disadvantages that dimensional analysis libraries are solving.
Quite contrary i think it is pretty much spot on, if it is not but just its representation is boolean so is every other usage of boolean. The only reason we use an enum instead of simple bool is self documentation "fun(OpenRight.yes)". You simply can't deny the named arguments solve not only this particular issue but the entire area nicely "fun(openRight:true, width:4, height:3, depth:5)".
Jun 12 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
so:

 Quite contrary i think it is pretty much spot on, if it is not but just  
 its representation is boolean so is every other usage of boolean.
This is an unusual teacher that use functional languages, the blog post is about booleans and related matters: http://existentialtype.wordpress.com/2011/03/15/boolean-blindness/ (Often I don't agree with this author, but I try to read some of his posts.) Bye, bearophile
Jun 12 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/12/11 7:26 AM, so wrote:
 My take on this is that we shouldn't try to reinvent the boolean in the
 standard library.
I think this characterization is wrong. Let me replace the meaningless Abc with an actual example, e.g. OpenRight in std.algorithm. OpenRight is not a Boolean. Its *representation* is Boolean. It is categorical data with two categories. You can represent it with an unstructured Boolean the same way you can represent an automaton state with an unstructured integer or temperature with an unstructured double, but then you'd have the disadvantages that dimensional analysis libraries are solving.
Quite contrary i think it is pretty much spot on, if it is not but just its representation is boolean so is every other usage of boolean. The only reason we use an enum instead of simple bool is self documentation "fun(OpenRight.yes)". You simply can't deny the named arguments solve not only this particular issue but the entire area nicely "fun(openRight:true, width:4, height:3, depth:5)".
Never did. Andrei
Jun 12 2011
prev sibling next sibling parent reply David Nadlinger <see klickverbot.at> writes:
On 6/11/11 1:54 PM, Andrei Alexandrescu wrote:
 Consider two statements:

 1. "I dislike Flag. It looks ugly to me."

 2. "I dislike Flag. Instead I want named arguments."

 There is little retort to (1) - it simply counts as a vote against. For
 (2) the course of action is to point out the liabilities of changing the
 language.
*And*, at least for me, still count it as an (informal) vote against Flag. You wrote about »The point is it [named arguments] would also have disadvantages«, but at the same time, you seem to ignore that using a non-obvious construct all over the standard library adds to perceived the »language complexity« (from the user's perspective) just as well, even more so if opDispatch or other »hacks« are used to beautify the implementation. Yes, I do think named parameters would be a step forward and we should definitely look into adding them to D. But independently, I don't think that reinventing bool in Phobos is a good idea. How would you explain somebody new to D that, while usually it's »Something.property«, you have to write »Yes.foo« instead of »Foo.yes«? Also, there is the issue of error messages: --- void foo(Flag!"bar" flag) {} void main() { foo(No.baz); } --- leads to --- Error: function foo (Flag flag) is not callable using argument types (Flag) Error: cannot implicitly convert expression (opDispatch()) of type Flag to Flag --- I don't know about you, but I think this is not quite an acceptable error message for mistyping a single character while trying to pass a boolean parameter to some standard library function. David
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 9:08 AM, David Nadlinger wrote:
 On 6/11/11 1:54 PM, Andrei Alexandrescu wrote:
 Consider two statements:

 1. "I dislike Flag. It looks ugly to me."

 2. "I dislike Flag. Instead I want named arguments."

 There is little retort to (1) - it simply counts as a vote against. For
 (2) the course of action is to point out the liabilities of changing the
 language.
*And*, at least for me, still count it as an (informal) vote against Flag.
Of course it does, but the point is there are arguments that might convince the person.
 You wrote about »The point is it [named arguments] would also have
 disadvantages«, but at the same time, you seem to ignore that using a
 non-obvious construct all over the standard library adds to perceived
 the »language complexity« (from the user's perspective) just as well,
 even more so if opDispatch or other »hacks« are used to beautify the
 implementation.
I agree that implementation complexity has a cost. That would be justified if the idiom becomes commonly used outside the library.
 Yes, I do think named parameters would be a step forward and we should
 definitely look into adding them to D. But independently, I don't think
 that reinventing bool in Phobos is a good idea.
You may want to refer to my answer to Michel. Andrei
Jun 11 2011
parent Ben Grabham <Evil.Nebster gmail.com> writes:
On 11/06/11 15:28, Andrei Alexandrescu wrote:
 On 6/11/11 9:08 AM, David Nadlinger wrote:
 On 6/11/11 1:54 PM, Andrei Alexandrescu wrote:
 Consider two statements:

 1. "I dislike Flag. It looks ugly to me."

 2. "I dislike Flag. Instead I want named arguments."

 There is little retort to (1) - it simply counts as a vote against. For
 (2) the course of action is to point out the liabilities of changing the
 language.
*And*, at least for me, still count it as an (informal) vote against Flag.
Of course it does, but the point is there are arguments that might convince the person.
 You wrote about »The point is it [named arguments] would also have
 disadvantages«, but at the same time, you seem to ignore that using a
 non-obvious construct all over the standard library adds to perceived
 the »language complexity« (from the user's perspective) just as well,
 even more so if opDispatch or other »hacks« are used to beautify the
 implementation.
I agree that implementation complexity has a cost. That would be justified if the idiom becomes commonly used outside the library.
 Yes, I do think named parameters would be a step forward and we should
 definitely look into adding them to D. But independently, I don't think
 that reinventing bool in Phobos is a good idea.
You may want to refer to my answer to Michel. Andrei
Hey, Don't know whether I can vote but I looked through it and I prefer using booleans over this. This just doesn't look very nice to me and if you *really* wanted to use this in a program, you could just use an enum but I don't see why flags is good (even after reading through all your counter-arguments). Nebster
Jun 11 2011
prev sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 11/06/2011 12:54, Andrei Alexandrescu wrote:
 Consider two statements:

 1. "I dislike Flag. It looks ugly to me."
This statement holds true for me.
 2. "I dislike Flag. Instead I want named arguments."
This one is perhaps true. I've never needed named arguments.
 There is little retort to (1) - it simply counts as a vote against. For
 (2) the course of action is to point out the liabilities of changing the
 language.

 Andrei
So I had an idea. ---- struct Flag { static bool opDispatch(string n)() { static if (n[0..2] == "no") { return false; } else { return true; } } } void myFunc(bool foo, bool bar) { } void main() { myFunc(Flag.foo, Flag.noBar); } ---- * No ugly templates * Self documenting * No overhead (dmd can inline it to myFunc(true, false)) * Caller decides if they want it -- Robert http://octarineparrot.com/
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 2:12 PM, Robert Clipsham wrote:
 On 11/06/2011 12:54, Andrei Alexandrescu wrote:
 Consider two statements:

 1. "I dislike Flag. It looks ugly to me."
This statement holds true for me.
 2. "I dislike Flag. Instead I want named arguments."
This one is perhaps true. I've never needed named arguments.
 There is little retort to (1) - it simply counts as a vote against. For
 (2) the course of action is to point out the liabilities of changing the
 language.

 Andrei
So I had an idea. ---- struct Flag { static bool opDispatch(string n)() { static if (n[0..2] == "no") { return false; } else { return true; } } } void myFunc(bool foo, bool bar) { } void main() { myFunc(Flag.foo, Flag.noBar); } ---- * No ugly templates * Self documenting * No overhead (dmd can inline it to myFunc(true, false)) * Caller decides if they want it
// Generate document in nook format generatePdf("doc.pdf", Flag.nook); Andrei
Jun 11 2011
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 11/06/2011 20:59, Andrei Alexandrescu wrote:
 On 6/11/11 2:12 PM, Robert Clipsham wrote:
 ....
 * No ugly templates
 * Self documenting
 * No overhead (dmd can inline it to myFunc(true, false))
 * Caller decides if they want it
// Generate document in nook format generatePdf("doc.pdf", Flag.nook); Andrei
I'd call this a documentation issue. It's obvious you're passing true to the function. Of course, if you want to mitigate this somewhat, something like this could work: struct FuncFlag(alias func) { // See code from above, but use typeof(&func).stringof to get // a list of parameter names and make sure the passed name is valid // of course, you can't check position, but the only way to get // around that is named parameters or some sort of compiler support } alias FuncFlag!generatePdf PdfFlag; // This now fails to compile generatePdf("doc.pdf", PdfFlag.nook); -- Robert http://octarineparrot.com/
Jun 11 2011
parent Robert Clipsham <robert octarineparrot.com> writes:
On 11/06/2011 21:31, Robert Clipsham wrote:
 On 11/06/2011 20:59, Andrei Alexandrescu wrote:
 On 6/11/11 2:12 PM, Robert Clipsham wrote:
 ....
 * No ugly templates
 * Self documenting
 * No overhead (dmd can inline it to myFunc(true, false))
 * Caller decides if they want it
// Generate document in nook format generatePdf("doc.pdf", Flag.nook); Andrei
I'd call this a documentation issue. It's obvious you're passing true to the function. Of course, if you want to mitigate this somewhat, something like this could work: struct FuncFlag(alias func) { // See code from above, but use typeof(&func).stringof to get // a list of parameter names and make sure the passed name is valid // of course, you can't check position, but the only way to get // around that is named parameters or some sort of compiler support } alias FuncFlag!generatePdf PdfFlag; // This now fails to compile generatePdf("doc.pdf", PdfFlag.nook);
<idea> You can actually check the order! Add in a counter to FuncFlag, and each time opDispatch is called increment it. You can use this to check the position. The obvious downside is optional parameters, where the counter will be incorrect unless you reset it. </idea> -- Robert http://octarineparrot.com/
Jun 11 2011
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
David Nadlinger:

 At least allowing imports in unittests would be nice though – I 
 frequently find myself writing »version (unittest) {}« blocks before the 
 actual unit tests just to import some modules not needed during regular 
 builds (yeah, I suppose I'm somewhat pedantic about that).
version(unittest) was added just to solve this problem, and for me it's a good solution. So imports in unittests is an anti-justification for the turtle-import feature. Bye, bearophile
Jun 10 2011
parent reply Adam Ruppe <destructionator gmail.com> writes:
Function local imports make it easier to reason about the code
which is of slight importance. The big thing I'd like though is
using it with mixins.

In my cgi.d, there's a mixin main that depends on std.string being
available inside the mixed in function.

Currently, I use a public import of std.string. Alternatively, the
other module could import it too, but that is pretty opaque.


But a scoped import would be cleaner: I could ensure it's always
available in that function without making the mixin user wonder
WTF the error messages are about and without polluting his namespace.
Jun 10 2011
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/10/11 8:44 PM, Adam Ruppe wrote:
 Function local imports make it easier to reason about the code
 which is of slight importance. The big thing I'd like though is
 using it with mixins.

 In my cgi.d, there's a mixin main that depends on std.string being
 available inside the mixed in function.

 Currently, I use a public import of std.string. Alternatively, the
 other module could import it too, but that is pretty opaque.


 But a scoped import would be cleaner: I could ensure it's always
 available in that function without making the mixin user wonder
 WTF the error messages are about and without polluting his namespace.
Yes. Local imports facilitate local reasoning. Andrei
Jun 10 2011
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Adam Ruppe" <destructionator gmail.com> wrote in message 
news:isuhab$17hb$1 digitalmars.com...
 Function local imports make it easier to reason about the code
 which is of slight importance. The big thing I'd like though is
 using it with mixins.

 In my cgi.d, there's a mixin main that depends on std.string being
 available inside the mixed in function.

 Currently, I use a public import of std.string. Alternatively, the
 other module could import it too, but that is pretty opaque.
I have need to do that sort of thing now and then, too. What I usually do is include it in my module as a public renamed import, renamed with some special prefix, like "_myModuleName_theOriginalName". Then I use that super-ugly name inside the code that's intended to be mixed in. It's an ugly hack, but at least it's semi-hygenic and works. Scoped imports would probably be far better.
 But a scoped import would be cleaner: I could ensure it's always
 available in that function without making the mixin user wonder
 WTF the error messages are about and without polluting his namespace.
Jun 10 2011
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
 There are also few little feature changes I have put in Bugzilla since lot of
time.
I am starting to think that just putting those issues in bugzilla was not enough, they seem to get mostly ignored. More periodic drumming in this newsgroup was needed... :-( Bye, bearophile
Jun 11 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-10 09:15, Andrei Alexandrescu wrote:
 https://github.com/D-Programming-Language/phobos/pull/94
 
 Discuss!
Okay. Let's see if I can summarize this. Andrei thinks that have a categorized boolean type which is explicit about what it's used for is valuable. So, for instance, std.algorithm.until takes OpenRight.yes and OpenRight.no rather than bool so that it's explicit to the caller what the boolean value indicates and so that you don't accidentally pass a bool which means something else entirely to until. This currently requires declaring a separate enum with yes and no values for every function that does this with the occasional function which can reuse such an enum from another function, because it needs a boolean value for exactly the same thing. Andrei therefore have 2 problems with the status quo: 1. Programmers following this idiom (including the Phobos devs) end up creating enums with yes and no values and are effectively identical to other enums except for their names. So, we end up with a fair bit of boilerplate code just to pass a strict boolean value. 2. The documentation for these yes/no enums generally really should be with the function that they're using but ends up on the enum itself or in both places. Ideally, it would just go with the function. So, Andrei created the Flag template in an attempt to do 3 things: 1. Be able to create the yes/no enum just by declaring the type of the function parameter - you eliminate boilerplate code. 2. The documentation is then clearly with the function that the yes/no enum goes with (it has nowhere else to go). 3. It promotes the yes/no idiom in a manner than seeing Flag!"enumName" as the type makes it immediately clear what the type in question is trying to do, and no one feels the need to go looking for the documentation for the enum because the use of the Flag idiom makes it clear what the type is. The complaints about this generally seem to be one of these: 1. Dislike of the yes/no enum idiom in the first place. Regardless of how Flag does it, it's a problem, because it's promoting an idiom that the poster dislikes in the first place. 2. Flag!"enumName".yes and Flag!"enumName".no are ugly. 3. The use of a template such as Flag results in ugly error messages when it's mistyped. EnumName.yes gets _much_ better errors when mistyped than Flag!"enumName".yes. 4. Flag is seen as a narrow attempt at named arguments which would be far better served by actually implementing named arguments. Andrei's response to each of these in turn is: 1. He argues for the yes/no enum idiom, citing issues with naked bool values and lack of clarity in code - how it saves you from having to look at the documentation to figure out what a particular boolean value means. It's essentially the same arguments he's made for the idiom ever since it was introduced into Phobos. 2. He proposed a template wrapper which would allow you to type yes!"enumName" and no!"enumName" instead of the full Flag!"enumName".yes and think that it's still quite ugly. 3. He essentially says that the compiler's error messages for templates need to be improved. It's an inherent problem with templates. 4. He's not trying to solve anything with named arguments. He's trying to solve a much narrower problem of naked bool values being relatively meaningless for many function arguments and error-prone when you pass a boolean value which meant something else entirely. yes/no enums solve that specific problem. Named arguments would be a change to the language at a time when we should be looking at doing as much with the language as possible rather than looking to add new features to it. Features which solve restrictions and intrinsic problems in the language need to be looked at, but those which could be solved by using the existing language and creating a library-based solution should be first explored as library solutions. Would you say that this is a fair summary of this debate so far? - Jonathan M Davis
Jun 11 2011
next sibling parent reply David Nadlinger <see klickverbot.at> writes:
On 6/11/11 11:20 PM, Jonathan M Davis wrote:
 1. Programmers following this idiom (including the Phobos devs) end up
 creating enums with yes and no values and are effectively identical to other
 enums except for their names. So, we end up with a fair bit of boilerplate
 code just to pass a strict boolean value.
s/fair/tiny/, imho: --- /// ditto. enum SomeFlag { enable, disable } --- David
Jun 11 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-11 14:32, David Nadlinger wrote:
 On 6/11/11 11:20 PM, Jonathan M Davis wrote:
 1. Programmers following this idiom (including the Phobos devs) end up
 creating enums with yes and no values and are effectively identical to
 other enums except for their names. So, we end up with a fair bit of
 boilerplate code just to pass a strict boolean value.
s/fair/tiny/, imho: --- /// ditto. enum SomeFlag { enable, disable } ---
It's a fair bit only insomuch as the same code is duplicated in several places. The code itself in each instance is small. But if you do that enough times, it adds up. Whether it's enough to matter is debatable, but there is definitely boilerplate code there which could be reduced. - Jonathan M Davis
Jun 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/11/2011 04:42 PM, Jonathan M Davis wrote:
 On 2011-06-11 14:32, David Nadlinger wrote:
 On 6/11/11 11:20 PM, Jonathan M Davis wrote:
 1. Programmers following this idiom (including the Phobos devs) end up
 creating enums with yes and no values and are effectively identical to
 other enums except for their names. So, we end up with a fair bit of
 boilerplate code just to pass a strict boolean value.
s/fair/tiny/, imho: --- /// ditto. enum SomeFlag { enable, disable } ---
It's a fair bit only insomuch as the same code is duplicated in several places. The code itself in each instance is small. But if you do that enough times, it adds up. Whether it's enough to matter is debatable, but there is definitely boilerplate code there which could be reduced. - Jonathan M Davis
It's the namespace pollution and the non-self-containedness of the function that's most troublesome. Also see Steve's point about methods. It's just untenable - to use the idiom with a class/struct method, you need to go all the way _outside_ of it an plant a symbol there. What I find most interesting is that the lack of strong counterarguments has not stood in the way of a strong emotional response. This mood has made it difficult for exchange of rational arguments. Funny thing is, the change is tiny. "Here, I'll add a handful of yes/no enums here and there in the standard library, just to help some algorithms. More to come." "Yeah, sure, whatevs." "Here, there's a way to define them once so we don't need to define them everywhere." "Gaaaaaaaaaaaaaa!!!" Andrei
Jun 11 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-11 20:44, Andrei Alexandrescu wrote:
 On 06/11/2011 04:42 PM, Jonathan M Davis wrote:
 On 2011-06-11 14:32, David Nadlinger wrote:
 On 6/11/11 11:20 PM, Jonathan M Davis wrote:
 1. Programmers following this idiom (including the Phobos devs) end up
 creating enums with yes and no values and are effectively identical to
 other enums except for their names. So, we end up with a fair bit of
 boilerplate code just to pass a strict boolean value.
s/fair/tiny/, imho: --- /// ditto. enum SomeFlag { enable, disable } ---
It's a fair bit only insomuch as the same code is duplicated in several places. The code itself in each instance is small. But if you do that enough times, it adds up. Whether it's enough to matter is debatable, but there is definitely boilerplate code there which could be reduced. - Jonathan M Davis
It's the namespace pollution and the non-self-containedness of the function that's most troublesome. Also see Steve's point about methods. It's just untenable - to use the idiom with a class/struct method, you need to go all the way _outside_ of it an plant a symbol there. What I find most interesting is that the lack of strong counterarguments has not stood in the way of a strong emotional response. This mood has made it difficult for exchange of rational arguments. Funny thing is, the change is tiny. "Here, I'll add a handful of yes/no enums here and there in the standard library, just to help some algorithms. More to come." "Yeah, sure, whatevs." "Here, there's a way to define them once so we don't need to define them everywhere." "Gaaaaaaaaaaaaaa!!!"
Honestly, at this point, I think that your proposal is pretty good, but I'm not sure that it's worth the degradation in error messages that the added templatization causes. But for a lot of people, I think that it's simply a combination of them not liking the yes/no enum idiom in the first place and/or feeling like what they really want is named parameters and that this really should be solved by named parameters. So, they don't like it. Personally, I'm a bit ambivalent towards yes/no enums, but I'm fine with having them. At this point, I'm just concerned about the worse error messages that the use of Flag will create and whether that pain is worth the added benefit that Flag brings. - Jonathan M Davis
Jun 11 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-11 20:50, Jonathan M Davis wrote:
 On 2011-06-11 20:44, Andrei Alexandrescu wrote:
 On 06/11/2011 04:42 PM, Jonathan M Davis wrote:
 On 2011-06-11 14:32, David Nadlinger wrote:
 On 6/11/11 11:20 PM, Jonathan M Davis wrote:
 1. Programmers following this idiom (including the Phobos devs) end
 up creating enums with yes and no values and are effectively
 identical to other enums except for their names. So, we end up with
 a fair bit of boilerplate code just to pass a strict boolean value.
s/fair/tiny/, imho: --- /// ditto. enum SomeFlag { enable, disable } ---
It's a fair bit only insomuch as the same code is duplicated in several places. The code itself in each instance is small. But if you do that enough times, it adds up. Whether it's enough to matter is debatable, but there is definitely boilerplate code there which could be reduced. - Jonathan M Davis
It's the namespace pollution and the non-self-containedness of the function that's most troublesome. Also see Steve's point about methods. It's just untenable - to use the idiom with a class/struct method, you need to go all the way _outside_ of it an plant a symbol there. What I find most interesting is that the lack of strong counterarguments has not stood in the way of a strong emotional response. This mood has made it difficult for exchange of rational arguments. Funny thing is, the change is tiny. "Here, I'll add a handful of yes/no enums here and there in the standard library, just to help some algorithms. More to come." "Yeah, sure, whatevs." "Here, there's a way to define them once so we don't need to define them everywhere." "Gaaaaaaaaaaaaaa!!!"
Honestly, at this point, I think that your proposal is pretty good, but I'm not sure that it's worth the degradation in error messages that the added templatization causes. But for a lot of people, I think that it's simply a combination of them not liking the yes/no enum idiom in the first place and/or feeling like what they really want is named parameters and that this really should be solved by named parameters. So, they don't like it. Personally, I'm a bit ambivalent towards yes/no enums, but I'm fine with having them. At this point, I'm just concerned about the worse error messages that the use of Flag will create and whether that pain is worth the added benefit that Flag brings.
Yikes! How did that get posted three times?! I wonder if my mail client is on the fritz... - Jonathan M Davis
Jun 11 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/12/11, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 Funny thing is,
 the change is tiny.
You seem to be forgetting that there are library writers and then there are library *users*. :) Seeing Flag!"foo".yes in the calling code scared people. So naturally people wanted to nuke it from orbit. If the proposal was yes.foo from the beginning things would much quieter around here, methinks.
Jun 11 2011
prev sibling next sibling parent so <so so.so> writes:
 It's the namespace pollution and the non-self-containedness of the  
 function that's most troublesome. Also see Steve's point about methods.  
 It's just untenable - to use the idiom with a class/struct method, you  
 need to go all the way _outside_ of it an plant a symbol there.

 What I find most interesting is that the lack of strong counterarguments  
 has not stood in the way of a strong emotional response. This mood has  
 made it difficult for exchange of rational arguments. Funny thing is,  
 the change is tiny.

 "Here, I'll add a handful of yes/no enums here and there in the standard  
 library, just to help some algorithms. More to come."

 "Yeah, sure, whatevs."

 "Here, there's a way to define them once so we don't need to define them  
 everywhere."

 "Gaaaaaaaaaaaaaa!!!"


 Andrei
(Trying the 3rd time, something wrong with newsreader) As you might know i prefer library solutions to language changes any day even the change is additive, yet this one i don't like. Library solutions, especially those affect user must be IMO both elegant and generic, this one is not. I think we are agree on this. There might be 7 in only std.algorithm but it is after all belongs to the std library, with the importance of phobos we can't change anything that is not accepted by majority. These are i think pretty strong arguments, though i believe it is you that needs to come up with strong arguments and i can't see any from you either :) Introducing an idiom to phobos means it is the D way, there should be many other frameworks that would use such a solution much more frequently. They will either dismiss this solution (most likely) or populate it. The former means the failure of the change, the latter is ugly code (again, when it is used more frequently). Named arguments both clean and generic. On one drawback (?) that variable names being part of library definition, i don't see how it is a drawback.
Jun 12 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:it1cvf$21d4$1 digitalmars.com...
 It's the namespace pollution and the non-self-containedness of the 
 function that's most troublesome. Also see Steve's point about methods. 
 It's just untenable - to use the idiom with a class/struct method, you 
 need to go all the way _outside_ of it an plant a symbol there.
You can't put an enum in a class/struct?
 What I find most interesting is that the lack of strong counterarguments 
 has not stood in the way of a strong emotional response.
Correction: Andrei's staunch dismissal of all counterarguments has not stood in the way of a strong emotional response.
 This mood has made it difficult for exchange of rational arguments. Funny 
 thing is, the change is tiny.

 "Here, I'll add a handful of yes/no enums here and there in the standard 
 library, just to help some algorithms. More to come."

 "Yeah, sure, whatevs."

 "Here, there's a way to define them once so we don't need to define them 
 everywhere."
Correction: "Here, there's a way to solve a barely-existant problem by botching up syntax (and error messages) for the user."
 "Gaaaaaaaaaaaaaa!!!"
Jun 12 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/12/11 1:59 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it1cvf$21d4$1 digitalmars.com...
 It's the namespace pollution and the non-self-containedness of the
 function that's most troublesome. Also see Steve's point about methods.
 It's just untenable - to use the idiom with a class/struct method, you
 need to go all the way _outside_ of it an plant a symbol there.
You can't put an enum in a class/struct?
 What I find most interesting is that the lack of strong counterarguments
 has not stood in the way of a strong emotional response.
Correction: Andrei's staunch dismissal of all counterarguments has not stood in the way of a strong emotional response.
 This mood has made it difficult for exchange of rational arguments. Funny
 thing is, the change is tiny.

 "Here, I'll add a handful of yes/no enums here and there in the standard
 library, just to help some algorithms. More to come."

 "Yeah, sure, whatevs."

 "Here, there's a way to define them once so we don't need to define them
 everywhere."
Correction: "Here, there's a way to solve a barely-existant problem by botching up syntax (and error messages) for the user."
 "Gaaaaaaaaaaaaaa!!!"
I'm not sure, but I think I see a sarcasm in there. Andrei
Jun 12 2011
parent "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:it32kq$2gfq$2 digitalmars.com...
 On 6/12/11 1:59 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 news:it1cvf$21d4$1 digitalmars.com...
 It's the namespace pollution and the non-self-containedness of the
 function that's most troublesome. Also see Steve's point about methods.
 It's just untenable - to use the idiom with a class/struct method, you
 need to go all the way _outside_ of it an plant a symbol there.
You can't put an enum in a class/struct?
 What I find most interesting is that the lack of strong counterarguments
 has not stood in the way of a strong emotional response.
Correction: Andrei's staunch dismissal of all counterarguments has not stood in the way of a strong emotional response.
 This mood has made it difficult for exchange of rational arguments. 
 Funny
 thing is, the change is tiny.

 "Here, I'll add a handful of yes/no enums here and there in the standard
 library, just to help some algorithms. More to come."

 "Yeah, sure, whatevs."

 "Here, there's a way to define them once so we don't need to define them
 everywhere."
Correction: "Here, there's a way to solve a barely-existant problem by botching up syntax (and error messages) for the user."
 "Gaaaaaaaaaaaaaa!!!"
I'm not sure, but I think I see a sarcasm in there.
I guess it could be taken that way, but it wasn't really my point to be sarcastic. My intent was just to summarize the way I see the situation.
Jun 12 2011
prev sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Sun, 12 Jun 2011 14:59:57 -0400, Nick Sabalausky wrote:

 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
 news:it1cvf$21d4$1 digitalmars.com...
 It's the namespace pollution and the non-self-containedness of the
 function that's most troublesome. Also see Steve's point about methods.
 It's just untenable - to use the idiom with a class/struct method, you
 need to go all the way _outside_ of it an plant a symbol there.
You can't put an enum in a class/struct?
Yes, but then you have to qualify it with the name of the class/struct when using it. See Steve's post: http://www.digitalmars.com/webnews/newsgroups.php? art_group=digitalmars.D&article_id=138281 -Lars
Jun 13 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 11 Jun 2011 17:32:56 -0400, David Nadlinger <see klickverbot.at>  
wrote:

 On 6/11/11 11:20 PM, Jonathan M Davis wrote:
 1. Programmers following this idiom (including the Phobos devs) end up
 creating enums with yes and no values and are effectively identical to  
 other
 enums except for their names. So, we end up with a fair bit of  
 boilerplate
 code just to pass a strict boolean value.
s/fair/tiny/, imho: --- /// ditto. enum SomeFlag { enable, disable } ---
A big problem with this (and enums in general), what if your flag function is defined inside a struct or class? struct MyStruct { /// This function ROCKS! void someKickAssFunction(MoreBitchin moreBitchin) {} /// ditto enum MoreBitchin { yes, no } } // the call, not so much. s.someKickAssFunction(MyStruct.MoreBitchin.yes); In other words, in order for your doc trick to work, member functions have to require an additional namespace to the enum. IMO, however, we need a better way to access the enum values without specifying the entire namespace. The difficult part is to do it in a way which doesn't conflict with normal symbols. Of course, such an improvement would pull the rug from this Flag proposal... -Steve
Jun 11 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/11/11 8:49 PM, Steven Schveighoffer wrote:
 On Sat, 11 Jun 2011 17:32:56 -0400, David Nadlinger <see klickverbot.at>
 wrote:

 On 6/11/11 11:20 PM, Jonathan M Davis wrote:
 1. Programmers following this idiom (including the Phobos devs) end up
 creating enums with yes and no values and are effectively identical
 to other
 enums except for their names. So, we end up with a fair bit of
 boilerplate
 code just to pass a strict boolean value.
s/fair/tiny/, imho: --- /// ditto. enum SomeFlag { enable, disable } ---
A big problem with this (and enums in general), what if your flag function is defined inside a struct or class? struct MyStruct { /// This function ROCKS! void someKickAssFunction(MoreBitchin moreBitchin) {} /// ditto enum MoreBitchin { yes, no } } // the call, not so much. s.someKickAssFunction(MyStruct.MoreBitchin.yes); In other words, in order for your doc trick to work, member functions have to require an additional namespace to the enum. IMO, however, we need a better way to access the enum values without specifying the entire namespace. The difficult part is to do it in a way which doesn't conflict with normal symbols. Of course, such an improvement would pull the rug from this Flag proposal... -Steve
Thanks, Steve, this is an excellent point - as are all you made in this discussion (pro and con)! Andrei
Jun 12 2011
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
Jonathan M Davis wrote:
 ...
 The complaints about this generally seem to be one of these:

 1. Dislike of the yes/no enum idiom in the first place. Regardless of how Flag
 does it, it's a problem, because it's promoting an idiom that the poster
 dislikes in the first place.

 2. Flag!"enumName".yes and Flag!"enumName".no are ugly.

 3. The use of a template such as Flag results in ugly error messages when it's
 mistyped. EnumName.yes gets _much_ better errors when mistyped than
 Flag!"enumName".yes.

 4. Flag is seen as a narrow attempt at named arguments which would be far
 better served by actually implementing named arguments.
 [snip.]
5. The approach is too sophisticated and does not pull its own weight. Imagine what you would have to explain to somebody new to the language who wondered how Yes.sortOutput works... instant turn-off! What about allowing anonymous enums in parameter lists? Unfortunately that would be a language feature. :) T someAlgorithm(..., enum {unsorted, sorted} sortOutput); To call: someAlgorithm(..., sorted); / someAlgorithm(..., unsorted); Timon
Jun 11 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/11/2011 04:58 PM, Timon Gehr wrote:
 Jonathan M Davis wrote:
 ...
 The complaints about this generally seem to be one of these:

 1. Dislike of the yes/no enum idiom in the first place. Regardless of how Flag
 does it, it's a problem, because it's promoting an idiom that the poster
 dislikes in the first place.

 2. Flag!"enumName".yes and Flag!"enumName".no are ugly.

 3. The use of a template such as Flag results in ugly error messages when it's
 mistyped. EnumName.yes gets _much_ better errors when mistyped than
 Flag!"enumName".yes.

 4. Flag is seen as a narrow attempt at named arguments which would be far
 better served by actually implementing named arguments.
 [snip.]
5. The approach is too sophisticated and does not pull its own weight. Imagine what you would have to explain to somebody new to the language who wondered how Yes.sortOutput works... instant turn-off! What about allowing anonymous enums in parameter lists? Unfortunately that would be a language feature. :) T someAlgorithm(..., enum {unsorted, sorted} sortOutput); To call: someAlgorithm(..., sorted); / someAlgorithm(..., unsorted);
I proposed this to Walter some years ago, around the time I was anticipating the nascent yes/no enum proliferation. The problem with this is it defines a type in a function parameter specification, which is unprecedented and therefore surprising. There's a closely related slide in our D 2007 conference talk. Andrei
Jun 11 2011
parent "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:it1cd7$1vv2$1 digitalmars.com...
 On 06/11/2011 04:58 PM, Timon Gehr wrote:
 Jonathan M Davis wrote:
 ...
 The complaints about this generally seem to be one of these:

 1. Dislike of the yes/no enum idiom in the first place. Regardless of 
 how Flag
 does it, it's a problem, because it's promoting an idiom that the poster
 dislikes in the first place.

 2. Flag!"enumName".yes and Flag!"enumName".no are ugly.

 3. The use of a template such as Flag results in ugly error messages 
 when it's
 mistyped. EnumName.yes gets _much_ better errors when mistyped than
 Flag!"enumName".yes.

 4. Flag is seen as a narrow attempt at named arguments which would be 
 far
 better served by actually implementing named arguments.
 [snip.]
5. The approach is too sophisticated and does not pull its own weight. Imagine what you would have to explain to somebody new to the language who wondered how Yes.sortOutput works... instant turn-off! What about allowing anonymous enums in parameter lists? Unfortunately that would be a language feature. :) T someAlgorithm(..., enum {unsorted, sorted} sortOutput); To call: someAlgorithm(..., sorted); / someAlgorithm(..., unsorted);
I like the basic idea, and it's a change that falls into the "removing restrictions" category. But the issue "so" brought up with this about not being able to pass in a variable would need to be solved for the general case. It's trivial in the case of two options: bool useSorted = ...; someAlgorithm(..., useSorted? sorted : unsorted); Although, really, that just shifts the boilerplate from the callee to the caller, so it's really a net loss. You could maybe do: T someAlgorithm(..., enum Sorted {yes, no} sortOutput); Which would be equivalent to: enum Sorted {yes, no} T someAlgorithm(..., Sorted sortOutput); But I don't now if Andrei would like that (it makes the func signature kinda verbose, too).
 I proposed this to Walter some years ago, around the time I was 
 anticipating the nascent yes/no enum proliferation. The problem with this 
 is it defines a type in a function parameter specification, which is 
 unprecedented and therefore surprising.
Your Flag idiom essentially defines a type in a function parameter specification.
Jun 12 2011
prev sibling next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Timon Gehr" <timon.gehr gmx.ch> wrote in message 
news:it0oee$ehu$1 digitalmars.com...
 What about allowing anonymous enums in parameter lists? Unfortunately that 
 would
 be a language feature. :)

 T someAlgorithm(..., enum {unsorted, sorted} sortOutput);

 To call: someAlgorithm(..., sorted); / someAlgorithm(..., unsorted);
Wow - I actually really like this! It would provide an even _better_ solution than named arguments for this type of thing! The best part is that it could degrade to the enum's base type when taking a function pointer, mangling the function's name and even inside the function's body! void myfunction(enum : int { option1, option2, option3 } options) { static assert(is(typeof(options) == int)); } static assert(is(typeof(&myfunction) == void function(int)); myfunction(option2);
Jun 12 2011
parent so <so so.so> writes:
On Sun, 12 Jun 2011 15:33:00 +0300, Daniel Murphy  
<yebblies nospamgmail.com> wrote:

 "Timon Gehr" <timon.gehr gmx.ch> wrote in message
 news:it0oee$ehu$1 digitalmars.com...
 What about allowing anonymous enums in parameter lists? Unfortunately  
 that
 would
 be a language feature. :)

 T someAlgorithm(..., enum {unsorted, sorted} sortOutput);

 To call: someAlgorithm(..., sorted); / someAlgorithm(..., unsorted);
Wow - I actually really like this! It would provide an even _better_ solution than named arguments for this type of thing! The best part is that it could degrade to the enum's base type when taking a function pointer, mangling the function's name and even inside the function's body! void myfunction(enum : int { option1, option2, option3 } options) { static assert(is(typeof(options) == int)); } static assert(is(typeof(&myfunction) == void function(int)); myfunction(option2);
This also means you can use it only once. Not knowing the type, you can't pass as a variable either. The loss is too big compared to the gain. fun_step_one(enum whatever) fun_step_two(enum?) enum type? val fun(val)
Jun 12 2011
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Timon Gehr" <timon.gehr gmx.ch> wrote in message 
news:it0oee$ehu$1 digitalmars.com...
 Jonathan M Davis wrote:
 ...
 The complaints about this generally seem to be one of these:

 1. Dislike of the yes/no enum idiom in the first place. Regardless of how 
 Flag
 does it, it's a problem, because it's promoting an idiom that the poster
 dislikes in the first place.

 2. Flag!"enumName".yes and Flag!"enumName".no are ugly.

 3. The use of a template such as Flag results in ugly error messages when 
 it's
 mistyped. EnumName.yes gets _much_ better errors when mistyped than
 Flag!"enumName".yes.

 4. Flag is seen as a narrow attempt at named arguments which would be far
 better served by actually implementing named arguments.
 [snip.]
5. The approach is too sophisticated and does not pull its own weight. Imagine what you would have to explain to somebody new to the language who wondered how Yes.sortOutput works... instant turn-off!
Not only that, but just simply trying to explain why you sometimes do "enumName.value" and sometimes do "value.enumName". It introduces a big inconsistency for callers, just for the sake of a trivial decrease in boilerplate for the callee. Also, one thing I'm unclear on: If you do: void foo(Flag!"bar" a) {} Can the caller do something like this?: bar barValue = yes.bar; foo(barValue);
Jun 12 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/11/2011 04:20 PM, Jonathan M Davis wrote:
 2. He proposed a template wrapper which would allow you to type yes!"enumName"
 and no!"enumName" instead of the full Flag!"enumName".yes and

 think that it's still quite ugly.
Those were since replaced with No.enumName and Yes.enumName by Dmitry's idea: https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330 Andrei
Jun 11 2011
parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 12, 11 11:18, Andrei Alexandrescu wrote:
 On 06/11/2011 04:20 PM, Jonathan M Davis wrote:
 2. He proposed a template wrapper which would allow you to type
 yes!"enumName"
 and no!"enumName" instead of the full Flag!"enumName".yes and

 Others
 think that it's still quite ugly.
Those were since replaced with No.enumName and Yes.enumName by Dmitry's idea: https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0b608895269bdccba4330 Andrei
Yes.X and No.X looks grammatically wrong. In D you usually have 'Aggregate.member', not 'Member.aggregate'.
Jun 11 2011
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 12.06.2011 10:31, KennyTM~ wrote:
 On Jun 12, 11 11:18, Andrei Alexandrescu wrote:
 On 06/11/2011 04:20 PM, Jonathan M Davis wrote:
 2. He proposed a template wrapper which would allow you to type
 yes!"enumName"
 and no!"enumName" instead of the full Flag!"enumName".yes and

 Others
 think that it's still quite ugly.
Those were since replaced with No.enumName and Yes.enumName by Dmitry's idea: https://github.com/andralex/phobos/commit/801ccc96ce56827cd0d0 608895269bdccba4330 Andrei
Yes.X and No.X looks grammatically wrong. In D you usually have 'Aggregate.member', not 'Member.aggregate'.
Well, you can do only as much staying within the language. Personally, I think the biggest stumbling block is error messages, maybe we can do something about them. Like make Flag struct with alias this and provide this(Flag!s) constructor, opAssign etc. that static assert something sensible on mismatch. -- Dmitry Olshansky
Jun 12 2011
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Michel Fortin:

 <https://github.com/michelf/dmd/commit/673bae4982ff18a3d216bc1578f50d40f4d26d7a>
 Took me less time than what I took arguing about Flag!"".
I don't know if Walter will appreciate this, or if this will need improvements, but you have done something better than my posts where I just talk :-) Bye, bearophile
Jun 11 2011
prev sibling next sibling parent reply foobar <foo bar.com> writes:
People here already noted most advantages and disadvantages of this proposal so
I'll just add one more: KISS.
I too am against this proposal since it's very unKISS. 
I think, that either you really need a separate enum type to document the
different values and hence use *should* define the enum or you don't really
need it and hence KISS it with a plain boolean. 
I see zero benefit from adding so much complexity here. Are we trying to kill a
fly with a hammer (and by that i mean the vehicle)?

I see no benefit in adding redundant "Yes" / "No" values.

Regarding named arguments, I don't like this "feature" and believe that it's
more trouble than its worth. For example, Ruby managed to live without it and
Rails uses AAs instead. 

And finally, Andrei's complain about scrolling up and down because of this so
called boilerplate (7 lines of code in all of phobos): 
Even though D has a far superior module system compared to c++ (which has no
such system whatsoever) you still chose to implement library-in-a-file. You
even went so far as to add "groups" to DDoc. Is there some sort of weird metric
at Facebook that gives you a bigger bonus if you manage to cram more code per
file? Are you getting deducted per the amount of files you've added? 
Jun 12 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/12/2011 03:55 PM, foobar wrote:
 People here already noted most advantages and disadvantages of this proposal
so I'll just add one more: KISS.
 I too am against this proposal since it's very unKISS.
I agree that KISS is important and that Flag is failing it. Andrei
Jun 12 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/12/2011 1:54 PM, Andrei Alexandrescu wrote:
 On 06/12/2011 03:55 PM, foobar wrote:
 People here already noted most advantages and disadvantages of this proposal
 so I'll just add one more: KISS.
 I too am against this proposal since it's very unKISS.
I agree that KISS is important and that Flag is failing it.
Set phasers to "vaporize".
Jun 12 2011
prev sibling parent reply bearophile < bearophileHUGS lycos.com> writes:
Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature. I am for it, if it's well implemented. The reordering is one important part of this feature. An optional sub-feature is a way to deprecate argument names. Thankfully in D there is already the deprecated keyword; a first idea: void foo(int deprecated(y) x) {} Or: void foo(int deprecated{y} x) {} Bye, bearophile
Jun 13 2011
next sibling parent "Nick Sabalausky" <a a.a> writes:
"bearophile" < bearophileHUGS lycos.com> wrote in message 
news:it5gqj$a1g$1 digitalmars.com...
 Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature. I am for it, if it's well implemented. The reordering is one important part of this feature. An optional sub-feature is a way to deprecate argument names. Thankfully in D there is already the deprecated keyword; a first idea: void foo(int deprecated(y) x) {} Or: void foo(int deprecated{y} x) {}
I like it!
Jun 13 2011
prev sibling parent reply so <so so.so> writes:
On Mon, 13 Jun 2011 20:19:15 +0300, bearophile <  
<bearophileHUGS lycos.com> wrote:

 Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature.
I think they worth it and it is the right time to talk extensively why people think they don't. And reasoning should not be about its failure or success in another language, we better have our own rules. IMO named arguments in D at least should do: - Reordering (since we got default parameters, even better) - It is enabled only if we have access to the function declaration. - In a function call we either use named arguments for all the non-default arguments or call it with the usual syntax. No hybrid stuff, no confusion. fun(int a, int b, int c=3) fun(1, 2, 3) // fine - current fun(1, 2) // fine - current fun(a:1, b:3, c:5) // fine fun(a:1, b:3) // fine fun(b:1, c:3, a:5) // fine fun(b:1, a:3) // fine fun(b:1) // error fun(c:1) // error fun(2, b:1) // error fun(2, c:1) // error fun(2, c:2, 3) // error Thanks.
Jun 13 2011
next sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
On 6/14/11 8:36 AM, so wrote:
 On Mon, 13 Jun 2011 20:19:15 +0300, bearophile <
 <bearophileHUGS lycos.com> wrote:

 Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature.
I think they worth it and it is the right time to talk extensively why people think they don't. And reasoning should not be about its failure or success in another language, we better have our own rules. IMO named arguments in D at least should do: - Reordering (since we got default parameters, even better) - It is enabled only if we have access to the function declaration. - In a function call we either use named arguments for all the non-default arguments or call it with the usual syntax. No hybrid stuff, no confusion.
A different rule can be: - Named arguments come last. - Any previous arguments match the order.
 fun(int a, int b, int c=3)

 fun(1, 2, 3) // fine - current
 fun(1, 2) // fine - current

 fun(a:1, b:3, c:5) // fine
 fun(a:1, b:3) // fine
 fun(b:1, c:3, a:5) // fine
 fun(b:1, a:3) // fine
 fun(b:1) // error
// error: missing a
 fun(c:1) // error
// error: missing a and b
 fun(2, b:1) // error
// ok, a is 2, b is 1, c is 3
 fun(2, c:1) // error
// error: missing b
 fun(2, c:2, 3) // error
// error, 3 after named arguments
Jun 13 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 04:46:54 +0300, Ary Manzana <ary esperanto.org.ar>  
wrote:

 On 6/14/11 8:36 AM, so wrote:
 On Mon, 13 Jun 2011 20:19:15 +0300, bearophile <
 <bearophileHUGS lycos.com> wrote:

 Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature.
I think they worth it and it is the right time to talk extensively why people think they don't. And reasoning should not be about its failure or success in another language, we better have our own rules. IMO named arguments in D at least should do: - Reordering (since we got default parameters, even better) - It is enabled only if we have access to the function declaration. - In a function call we either use named arguments for all the non-default arguments or call it with the usual syntax. No hybrid stuff, no confusion.
A different rule can be: - Named arguments come last. - Any previous arguments match the order.
IMO the main that makes NAs confusing is allowing hybrid calls. I don't think allowing reordering then introducing two new rules on ordering is a good idea.
Jun 13 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"so" <so so.so> wrote in message news:op.vw1msqy0mpw3zg so-pc...
 On Tue, 14 Jun 2011 04:46:54 +0300, Ary Manzana <ary esperanto.org.ar> 
 wrote:

 On 6/14/11 8:36 AM, so wrote:
 On Mon, 13 Jun 2011 20:19:15 +0300, bearophile <
 <bearophileHUGS lycos.com> wrote:

 Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature.
I think they worth it and it is the right time to talk extensively why people think they don't. And reasoning should not be about its failure or success in another language, we better have our own rules. IMO named arguments in D at least should do: - Reordering (since we got default parameters, even better) - It is enabled only if we have access to the function declaration. - In a function call we either use named arguments for all the non-default arguments or call it with the usual syntax. No hybrid stuff, no confusion.
A different rule can be: - Named arguments come last. - Any previous arguments match the order.
IMO the main that makes NAs confusing is allowing hybrid calls. I don't think allowing reordering then introducing two new rules on ordering is a good idea.
I think Ary's suggestion is very simple and easy to understand. Hybrid calls are *only* confusing when an unnamed parameter comes after a named one.
Jun 13 2011
next sibling parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 08:32:59 +0300, Nick Sabalausky <a a.a> wrote:

 I think Ary's suggestion is very simple and easy to understand. Hybrid  
 calls
 are *only* confusing when an unnamed parameter comes after a named one.
An example to it. fun(int a, int b, int c, int d) Say we want to name only c: fun(2, 3, 1, c:5) Ary's rules and function signature in mind, after you glance the call you'd do some calculations and eventually find out the caller meant: fun(a:2, b:3, d:1, c:5) This is only 4 parameters and i named only one. Now NAs supposed to ease to process of self-documenting, not complicate it even further. I'm in favor of keeping it as simple as possible without creating any confusion.
Jun 13 2011
parent reply Ary Manzana <ary esperanto.org.ar> writes:
On 6/14/11 12:58 PM, so wrote:
 On Tue, 14 Jun 2011 08:32:59 +0300, Nick Sabalausky <a a.a> wrote:

 I think Ary's suggestion is very simple and easy to understand. Hybrid
 calls
 are *only* confusing when an unnamed parameter comes after a named one.
An example to it. fun(int a, int b, int c, int d) Say we want to name only c: fun(2, 3, 1, c:5)
// error: c assigned twice Remember, the third argument is positional so it's assigned to c. Then you are trying to assign c again. It's an error.
Jun 13 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 09:33:54 +0300, Ary Manzana <ary esperanto.org.ar>  
wrote:

 On 6/14/11 12:58 PM, so wrote:
 On Tue, 14 Jun 2011 08:32:59 +0300, Nick Sabalausky <a a.a> wrote:

 I think Ary's suggestion is very simple and easy to understand. Hybrid
 calls
 are *only* confusing when an unnamed parameter comes after a named one.
An example to it. fun(int a, int b, int c, int d) Say we want to name only c: fun(2, 3, 1, c:5)
// error: c assigned twice Remember, the third argument is positional so it's assigned to c. Then you are trying to assign c again. It's an error.
Sorry i don't understand, what should i do?
Jun 13 2011
parent Ary Manzana <ary esperanto.org.ar> writes:
On 6/14/11 1:38 PM, so wrote:
 On Tue, 14 Jun 2011 09:33:54 +0300, Ary Manzana <ary esperanto.org.ar>
 wrote:

 On 6/14/11 12:58 PM, so wrote:
 On Tue, 14 Jun 2011 08:32:59 +0300, Nick Sabalausky <a a.a> wrote:

 I think Ary's suggestion is very simple and easy to understand. Hybrid
 calls
 are *only* confusing when an unnamed parameter comes after a named one.
An example to it. fun(int a, int b, int c, int d) Say we want to name only c: fun(2, 3, 1, c:5)
// error: c assigned twice Remember, the third argument is positional so it's assigned to c. Then you are trying to assign c again. It's an error.
Sorry i don't understand, what should i do?
You can't only name c. You can name arguments from the end to the beginning: fun(2, 3, 1, d: 99) fun(2, 3, c: 98, d:99) fun(2, 3, d: 98, c:99) fun(2, c: 97, b: 98, d:99) etc.
Jun 13 2011
prev sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
On 6/14/11 12:32 PM, Nick Sabalausky wrote:
 "so"<so so.so>  wrote in message news:op.vw1msqy0mpw3zg so-pc...
 On Tue, 14 Jun 2011 04:46:54 +0300, Ary Manzana<ary esperanto.org.ar>
 wrote:

 On 6/14/11 8:36 AM, so wrote:
 On Mon, 13 Jun 2011 20:19:15 +0300, bearophile<
 <bearophileHUGS lycos.com>  wrote:

 Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature.
I think they worth it and it is the right time to talk extensively why people think they don't. And reasoning should not be about its failure or success in another language, we better have our own rules. IMO named arguments in D at least should do: - Reordering (since we got default parameters, even better) - It is enabled only if we have access to the function declaration. - In a function call we either use named arguments for all the non-default arguments or call it with the usual syntax. No hybrid stuff, no confusion.
A different rule can be: - Named arguments come last. - Any previous arguments match the order.
IMO the main that makes NAs confusing is allowing hybrid calls. I don't think allowing reordering then introducing two new rules on ordering is a good idea.
I think Ary's suggestion is very simple and easy to understand. Hybrid calls are *only* confusing when an unnamed parameter comes after a named one.
Well, that's the way Ruby works :-) In fact, in Ruby there are no named arguments. So people came up with this idea. def some_function(param_a, param_b, options = {}) param_c = options['param_c'] || default_for_c param_d = options['param_d'] || default_for_d end The last argument is a hash (a dictionary) with a default value of an empty hash. So you can call it: some_function(1, 2) some_function(1, 2, {'param_c' => 3}) some_function(1, 2, {'param_c' => 3, 'param_d' => 4}) But in Ruby there's a rule: you can skip parenthesis. And you can skip the brackets for a hash if it's the last argument. And instead of strings symbols are much nicer and efficient. So... some_function 1, 2 some_function 1, 2, :param_c => 3 some_function 1, 3, :param_c => 3, :param_d => 4 Of course this won't work in D because passing hashes all the time would be very inneficcient. But I think positional arguments first, named arguments last is a simple rule that's easy to follow and probably implement (maybe when I'll go back to my country I'll try to implement it).
Jun 13 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 09:48:14 +0300, Ary Manzana <ary esperanto.org.ar>  
wrote:

 Well, that's the way Ruby works :-)

 In fact, in Ruby there are no named arguments. So people came up with  
 this idea.

 def some_function(param_a, param_b, options = {})
    param_c = options['param_c'] || default_for_c
    param_d = options['param_d'] || default_for_d
 end

 The last argument is a hash (a dictionary) with a default value of an  
 empty hash.

 So you can call it:

 some_function(1, 2)
 some_function(1, 2, {'param_c' => 3})
 some_function(1, 2, {'param_c' => 3, 'param_d' => 4})

 But in Ruby there's a rule: you can skip parenthesis. And you can skip  
 the brackets for a hash if it's the last argument. And instead of  
 strings symbols are much nicer and efficient. So...

 some_function 1, 2
 some_function 1, 2, :param_c => 3
 some_function 1, 3, :param_c => 3, :param_d => 4

 Of course this won't work in D because passing hashes all the time would  
 be very inneficcient. But I think positional arguments first, named  
 arguments last is a simple rule that's easy to follow and probably  
 implement (maybe when I'll go back to my country I'll try to implement  
 it).
Tell me this is not true! :) So ruby don't have named arguments and the community came up with a solution which is by the look of it heavily influenced by language capabilities. No offense and please no kicking butts but... This is madness!!!
Jun 13 2011
next sibling parent Ary Manzana <ary esperanto.org.ar> writes:
On 6/14/11 1:58 PM, so wrote:
 On Tue, 14 Jun 2011 09:48:14 +0300, Ary Manzana <ary esperanto.org.ar>
 wrote:

 Well, that's the way Ruby works :-)

 In fact, in Ruby there are no named arguments. So people came up with
 this idea.

 def some_function(param_a, param_b, options = {})
 param_c = options['param_c'] || default_for_c
 param_d = options['param_d'] || default_for_d
 end

 The last argument is a hash (a dictionary) with a default value of an
 empty hash.

 So you can call it:

 some_function(1, 2)
 some_function(1, 2, {'param_c' => 3})
 some_function(1, 2, {'param_c' => 3, 'param_d' => 4})

 But in Ruby there's a rule: you can skip parenthesis. And you can skip
 the brackets for a hash if it's the last argument. And instead of
 strings symbols are much nicer and efficient. So...

 some_function 1, 2
 some_function 1, 2, :param_c => 3
 some_function 1, 3, :param_c => 3, :param_d => 4

 Of course this won't work in D because passing hashes all the time
 would be very inneficcient. But I think positional arguments first,
 named arguments last is a simple rule that's easy to follow and
 probably implement (maybe when I'll go back to my country I'll try to
 implement it).
Tell me this is not true! :)
:-P
 So ruby don't have named arguments and the community came up with a
 solution which is by the look of it heavily influenced by language
 capabilities. No offense and please no kicking butts but... This is
 madness!!!
Well, in fact I don't know if the community came up with this or if the creators came up with this. But I'm sure at some point they agreed on this because it's supported on the syntax level.
Jun 14 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/14/11 1:58 AM, so wrote:
 Tell me this is not true! :)
 So ruby don't have named arguments and the community came up with a
 solution which is by the look of it heavily influenced by language
 capabilities. No offense and please no kicking butts but... This is
 madness!!!
Ha! My Flag chef d'oeuvre would enjoy appreciation, just in another language. Andrei
Jun 14 2011
prev sibling next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 14, 11 09:36, so wrote:
 On Mon, 13 Jun 2011 20:19:15 +0300, bearophile <
 <bearophileHUGS lycos.com> wrote:

 Andrei:

 If we all get convinced that named parameters are worth it,
I think this is not going to happen because some people (two?) don't want this feature.
I think they worth it and it is the right time to talk extensively why people think they don't. And reasoning should not be about its failure or success in another language, we better have our own rules. IMO named arguments in D at least should do: - Reordering (since we got default parameters, even better) - It is enabled only if we have access to the function declaration. - In a function call we either use named arguments for all the non-default arguments or call it with the usual syntax. No hybrid stuff, no confusion. fun(int a, int b, int c=3) fun(1, 2, 3) // fine - current fun(1, 2) // fine - current fun(a:1, b:3, c:5) // fine fun(a:1, b:3) // fine fun(b:1, c:3, a:5) // fine fun(b:1, a:3) // fine fun(b:1) // error fun(c:1) // error fun(2, b:1) // error fun(2, c:1) // error fun(2, c:2, 3) // error Thanks.
I'd rather have no reordering and allow hybrid call. Named argument is useful for specifying the nature of an argument. If the type is clear for all but one argument, the rest is just noisy redundant info. e.g. MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height, bRepaint:true); is no worse than MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y, nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);
Jun 13 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 09:18:42 +0300, KennyTM~ <kennytm gmail.com> wrote:

 I'd rather have no reordering and allow hybrid call. Named argument is  
 useful for specifying the nature of an argument. If the type is clear  
 for all but one argument, the rest is just noisy redundant info.
fun(bool, bool, bool, bool, bool...) Isn't the type clear for every argument here?
 e.g.

      MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height,
                 bRepaint:true);

 is no worse than

      MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y,
                 nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);
Reordering is important an example: fun(int a, int b=2, int c=3) If you want to name c but not b what are you going to do? Named arguments isn't something to save typing. Also the first version of the MoveWindow indeed worse than the second, which again i think requires no explanation.
Jun 13 2011
next sibling parent so <so so.so> writes:
 Reordering is important an example:

 fun(int a, int b=2, int c=3)
 If you want to name c but not b what are you going to do?
In fact, i was wrong on this one, you'd simply call fun(a, c:4). Reordering is nice because if you remove hybrid calls you no longer need an order, you are free to change priority.
Jun 14 2011
prev sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 14, 11 14:46, so wrote:
 On Tue, 14 Jun 2011 09:18:42 +0300, KennyTM~ <kennytm gmail.com> wrote:

 I'd rather have no reordering and allow hybrid call. Named argument is
 useful for specifying the nature of an argument. If the type is clear
 for all but one argument, the rest is just noisy redundant info.
fun(bool, bool, bool, bool, bool...) Isn't the type clear for every argument here?
By "type" I mean the purpose of an argument, e.g. the first 'int' in MoveWindow is an x-coordinate, the second is a y-coordinate, etc. Sorry I don't know of a better term. When what one argument does is clear for the caller, forcing NA on it just annoys the programmer.
 e.g.

 MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height,
 bRepaint:true);

 is no worse than

 MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y,
 nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);
Reordering is important an example: fun(int a, int b=2, int c=3) If you want to name c but not b what are you going to do?
That's skipping, not really reordering. 'a' still precedes 'c'. Also, I'm not against reordering, but I'm against using reordering as a reason to abandon hybrid.
 Named arguments isn't something to save typing.
 Also the first version of the MoveWindow indeed worse than the second,
 which again i think requires no explanation.
No, please explain. What does the extra hWnd, X, Y, nWidth, nHeight buy, when the respective arguments already show what they are?'
Jun 14 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 11:23:12 +0300, KennyTM~ <kennytm gmail.com> wrote:

 On Jun 14, 11 14:46, so wrote:
 On Tue, 14 Jun 2011 09:18:42 +0300, KennyTM~ <kennytm gmail.com> wrote:

 I'd rather have no reordering and allow hybrid call. Named argument is
 useful for specifying the nature of an argument. If the type is clear
 for all but one argument, the rest is just noisy redundant info.
fun(bool, bool, bool, bool, bool...) Isn't the type clear for every argument here?
By "type" I mean the purpose of an argument, e.g. the first 'int' in MoveWindow is an x-coordinate, the second is a y-coordinate, etc. Sorry I don't know of a better term. When what one argument does is clear for the caller, forcing NA on it just annoys the programmer.
This is the whole point of NAs, it is not clear, you need to check the function definition whenever you read the call.
 e.g.

 MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height,
 bRepaint:true);

 is no worse than

 MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y,
 nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);
Reordering is important an example: fun(int a, int b=2, int c=3) If you want to name c but not b what are you going to do?
That's skipping, not really reordering. 'a' still precedes 'c'. Also, I'm not against reordering, but I'm against using reordering as a reason to abandon hybrid.
It is not a reason to abandon hybrid, it is a consequence of abandoning it.
 Named arguments isn't something to save typing.
 Also the first version of the MoveWindow indeed worse than the second,
 which again i think requires no explanation.
No, please explain. What does the extra hWnd, X, Y, nWidth, nHeight buy, when the respective arguments already show what they are?'
Matching, with fun(x:x, y:y) or fun(y:y, x:x) you are done, you don't ever need to check function definition again. With your reasoning you don't need named arguments at all. enum bRepaint=true; MoveWindow(... bRepaint)
Jun 14 2011
parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 14, 11 16:39, so wrote:
 On Tue, 14 Jun 2011 11:23:12 +0300, KennyTM~ <kennytm gmail.com> wrote:

 On Jun 14, 11 14:46, so wrote:
 On Tue, 14 Jun 2011 09:18:42 +0300, KennyTM~ <kennytm gmail.com> wrote:

 I'd rather have no reordering and allow hybrid call. Named argument is
 useful for specifying the nature of an argument. If the type is clear
 for all but one argument, the rest is just noisy redundant info.
fun(bool, bool, bool, bool, bool...) Isn't the type clear for every argument here?
By "type" I mean the purpose of an argument, e.g. the first 'int' in MoveWindow is an x-coordinate, the second is a y-coordinate, etc. Sorry I don't know of a better term. When what one argument does is clear for the caller, forcing NA on it just annoys the programmer.
This is the whole point of NAs, it is not clear, you need to check the function definition whenever you read the call.
And yet, with loc.x, myWin.width etc, you don't need to check the definition to know those should be coordinates and widths.
 e.g.

 MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height,
 bRepaint:true);

 is no worse than

 MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y,
 nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);
Reordering is important an example: fun(int a, int b=2, int c=3) If you want to name c but not b what are you going to do?
That's skipping, not really reordering. 'a' still precedes 'c'. Also, I'm not against reordering, but I'm against using reordering as a reason to abandon hybrid.
It is not a reason to abandon hybrid, it is a consequence of abandoning it.
You don't need to abandon hybrid to enable reordering. Ary's suggestion, for example, allows positional and named arguments to coexist.
 Named arguments isn't something to save typing.
 Also the first version of the MoveWindow indeed worse than the second,
 which again i think requires no explanation.
No, please explain. What does the extra hWnd, X, Y, nWidth, nHeight buy, when the respective arguments already show what they are?'
Matching, with fun(x:x, y:y) or fun(y:y, x:x) you are done, you don't ever need to check function definition again. With your reasoning you don't need named arguments at all.
Why do you need to check the function definition when you see 'moveTo(x, y)'?
 enum bRepaint=true;
 MoveWindow(... bRepaint)
Non sequitur. In my MoveWindow example hWnd, loc and myWin are assumed to be variables you got from elsewhere. The names of these variables already provide the semantics to the readers, making NA for those arguments redundant. If they were constants it's nothing wrong with MoveWindow(hWnd, X:0, Y:0, nWidth:200, nHeight:200, bRepaint:true);
Jun 14 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 12:58:30 +0300, KennyTM~ <kennytm gmail.com> wrote:

 And yet, with loc.x, myWin.width etc, you don't need to check the  
 definition to know those should be coordinates and widths.
loc.x on the caller side, it has no idea about function signature, and you don't know if it was 10th or 2nd argument in function. // definition fun(int x, int y) { } // call fun(x, y) // you need to check the definition if you think something wrong with parameters the second time you come here fun(y, x) // same fun(x:x, y:y) // you know there is nothing wrong with parameters fun(y:y, x:x) // same
 You don't need to abandon hybrid to enable reordering. Ary's suggestion,  
 for example, allows positional and named arguments to coexist.
Allows reordering by introducing two new order restrictions which i still had trouble understanding, sorry Ary :)
 Why do you need to check the function definition when you see 'moveTo(x,  
 y)'?
Same question, why do you need named arguments?
 enum bRepaint=true;
 MoveWindow(... bRepaint)
Non sequitur. In my MoveWindow example hWnd, loc and myWin are assumed to be variables you got from elsewhere. The names of these variables already provide the semantics to the readers, making NA for those arguments redundant. If they were constants it's nothing wrong with MoveWindow(hWnd, X:0, Y:0, nWidth:200, nHeight:200, bRepaint:true);
Again, they are variables you get on the caller side, they got no idea about function signature. Also i don't understand why some think allowing hybrid calls has any merit. Just search "named arguments" and first thing you'd see is calls with all arguments named, no exception. Allowing unnamed arguments and named arguments in one call doesn't make any sense to me, it is almost opposite to the reasons named arguments designed for, you don't even need to talk about its drawbacks like the complications and confusions.
Jun 14 2011
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 14, 11 19:11, so wrote:
 On Tue, 14 Jun 2011 12:58:30 +0300, KennyTM~ <kennytm gmail.com> wrote:

 And yet, with loc.x, myWin.width etc, you don't need to check the
 definition to know those should be coordinates and widths.
loc.x on the caller side, it has no idea about function signature, and you don't know if it was 10th or 2nd argument in function. // definition fun(int x, int y) { } // call fun(x, y) // you need to check the definition if you think something wrong with parameters the second time you come here fun(y, x) // same fun(x:x, y:y) // you know there is nothing wrong with parameters fun(y:y, x:x) // same
If you have no idea about the function signature, you have no idea about the parameter names either.
 You don't need to abandon hybrid to enable reordering. Ary's
 suggestion, for example, allows positional and named arguments to
 coexist.
Allows reordering by introducing two new order restrictions which i still had trouble understanding, sorry Ary :)
 Why do you need to check the function definition when you see
 'moveTo(x, y)'?
Same question, why do you need named arguments?
You see the difference between variables and generic constants? RECT bounds; GetWindowRect(hWnd, &bounds); writeln("Please enter the coordinates."); auto x = readln().chomp().to!int(); auto y = readln().chomp().to!int(); auto width = bounds.right - bounds.left; auto height = bounds.bottom - bounds.top; MoveWindow(hWnd, x, y, width, height, bRepaint:true); vs. writeln("Resetting window dimensions"); ... MoveWindow(hWnd, X:0, Y:0, nWidth:800, nHeight:600, bRepaint:true); Named arguments provides clarification when the argument itself (e.g. 0, false, true) is meaningless. But with a variable which itself provides a meaning, forcing named argument on _every_argument_passed_ is just annoying.
 enum bRepaint=true;
 MoveWindow(... bRepaint)
Non sequitur. In my MoveWindow example hWnd, loc and myWin are assumed to be variables you got from elsewhere. The names of these variables already provide the semantics to the readers, making NA for those arguments redundant. If they were constants it's nothing wrong with MoveWindow(hWnd, X:0, Y:0, nWidth:200, nHeight:200, bRepaint:true);
Again, they are variables you get on the caller side, they got no idea about function signature.
See above.
 Also i don't understand why some think allowing hybrid calls has any
 merit. Just search "named arguments" and first thing you'd see is calls
 with all arguments named, no exception. Allowing unnamed arguments and
 named arguments in one call doesn't make any sense to me, it is almost
 opposite to the reasons named arguments designed for, you don't even
 need to talk about its drawbacks like the complications and confusions.
Yet all well-known languages that support named arguments that support
Jun 14 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 15:18:09 +0300, KennyTM~ <kennytm gmail.com> wrote:

 loc.x on the caller side, it has no idea about function signature, and
 you don't know if it was 10th or 2nd argument in function.

 // definition
 fun(int x, int y) {
 }

 // call
 fun(x, y) // you need to check the definition if you think something
 wrong with parameters the second time you come here
 fun(y, x) // same
 fun(x:x, y:y) // you know there is nothing wrong with parameters
 fun(y:y, x:x) // same
If you have no idea about the function signature, you have no idea about the parameter names either.
I think you are just resisting here, if you write a call once with named arguments, you documented it in place, the next time you visit this call all you need to see is in the call site.
 You see the difference between variables and generic constants?

       RECT bounds;
       GetWindowRect(hWnd, &bounds);

       writeln("Please enter the coordinates.");
       auto x = readln().chomp().to!int();
       auto y = readln().chomp().to!int();
       auto width = bounds.right - bounds.left;
       auto height = bounds.bottom - bounds.top;

       MoveWindow(hWnd, x, y, width, height, bRepaint:true);
 vs.

       writeln("Resetting window dimensions");
       ...
       MoveWindow(hWnd, X:0, Y:0, nWidth:800, nHeight:600, bRepaint:true);

 Named arguments provides clarification when the argument itself (e.g. 0,  
 false, true) is meaningless. But with a variable which itself provides a  
 meaning, forcing named argument on _every_argument_passed_ is just  
 annoying.
Looks like i am just repeating myself but i don't understand how is pssing constants meaningless and variables, and why do you even need named arguments for those? enum x=... enum y=... ... fun(x, y)
 Yet all well-known languages that support named arguments that support  

This is not an argument.
Jun 14 2011
parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 15, 11 00:45, so wrote:
 On Tue, 14 Jun 2011 15:18:09 +0300, KennyTM~ <kennytm gmail.com> wrote:

 loc.x on the caller side, it has no idea about function signature, and
 you don't know if it was 10th or 2nd argument in function.

 // definition
 fun(int x, int y) {
 }

 // call
 fun(x, y) // you need to check the definition if you think something
 wrong with parameters the second time you come here
 fun(y, x) // same
 fun(x:x, y:y) // you know there is nothing wrong with parameters
 fun(y:y, x:x) // same
If you have no idea about the function signature, you have no idea about the parameter names either.
I think you are just resisting here, if you write a call once with named arguments, you documented it in place, the next time you visit this call all you need to see is in the call site.
I'm just bringing up the fact. Why would you need to check the function signature when reading MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height, bRepaint:true); ? It's clear what each argument does. If you feel the need of duplicating the same information, fine, write MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y, nWidth:myWin.width, nHeight:myWin.height, bRepaint:true); in your code. But don't make it mandatory, it's a waste of time and space when the writer just wants to clarify that 'true' is a bRepaint.
 You see the difference between variables and generic constants?

 RECT bounds;
 GetWindowRect(hWnd, &bounds);

 writeln("Please enter the coordinates.");
 auto x = readln().chomp().to!int();
 auto y = readln().chomp().to!int();
 auto width = bounds.right - bounds.left;
 auto height = bounds.bottom - bounds.top;

 MoveWindow(hWnd, x, y, width, height, bRepaint:true);
 vs.

 writeln("Resetting window dimensions");
 ...
 MoveWindow(hWnd, X:0, Y:0, nWidth:800, nHeight:600, bRepaint:true);

 Named arguments provides clarification when the argument itself (e.g.
 0, false, true) is meaningless. But with a variable which itself
 provides a meaning, forcing named argument on _every_argument_passed_
 is just annoying.
Looks like i am just repeating myself but i don't understand how is pssing constants meaningless and variables, and why do you even need named arguments for those? enum x=... enum y=... ... fun(x, y)
If you want to disregard named argument, why go the complicated route and define enums? You could do as well fun(/*x*/0, /*y*/0); (and yes I'm currently using it.) But the point is it's ugly. Heck why do we need to defend NA. My point is only "hybrid should be allowed if I want to".
 Yet all well-known languages that support named arguments that support

This is not an argument.
Neither is 'Just search "named arguments" and first thing you'd see is calls with all arguments named, no exception.' Maybe another argument: D's static struct initializer already supports hybrid and reordering. Extending that to function arguments is natural. ------------------------------------ struct S { int x; int y; } void main() { S s0 = {4, 5}; S s1 = {x:4, 5}; S s2 = {4, y:5}; S s3 = {x:4, y:5}; // S s4 = {y:4, 5}; // error S s5 = {y:5, x:4}; } ------------------------------------
Jun 14 2011
next sibling parent reply so <so so.so> writes:
 I'm just bringing up the fact. Why would you need to check the function  
 signature when reading

      MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height,
                 bRepaint:true);

 ? It's clear what each argument does. If you feel the need of  
 duplicating the same information, fine, write

      MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y,
                 nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);

 in your code. But don't make it mandatory, it's a waste of time and  
 space when the writer just wants to clarify that 'true' is a bRepaint.
Waste of time? so is writing docs and comments, so is checking the library everytime you have trouble understanding a call. It is designed to ease understanding your own or others code. I have no idea how you can think about writing a few chars more as if something bad. In programming we waste our times not when we are actually writing but while doing everything else!
 Looks like i am just repeating myself but i don't understand how is
 pssing constants meaningless and variables, and why do you even need
 named arguments for those?

 enum x=...
 enum y=...
 ...
 fun(x, y)
If you want to disregard named argument, why go the complicated route and define enums? You could do as well fun(/*x*/0, /*y*/0);
No, you are the one suggesting that, in your example you called MoveWindow(hwnd) and said it was all you need, then i gave this example to prove if all you need is that, you don't need NAs anyways since it is just so easy to treat other things as "hwnd".
 (and yes I'm currently using it.) But the point is it's ugly. Heck why  
 do we need to defend NA. My point is only "hybrid should be allowed if I  
 want to".
It is ugly but it is not heck, it does nothing, it gives you no guaranties, compiler does no matching. It is no better than fun(0, 0). We came this far but we still don't think the NAs same way, and i am starting to lose my hope explaining myself.
 Yet all well-known languages that support named arguments that support

This is not an argument.
Neither is 'Just search "named arguments" and first thing you'd see is calls with all arguments named, no exception.'
Why not? first thing you would encounter is its prototype, its best usage that makes most sense, i told it because you seem to give its primary function no value at all.
 Maybe another argument: D's static struct initializer already supports  
 hybrid and reordering. Extending that to function arguments is natural.

 ------------------------------------
 struct S { int x; int y; }
 void main() {
      S s0 = {4, 5};
      S s1 = {x:4, 5};
      S s2 = {4, y:5};
      S s3 = {x:4, y:5};
 //  S s4 = {y:4, 5};    // error
      S s5 = {y:5, x:4};
 }
 ------------------------------------
I didn't know they work this way, i agree it is a good argument (finally we agree on something!) Though i have to say it looks quite confusing and verbose (rules). Then again, it looks like i am alone on this one, quite possibly i am wrong :)
Jun 15 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
so:

 I didn't know they work this way, i agree it is a good argument (finally  
 we agree on something!)
To not waste all the good discussions I suggest to write down a DEP (D Enhancement Proposal), that tries to list what to do in all corner cases, even just a "?" where you don't know what to do (and including my Scala-style deprecated(oldArgName) idea). Even writing a pre-DEP will be a good starting point. Even if in the end named arguments don't get added to D, having this DEP will be good to avoid further future discussions, or as starting point for a future desire to try adding them again. Bye, bearophile
Jun 15 2011
parent KennyTM~ <kennytm gmail.com> writes:
On Jun 16, 11 00:43, bearophile wrote:
 so:

 I didn't know they work this way, i agree it is a good argument (finally
 we agree on something!)
To not waste all the good discussions I suggest to write down a DEP (D Enhancement Proposal), that tries to list what to do in all corner cases, even just a "?" where you don't know what to do (and including my Scala-style deprecated(oldArgName) idea). Even writing a pre-DEP will be a good starting point. Even if in the end named arguments don't get added to D, having this DEP will be good to avoid further future discussions, or as starting point for a future desire to try adding them again. Bye, bearophile
You mean a DIP :)
Jun 15 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"KennyTM~" <kennytm gmail.com> wrote in message 
news:it8f4s$1gve$1 digitalmars.com...
 On Jun 15, 11 00:45, so wrote:
 On Tue, 14 Jun 2011 15:18:09 +0300, KennyTM~ <kennytm gmail.com> wrote:

 loc.x on the caller side, it has no idea about function signature, and
 you don't know if it was 10th or 2nd argument in function.

 // definition
 fun(int x, int y) {
 }

 // call
 fun(x, y) // you need to check the definition if you think something
 wrong with parameters the second time you come here
 fun(y, x) // same
 fun(x:x, y:y) // you know there is nothing wrong with parameters
 fun(y:y, x:x) // same
If you have no idea about the function signature, you have no idea about the parameter names either.
I think you are just resisting here, if you write a call once with named arguments, you documented it in place, the next time you visit this call all you need to see is in the call site.
I'm just bringing up the fact. Why would you need to check the function signature when reading MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height, bRepaint:true); ? It's clear what each argument does.
Because it might be wrong.
 If you feel the need of duplicating the same information, fine, write

     MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y,
                nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);

 in your code. But don't make it mandatory, it's a waste of time and space 
 when the writer just wants to clarify that 'true' is a bRepaint.
I don't think anyone suggested named arguments should be manditory.
Jun 19 2011
parent KennyTM~ <kennytm gmail.com> writes:
On Jun 20, 11 03:03, Nick Sabalausky wrote:
 "KennyTM~"<kennytm gmail.com>  wrote in message
 news:it8f4s$1gve$1 digitalmars.com...
 On Jun 15, 11 00:45, so wrote:
 On Tue, 14 Jun 2011 15:18:09 +0300, KennyTM~<kennytm gmail.com>  wrote:

 loc.x on the caller side, it has no idea about function signature, and
 you don't know if it was 10th or 2nd argument in function.

 // definition
 fun(int x, int y) {
 }

 // call
 fun(x, y) // you need to check the definition if you think something
 wrong with parameters the second time you come here
 fun(y, x) // same
 fun(x:x, y:y) // you know there is nothing wrong with parameters
 fun(y:y, x:x) // same
If you have no idea about the function signature, you have no idea about the parameter names either.
I think you are just resisting here, if you write a call once with named arguments, you documented it in place, the next time you visit this call all you need to see is in the call site.
I'm just bringing up the fact. Why would you need to check the function signature when reading MoveWindow(hWnd, loc.x, loc.y, myWin.width, myWin.height, bRepaint:true); ? It's clear what each argument does.
Because it might be wrong.
 If you feel the need of duplicating the same information, fine, write

      MoveWindow(hWnd:hWnd, X:loc.x, Y:loc.y,
                 nWidth:myWin.width, nHeight:myWin.height, bRepaint:true);

 in your code. But don't make it mandatory, it's a waste of time and space
 when the writer just wants to clarify that 'true' is a bRepaint.
I don't think anyone suggested named arguments should be manditory.
Right, no one suggested named arguments should be mandatory, but so's original suggestion is either "all on" or "all off", which makes this example pretty much mandatory because of a 'bRepaint: true'.
Jun 19 2011
prev sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 14, 11 19:11, so wrote:
[snip]
 Also i don't understand why some think allowing hybrid calls has any
 merit. Just search "named arguments" and first thing you'd see is calls
 with all arguments named, no exception. Allowing unnamed arguments and
 named arguments in one call doesn't make any sense to me, it is almost
 opposite to the reasons named arguments designed for, you don't even
 need to talk about its drawbacks like the complications and confusions.
And if you think it's complicated, you're just thinking in a too complicated way. The rule is simple. Say there is a function pure nothrow S parseString(S=const(char)[], C) (ref C[] input, out ConversionResult result, char quote='"', bool recognizePrefix=true) if (...); and you call it as string s = `"hello"`; ConversionResult detailResult; auto parsed = parseString(s, recognizePrefix:false, result:detailResult); The first step is identify all positional arguments ('s' here), and fill them in in-order. input <- s result <- ... quote <- ... recognizePrefix <- ... next, we match the named args input <- s result <- detailResult quote <- ... recognizePrefix <- false finally we fill in the optional parameters input <- s result <- detailResult quote <- '"' recognizePrefix <- false what's so complicated? Actually, reordering creates more complication than hybrid (e.g. ambiguity in selecting an overload).
Jun 14 2011
parent reply so <so so.so> writes:
On Tue, 14 Jun 2011 16:01:20 +0300, KennyTM~ <kennytm gmail.com> wrote:

 On Jun 14, 11 19:11, so wrote:
 [snip]
 Also i don't understand why some think allowing hybrid calls has any
 merit. Just search "named arguments" and first thing you'd see is calls
 with all arguments named, no exception. Allowing unnamed arguments and
 named arguments in one call doesn't make any sense to me, it is almost
 opposite to the reasons named arguments designed for, you don't even
 need to talk about its drawbacks like the complications and confusions.
And if you think it's complicated, you're just thinking in a too complicated way. The rule is simple. Say there is a function pure nothrow S parseString(S=const(char)[], C) (ref C[] input, out ConversionResult result, char quote='"', bool recognizePrefix=true) if (...); and you call it as string s = `"hello"`; ConversionResult detailResult; auto parsed = parseString(s, recognizePrefix:false, result:detailResult); The first step is identify all positional arguments ('s' here), and fill them in in-order. input <- s result <- ... quote <- ... recognizePrefix <- ... next, we match the named args input <- s result <- detailResult quote <- ... recognizePrefix <- false finally we fill in the optional parameters input <- s result <- detailResult quote <- '"' recognizePrefix <- false what's so complicated? Actually, reordering creates more complication than hybrid (e.g. ambiguity in selecting an overload).
So complicated because it took you this long to match the parameters with the variables, you still need to check function definition because you have parameters that have no match. These are the very things named arguments needs to solve or am i missing something? You could just drop it and go read the function signature everytime, it'd save you time :P
Jun 14 2011
next sibling parent KennyTM~ <kennytm gmail.com> writes:
On Jun 15, 11 01:18, so wrote:
 On Tue, 14 Jun 2011 16:01:20 +0300, KennyTM~ <kennytm gmail.com> wrote:

 On Jun 14, 11 19:11, so wrote:
 [snip]
 Also i don't understand why some think allowing hybrid calls has any
 merit. Just search "named arguments" and first thing you'd see is calls
 with all arguments named, no exception. Allowing unnamed arguments and
 named arguments in one call doesn't make any sense to me, it is almost
 opposite to the reasons named arguments designed for, you don't even
 need to talk about its drawbacks like the complications and confusions.
And if you think it's complicated, you're just thinking in a too complicated way. The rule is simple. Say there is a function pure nothrow S parseString(S=const(char)[], C) (ref C[] input, out ConversionResult result, char quote='"', bool recognizePrefix=true) if (...); and you call it as string s = `"hello"`; ConversionResult detailResult; auto parsed = parseString(s, recognizePrefix:false, result:detailResult); The first step is identify all positional arguments ('s' here), and fill them in in-order. input <- s result <- ... quote <- ... recognizePrefix <- ... next, we match the named args input <- s result <- detailResult quote <- ... recognizePrefix <- false finally we fill in the optional parameters input <- s result <- detailResult quote <- '"' recognizePrefix <- false what's so complicated? Actually, reordering creates more complication than hybrid (e.g. ambiguity in selecting an overload).
So complicated because it took you this long to match the parameters with the variables, you still need to check function definition because you have parameters that have no match. These are the very things named arguments needs to solve or am i missing something? You could just drop it and go read the function signature everytime, it'd save you time :P
What you're missing may be that what I'm outlining is how the /compiler/ matches the parameters. The /compiler/ of course needs to check the function definition every time, otherwise how could it emit errors when you give a wrong name? :)
Jun 14 2011
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"so" <so so.so> wrote in message news:op.vw2s1b19mpw3zg tan-pc...
 On Tue, 14 Jun 2011 16:01:20 +0300, KennyTM~ <kennytm gmail.com> wrote:

 On Jun 14, 11 19:11, so wrote:
 [snip]
 Also i don't understand why some think allowing hybrid calls has any
 merit. Just search "named arguments" and first thing you'd see is calls
 with all arguments named, no exception. Allowing unnamed arguments and
 named arguments in one call doesn't make any sense to me, it is almost
 opposite to the reasons named arguments designed for, you don't even
 need to talk about its drawbacks like the complications and confusions.
And if you think it's complicated, you're just thinking in a too complicated way. The rule is simple. Say there is a function pure nothrow S parseString(S=const(char)[], C) (ref C[] input, out ConversionResult result, char quote='"', bool recognizePrefix=true) if (...); and you call it as string s = `"hello"`; ConversionResult detailResult; auto parsed = parseString(s, recognizePrefix:false, result:detailResult); The first step is identify all positional arguments ('s' here), and fill them in in-order. input <- s result <- ... quote <- ... recognizePrefix <- ... next, we match the named args input <- s result <- detailResult quote <- ... recognizePrefix <- false finally we fill in the optional parameters input <- s result <- detailResult quote <- '"' recognizePrefix <- false what's so complicated? Actually, reordering creates more complication than hybrid (e.g. ambiguity in selecting an overload).
So complicated because it took you this long to match the parameters with the variables, you still need to check function definition because you have parameters that have no match. These are the very things named arguments needs to solve or am i missing something?
Simple rule for combining hybrid and reordering: Look at the caller's args one at a time: as soon as one is reordered, the rest of the args must be named (otherwise you wouldn't know which param it's supposed to be).
Jun 19 2011
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-06-13 21:36:01 -0400, so <so so.so> said:

 IMO named arguments in D at least should do:
 
 - Reordering (since we got default parameters, even better)
 
 - It is enabled only if we have access to the function declaration.
 
 - In a function call we either use named arguments for all the 
 non-default  arguments or call it with the usual syntax. No hybrid 
 stuff, no confusion.
 
    fun(int a, int b, int c=3)
 
    fun(1, 2, 3) // fine - current
    fun(1, 2) // fine - current
 
    fun(a:1, b:3, c:5) // fine
    fun(a:1, b:3) // fine
    fun(b:1, c:3, a:5) // fine
    fun(b:1, a:3) // fine
    fun(b:1) // error
    fun(c:1) // error
    fun(2, b:1) // error
    fun(2, c:1) // error
    fun(2, c:2, 3) // error
There's much more to named arguments as it first appears. Have you thought about: 1. variadic arguments? 2. named template arguments? 3. template variadic arguments (tuples) and how they expand as function parameters? Also, with reordering, if you have two overloaded functions of this form: void fun(int a, string b) {} void fun(string b, int a) {} which one does this calls: fun(a: 1, b: "hello"); ? Does the call become ambiguous when using named arguments? It with this? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 14 2011
next sibling parent KennyTM~ <kennytm gmail.com> writes:
On Jun 14, 11 20:34, Michel Fortin wrote:
 On 2011-06-13 21:36:01 -0400, so <so so.so> said:

 IMO named arguments in D at least should do:

 - Reordering (since we got default parameters, even better)

 - It is enabled only if we have access to the function declaration.

 - In a function call we either use named arguments for all the
 non-default arguments or call it with the usual syntax. No hybrid
 stuff, no confusion.

 fun(int a, int b, int c=3)

 fun(1, 2, 3) // fine - current
 fun(1, 2) // fine - current

 fun(a:1, b:3, c:5) // fine
 fun(a:1, b:3) // fine
 fun(b:1, c:3, a:5) // fine
 fun(b:1, a:3) // fine
 fun(b:1) // error
 fun(c:1) // error
 fun(2, b:1) // error
 fun(2, c:1) // error
 fun(2, c:2, 3) // error
There's much more to named arguments as it first appears. Have you thought about: 1. variadic arguments? 2. named template arguments?
partition!(ss:SwapStrategy.stable, predicate:"a>0") (r:[1,2,3,4]);
 3. template variadic arguments (tuples) and how they expand as function
 parameters?

 Also, with reordering, if you have two overloaded functions of this form:

 void fun(int a, string b) {}
 void fun(string b, int a) {}

 which one does this calls:

 fun(a: 1, b: "hello");

 ? Does the call become ambiguous when using named arguments? It wouldn't

Looks like the last one get the precedence. At least for Mono (see http://ideone.com/REXC0). MSDN says ============================================ Use of named and optional arguments affects overload resolution in the following ways: - A method, indexer, or constructor is a candidate for execution if each of its parameters either is optional or corresponds, by name or by position, to a single argument in the calling statement, and that argument can be converted to the type of the parameter. - If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are explicitly specified. Omitted arguments for optional parameters are ignored. - If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters. ============================================ It doesn't cover your case. Of course this is bad. But this isn't much different from another solved problem... ---------------------------------------- void f(float s){} void f(double s){} void main() { f(3); } ---------------------------------------- x.d(5): Error: function x.f called with argument types: ((int)) matches both: x.f(float s) and: x.f(double s) ---------------------------------------- We could do the same for named arguments. ---------------------------------------- void fun(int a, string b) {} void fun(string b, int a) {} void main() { fun(a: 1, b: "hello"); } ---------------------------------------- x.d(5): Error: function x.fun called with argument names and types: ((int a, string b)) matches both: x.f(int a, string b) and: x.f(string b, int a) ----------------------------------------
Jun 14 2011
prev sibling next sibling parent so <so so.so> writes:
On Tue, 14 Jun 2011 15:34:53 +0300, Michel Fortin  
<michel.fortin michelf.com> wrote:

 There's much more to named arguments as it first appears. Have you  
 thought about:

 1. variadic arguments?
There is already a syntax for this in the language. fun(a:1, var:{3,5,7})
 2. named template arguments?
Do we need this?
 3. template variadic arguments (tuples) and how they expand as function  
 parameters?
This one is a bit tricky but wouldn't 1 also apply here?
 Also, with reordering, if you have two overloaded functions of this form:

 	void fun(int a, string b) {}
 	void fun(string b, int a) {}
Only solution i can think of to this would be changing argument names, otherwise an error.
Jun 14 2011
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Michel Fortin" <michel.fortin michelf.com> wrote in message 
news:it7kq2$26ha$1 digitalmars.com...
 Also, with reordering, if you have two overloaded functions of this form:

 void fun(int a, string b) {}
 void fun(string b, int a) {}

 which one does this calls:

 fun(a: 1, b: "hello");

 ? Does the call become ambiguous when using named arguments?
I'd say "yes". But even if you said "no, the winner is whichever matches the order given, if there is a perfect match", that would be fine too. I'd further argue that either way it's not a significant problem, because it seems that situation would be extremely rare. And the only realistic case I can think of where it would might occur is if the callee wants to allow re-ordered params. But that would already solved by re-orderable names arguments anyway.

 with this?
Jun 14 2011