March 25, 2010
Hello Yigal,

> I meant implicit, sorry about that. The pascal way is definitely the
> correct way. 

Wrong. It is not "definitely" the correct way because there are many smart people who disagree. It might *be* the correct way, but it that has yet to be shown.

> what's the semantics in your opinion of ('f' + 3) ? what
> about ('?' + 4)? making such arithmetic valid is wrong.

The above will depend on the underlying system (because we are talking D, that would be UTF). The first will result in the value three grater than the value used to represent 'f' (in UTF, 'i'). The same happens for the second with suitable substations.

>>> The fact that D has 12 integral types is a bad design, why do we
>>> need so many built in types? to me this clearly shows a need to
>>> refactor this aspect of D.
>>> 
>> Which would you get rid of? (13, I forgot bool!)
>> 
>> bool
>> byte
>> ubyte
>> short
>> ushort
>> int
>> uint
>> long
>> ulong
>> char
>> wchar
>> dchar
>> enum
>
> you forgot the cent and ucent types and what about 256bit types?
> 
> Here's How I'd want it designed:
> 
> First of, a Boolean type should not belong to this list at all and
> shouldn't be treated as a numeric type.

Agree, and it isn't for the most part.

> 
> Second, there really only few use-cases that are relevant
> 
> signed types for representing numbers:
> 1) unlimited integral type - int

Very rare and expensive. This, IMHO, should not be a built in type

> 3) user defined range: e.g. [0, infinity) for positive numbers, etc..

Also rare and expensive for most uses. Again, not built in.

[reordered a bit]

> 2) limited integral type  - int!(bits), e.g. int!16, int!8, etc..
> unsigned bit-packs:
> 4) bits!(size), e.g. bits!8, bits!32, etc..

This would make it look like int!13 and int!16 are both valid and similarly costly. If you do make int!13 valid how will it pack in arrays? (Hint: if it doesn't pack, I see no more value in it than in a range type, see comment to item 3) Will you be able to take a pointer to any element? (Hint: the problems with that are why D dropped the bit type.)

When you get right down to it, the types supported by hardware are fairly standard (8,16,32,64,... bits signed and unsigned) so why shouldn't the language support them directly? I will grant that there are reasons to do what you are suggesting, but I don't think they are valid reason with regards to the language the D is trying to be.

> of course you can define useful aliases, e.g.
> alias bits!8 Byte;
> alias bits!16 Word;
> ..
> or you can define the aliases per the architecture, so that Word above
> will be defined for the current arch (I don't know what's the native
> word size on say ARM and other platforms)

C more or less has that with int. That D dropped the "what size is int" problem is a good thing in my book.

> char and relatives should be for text only per Unicode, (perhaps a
> better name is code-point). for other encodings use the above bit
> packs, e.g.
> 
> alias bits!7 Ascii;
> 
> alias bits!8 ExtendedAscii;
> 
> etc..

D defines text to be unicode. Unicode is a sequence of numbers. It's all well defined and whatnot so allowing the programmer to handle them as numbers is a must as far as I'm concerned.

Finally, none of that part about integers has anything to do with implicit casts. If anything, it would make it harder as you now have even more types, not less. 

> 
> enum should be an enumeration type. You can find an excellent
> strongly-typed  design in Java 5.0
> 
-- 
... <IXOYE><



March 25, 2010
Andrei Alexandrescu wrote:
> On 03/25/2010 11:57 AM, Lars T. Kyllingstad wrote:
>> Andrei Alexandrescu wrote:
>>> On 03/25/2010 11:17 AM, bearophile wrote:
>>>> Andrei Alexandrescu:
>>>>> The problem is it asks you to insert casts all too often. I think the
>>>>> value range propagation is a principled and correct solution to that
>>>>> problem.
>>>>
>>>> In bugzilla I have asked to disable the implicit conversion enum =>
>>>> base type in an equality test, see:
>>>> http://d.puremagic.com/issues/show_bug.cgi?id=3999
>>>>
>>>> In bugzilla I have never asked to disable implicit signed => unsigned
>>>> casts, I am able to see they are two quite different situations.
>>>>
>>>> I think the implicit conversions from enum => base types are uncommon
>>>> enough, so they can't introduce too many casts.
>>>>
>>>> If Walter doesn't agree with me (and few other people here) then
>>>> there's no point in keeping bug 3999 open, it can be closed. Because
>>>> it's better to fix/change similar things now, when the D2 language is
>>>> not diffused yet. Later such changes are harder to do.
>>>>
>>>> In bugzilla there are few other things that deserve a similar look.
>>>> Those changes can't be done all at the same time, but the decision
>>>> can be taken in a short enough time, and it's better to think about
>>>> them now.
>>>>
>>>> Bye and thank you for your attention,
>>>> bearophile
>>>
>>> I think defining a integral() function that gives the value of the
>>> enum as an appropriately-typed integral number wouldn't harm.
>>>
>>> Andrei
>>
>> Why not let to!int() do this?
>>
>> -Lars
> 
> Because an enum that uses long as a base will not be converted. integral() would automatically deduce and return the appropriate base type.

Ah, now I understand.  I thought you meant a function to convert an enum to a user-specified type, i.e. integral!T(myEnum).

-Lars
March 25, 2010
Yigal Chripun wrote:
> Walter Bright Wrote:
>> Pascal has explicit casts. The integer to character one is CHR(i), the
>> character to integer is ORD(c).
> I meant implicit, sorry about that. The pascal way is definitely the correct
> way. what's the semantics in your opinion of ('f' + 3) ? what about ('?' +
> 4)? making such arithmetic valid is wrong.

Yes, that is exactly the opinion of Pascal. As I said, I've programmed in Pascal, suffered as it blasted my kingdom, and I don't wish to do that again. I see no use in pretending '?' does not have a numerical value that is very useful to manipulate.

> I'm sure that the first Pascal
> versions had problems which caused you to ditch that language (they where
> fixed later).

They weren't compiler bugs I was wrestling with. They were fundamental design decisions of the language.

> I doubt it though that this had a large impact on Pascal's
> problems.

I don't agree. Pascal was a useless language as designed. This meant that every vendor added many incompatible extensions. Anyone who used Pascal got locked into a particular vendor. That killed it.


>>> The fact that D has 12 integral types is a bad design, why do we need so
>>> many built in types? to me this clearly shows a need to refactor this
>>> aspect of D.
>> Which would you get rid of? (13, I forgot bool!)
>> 
>> bool byte ubyte short ushort int uint long ulong char wchar dchar enum
> 
> you forgot the cent and ucent types and what about 256bit types?

They are reserved, not implemented, so I left them out. In or out, they don't change the point.


> Here's How I'd want it designed: First of, a Boolean type should not belong
> to this list at all and shouldn't be treated as a numeric type. Second, there
> really only few use-cases that are relevant
> 
> signed types for representing numbers: 1) unlimited integral type - int 2)
> limited integral type  - int!(bits), e.g. int!16, int!8, etc.. 3) user
> defined range: e.g. [0, infinity) for positive numbers, etc..
> 
> unsigned bit-packs: 4) bits!(size), e.g. bits!8, bits!32, etc..
> 
> of course you can define useful aliases, e.g. alias bits!8 Byte; alias
> bits!16 Word; .. or you can define the aliases per the architecture, so that
> Word above will be defined for the current arch (I don't know what's the
> native word size on say ARM and other platforms)

People are going to quickly tire of writing:

bits!8 b;
bits!16 s;

and are going to use aliases:

   alias bits!8 ubyte;
   alias bits!16 ushort;

Naturally, either everyone invents their own aliases (like they do in C with its indeterminate int sizes), or they are standardized, in which case we're back to pretty much exactly the same point we are at now. I don't see where anything was accomplished.


> char and relatives should be for text only per Unicode, (perhaps a better
> name is code-point).

There have been many proposals to try and hide the fact that UTF-8 is really a multibyte encoding, but that makes for some pretty inefficient code in too many cases.

> for other encodings use the above bit packs, e.g. alias
> bits!7 Ascii; alias bits!8 ExtendedAscii; etc..
> 
> enum should be an enumeration type. You can find an excellent strongly-typed
> design in Java 5.0

Those enums are far more heavyweight - they are a syntactic sugar around a class type complete with methods, interfaces, constructors, etc. They aren't even compile time constants! If you need those in D, it wouldn't be hard at all to make a library class template that does the same thing.

March 25, 2010
grauzone wrote:
> Walter Bright wrote:
> That's funny that you're saying this. Casts are totally messed up in D. Some casts do safe operations (casts between objects and interfaces), some are absolutely ridiculous and only useful in low level situations (casting array slices), some are safe whenever the compiler feels like it (array casts of array literals versus array slices), and some fundamentally break other language features, even accidentally (immutable).

The unsafe casts are not allowed in safe mode.

> casts are easily grepable, but you never know what a specific cast actually does. Think about what this means for generic templated code.
> 
> In summary, I'd say casting rules in D are the worst spawn of hell.
> 
> I mean, that's ok, it doesn't exactly make D useless. And you can always introduce your own safe (exe bloating, sigh) casting template functions. But I still find it funny that you say this.

Sure, but I think it misses the point a bit. My point was that one should strive to eliminate casts from your code. A type system that requires a lot of casts is going to be less safe than one that does not.


>> Implicit integral conversions are not without problems, but when I found C I threw Pascal under the nearest bus and never wrote a line in it again. The taste was so bad, I refused to even look at Modula II and its failed successors.
> 
> For your information, programming in Delphi (modern Pascal dialect) was quite a joy. It combined the advantages of the low level programming of C (pointers, inline assembler), was safer than C, and included a sane object model similar to Java/C#. Sounds familiar?

If there's a particular aspect of Delphi you feel would be a good fit for D, please make a proposal. There's no surprise you like both C# and Delphi, as they were created by the same person!


> (Yeah, the template fetishists must have been very unhappy with it.)
> 
> I really don't understand why you're bashing Pascal at large. You must have had only experience with early Pascal dialects... and then never looked at anything that smelled like Pascal... and this as a language designer??

There are thousands of languages out there. If I did due diligence researching them all, I'd never finish, as new languages get created faster than anyone could ever study them. At some point, you've gotta pick and choose what you're going to look at in depth. Each language family is based on a core set of principles that get carried from one version to the next. Pascal's core set is unbearably restrictive to me. Sure, a lot of people strongly disagree, and that's fair, it is subjective, after all.

Furthermore, like I said, anyone can propose features from any language they feel would make a good fit for D. None will be automatically rejected just because it came from a Pascal family language.


> PS: while you guys are talking about new "absolutely necessary" language features, people new to D are despairing to get a working D installation and *trying* to use external libraries from dsource (that kind of struggling really isn't nice to watch), and people "old" to D are desparing over compiler regressions and random bugs that have global effects on middle-sized to large codebases (circular dependency and optlink bugs come to mind). The situation is slowly improving, but too slow and problems *never* get completely eliminated.

I understand the issues, but we have to get the feature set for D2 finalized before it can be made stable. D1 is stable. The optlink problems have been solved months ago. The compiler regressions have been unanticipated effects from fixing long standing problems in bugzilla, and fixing them has been taken care of reasonably quickly.

I'd welcome your help in fixing issues you feel are most important. There are a lot of people working hard on them, but we can use more help. After all, there is no corporation pouring billions into D. We're a bunch of volunteers.
March 25, 2010
"Don" <nospam@nospam.com> wrote in message news:hof6fe$6ah$1@digitalmars.com...
>
> I think there might be some low-hanging fruit, though.
> Supposed we distinguished enums containing AssignExpressions from those
> which do not.
> It seems clear to me that logical operations should always be permitted on
> enums where every member of the enum has been explicitly assigned a value.
> enum Enum1 { A = 1, B = 2, C = 4 }
>  ---> A|B makes sense.
>
> But if there are no assign expressions at all:
> enum Enum2 { A, B, C }
> then I think that performing arithmetic on that enum is almost certainly a
> bug.
>
> The case where only some of the enum members have assign expressions is less clear. Some cases, such as synonyms { A, B, C=B } aren't really any different from the no-assign expression case. But other cases are less clear, so I'll just ignore them all. So I propose a simple rule:
>
> Suppose that implicit integral conversions (and arithmetic/logical operations) involving enums were permitted ONLY if the enum has at least one AssignExpression.
>
> This would catch some bugs, without (I think) causing much pain for valid code. At the very least, this is something I'd want in a lint tool. (But note that it wouldn't fix the issue in the original post).
>

If I understand that right, I think that side-steps what I see as the important goal: To *have* an associated value with each enum member but just have to be explicit about obtaining it. The above scheme doesn't really bring things significantly closer to that, you have to make a choice between type-safety and being able actually have an underlying value at all. So when you need an associated value but you're not doing bitfields/flags (which is a situation I find to be very common for enums), then that solution provides no improvement over the current state.

Here's the low-hanging fruit I see:

Step 1: Remove implicit enum->base-type conversions
Step 2: Allow '|' (and maybe '&'?) on enums, and consider the result of the
operation be the base type.

Certainly not ideal, but it provides far more type-safety than we currently have on non-bitfield/non-flag enums, even if you're using associated values, and still allows enums to be used for bitfields/flags without any code breakage or ugly "cast(int)Foo.a | cast(int)Foo.b".


March 25, 2010
Nick Sabalausky wrote:
> Here's the low-hanging fruit I see:
> 
> Step 1: Remove implicit enum->base-type conversions
> Step 2: Allow '|' (and maybe '&'?) on enums, and consider the result of the operation be the base type.

I would prefer the result of Step 2 to be the enum type, not the base type(*)

The typical case I see for enums as flags is passing a combination of them to a function, where the parameter (for type-safety & self-documentation) will probably be of the enum type.

However, it occurs to me we don't actually get full type safety unless we also ensure the enum never has a value outside those defined, or a combination thereof(*)

Example:

enum Flags
{
  A = 0x1,
  B = 0x2,
  C = 0x4,
  D = 0x8
}
//
// possible values for a variable of type 'Flags'
// 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA
// 0xB, 0xC, 0xD, 0xE, 0xF
//
// values < 0x1 and > 0xF are illegal
//
// default value of variable of type 'Flags' is 0x1 (A)
//

<incomplete code snippets..>

void foo(Flags f) {}    //accepts only legal values for Flags

foo(Flags.A|Flags.B);  //ok
foo(0x10);             //error

Flags f;               //ok, f = 0x1
Flags err = 0x10;      //error

foo(Flags.A|0x10);     //error

</incomplete code snippets..>


(*) Some operators would return the base type, take ~ for example, it naturally produces a value outside the range of values defined by the enum type.

It follows that operators like |[=], &[=] etc would need to accept enum and base types as operands, otherwise some common idioms would be illegal, eg.

Flags f = Flags.A|Flags.B|Flags.C;
f &= ~Flags.A; // remove Flags.A from 'f'

R
March 25, 2010
Walter Bright:
> There are thousands of languages out there. If I did due diligence researching them all, I'd never finish, as new languages get created faster than anyone could ever study them. At some point, you've gotta pick and choose what you're going to look at in depth.

I agree. On the other hand using few days every year, to try in their native environment one or two new languages every year is good, to keep a hold of what others are doing. In the past I have suggested C#3 and Scala. So you can learn why people ask for IDE-related features, or a useful unit-testing, etc.


> There are a lot of people working hard on them, but we can use more help. After all, there is no corporation pouring billions into D. We're a bunch of volunteers.

I think that eventually I will try to fix D bugs myself :-)


Regarding base type names I have proposed :
byte => sbyte
wchar => char16 (or shortchar)
dchar => char32 (or intchar)

http://d.puremagic.com/issues/show_bug.cgi?id=3850 http://d.puremagic.com/issues/show_bug.cgi?id=3936

Bye,
bearophile
March 25, 2010
Ellery Newcomer wrote:
> On 03/24/2010 11:40 PM, Walter Bright wrote:
>> Nick Sabalausky wrote:
>>>> In D1, is there any reason I should be getting an error on this?:
>>>>
>>>> // module A:
>>>> enum FooA { fooA };
>>>> void bar(FooA x) {}
>>>>
>>>> // module B:
>>>> import A;
>>>> enum FooB { fooB };
>>>> void bar(FooB x) {}
>>>>
>>>> bar(FooB.fooB); // Error: A.bar conflicts with B.bar (WTF?)
>>
>> ------- a.d -------------------
>> enum FooA { fooA };
>> void bar(FooA x) {}
>> ------- test.d ----------------
>> import a;
>> enum FooB { fooB };
>> void bar(FooB x) {}
>>
>> void test()
>> {
>> bar(FooB.fooB);
>> }
>> ------------------------------
>>
>> with:
>>
>> dmd test
>>
>> I do not get an error with either D1 or D2. So, if you are getting an
>> error, how is your code different?
> 
> ------- a.d -------------------
> enum FooA { fooA };
> void bar(FooA x) {}
> ------- test.d ----------------
> import a;
> mixin(`
> enum FooB { fooB };
> void bar(FooB x) {}
> `);
> 
> void test()
> {
>     bar(FooA.fooA); //error
>     bar(FooB.fooB);
> }
> ------------------------------


This error is quite correct (and happens with or without the mixin). The idea is if you define a function in a local scope, it *completely hides* functions with the same name in imported scopes. In order to overload local functions with imported ones, an alias is necessary to bring the imported functions into the same scope.

This allows the user complete control over which functions get overloaded when they come from diverse, and possibly completely independent, imports.



> ------- a.d -------------------
> enum FooA { fooA };
> void bar(FooA x) {}
> ------- test.d ----------------
> import a;
> alias a.bar bar;
> mixin(`
> enum FooB { fooB };
> void bar(FooB x) {}
> `);
> 
> void test()
> {
>     bar(FooA.fooA);
>     bar(FooB.fooB); //error
> }
> ------------------------------

I'm not sure why this error is happening, it definitely has something to do with the mixin. Let me look into it some more.
March 25, 2010
Walter Bright Wrote:

> Yigal Chripun wrote:
> > Walter Bright Wrote:
> >> Pascal has explicit casts. The integer to character one is CHR(i), the
> >> character to integer is ORD(c).
> > I meant implicit, sorry about that. The pascal way is definitely the correct
> > way. what's the semantics in your opinion of ('f' + 3) ? what about ('?' +
> > 4)? making such arithmetic valid is wrong.
> 
> Yes, that is exactly the opinion of Pascal. As I said, I've programmed in Pascal, suffered as it blasted my kingdom, and I don't wish to do that again. I see no use in pretending '?' does not have a numerical value that is very useful to manipulate.
> 

'?' indeed does *not* have a single numerical value that identiies it in a unique manner. You can map it to different numeric values based on encoding and even within the same encoding this doesn't always hold. See normalization in Unicode for different encodings for the same character.

> > I'm sure that the first Pascal
> > versions had problems which caused you to ditch that language (they where
> > fixed later).
> 
> They weren't compiler bugs I was wrestling with. They were fundamental design decisions of the language.
> 
> > I doubt it though that this had a large impact on Pascal's problems.
> 
> I don't agree. Pascal was a useless language as designed. This meant that every vendor added many incompatible extensions. Anyone who used Pascal got locked into a particular vendor. That killed it.
> 
> 
> >>> The fact that D has 12 integral types is a bad design, why do we need so many built in types? to me this clearly shows a need to refactor this aspect of D.
> >> Which would you get rid of? (13, I forgot bool!)
> >> 
> >> bool byte ubyte short ushort int uint long ulong char wchar dchar enum
> > 
> > you forgot the cent and ucent types and what about 256bit types?
> 
> They are reserved, not implemented, so I left them out. In or out, they don't change the point.
> 
> 
> > Here's How I'd want it designed: First of, a Boolean type should not belong to this list at all and shouldn't be treated as a numeric type. Second, there really only few use-cases that are relevant
> > 
> > signed types for representing numbers: 1) unlimited integral type - int 2)
> > limited integral type  - int!(bits), e.g. int!16, int!8, etc.. 3) user
> > defined range: e.g. [0, infinity) for positive numbers, etc..
> > 
> > unsigned bit-packs: 4) bits!(size), e.g. bits!8, bits!32, etc..
> > 
> > of course you can define useful aliases, e.g. alias bits!8 Byte; alias bits!16 Word; .. or you can define the aliases per the architecture, so that Word above will be defined for the current arch (I don't know what's the native word size on say ARM and other platforms)
> 
> People are going to quickly tire of writing:
> 
> bits!8 b;
> bits!16 s;
> 
> and are going to use aliases:
> 
>     alias bits!8 ubyte;
>     alias bits!16 ushort;
> 
> Naturally, either everyone invents their own aliases (like they do in C with its indeterminate int sizes), or they are standardized, in which case we're back to pretty much exactly the same point we are at now. I don't see where anything was accomplished.
> 
Not true. say I'm using my own proprietary hardware and I want to have bits!24. How would I do that in current D? what if new hardware adds support for larger vector ops and 512bit registers, will we now need to extend the language with another type?

On the flip side of this, programmers almost always will need just an int since they need the mathematical notion of an integral type.
Iit's prtty rare when programmers want something other than int and in those cases they'll define thir own types anyway since they know what their requirements are.

> 
> > char and relatives should be for text only per Unicode, (perhaps a better
> > name is code-point).
> 
> There have been many proposals to try and hide the fact that UTF-8 is really a multibyte encoding, but that makes for some pretty inefficient code in too many cases.

I'm not saying we should hide that, on the contrary, the compiler should enforce unicode and other encodings should use a bits type instead. a [w|d]char must always contain a valid unicode value.
calling char[] a string is wrong since it is actually an array of code-points which is not always a valid encoding. a dchar[] is however a valid string since each individual dchar contains a full code-unit.

> 
> > for other encodings use the above bit packs, e.g. alias bits!7 Ascii; alias bits!8 ExtendedAscii; etc..
> > 
> > enum should be an enumeration type. You can find an excellent strongly-typed design in Java 5.0
> 
> Those enums are far more heavyweight - they are a syntactic sugar around a class type complete with methods, interfaces, constructors, etc. They aren't even compile time constants! If you need those in D, it wouldn't be hard at all to make a library class template that does the same thing.
> 

They aren't that heavy weight. Instead of assigning an int to each symbol you assign a pointer address which is the same size.
Regarding the compile time property:
for an int type:
const int a = 5; //compile time
the same should apply to enums as well.

The problem with the library solution is that it can't provide the syntax sugar for this.
March 25, 2010
yigal chripun wrote:
> Walter Bright Wrote:
> 
>> Yigal Chripun wrote:
>>> Walter Bright Wrote:
>>>> Pascal has explicit casts. The integer to character one is CHR(i), the character to integer is ORD(c).
>>> I meant implicit, sorry about that. The pascal way is definitely the
>>> correct way. what's the semantics in your opinion of ('f' + 3) ? what
>>> about ('?' + 4)? making such arithmetic valid is wrong.
>> Yes, that is exactly the opinion of Pascal. As I said, I've programmed in Pascal, suffered as it blasted my kingdom, and I don't wish to do that
>> again. I see no use in pretending '?' does not have a numerical value that
>> is very useful to manipulate.
>> 
> 
> '?' indeed does *not* have a single numerical value that identiies it in a
> unique manner. You can map it to different numeric values based on encoding
> and even within the same encoding this doesn't always hold. See normalization
> in Unicode for different encodings for the same character.


That's true, '?' can have different encodings, such as for EBCDIC and RADIX50. Those formats are dead, however, and ASCII has won. D is specifically a Unicode language (a superset of ASCII) and '?' has a single defined value for it.

Yes, Unicode has some oddities about it, and the poor programmer using those characters will have to deal with it, but that does not change that quoted character literals are always the same numerical value. '?' is not going to change to another one tomorrow or in any conceivable future incarnation of Unicode.

>> Naturally, either everyone invents their own aliases (like they do in C
>> with its indeterminate int sizes), or they are standardized, in which case
>> we're back to pretty much exactly the same point we are at now. I don't see
>> where anything was accomplished.
>> 
> Not true. say I'm using my own proprietary hardware and I want to have
> bits!24. How would I do that in current D?

You'd be on your own with that. I had a discussion recently with a person who defended C's notion of compiler defined integer sizes, pointing out that this enabled compliant C compilers to be written for DSLs with 32 bit bytes. That is pedantically correct, compliant C compilers were written for it. Unfortunately, practically no C applications could be ported to it without extensive modification!

For your 24 bit machine, you will be forced to write all your own custom software, even if the D specification supported it.


> what if new hardware adds support
> for larger vector ops and 512bit registers, will we now need to extend the
> language with another type?

D will do something to accommodate it, obviously we don't know what that will be until we see what those types are and what they do. What I don't see is using 512 bit ints for normal use.



>>> char and relatives should be for text only per Unicode, (perhaps a better
>>>  name is code-point).
>> There have been many proposals to try and hide the fact that UTF-8 is
>> really a multibyte encoding, but that makes for some pretty inefficient
>> code in too many cases.
> 
> I'm not saying we should hide that, on the contrary, the compiler should
> enforce unicode and other encodings should use a bits type instead. a
> [w|d]char must always contain a valid unicode value. calling char[] a string
> is wrong since it is actually an array of code-points which is not always a
> valid encoding. a dchar[] is however a valid string since each individual
> dchar contains a full code-unit.

Conceptually, I agree, it's wrong, but it's not practical to force the issue.


>>> enum should be an enumeration type. You can find an excellent
>>> strongly-typed design in Java 5.0
>> Those enums are far more heavyweight - they are a syntactic sugar around a
>> class type complete with methods, interfaces, constructors, etc. They
>> aren't even compile time constants! If you need those in D, it wouldn't be
>> hard at all to make a library class template that does the same thing.
>> 
> 
> They aren't that heavy weight. Instead of assigning an int to each symbol you
> assign a pointer address which is the same size.

No, it's not the same. A compile time constant has many advantages over a runtime one. Java creates an inner class for each enum member, not just the enum itself! It's heavyweight.

> Regarding the compile time
> property: for an int type: const int a = 5; //compile time the same should
> apply to enums as well.

Having a runtime pointer to an inner class for each enum value is far from the advantages of a compile time constant.


> The problem with the library solution is that it can't provide the syntax
> sugar for this.

It can get pretty close. Java has poor abstraction facilities, and so building it into the language was the only solution.