www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Implicit enum conversions are a stupid PITA

reply bearophile <bearophileHUGS lycos.com> writes:
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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply "Nick Sabalausky" <a a.a> writes:
"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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply "Nick Sabalausky" <a a.a> writes:
"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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply "Nick Sabalausky" <a a.a> writes:
"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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply "Nick Sabalausky" <a a.a> writes:
"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
parent Mike Parker <aldacron gmail.com> writes:
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
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"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
next sibling parent Don <nospam nospam.com> writes:
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
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent reply KennyTM~ <kennytm gmail.com> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent "Nick Sabalausky" <a a.a> writes:
"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
prev sibling parent Justin Johansson <no spam.com> writes:
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
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent reply Don <nospam nospam.com> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent "Nick Sabalausky" <a a.a> writes:
"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
prev sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent reply Rainer Deyke <rainerd eldwood.com> writes:
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
parent Don <nospam nospam.com> writes:
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
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
prev sibling parent reply Don <nospam nospam.com> writes:
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
parent Don <nospam nospam.com> writes:
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
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"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
prev sibling parent reply BCS <none anon.com> writes:
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
parent "Nick Sabalausky" <a a.a> writes:
"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
prev sibling parent reply Clemens <eriatarka84 gmail.com> writes:
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
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"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
parent reply BCS <none anon.com> writes:
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
parent reply "Nick Sabalausky" <a a.a> writes:
"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
parent bearophile <bearophileHUGS lycos.com> writes:
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
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"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
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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
next sibling parent BCS <none anon.com> writes:
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
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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
prev sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply bearophile <bearophileHUGS lycos.com> writes:
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
parent reply bearophile <bearophileHUGS lycos.com> writes:
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
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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