digitalmars.D - Re: Implicit enum conversions are a stupid PITA
- bearophile <bearophileHUGS lycos.com> Mar 24 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- Mike Parker <aldacron gmail.com> Mar 26 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- Don <nospam nospam.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- KennyTM~ <kennytm gmail.com> Mar 26 2010
- Walter Bright <newshound1 digitalmars.com> Mar 26 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 26 2010
- Walter Bright <newshound1 digitalmars.com> Mar 26 2010
- "Nick Sabalausky" <a a.a> Mar 26 2010
- Justin Johansson <no spam.com> Mar 27 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- Don <nospam nospam.com> Mar 25 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- Rainer Deyke <rainerd eldwood.com> Mar 25 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- Rainer Deyke <rainerd eldwood.com> Mar 25 2010
- Don <nospam nospam.com> Mar 26 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- Don <nospam nospam.com> Mar 25 2010
- Don <nospam nospam.com> Mar 25 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- Walter Bright <newshound1 digitalmars.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- BCS <none anon.com> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- Clemens <eriatarka84 gmail.com> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- BCS <none anon.com> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- bearophile <bearophileHUGS lycos.com> Mar 26 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 25 2010
- "Nick Sabalausky" <a a.a> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- BCS <none anon.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Adam D. Ruppe" <destructionator gmail.com> Mar 25 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Mar 27 2010
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Mar 28 2010
- bearophile <bearophileHUGS lycos.com> Mar 28 2010
- bearophile <bearophileHUGS lycos.com> Mar 28 2010
Andrei:Nick Sabalausky:He was modifying the common expression "Those who don't learn from the past are doomed to repeat it."
But paraphrasing ain't "as they say" because they don't say that. Besides, I thought he's paraphrasing "Any sufficiently complicated C or Fortran program contains a buggy implementation of Common Lisp." But I guess that's just me being cranky - I'm sick.
Nick was right. Sorry for upsetting you, I am sorry. Hugs, bearophile
Mar 24 2010
On 03/24/2010 07:34 PM, bearophile wrote:Andrei:Nick Sabalausky:He was modifying the common expression "Those who don't learn from the past are doomed to repeat it."
But paraphrasing ain't "as they say" because they don't say that. Besides, I thought he's paraphrasing "Any sufficiently complicated C or Fortran program contains a buggy implementation of Common Lisp." But I guess that's just me being cranky - I'm sick.
Nick was right. Sorry for upsetting you, I am sorry.
I missed this. There's no need for anything close to that. We all could get "upset" regarding a post or a notion, not against the person airing it. As far as the matter at hand of that thread is concerned, you mentioned the possibility: alias Flags!(ubyte, "do_nothing", "walk_dog" "cook_breakfast" "deliver_newspaper" "visit_miss_kerbopple" "wash_covers") Todo; I encourage you to code that up and see how it swims. We need to stop inventing syntax for any single thing that seems useful, and start eating our dogfood. If our mechanism for code generation is not good enough, we should improve it, not generate by hand ever new constructs. That reminds me of my late night conversation with Walter of yesterday. I'm sure he wouldn't mind me posting it. Summarized, it's as follows: A: I'm revising the copyedited manuscript for TDPL. This is the last chance to remove octal literals!!! W: I know everybody hates them, but I like them. A: Use octal!"177" W: Ugh. A (esprit d'escalier): If you don't like the universal notation you invented, who will? Since there's always something useful coming up, we need to figure out how our code generation abilities step up to the plate. I will add octal to Phobos, and if it is problematic then probably we need to adjust template syntax. My opinion in the matter is that there may be at most a handful of octal constants total in anyone's codebase, so having a cleverer syntax for them ain't going to make any difference. Andrei
Mar 25 2010
Andrei Alexandrescu:I encourage you to code that up and see how it swims.<
The idea of using that syntax gives me nausea, I can't use that even if I implement that myself.We need to stop inventing syntax for any single thing that seems useful, and start eating our dogfood. If our mechanism for code generation is not good enough, we should improve it, not generate by hand ever new constructs.<
In C# there are ways to define your own properties, so you can possibly use C# to define something like that fields. This is an example of a general tool that can be used to meta-program, keeping the C# compiler unchanged (I am not proposing to add this to D2, but user-defined attributes can be OK in D3. They can be a partial alternative to macros too).and if it is problematic then probably we need to adjust template syntax.<
What kind of changes are you thinking of? Regarding octals (and multi-precision integer literals, and unit system suffixes), it seems C++0x has user-defined literals :-) http://en.wikipedia.org/wiki/C++0x#User-defined_literals (I am not asking to solve the D octal problem with them.) Bye, bearophile
Mar 25 2010
On 03/25/2010 01:33 PM, bearophile wrote:Andrei Alexandrescu:I encourage you to code that up and see how it swims.<
The idea of using that syntax gives me nausea, I can't use that even if I implement that myself.
I believe you're exaggerating.We need to stop inventing syntax for any single thing that seems useful, and start eating our dogfood. If our mechanism for code generation is not good enough, we should improve it, not generate by hand ever new constructs.<
In C# there are ways to define your own properties, so you can possibly use C# to define something like that fields.
Could you please paste C# code doing that here? Then we have a good baseline to compare the D implementation with.This is an example of a general tool that can be used to meta-program, keeping the C# compiler unchanged (I am not proposing to add this to D2, but user-defined attributes can be OK in D3. They can be a partial alternative to macros too).
Why and how do you believe that whatever mechanism we come up with (possibly following a proposal authored by you) will be a net improvement over mixins?and if it is problematic then probably we need to adjust template syntax.<
What kind of changes are you thinking of?
Whatever doesn't give you nausea.Regarding octals (and multi-precision integer literals, and unit system suffixes), it seems C++0x has user-defined literals :-) http://en.wikipedia.org/wiki/C++0x#User-defined_literals (I am not asking to solve the D octal problem with them.)
auto someVariable = "1234"_Octal; Doesn't look like a day and night to me compared to auto someVariable = octal!"1234"; Are you sure you are saying what you mean to say? Andrei
Mar 25 2010
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:hogc1o$2pm8$1 digitalmars.com...On 03/25/2010 01:33 PM, bearophile wrote:Andrei Alexandrescu:I encourage you to code that up and see how it swims.<
The idea of using that syntax gives me nausea, I can't use that even if I implement that myself.
I believe you're exaggerating.
Of course he is. But using mixins to "solve" every need that comes up is a bit like saying "LISP does everything!" even though LISP gets that flexibity by imposing a butt-ugly syntax ("Lost In Stupid Parenthesis", anyone?) on pretty much everything.
Mar 25 2010
On 03/25/2010 02:28 PM, Nick Sabalausky wrote:"Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org> wrote in message news:hogc1o$2pm8$1 digitalmars.com...On 03/25/2010 01:33 PM, bearophile wrote:Andrei Alexandrescu:I encourage you to code that up and see how it swims.<
The idea of using that syntax gives me nausea, I can't use that even if I implement that myself.
I believe you're exaggerating.
Of course he is. But using mixins to "solve" every need that comes up is a bit like saying "LISP does everything!" even though LISP gets that flexibity by imposing a butt-ugly syntax ("Lost In Stupid Parenthesis", anyone?) on pretty much everything.
I'm not saying to use mixins to solve every need that comes up. I'm saying it's worth trying them to solve a few obscure needs. Andrei
Mar 25 2010
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:hogdpf$2te7$1 digitalmars.com...On 03/25/2010 02:28 PM, Nick Sabalausky wrote:"Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org> wrote in message news:hogc1o$2pm8$1 digitalmars.com...On 03/25/2010 01:33 PM, bearophile wrote:Andrei Alexandrescu:I encourage you to code that up and see how it swims.<
The idea of using that syntax gives me nausea, I can't use that even if I implement that myself.
I believe you're exaggerating.
Of course he is. But using mixins to "solve" every need that comes up is a bit like saying "LISP does everything!" even though LISP gets that flexibity by imposing a butt-ugly syntax ("Lost In Stupid Parenthesis", anyone?) on pretty much everything.
I'm not saying to use mixins to solve every need that comes up. I'm saying it's worth trying them to solve a few obscure needs.
I can agree mixins are a perfectly fine interim solution for anything not already in the language, and for truly obscure needs (I use them all the time for both situations myself). But I'd still hardly consider flags and bitfields (to be clear, I'm talking about the abstract concept of a bitfield in general, not necessarily the C-style struct-with-sub-byte-member-alignment bitfield syntax/semantics) to be an "obscure" need in something that's supposed to be a systems language. I guess we just have a fundamental disagreement on that.
Mar 25 2010
On 03/25/2010 02:52 PM, Nick Sabalausky wrote:"Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org> wrote in message news:hogdpf$2te7$1 digitalmars.com...On 03/25/2010 02:28 PM, Nick Sabalausky wrote:"Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org> wrote in message news:hogc1o$2pm8$1 digitalmars.com...On 03/25/2010 01:33 PM, bearophile wrote:Andrei Alexandrescu:I encourage you to code that up and see how it swims.<
The idea of using that syntax gives me nausea, I can't use that even if I implement that myself.
I believe you're exaggerating.
Of course he is. But using mixins to "solve" every need that comes up is a bit like saying "LISP does everything!" even though LISP gets that flexibity by imposing a butt-ugly syntax ("Lost In Stupid Parenthesis", anyone?) on pretty much everything.
I'm not saying to use mixins to solve every need that comes up. I'm saying it's worth trying them to solve a few obscure needs.
I can agree mixins are a perfectly fine interim solution for anything not already in the language, and for truly obscure needs (I use them all the time for both situations myself). But I'd still hardly consider flags and bitfields (to be clear, I'm talking about the abstract concept of a bitfield in general, not necessarily the C-style struct-with-sub-byte-member-alignment bitfield syntax/semantics) to be an "obscure" need in something that's supposed to be a systems language. I guess we just have a fundamental disagreement on that.
In what ways do you find the bitfield interface wanting? Andrei
Mar 25 2010
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:4BABC1F7.6080504 erdani.org...On 03/25/2010 02:52 PM, Nick Sabalausky wrote:I can agree mixins are a perfectly fine interim solution for anything not already in the language, and for truly obscure needs (I use them all the time for both situations myself). But I'd still hardly consider flags and bitfields (to be clear, I'm talking about the abstract concept of a bitfield in general, not necessarily the C-style struct-with-sub-byte-member-alignment bitfield syntax/semantics) to be an "obscure" need in something that's supposed to be a systems language. I guess we just have a fundamental disagreement on that.
In what ways do you find the bitfield interface wanting?
Ignoring frequency-of-usage for the moment, since this is a question of syntax, compare these two syntaxes of creating a struct: mixin(struct!("myStruct" uint, "x", int, "y", uint, "z", bool, "flag")); Versus the current: struct myStruct { uint x; int y; uint z; bool flag; } There's just less syntactical noise, and the syntax is designed around the semantics rather than shoehorning various generic syntaxes to fit the purpose.
Mar 25 2010
On 03/25/2010 09:38 PM, Nick Sabalausky wrote:"Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org> wrote in message news:4BABC1F7.6080504 erdani.org...On 03/25/2010 02:52 PM, Nick Sabalausky wrote:I can agree mixins are a perfectly fine interim solution for anything not already in the language, and for truly obscure needs (I use them all the time for both situations myself). But I'd still hardly consider flags and bitfields (to be clear, I'm talking about the abstract concept of a bitfield in general, not necessarily the C-style struct-with-sub-byte-member-alignment bitfield syntax/semantics) to be an "obscure" need in something that's supposed to be a systems language. I guess we just have a fundamental disagreement on that.
In what ways do you find the bitfield interface wanting?
Ignoring frequency-of-usage for the moment, since this is a question of syntax, compare these two syntaxes of creating a struct: mixin(struct!("myStruct" uint, "x", int, "y", uint, "z", bool, "flag")); Versus the current: struct myStruct { uint x; int y; uint z; bool flag; } There's just less syntactical noise, and the syntax is designed around the semantics rather than shoehorning various generic syntaxes to fit the purpose.
But frequency of usage is essential. This is about bitfields, not struct. The former are arguably much less used than the latter. And then, there are many more uses than definitions. Andrei
Mar 25 2010
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:hoh8eb$1kba$1 digitalmars.com...On 03/25/2010 09:38 PM, Nick Sabalausky wrote:"Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org> wrote in message news:4BABC1F7.6080504 erdani.org...On 03/25/2010 02:52 PM, Nick Sabalausky wrote:I can agree mixins are a perfectly fine interim solution for anything not already in the language, and for truly obscure needs (I use them all the time for both situations myself). But I'd still hardly consider flags and bitfields (to be clear, I'm talking about the abstract concept of a bitfield in general, not necessarily the C-style struct-with-sub-byte-member-alignment bitfield syntax/semantics) to be an "obscure" need in something that's supposed to be a systems language. I guess we just have a fundamental disagreement on that.
In what ways do you find the bitfield interface wanting?
Ignoring frequency-of-usage for the moment, since this is a question of syntax, compare these two syntaxes of creating a struct: mixin(struct!("myStruct" uint, "x", int, "y", uint, "z", bool, "flag")); Versus the current: struct myStruct { uint x; int y; uint z; bool flag; } There's just less syntactical noise, and the syntax is designed around the semantics rather than shoehorning various generic syntaxes to fit the purpose.
But frequency of usage is essential. This is about bitfields, not struct. The former are arguably much less used than the latter. And then, there are many more uses than definitions.
The question was "In what ways do you find the bitfield interface wanting?" I gave you my answer (syntactical noise and the syntax isn't designed around the feature but rather takes other syntaxes and shoehornes them in to fit the purpose.) That is the fault I find with it. Regardless of how common or uncommon it is, I still find that fault with it. Now certainly, if something is an rare enough need, than I can accept a certain amount of fault in the syntax. But that still doesn't change the syntax's faults. They're still there, they just may or may not be forgivable. If structs were a super-duper rare need, then I could live with the "bad" struct syntax above even though it clearly has faults. Maybe I didn't make this clear before (and I apologize for that), but anytime I've talked about bitfields being a common need, I've been talking about the abstract concept of a bitfield in general, not necessarily std.bitmanip.bitfield. I've been in D1/Tango-land for all of my D development lately, so I have to rely on the docs for my knowledge of std.bitmanip.bitfield. And the docs for std.bitmanip.bitfield don't appear to say anything about them other than just simply the syntax for how to create one (I can see that now that I realize the bitarray documentation is unrelated). So, to be clear: I have no idea whether or not I would find std.bitmanip.bitfield suitable enough for a large enough portion of the general bitfield uses out there (ie, to replace typical uses of manual bit-twiddling with ANDs, ORs, and bitmasks) that I would consider it as common a need as bitfields in general are. Bitfields in general: Very common need for systems programming, just ask Walter how many times he's ANDed or ORed a bitmask in his career. Phobos's 'std.bitmanip.bitfield': I have no idea how common the need.
Mar 25 2010
Nick Sabalausky wrote:Bitfields in general: Very common need for systems programming, just ask Walter how many times he's ANDed or ORed a bitmask in his career. Phobos's
To make this conversation a little less confusing, I think the term you should be using here is 'bitmasks'.
Mar 26 2010
bearophile wrote:Regarding octals (and multi-precision integer literals, and unit system suffixes), it seems C++0x has user-defined literals :-) http://en.wikipedia.org/wiki/C++0x#User-defined_literals (I am not asking to solve the D octal problem with them.)
The C++0x syntax for them to me appears to be a workaround for the bug that C++ templates cannot accept string literal arguments. As Andrei mentioned, the D version: Suffix!"string" more than adequately replaces it, and has the advantage of not requiring the user to learn a new syntax. Even better, D's user defined literals can be executed and resolved at compile time, while C++0x's are runtime only creations.
Mar 25 2010
On 03/25/2010 05:12 PM, Walter Bright wrote:bearophile wrote:Regarding octals (and multi-precision integer literals, and unit system suffixes), it seems C++0x has user-defined literals :-) http://en.wikipedia.org/wiki/C++0x#User-defined_literals (I am not asking to solve the D octal problem with them.)
The C++0x syntax for them to me appears to be a workaround for the bug that C++ templates cannot accept string literal arguments. As Andrei mentioned, the D version: Suffix!"string" more than adequately replaces it, and has the advantage of not requiring the user to learn a new syntax. Even better, D's user defined literals can be executed and resolved at compile time, while C++0x's are runtime only creations.
Then you'll be happy to start using octal as soon as I commit it. Andrei
Mar 25 2010
Andrei Alexandrescu wrote:Then you'll be happy to start using octal as soon as I commit it.
Haven't changed my mind about that, nor the reasons!
Mar 25 2010
On 03/25/2010 06:11 PM, Walter Bright wrote:Andrei Alexandrescu wrote:Then you'll be happy to start using octal as soon as I commit it.
Haven't changed my mind about that, nor the reasons!
Haven't seen you posting the results of the grep. As "reason" has the same root as "reasoning", there must be some of it aside from just subjective preference. As such, there must be some way you could respond to this:Symbolic constants are the best way to deal with the filesystem. It's not at all hard to beat. It would be if octal constants would be ubiquitous and ubiquitously useful. To disabuse yourself of that fallacious notion, PLEASE grep ALL your code for [^0-9A-Za-Z."%_:\]0[0-9] and let us know how many instances you find. druntime has 152 octal constants for a total of 53130 lines. That's one for each 350 lines of code, or less than 0.3%. Ironically, most occurrences are used in defining symbolic constants that are good style for handling permission bits. For Phobos I counted 11 true positives in 93,963 lines, which means one per 8542 lines of code or 0.01% of total.
Andrei
Mar 25 2010
Andrei Alexandrescu wrote:On 03/25/2010 06:11 PM, Walter Bright wrote:Andrei Alexandrescu wrote:Then you'll be happy to start using octal as soon as I commit it.
Haven't changed my mind about that, nor the reasons!
Haven't seen you posting the results of the grep. As "reason" has the same root as "reasoning", there must be some of it aside from just subjective preference. As such, there must be some way you could respond to this:druntime has 152 octal constants for a total of 53130 lines.
That's a lot more than I expected. And yes, there are reasons to have octal constants, and reasons not to. D will survive with or without them. In the end, it's a subjective call, dare I say a matter of 'taste'? I admit it, I just like octal constants. I like the way they look. I don't feel an urge to kill it with fire. I'd be sad to see them go. I like disco music, too, despite it being definitely out of style. One thing is clear, though. 0177 is never going to be a decimal number in D, because it will silently and disastrously break code translated from C. The only choice is to support 0177 as octal or make it a syntax error. I'd rather support them.
Mar 25 2010
Walter Bright:I admit it, I just like octal constants. I like the way they look. I don't feel an urge to kill it with fire. I'd be sad to see them go. I like disco music, too, despite it being definitely out of style.
OK :-) There are other problems to fix :-) Bye, bearophile
Mar 25 2010
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:hogsv9$11u7$1 digitalmars.com...One thing is clear, though. 0177 is never going to be a decimal number in D, because it will silently and disastrously break code translated from C.
I'm certainly fine with that, since not breaking ported C code is one of D's philosophies.The only choice is to support 0177 as octal or make it a syntax error. I'd rather support them.
Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru, and very few people these days are (I used C for years without being aware of that octal syntax - it's only by dumb luck I didn't try to use a leading zero). Granted, it may not be common for someone to try to use leading zeroes, but it's a landmine I'd rather not have, even if it is down a less-travelled sidestreet, expecially considering it's all for such a trivial benefit (which amounts to what, one person who just thinks it looks pretty?)
Mar 25 2010
Nick Sabalausky wrote:"Walter Bright" <newshound1 digitalmars.com> wrote in message news:hogsv9$11u7$1 digitalmars.com...One thing is clear, though. 0177 is never going to be a decimal number in D, because it will silently and disastrously break code translated from C.
I'm certainly fine with that, since not breaking ported C code is one of D's philosophies.The only choice is to support 0177 as octal or make it a syntax error. I'd rather support them.
Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru, and very few people these days are (I used C for years without being aware of that octal syntax - it's only by dumb luck I didn't try to use a leading zero). Granted, it may not be common for someone to try to use leading zeroes, but it's a landmine I'd rather not have, even if it is down a less-travelled sidestreet, expecially considering it's all for such a trivial benefit (which amounts to what, one person who just thinks it looks pretty?)
Mar 25 2010
On 03/25/2010 08:10 PM, Nick Sabalausky wrote:"Walter Bright"<newshound1 digitalmars.com> wrote in message news:hogsv9$11u7$1 digitalmars.com...The only choice is to support 0177 as octal or make it a syntax error. I'd rather support them.
Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru, and very few people these days are (I used C for years without being aware of that octal syntax - it's only by dumb luck I didn't try to use a leading zero). Granted, it may not be common for someone to try to use leading zeroes, but it's a landmine I'd rather not have, even if it is down a less-travelled sidestreet, expecially considering it's all for such a trivial benefit (which amounts to what, one person who just thinks it looks pretty?)
That kind of destroys Walter's argument. Andrei
Mar 25 2010
Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru,
You don't need to be a guru to know that. I was once a C newbie, and never had any trouble with it. It isn't just C, either, the same syntax is used in C++, Objective-C, Groovy, M4, Clojure, Go, Java, Scala, Javascript, PHP, Ruby, bash, Python (2.6 and earlier) and Perl. (It is not used in C#, Python 3.0, Fortran, or VisualBasic.)
Mar 25 2010
On Mar 26, 10 11:32, Walter Bright wrote:Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru,
You don't need to be a guru to know that. I was once a C newbie, and never had any trouble with it. It isn't just C, either, the same syntax is used in C++, Objective-C, Groovy, M4, Clojure, Go, Java, Scala, Javascript, PHP, Ruby, bash, Python (2.6 and earlier) and Perl. (It is not used in C#, Python 3.0, Fortran, or VisualBasic.)
And removed in ECMAScript 5 (next standard of Javascript).
Mar 26 2010
KennyTM~ wrote:On Mar 26, 10 11:32, Walter Bright wrote:Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru,
You don't need to be a guru to know that. I was once a C newbie, and never had any trouble with it. It isn't just C, either, the same syntax is used in C++, Objective-C, Groovy, M4, Clojure, Go, Java, Scala, Javascript, PHP, Ruby, bash, Python (2.6 and earlier) and Perl. (It is not used in C#, Python 3.0, Fortran, or VisualBasic.)
And removed in ECMAScript 5 (next standard of Javascript).
I didn't know that. But still, it's hard to be a programmer and not use a language that has such literals.
Mar 26 2010
On 03/26/2010 06:26 PM, Walter Bright wrote:KennyTM~ wrote:On Mar 26, 10 11:32, Walter Bright wrote:Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru,
You don't need to be a guru to know that. I was once a C newbie, and never had any trouble with it. It isn't just C, either, the same syntax is used in C++, Objective-C, Groovy, M4, Clojure, Go, Java, Scala, Javascript, PHP, Ruby, bash, Python (2.6 and earlier) and Perl. (It is not used in C#, Python 3.0, Fortran, or VisualBasic.)
And removed in ECMAScript 5 (next standard of Javascript).
I didn't know that. But still, it's hard to be a programmer and not use a language that has such literals.
http://en.wikipedia.org/wiki/Argumentum_ad_populum Andrei
Mar 26 2010
Andrei Alexandrescu wrote:On 03/26/2010 06:26 PM, Walter Bright wrote:KennyTM~ wrote:On Mar 26, 10 11:32, Walter Bright wrote:Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru,
You don't need to be a guru to know that. I was once a C newbie, and never had any trouble with it. It isn't just C, either, the same syntax is used in C++, Objective-C, Groovy, M4, Clojure, Go, Java, Scala, Javascript, PHP, Ruby, bash, Python (2.6 and earlier) and Perl. (It is not used in C#, Python 3.0, Fortran, or VisualBasic.)
And removed in ECMAScript 5 (next standard of Javascript).
I didn't know that. But still, it's hard to be a programmer and not use a language that has such literals.
http://en.wikipedia.org/wiki/Argumentum_ad_populum
I was responding to Nick's argument: ------------------------------ Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru, and very few people these days are (I used C for years without being aware of that octal syntax - it's only by dumb luck I didn't try to use a leading zero). ------------------------------- where the statement of very few people being exposed to such literals is the issue. I should have left in the fuller quote.
Mar 26 2010
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:hojjk3$3ch$1 digitalmars.com...Andrei Alexandrescu wrote:On 03/26/2010 06:26 PM, Walter Bright wrote:KennyTM~ wrote:On Mar 26, 10 11:32, Walter Bright wrote:Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru,
You don't need to be a guru to know that. I was once a C newbie, and never had any trouble with it. It isn't just C, either, the same syntax is used in C++, Objective-C, Groovy, M4, Clojure, Go, Java, Scala, Javascript, PHP, Ruby, bash, Python (2.6 and earlier) and Perl. (It is not used in C#, Python 3.0, Fortran, or VisualBasic.)
And removed in ECMAScript 5 (next standard of Javascript).
I didn't know that. But still, it's hard to be a programmer and not use a language that has such literals.
http://en.wikipedia.org/wiki/Argumentum_ad_populum
I was responding to Nick's argument: ------------------------------ Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru, and very few people these days are (I used C for years without being aware of that octal syntax - it's only by dumb luck I didn't try to use a leading zero). ------------------------------- where the statement of very few people being exposed to such literals is the issue. I should have left in the fuller quote.
Using a language that has 0xxx-style octal literals and actually being aware of it are two different things. And I'd say that my assumption it was only C speaks to its obscurity.
Mar 26 2010
Andrei Alexandrescu Wrote:On 03/26/2010 06:26 PM, Walter Bright wrote:KennyTM~ wrote:On Mar 26, 10 11:32, Walter Bright wrote:Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero and *isn't* a C guru,
You don't need to be a guru to know that. I was once a C newbie, and never had any trouble with it. It isn't just C, either, the same syntax is used in C++, Objective-C, Groovy, M4, Clojure, Go, Java, Scala, Javascript, PHP, Ruby, bash, Python (2.6 and earlier) and Perl. (It is not used in C#, Python 3.0, Fortran, or VisualBasic.)
And removed in ECMAScript 5 (next standard of Javascript).
I didn't know that. But still, it's hard to be a programmer and not use a language that has such literals.
http://en.wikipedia.org/wiki/Argumentum_ad_populum Andrei
I'll see you and raise you one. http://en.wikipedia.org/wiki/Meme Justin
Mar 27 2010
Nick Sabalausky wrote:(I used C for years without being aware of that octal syntax - it's only by dumb luck I didn't try to use a leading zero).
It is on the 3rd page of chapter 2 in K&R (and chapter 2 is the first chapter of the specification). A mitigating factor is who uses leading 0's for integer literals? Another is if you started using leading 0's, very quickly you'd try using the digits 8 or 9, and would get an error. I don't think you'd get very far using leading 0's without discovering the issue.
Mar 25 2010
Walter Bright wrote:Nick Sabalausky wrote:(I used C for years without being aware of that octal syntax - it's only by dumb luck I didn't try to use a leading zero).
It is on the 3rd page of chapter 2 in K&R (and chapter 2 is the first chapter of the specification). A mitigating factor is who uses leading 0's for integer literals? Another is if you started using leading 0's, very quickly you'd try using the digits 8 or 9, and would get an error. I don't think you'd get very far using leading 0's without discovering the issue.
001, 010, 100 and then wondered why my code was wrong. It's the only time in my life I've ever used an octal literal.
Mar 25 2010
Don wrote:I've done it with powers of 10: 001, 010, 100 and then wondered why my code was wrong. It's the only time in my life I've ever used an octal literal.
I see that and it screams BINARY to me, not decimal! I guess I'm not sure why it never was a problem for me. It's just "oh, that's octal, ok" and went on to more interesting things.
Mar 25 2010
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:hohhnn$252d$1 digitalmars.com...Don wrote:I've done it with powers of 10: 001, 010, 100 and then wondered why my code was wrong. It's the only time in my life I've ever used an octal literal.
I see that and it screams BINARY to me, not decimal!
0b001, 0b010, 0b100 To me, *that* screams binary. ;)
Mar 25 2010
On 3/25/2010 17:52, Walter Bright wrote:One thing is clear, though. 0177 is never going to be a decimal number in D, because it will silently and disastrously break code translated from C. The only choice is to support 0177 as octal or make it a syntax error. I'd rather support them.
I don't mind octal literals, but '0177' is a horrible syntax. *Every* *single* *time* that I used that syntax in C or C++, I really meant to use a decimal. -- Rainer Deyke - rainerd eldwood.com
Mar 25 2010
Rainer Deyke wrote:I don't mind octal literals, but '0177' is a horrible syntax. *Every* *single* *time* that I used that syntax in C or C++, I really meant to use a decimal.
I'm curious what tempted you to use a leading 0 in the first place.
Mar 25 2010
On 3/25/2010 23:40, Walter Bright wrote:Rainer Deyke wrote:I don't mind octal literals, but '0177' is a horrible syntax. *Every* *single* *time* that I used that syntax in C or C++, I really meant to use a decimal.
I'm curious what tempted you to use a leading 0 in the first place.
Padding to get an array literal to align properly. Something like this: int a[3][3] = { {001, 002, 003}, {010, 020, 030}, {100, 200, 300}, }; I could have used (and should have used, and eventually did use) spaces instead, but I don't think they look as nice in this instance. -- Rainer Deyke - rainerd eldwood.com
Mar 25 2010
Rainer Deyke wrote:On 3/25/2010 23:40, Walter Bright wrote:Rainer Deyke wrote:I don't mind octal literals, but '0177' is a horrible syntax. *Every* *single* *time* that I used that syntax in C or C++, I really meant to use a decimal.
Padding to get an array literal to align properly. Something like this: int a[3][3] = { {001, 002, 003}, {010, 020, 030}, {100, 200, 300}, }; I could have used (and should have used, and eventually did use) spaces instead, but I don't think they look as nice in this instance.
fonts.
Mar 26 2010
Andrei Alexandrescu wrote:A: Use octal!"177" W: Ugh. A (esprit d'escalier): If you don't like the universal notation you invented, who will?
Good point. As I recall, we expended an enormous amount of effort working on template syntax, and I certainly feel that octal!"177" is far better than, say: octal<"177">.value but when I compare it to 0177 that's just hard to beat. A customized syntax is always going to be better than a generic one. The octal syntax is used in several widely popular languages, and is convenient and looks attractive. It's used a lot in dealing with the unix file system.
Mar 25 2010
Adam D. Ruppe:What about O!177?
See the answer by Andrei: http://d.puremagic.com/issues/show_bug.cgi?id=2656 The answer is essentially: how can you represent very large 64 bit octal values with that syntax? Bye, bearophile
Mar 25 2010
On 03/25/2010 02:33 PM, Adam D. Ruppe wrote:On Thu, Mar 25, 2010 at 03:05:28PM -0400, bearophile wrote:The answer is essentially: how can you represent very large 64 bit octal values with that syntax?
Have the user switch over to the string notation in those rare cases.
I think that's a brilliant idea. Andrei
Mar 25 2010
Adam D. Ruppe:Have the user switch over to the string notation in those rare cases.
OK. But are you sure you want a template named just "O" in the std lib? Oct or Octal can cause less collisions.Another possibility might be having integer literals actually be infinite in size in the compiler, and use a template alias.. or something, to take them unmolested into CTFE for manipulation. This would also be useful for bignum structs. You can just reuse the plain old integer literal when initalizing them. Then, if the literal is too big to fit in the type requested, the compiler throws an error only at the last minute it can possibly check.
If this can work and be safe, then it's a cute idea. Bye, bearophile
Mar 25 2010
On 03/25/2010 03:20 PM, Adam D. Ruppe wrote:On Thu, Mar 25, 2010 at 04:08:26PM -0400, bearophile wrote:OK. But are you sure you want a template named just "O" in the std lib? Oct or Octal can cause less collisions.
The name doesn't matter much to me. I said O!777 just because looks as similar on the screen to 0777 as we can without changing the rules of the language. I'm ok with octal too; the name isn't a big deal.If this can work and be safe, then it's a cute idea.
Aye. If only implementing it were free :P
Contest: define "octal" as per the blueprint above and paste it here. Andrei
Mar 25 2010
On 03/25/2010 03:57 PM, Adam D. Ruppe wrote:On Thu, Mar 25, 2010 at 03:37:52PM -0500, Andrei Alexandrescu wrote:Contest: define "octal" as per the blueprint above and paste it here.
Trivial. I'll start with the code you posted on the bugzilla.
Now that's what I'd call fast. bearophile made a good point though: there are many template instantiations, so at best we should use CTFE. What changes would be needed? Thanks, Andrei
Mar 25 2010
Adam D. Ruppe:Trivial. I'll start with the code you posted on the bugzilla.
It's better to minimize the number of templates created by the code. I have used CTFE here (not much tested): import std.metastrings: toStringNow; ulong octal_helper(string value) { assert(value.length > 0); ulong result; foreach (digit; value) { assert(digit >= '0' && digit < '8', "Incorrect character in octal constant: '" ~ value[0] ~ "'"); result = result * 8 + (digit - '0'); } return result; } template octal(string s) { enum uint octal = octal_helper(s); } template octal(ulong s) { enum uint octal = octal_helper(toStringNow!(s)); } void main() { //unittest { static assert(octal!"45" == 37); static assert(octal!"0" == 0); static assert(octal!"7" == 7); static assert(octal!"10" == 8); static assert(octal!45 == 37); static assert(octal!0 == 0); static assert(octal!7 == 7); static assert(octal!10 == 8); //static assert(octal!(-2) == 8); } It needs many more unittests, to tests all the bounds, corner cases, etc. They also have to test that the code actually asserts when the inputs are wrong in various ways. This is how I test my D code. Bye, bearophile
Mar 25 2010
Every time I write a small number of lines of code in D2, like here, I find what I think is a bug: http://d.puremagic.com/issues/show_bug.cgi?id=4005 Bye, bearophile
Mar 25 2010
On 03/25/2010 04:32 PM, Adam D. Ruppe wrote:On Thu, Mar 25, 2010 at 05:12:07PM -0400, bearophile wrote:It needs many more unittests, to tests all the bounds, corner cases, etc. They also have to test that the code actually asserts when the inputs are wrong in various ways. This is how I test my D code.
Yeah, you're right on a few counts. The template there actually fails on any string with length> 2. I rewrote it just now to do CTFE too to get around it. I also let underscores into the string in my new version, and switched the uints to ulongs so we can get bigger literals before needing strings. It seems to work well. Here's my new code:
It does work well, but there's one more issue: the type of octal!x is always ulong. To make the code industrial strength, you should observe the usual D rules: * if it fits in an int it has type int, otherwise it has type long * the suffixes U, u, and L should be observed If you make these changes I'll commit your code in std.conv with credit. Andrei
Mar 25 2010
On 03/26/2010 12:47 AM, Adam D. Ruppe wrote:On Thu, Mar 25, 2010 at 04:52:29PM -0500, Andrei Alexandrescu wrote:It does work well, but there's one more issue: the type of octal!x is always ulong. To make the code industrial strength, you should observe the usual D rules:
I think I made it work.
http://www.dsource.org/projects/phobos/browser/trunk/phobos/std/conv.d?rev=1469 Andrei
Mar 26 2010
Adam D. Ruppe:It seems to work well.
It will need a more testing, and "negative testing" too: for example good tests must assert that this generates an error at compile time: octal!"_" Bye, bearophile
Mar 25 2010
bearophile wrote:Adam D. Ruppe:Trivial. I'll start with the code you posted on the bugzilla.
It's better to minimize the number of templates created by the code. I have used CTFE here (not much tested): import std.metastrings: toStringNow;
Do NOT use toStringNow. std.metastrings is mostly obsolete -- it predates CTFE. CTFE functions are much easier to test than templates, you can use run-time tests and check code coverage, for example. And the code is much easier to read.
Mar 25 2010
Adam D. Ruppe wrote:On Fri, Mar 26, 2010 at 02:38:53AM +0100, Don wrote:Do NOT use toStringNow. std.metastrings is mostly obsolete -- it predates CTFE.
All I wanted there was a quick conversion. At first, I wrote octal!(to!string(my_integer)); but it didn't compile... In any case, redoing it is simple enough, but if you don't want people using the solution in the library, it should at least be marked in the docs.
templates. But since he was using toStringNow, the code created a huge number of templates.
Mar 25 2010
Adam D. Ruppe wrote:The argument most often brought up for keeping octal *at all* is unix filesystem permissions. They are only ever as big as four digits (AFAIK).
There is one other reason: converting C code to D code. This should follow the principle of "if it doesn't give a compiler error, it should produce the same result". Translating: 0177 in C to: 0177 in D will silently produce a very different result (should such a number be decimal).
Mar 25 2010
Walter Bright:Translating: 0177 in C to: 0177 in D will silently produce a very different result
Nope, here I have suggested to turn leading zeros in syntax errors: http://d.puremagic.com/issues/show_bug.cgi?id=3837 Bye, bearophile
Mar 25 2010
bearophile wrote:Nope, here I have suggested to turn leading zeros in syntax errors: http://d.puremagic.com/issues/show_bug.cgi?id=3837
Right, but that doesn't help those who wish to use leading 0s.
Mar 25 2010
On 03/25/2010 06:12 PM, Walter Bright wrote:bearophile wrote:Nope, here I have suggested to turn leading zeros in syntax errors: http://d.puremagic.com/issues/show_bug.cgi?id=3837
Right, but that doesn't help those who wish to use leading 0s.
Why do they wish it, how often do they wish it, and why should we support the wrong style with an abundance of magic numbers? Andrei
Mar 25 2010
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:hogqkn$uma$2 digitalmars.com...bearophile wrote:Nope, here I have suggested to turn leading zeros in syntax errors: http://d.puremagic.com/issues/show_bug.cgi?id=3837
Right, but that doesn't help those who wish to use leading 0s.
I don't think anyone cares about being able to use leading zeros for a decimal literal. The primary complaint is that if a leading zero does get used (either by accident, or by someone who doesn't know that D breaks basic grade-school number convention), it results in a silent bug.
Mar 25 2010
Hello Walter,bearophile wrote:Nope, here I have suggested to turn leading zeros in syntax errors: http://d.puremagic.com/issues/show_bug.cgi?id=3837
Who wants to do that? -- ... <IXOYE><
Mar 25 2010
"BCS" <none anon.com> wrote in message news:a6268ff11b928cc9a720a2994a6 news.digitalmars.com...Hello Walter,bearophile wrote:Nope, here I have suggested to turn leading zeros in syntax errors: http://d.puremagic.com/issues/show_bug.cgi?id=3837
Who wants to do that?
At this point, I see that other people have mentioned in other branches of the thread that they would like to use loeading zeros as an alternate to spaces for visual alignment. But, I think think is one case where I can put words in people's mouths without risk of being wrong: I'm pretty sure even they would much rather leading zeroes be disallowed than have it silently change the literal's value.
Mar 25 2010
Walter Bright Wrote:Adam D. Ruppe wrote:The argument most often brought up for keeping octal *at all* is unix filesystem permissions. They are only ever as big as four digits (AFAIK).
There is one other reason: converting C code to D code. This should follow the principle of "if it doesn't give a compiler error, it should produce the same result". Translating: 0177 in C to: 0177 in D will silently produce a very different result (should such a number be decimal).
How about a command line argument to DMD which can be used to aid in porting legacy C code? It would cause the compiler to generate a warning (or error if you wish) for every occurrence of an ambiguous construct like this. Once all such cases have been converted to valid D code and the code compiles without warnings, the command line argument can be dropped. This allows D to escape from the C compatibility trap which has encumbered C++ so much while still giving safety against subtle bugs while porting old code.
Mar 25 2010
Clemens:a command line argument to DMD which can be used to aid in porting legacy C code?<
That's a nice idea, thank you for inventing it. Time ago I was vaguely thinking about something similar, but not quite. DMD1 has: -d allow deprecated features So D2 can grow a command line switch as (or another name): -ctest to be used in porting C code to D2. It probably just activates warnings that can help avoid many C porting bugs. For example it can warn the programmer that global floats are not initialized to zero, or fixed-sized arrays are passed by value, etc. In theory this new command line switch this can even allow D to improve the syntax of the switch, avoiding the fall-through :-) Bye, bearophile
Mar 25 2010
"Clemens" <eriatarka84 gmail.com> wrote in message news:hogss7$11nb$1 digitalmars.com...How about a command line argument to DMD which can be used to aid in porting legacy C code? It would cause the compiler to generate a warning (or error if you wish) for every occurrence of an ambiguous construct like this. Once all such cases have been converted to valid D code and the code compiles without warnings, the command line argument can be dropped. This allows D to escape from the C compatibility trap which has encumbered C++ so much while still giving safety against subtle bugs while porting old code.
I fear it's probably too late for that for D, but I do like it very much. If I ever make a C-style langauge myself, I'll definitely consider something like that.
Mar 25 2010
Hello Nick,I fear it's probably too late for that for D, but I do like it very much.
Why? The proposal is merely a compiler implementation detail rather than a language feature. It could even be done as part of a lint like tool. -- ... <IXOYE><
Mar 25 2010
"BCS" <none anon.com> wrote in message news:a6268ff11bc38cc9a74b199788a news.digitalmars.com...Hello Nick,I fear it's probably too late for that for D, but I do like it very much.
Why? The proposal is merely a compiler implementation detail rather than a language feature. It could even be done as part of a lint like tool.
A *lot* of D's design has already been based around the idea of C code doing either the same thing or erroring when compiled for D. Plus, Walter loves that strategy, and hates extra warnings. I'd love for it to happen, but I guess I'm just saying "I ain't holdin my breath!"
Mar 25 2010
Nick Sabalausky:A *lot* of D's design has already been based around the idea of C code doing either the same thing or erroring when compiled for D. Plus, Walter loves that strategy, and hates extra warnings. I'd love for it to happen, but I guess I'm just saying "I ain't holdin my breath!" <
This is not the same situation. As far as I know Walter doesn't like warnings for D code. But this compiler switch is not designed for D code, it's strictly designed for C code just ported to D, to warn in the porting of some possible traps/bugs, like: - global floats not initialized to 0.0 (this has caused a bug in code of mine translated from C); - fixed sized-arrays passed by value; - etc. Walter doesn't like warnings for example because there are shops that have a zero warning policy, they consider C compiler warnings as errors (and this is silly, I agree with Walter). But those warnings have no purpose for normal D code, they are not designed for D code, they are designed for C code that just looks like D. Bye, bearophile
Mar 26 2010
On Fri, Mar 26, 2010 at 02:53:58AM +0100, Don wrote:That reply was to bearophile, who said he was minimizing the number of templates. But since he was using toStringNow, the code created a huge number of templates.
Oh sorry, I generalize too hastily! -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On 03/25/2010 01:45 PM, Walter Bright wrote:Andrei Alexandrescu wrote:A: Use octal!"177" W: Ugh. A (esprit d'escalier): If you don't like the universal notation you invented, who will?
Good point. As I recall, we expended an enormous amount of effort working on template syntax, and I certainly feel that octal!"177" is far better than, say: octal<"177">.value but when I compare it to 0177 that's just hard to beat. A customized syntax is always going to be better than a generic one. The octal syntax is used in several widely popular languages, and is convenient and looks attractive. It's used a lot in dealing with the unix file system.
Symbolic constants are the best way to deal with the filesystem. It's not at all hard to beat. It would be if octal constants would be ubiquitous and ubiquitously useful. To disabuse yourself of that fallacious notion, PLEASE grep ALL your code for [^0-9A-Za-Z."%_:\]0[0-9] and let us know how many instances you find. druntime has 152 octal constants for a total of 53130 lines. That's one for each 350 lines of code, or less than 0.3%. Ironically, most occurrences are used in defining symbolic constants that are good style for handling permission bits. For Phobos I counted 11 true positives in 93,963 lines, which means one per 8542 lines of code or 0.01% of total. Andrei
Mar 25 2010
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:hogavk$2ll7$1 digitalmars.com...Good point. As I recall, we expended an enormous amount of effort working on template syntax, and I certainly feel that octal!"177" is far better than, say: octal<"177">.value but when I compare it to 0177 that's just hard to beat. A customized syntax is always going to be better than a generic one.
I agree that "A customized syntax is always going to be better than a generic one", all else being equal (hence my distaste for the enum-related mixin stuff in other branches of this thread). But I still very much fail to see how anyone can consider being able to change a number's value simply by adding (or removing) a leading zero to be anywhere remotely near "hard to beat". Though I suppose we've already tread this ground 64 times before (oops, I mean "a hundred").
Mar 25 2010
On Thu, Mar 25, 2010 at 05:12:07PM -0400, bearophile wrote:It needs many more unittests, to tests all the bounds, corner cases, etc. They also have to test that the code actually asserts when the inputs are wrong in various ways. This is how I test my D code.
Yeah, you're right on a few counts. The template there actually fails on any string with length > 2. I rewrote it just now to do CTFE too to get around it. I also let underscores into the string in my new version, and switched the uints to ulongs so we can get bigger literals before needing strings. It seems to work well. Here's my new code: === ulong octal(string num)() { static assert(num.length > 0); ulong pow = 1; ulong value = 0; for(int pos = num.length - 1; pos >= 0; pos--) { char s = num[pos]; if(s == '_') continue; assert(s >= '0' && s < '8', "Incorrect character in octal constant: `" ~ s ~ "'"); value += pow * (s - '0'); pow *= 8; } return value; } import std.metastrings; template octal(ulong s) { enum uint octal = octal!(toStringNow!(s)); } unittest { static assert(octal!"45" == 37); static assert(octal!"0" == 0); static assert(octal!"7" == 7); static assert(octal!"10" == 8); static assert(octal!"666" == 438); static assert(octal!45 == 37); static assert(octal!0 == 0); static assert(octal!7 == 7); static assert(octal!10 == 8); static assert(octal!666 == 438); static assert(octal!"66_6" == 438); static assert(octal!2520046213 == 356535435); static assert(octal!"2520046213" == 356535435); } import std.stdio; void main() { int a = octal!254; // just checking implicit conversion of ulong to int; it would suck if this failed writefln("%d", a); } ==== -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Fri, Mar 26, 2010 at 02:38:53AM +0100, Don wrote:Do NOT use toStringNow. std.metastrings is mostly obsolete -- it predates CTFE.
All I wanted there was a quick conversion. At first, I wrote octal!(to!string(my_integer)); but it didn't compile... In any case, redoing it is simple enough, but if you don't want people using the solution in the library, it should at least be marked in the docs. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 12:18:57PM -0500, Andrei Alexandrescu wrote:I missed this. There's no need for anything close to that. We all could get "upset" regarding a post or a notion, not against the person airing it. As far as the matter at hand of that thread is concerned, you mentioned the possibility: alias Flags!(ubyte, "do_nothing", "walk_dog" "cook_breakfast" "deliver_newspaper" "visit_miss_kerbopple" "wash_covers") Todo; I encourage you to code that up and see how it swims.
It just occurred to me that such a thing could work on the use-side exactly like the built in enum too, thanks to opDispatch. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On 03/25/2010 01:57 PM, Adam D. Ruppe wrote:On Thu, Mar 25, 2010 at 12:18:57PM -0500, Andrei Alexandrescu wrote:I missed this. There's no need for anything close to that. We all could get "upset" regarding a post or a notion, not against the person airing it. As far as the matter at hand of that thread is concerned, you mentioned the possibility: alias Flags!(ubyte, "do_nothing", "walk_dog" "cook_breakfast" "deliver_newspaper" "visit_miss_kerbopple" "wash_covers") Todo; I encourage you to code that up and see how it swims.
It just occurred to me that such a thing could work on the use-side exactly like the built in enum too, thanks to opDispatch.
Exactly. Andrei
Mar 25 2010
"Adam D. Ruppe" <destructionator gmail.com> wrote in message news:mailman.16.1269543119.2988.digitalmars-d puremagic.com...On Thu, Mar 25, 2010 at 12:18:57PM -0500, Andrei Alexandrescu wrote:I missed this. There's no need for anything close to that. We all could get "upset" regarding a post or a notion, not against the person airing it. As far as the matter at hand of that thread is concerned, you mentioned the possibility: alias Flags!(ubyte, "do_nothing", "walk_dog" "cook_breakfast" "deliver_newspaper" "visit_miss_kerbopple" "wash_covers") Todo; I encourage you to code that up and see how it swims.
It just occurred to me that such a thing could work on the use-side exactly like the built in enum too, thanks to opDispatch.
I haven't used opDispatch, and don't remember much from the discussions of it, so pardon a possibly dumb question: Would that prevent you from getting a (meaningful) compile-time error if you mis-typed one of the flags?
Mar 25 2010
On Thu, Mar 25, 2010 at 11:45:11AM -0700, Walter Bright wrote:Good point. As I recall, we expended an enormous amount of effort working on template syntax, and I certainly feel that octal!"177" is far better than, say: octal<"177">.value but when I compare it to 0177
What about O!177? The O template would take the integer passed as its argument, convert it to a string, then convert that back into number assuming it is octal. (Or some implementation of that idea.) It just saves the quotes there, but ends up looking very close to the custom syntax. And it frees up leading zeroes for use in base ten where they belong to make pretty tables. Though you might want to ban this for C compatibility anyway. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
Hello Adam,On Thu, Mar 25, 2010 at 11:45:11AM -0700, Walter Bright wrote:Good point. As I recall, we expended an enormous amount of effort working on template syntax, and I certainly feel that octal!"177" is far better than, say: octal<"177">.value but when I compare it to 0177
template O(ulong i) { static if(i <= 7) enum O = i; else { static assert(i%10 < 8); enum O = O!(i/10)*8 + i%10; } } OTOH you cant do: O!17777777_7777777_7777777; as that overflows as a base 10 number but not as a octal number. -- ... <IXOYE><
Mar 25 2010
On Thu, Mar 25, 2010 at 04:52:29PM -0500, Andrei Alexandrescu wrote:It does work well, but there's one more issue: the type of octal!x is always ulong. To make the code industrial strength, you should observe the usual D rules:
I think I made it work. Also used template constraints to pretty up the error messages a little on bad strings. The line number is still that of the template instead of the instantiation, but maybe it is just because my dmd is a few months old. I seem to recall seeing this improved in the compiler itself, so I'm not worrying about it here. The code is way at the bottom of this message. I'm going to show off a bit first :) Error messages: int w = octal!845; octal.d(106): Error: static assert "845 is not a valid octal literal" int w = octal!"spam"; octal.d(106): Error: static assert "spam is not a valid octal literal" The type magic works pretty well too: int w = octal!"017777777777"; // compiles int w = octal!"020000000000"; // but this doesn't... (this is int.max+1 btw) octal.d(147): Error: cannot implicitly convert expression (octal()) of type long to int int w = octal!"1L"; octal.d(147): Error: cannot implicitly convert expression (octal()) of type long to int int w = octal!"1uL"; octal.d(147): Error: cannot implicitly convert expression (octal()) of type ulong to int This also works with integer literals instead of strings: auto w = octal!1L; pragma(msg, typeof(w)); // prints "long" auto w = octal!1; pragma(msg, typeof(w)); // prints "int" auto w = octal!1u; pragma(msg, typeof(w)); // prints "uint" The only bug I'm seeing is if the integer literal is type long, but once converted to octal it will fit in an int, the template returns a long. Passing a string does the right thing and returns int, but the literal doesn't. I don't see a way to fix this without breaking the octal!1777[...]7L case. (To make the suffixes on literals work, I did typeof an alias for the helper template instead of analyzing the string like I did for the main template. I couldn't think of any other way to make it work; I even tried parsing stringof the alias, but alas. Anyway, aside from that, it works perfectly in my battery of tests. Handles suffixes, embedded underscores, bad strings, types. Pretty cool. Here's the code, with some comments added too: =============================== /* Take a look at int.max and int.max+1 in octal and the logic for this function follows directly. */ template octalFitsInInt(string octalNum) { // note it is important to strip the literal of all non-numbers. kill the suffix and underscores // lest they mess up the number of digits here that we depend on. static if(strippedOctalLiteral(octalNum).length < 11) enum bool octalFitsInInt = true; else static if(strippedOctalLiteral(octalNum).length == 11 && strippedOctalLiteral(octalNum)[0] == '1') enum bool octalFitsInInt = true; else enum bool octalFitsInInt = false; } string strippedOctalLiteral(string original) { string stripped = ""; foreach(c; original) if(c >= '0' && c <= '7') stripped ~= c; return stripped; } template literalIsLong(string num) { static if(num.length > 1) enum literalIsLong = (num[$-1] == 'L' || num[$-2] == 'L'); // can be xxL or xxLu according to spec else enum literalIsLong = false; } template literalIsUnsigned(string num) { static if(num.length > 1) enum literalIsUnsigned = (num[$-1] == 'u' || num[$-2] == 'u') // can be xxL or xxLu according to spec || (num[$-1] == 'U' || num[$-2] == 'U'); // both cases are allowed too else enum literalIsUnsigned = false; } /** These pass out the correctly typed literal based on the specifiers on the end of the string and the size of the literal. If it can fit in an int, it is an int. Otherwise, it is a long. But, if the user specifically asks for a long with the L suffix, always give the long. Give an unsigned iff it is asked for with the U or u suffix. */ int octal(string num)() if((octalFitsInInt!(num) && !literalIsLong!(num)) && !literalIsUnsigned!(num)) { return octal!(int, num); } long octal(string num)() if((!octalFitsInInt!(num) || literalIsLong!(num)) && !literalIsUnsigned!(num)) { return octal!(long, num); } uint octal(string num)() if((octalFitsInInt!(num) && !literalIsLong!(num)) && literalIsUnsigned!(num)) { return octal!(int, num); } ulong octal(string num)() if((!octalFitsInInt!(num) || literalIsLong!(num)) && literalIsUnsigned!(num)) { return octal!(long, num); } /* Returns if the given string is a correctly formatted octal literal. The format is specified in lex.html. The leading zero is allowed, but not required. */ bool isOctalLiteralString(string num) { if(num.length == 0) return false; // must start with a number if(num[0] < '0' || num[0] > '7') return false; foreach(i, c; num) { if((c < '0' || c > '7') && c != '_') // not a legal character if(i < num.length - 2) return false; else { // gotta check for those suffixes if(c != 'U' && c != 'u' && c != 'L') return false; if(i != num.length - 1) { // if we're not the last one, the next one must also be a suffix to be valid char c2 = num[$-1]; if(c2 != 'U' && c2 != 'u' && c2 != 'L') return false; // spam at the end of the string if(c2 == c) return false; // repeats are disallowed } } } return true; } /* Returns true if the given compile time string is an octal literal. */ template isOctalLiteral(string num) { enum bool isOctalLiteral = isOctalLiteralString(num); } /* Takes a string, num, which is an octal literal, and returns its value, in the type T specified. So: int a = octal!(int, "10"); assert(a == 8); */ T octal(T, string num)() { static assert(isOctalLiteral!num, num ~ " is not a valid octal literal"); ulong pow = 1; T value = 0; for(int pos = num.length - 1; pos >= 0; pos--) { char s = num[pos]; if(s < '0' || s > '7') // we only care about digits; skip the rest continue; // safe to skip - this is checked out in the assert so these are just suffixes value += pow * (s - '0'); pow *= 8; } return value; } import std.metastrings: toStringNow; import std.traits: isIntegral; /** Constructs an octal literal from a number, maintaining the type of the original number. For example: octal!10 is exactly the same as integer literal 8. octal!10U is identical to the literal 8U. */ template octal(alias s) if(isIntegral!(typeof(s))) { enum auto octal = octal!(typeof(s), toStringNow!(s)); } unittest { // ensure that you get the right types, even with embedded underscores auto w = octal!"100_000_000_000"; static assert(!is(typeof(w) == int)); auto w2 = octal!"1_000_000_000"; static assert(is(typeof(w2) == int)); static assert(octal!"45" == 37); static assert(octal!"0" == 0); static assert(octal!"7" == 7); static assert(octal!"10" == 8); static assert(octal!"666" == 438); static assert(octal!45 == 37); static assert(octal!0 == 0); static assert(octal!7 == 7); static assert(octal!10 == 8); static assert(octal!666 == 438); static assert(octal!"66_6" == 438); static assert(octal!2520046213 == 356535435); static assert(octal!"2520046213" == 356535435); static assert(octal!17777777777 == int.max); static assert(!__traits(compiles, octal!823)); // static assert(!__traits(compiles, octal!"823")); // for some reason, this line fails, though if you try it in code, it indeed doesn't compile... weird. static assert(!__traits(compiles, octal!"_823")); static assert(!__traits(compiles, octal!"spam")); static assert(!__traits(compiles, octal!"77%")); int a; long b; static assert(__traits(compiles, a = octal!"17777777777")); // biggest value that should fit in an it static assert(!__traits(compiles, a = octal!"20000000000")); // should not fit in the int static assert(__traits(compiles, b = octal!"20000000000")); // ... but should fit in a long static assert(!__traits(compiles, a = octal!"1L")); //static assert(!__traits(compiles, a = octal!1L)); // this should pass, but it doesn't, since the int converter doesn't pass along its suffix to helper templates static assert(__traits(compiles, b = octal!"1L")); static assert(__traits(compiles, b = octal!1L)); } =============================== -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 03:05:28PM -0400, bearophile wrote:The answer is essentially: how can you represent very large 64 bit octal values with that syntax?
Have the user switch over to the string notation in those rare cases. The argument most often brought up for keeping octal *at all* is unix filesystem permissions. They are only ever as big as four digits (AFAIK). 7777 certainly fits in an integer. Even 8 digits: 77_777_777 is still well within the limits of an integer literal. So, in theory, yeah, the integer can't express all numbers in octal that can fit. But in practice? How often would this come up? Does the language *really* need to address this globally just to avoid the quotes in those specific situations? The one person who has such a use for giant octal literals might complain "gah I have to quote it once it gets to a certain size, this kinda sucks", but I'm ok with that. Another possibility might be having integer literals actually be infinite in size in the compiler, and use a template alias.. or something, to take them unmolested into CTFE for manipulation. This would also be useful for bignum structs. You can just reuse the plain old integer literal when initalizing them. Then, if the literal is too big to fit in the type requested, the compiler throws an error only at the last minute it can possibly check. This would be more generally useful than a special octal literal, but since it means changes to the compiler, the cost is higher too. The nice thing about my O!100 or Andrei's octal!"100" is that they work in D today. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 03:34:06PM -0400, Nick Sabalausky wrote:I haven't used opDispatch, and don't remember much from the discussions of it, so pardon a possibly dumb question: Would that prevent you from getting a (meaningful) compile-time error if you mis-typed one of the flags?
A static assert would fire if the flag name given isn't in its internal table. The opDispatch function takes a string. It'd look something like this: ==== import std.stdio; struct Flags(T) { int opDispatch(string name)() { foreach(item; itemList) { if(name == item.name) return item.value; } static assert(0, "No such member: " ~ name); } struct Item { string name; T value; } Item[] itemList; } void main() { Flags!int a; int b = a.what; } === $ dmd -c test.d test.d(10): Error: static assert "No such member: what" The actual implementation of the Flags struct would be different to keep it all compile time (and of course, offer a constructor of sorts), but this show the idea and the error you can get. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 03:57:27PM -0400, Adam D. Ruppe wrote: Gah, that would always trigger. It would actually need to have a helper template and a constraint. So more along these lines: T opDispatch(string name)() if (isValidName!(name)) { } Where the isValidName loops through it. Poo, I make this mistake often. But the bright side is once this template is written, you needn't rewrite it to get the goods when using it. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 04:08:26PM -0400, bearophile wrote:OK. But are you sure you want a template named just "O" in the std lib? Oct or Octal can cause less collisions.
The name doesn't matter much to me. I said O!777 just because looks as similar on the screen to 0777 as we can without changing the rules of the language. I'm ok with octal too; the name isn't a big deal.If this can work and be safe, then it's a cute idea.
Aye. If only implementing it were free :P -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 03:37:52PM -0500, Andrei Alexandrescu wrote:Contest: define "octal" as per the blueprint above and paste it here.
Trivial. I'll start with the code you posted on the bugzilla. ===== template octal(string s) { static assert(s.length > 0); static assert(s[0] >= '0' && s[0] < '8', "Incorrect character in octal constant: `" ~ s[0] ~ "'"); static if (s.length == 1) { enum uint octal = s[0] - '0'; } else { enum uint octal = 8 * (s[0] - '0') + octal!(s[1 .. $]); } } ====== Then add just this: ==== import std.metastrings; template octal(uint s) { enum uint octal = octal!(toStringNow!(s)); } ===== Take the unittest from bugzilla and add the same using the literal: unittest { static assert(octal!"45" == 37); static assert(octal!"0" == 0); static assert(octal!"7" == 7); static assert(octal!"10" == 8); static assert(octal!45 == 37); static assert(octal!0 == 0); static assert(octal!7 == 7); static assert(octal!10 == 8); } void main() {} Run it. Boom! The tests pass. Change the names to your heart's desire. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 04:57:00PM -0400, Adam D. Ruppe wrote:Run it. Boom! The tests pass.
I always post too soon! It fails with larger numbers. The octal!(string) code is to blame; it doesn't raise 8 to the right power on strings with length > 2. And opPow doesn't seem to work here. So I'll do it slightly differently: ==== /* new function */ uint octal(string num)() { static assert(num.length > 0); uint pow = 1; uint value = 0; for(int pos = num.length - 1; pos >= 0; pos--) { char s = num[pos]; assert(s >= '0' && s < '8', "Incorrect character in octal constant: `" ~ s ~ "'"); value += pow * (s - '0'); pow *= 8; } return value; } /* end changes */ import std.metastrings; template octal(uint s) { enum uint octal = octal!(toStringNow!(s)); } unittest { static assert(octal!"45" == 37); static assert(octal!"0" == 0); static assert(octal!"7" == 7); static assert(octal!"10" == 8); static assert(octal!45 == 37); static assert(octal!0 == 0); static assert(octal!7 == 7); static assert(octal!10 == 8); } void main() { // a triple check pragma(msg, octal!666); // prints correctly as it compiles, yay } === And as a final check: pragma(msg, octal!6668); octal.d(9): Error: "Incorrect character in octal constant: `8'" octal.d(22): Error: cannot evaluate octal() at compile time octal.d(22): Error: cannot evaluate octal() at compile time octal.d(43): Error: template instance octal.octal!(6668) error instantiating Good, good. But is it still compile time elsewhere? writeln(octal!6668); Same spewing errors. A bit wordy, but definitely gives error correctly. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
On Thu, Mar 25, 2010 at 09:10:09PM -0400, Nick Sabalausky wrote:Supporting it means it will "silently and disastrously break code" from anyone who tries to use a leading zero
This is why I'd like them banned. Sometimes I write things like switch(a) { case 143: do something; break; case 642: do something; break; case 011: do something; break; } Using the leading zero just because I want it to line up in pretty columns. It has been a long time since I've actually made this mistake and got bit by it, but it has happened to me before. I'd feel better if it was a compile error just to ensure it never happens again. -- Adam D. Ruppe http://arsdnet.net
Mar 25 2010
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:alias Flags!(ubyte, "do_nothing", "walk_dog" "cook_breakfast" "deliver_newspaper" "visit_miss_kerbopple" "wash_covers") Todo; I encourage you to code that up and see how it swims. We need to stop inventing syntax for any single thing that seems useful, and start eating our dogfood. If our mechanism for code generation is not good enough, we should improve it, not generate by hand ever new constructs.
template withType( alias F ) { template withType( alias s ) { enum withType = F!( typeof( s ) ); } } mixin template Flags_mixin( T, U, U value, string name, V... ) { // Does not work, due to std.metastrings.toStringNow not supporting ubyte. //mixin( Format!( "enum %s = T( %s );", name, value ) ); mixin( "enum " ~ name ~ " = T( " ~ to!string( value ) ~ " );" ); static if ( V.length > 0 ) { mixin Flags_mixin!( T, U, value + 1, V ); } } struct Flags( T = uint, U... ) if ( allSatisfy!( withType!( isSomeString ), U ) && isIntegral!( T ) ) { T value; mixin Flags_mixin!( typeof( this ), T, T.init, U ); } usage: void foo( ) { alias Flags!( ubyte, "a", "b", "c" ) myFlags; myFlags f = myFlags.a; writeln( f.value ); alias Flags!( "d", "e", "f" ) myOtherFlags; myOtherFlags } It could do with some sanity checking (valid identifier names), but as this was just a proof of concept, I have not written that. btw, I really wish OpenGL headers could use a mechanism like this. Having to look up every single function to see which flags are allowed can be a PITA. -- Simen
Mar 27 2010
On 03/27/2010 09:02 AM, Simen kjaeraas wrote:Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:alias Flags!(ubyte, "do_nothing", "walk_dog" "cook_breakfast" "deliver_newspaper" "visit_miss_kerbopple" "wash_covers") Todo; I encourage you to code that up and see how it swims. We need to stop inventing syntax for any single thing that seems useful, and start eating our dogfood. If our mechanism for code generation is not good enough, we should improve it, not generate by hand ever new constructs.
[snip implementation] Looks good, but there are a couple of things I'm worried about. One is that it generates many templates (as opposed to CTFE). But that's an implementation detail. What I think this is lacking is the ability to predefine flags that are a combination of other flags. For example, some file open flags could define DEFAULT_READ as READ|SHARED. I'm not sure how to express that. Andrei
Mar 28 2010
Andrei Alexandrescu:What I think this is lacking is the ability to predefine flags that are a combination of other flags. For example, some file open flags could define DEFAULT_READ as READ|SHARED. I'm not sure how to express that.
It's not an enum, it's a struct, that contains a single value (for example an uint). The construct defines at compile-time a property for each given name. Then the assign operator tests that the input can be any of the possible ORs of the flags, otherwise asserts in not release mode. So I think it can be done. But it will come out a good amount of CTFE code. Bye, bearophile
Mar 28 2010
The construct defines at compile-time a property for each given name.<
A costant (enum) not a property, sorry. So this: alias Flags!q{ A, B, C } Foo; Becomes equivalent to: struct Foo { enum uint A = 1 << 0; enum uint B = 1 << 1; enum uint C = 1 << 2; private uint _data; // operators defined here, with full input tests: // = == | |= in & &= opBool ... } Foo f = Foo.A | Foo.B; Now f._data contains the or of the two flags... Bye, bearophile
Mar 28 2010
On 03/28/2010 06:03 PM, bearophile wrote:The construct defines at compile-time a property for each given name.<
A costant (enum) not a property, sorry. So this: alias Flags!q{ A, B, C } Foo; Becomes equivalent to: struct Foo { enum uint A = 1<< 0; enum uint B = 1<< 1; enum uint C = 1<< 2; private uint _data; // operators defined here, with full input tests: // = == | |= in& &= opBool ... } Foo f = Foo.A | Foo.B; Now f._data contains the or of the two flags... Bye, bearophile
Yah but let's say A|B is used very often so I want to call it AB. How do I specify in the definition of Flags such a definition? I guess alias Flags!q{ A, B, C, AB = A|B } Foo; which makes parsing rather difficult. Andrei
Mar 28 2010