www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Hmm - about manifest/enum

reply Mike <vertex gmx.at> writes:
Seems like we're running in circles again.

So I simply have to ask this:

Wouldn't it be better to ditch the _whole concept_ of constness and come=
  =

up with some thing else that actually solves problems instead of being a=
n  =

endless stream of new problems, arguments and confusion? After all this =
 =

time it seems quite obvious that the problem here is constness itself, n=
ot  =

the implementation. Didn't C++ fail to get it right? So maybe that's pro=
of  =

that the whole concept is flawed and that D won't get it right either.

What problem does constness solve anyway? Manifest const, read-only  =

access, const values/references ... aren't this unrelated concepts that =
 =

are shoehorned into one single syntax that doesn't fit?

Maybe it's time for some other approach - borrow C#'s property syntax, l=
et  =

properties stand free and make them "private scope". Borrow Pascal's ":=3D=
"  =

operator - this will mean "I define a manifest constant". Ok, please don=
't  =

take that too seriously, but the more discussion about const we have the=
  =

less faith I have that const will work in D.

-Mike

-- =

Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Dec 28 2007
next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Mike wrote:
 Seems like we're running in circles again.
 
 So I simply have to ask this:
 
 Wouldn't it be better to ditch the _whole concept_ of constness and come 
 up with some thing else that actually solves problems instead of being 
 an endless stream of new problems, arguments and confusion? After all 
 this time it seems quite obvious that the problem here is constness 
 itself, not the implementation. Didn't C++ fail to get it right? So 
 maybe that's proof that the whole concept is flawed and that D won't get 
 it right either.

It's a hard thing to define. Perhaps it's just something that's specific to each class, so you need to give programmers tools to define what const means for their code. Maybe not. If you have a good idea for const, you're free to download the gdc sources and implement it....
 What problem does constness solve anyway? Manifest const, read-only 
 access, const values/references ... aren't this unrelated concepts that 
 are shoehorned into one single syntax that doesn't fit?

This is why we're using enum now for things that are compile-time constants. You would blanch at using enum to indicate a runtime computed value that you can't modify with this reference.
 Maybe it's time for some other approach - borrow C#'s property syntax, 
 let properties stand free and make them "private scope". Borrow Pascal's 
 ":=" operator - this will mean "I define a manifest constant". Ok, 
 please don't take that too seriously, but the more discussion about 
 const we have the less faith I have that const will work in D.

I'd really love to see property syntax. And attributes, too. I would like an NHibernate equivalent for D, but I'd be stuck with ugly XML configuration, and I don't think that's a manageable solution.
 -Mike
 

Dec 28 2007
parent Mike <vertex gmx.at> writes:
On Sat, 29 Dec 2007 06:09:25 +0100, Christopher Wright  
<dhasenan gmail.com> wrote:

 It's a hard thing to define. Perhaps it's just something that's specific  
 to each class, so you need to give programmers tools to define what  
 const means for their code. Maybe not.

That's what I meant. Maybe there is not one single solution that works, only a bad compromise which noone really finds useful, so it could be beneficial to look at a completely different way of addressing the underlying problems.
 This is why we're using enum now for things that are compile-time  
 constants. You would blanch at using enum to indicate a runtime computed  
 value that you can't modify with this reference.

In the end I don't care. As I don't work in a team I don't need to protect anything, only manifest const is interesting. But I want to see it solved and Walter free to carry on. For months now everything just seems to revolve around constness and nothing else.
 I'd really love to see property syntax. And attributes, too. I would  
 like an NHibernate equivalent for D, but I'd be stuck with ugly XML  
 configuration, and I don't think that's a manageable solution.

Since I've done come C# lately and every time I use C# I think that this is a really nice solution (the one thing that's better in C# than in D imho). -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Dec 29 2007
prev sibling next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Mike" <vertex gmx.at> wrote in message news:op.t32vfhhpkgfkbn lucia...

------------------------------
Seems like we're running in circles again.

So I simply have to ask this:

Wouldn't it be better to ditch the _whole concept_ of constness and come
up with some thing else that actually solves problems instead of being an
endless stream of new problems, arguments and confusion? After all this
time it seems quite obvious that the problem here is constness itself, not
the implementation. Didn't C++ fail to get it right? So maybe that's proof
that the whole concept is flawed and that D won't get it right either.

What problem does constness solve anyway? Manifest const, read-only
access, const values/references ... aren't this unrelated concepts that
are shoehorned into one single syntax that doesn't fit?
------------------------------

Congratulations, you've completed the circle.  See my thread on this group 
from 6/4/2007.

Const isn't going to go away for the simple fact that there will always be 
people who were raised on C++ who think that you *need* const to do 
*anything* and *anything else* is heresy.

Sorry.  We lose. 
Dec 28 2007
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Sat, 29 Dec 2007 00:35:41 -0500, Jarrett Billingsley wrote:

 "Mike" <vertex gmx.at> wrote in message news:op.t32vfhhpkgfkbn lucia...

 What problem does constness solve anyway?


 Const isn't going to go away for the simple fact that there will always be 
 people who were raised on C++ who think that you *need* const to do 
 *anything* and *anything else* is heresy.

I thought the purpose of identifying immutable values to the compiler was to enable the compiler to perform optimiziation if it can, and to help the compiler to determine the correctness of algorithms. Optimisations would include being able to place such data in true ROM, use immediate values in the machine code where possible, allow caching of values across function calls, etc ... Correctness in terms of ensure that if the coder says something must not be modified, the compiler can detect code that attempts to do that. So I guess its not a necessary requirement but it is a nice thing to have, so we can lower the cost of developing acceptable applications. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Dec 28 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Derek Parnell wrote:
 So I guess its not a necessary requirement but it is a nice thing to have,
 so we can lower the cost of developing acceptable applications.

Constness has 2 main uses: 1) Better specification of an API. This is of little import for smaller projects or projects done by a very small team. It becomes important for large projects worked on by diverse teams. It essentially makes explicit what things a function can be expected to change, and what things it won't change. 2) It makes functional programming possible. The plum FP gets us is it opens the door to automatic parallelization of code! C++ and Java are dead in the water when it comes to automatic parallelization - if there are multiple cores, the app needs to be painfully and carefully recoded to take advantage of them. With FP, this can be done automatically. Some secondary advantages are: 3) Better optimization. 4) ROMable data. What languages we use definitely shape our thinking about programming. C++ has a crippled const system which delivers about half of (1) and none of (2). Java has no const at all, and doesn't deliver any of (1) or (2). But since nearly all of us came to D from C++ or Java, it's hard to see the value in something we have never known. It's like when the first car came to town - who needs it? It's noisy, smelly, breaks down, and gets stuck in the mud. My horse works just fine. I've been willing to put so much work into const because solving this problem will get us (1) and (2), and once those floodgates are open, we'll all gaze in pity at the backwards folk still using horses <g>.
Dec 29 2007
parent reply Derek Parnell <derek psych.ward> writes:
On Sat, 29 Dec 2007 11:39:14 -0800, Walter Bright wrote:

 Derek Parnell wrote:
 So I guess its not a necessary requirement but it is a nice thing to have,
 so we can lower the cost of developing acceptable applications.

Constness has 2 main uses: 1) Better specification of an API. This is of little import for smaller projects or projects done by a very small team. It becomes important for large projects worked on by diverse teams. It essentially makes explicit what things a function can be expected to change, and what things it won't change.

In short, improved "documentation".
 2) It makes functional programming possible. The plum FP gets us is it 
 opens the door to automatic parallelization of code! C++ and Java are 
 dead in the water when it comes to automatic parallelization - if there 
 are multiple cores, the app needs to be painfully and carefully recoded 
 to take advantage of them. With FP, this can be done automatically.

This sounds like your real underlying goal; to enable people to use D for FP.
 Some secondary advantages are:
 
 3) Better optimization.
 
 4) ROMable data.
 
 What languages we use definitely shape our thinking about programming. 
 C++  ... (2). Java  ...

I use neither. The languages I do use don't have much of a 'const' implementation and that has been a factor in the higher-than-acceptable cost of maintenance. I have long been sold on the benefits of being able to specify what and when data is immutable. You and I don't have an issue there. My problems with D2 revolve around the syntax you have chosen for us, and the omissions in the 'const' paradigm you have decided are acceptable for us. Both of those, I foresee, will add to the cost of maintenance. The D programming language already has too many over-used keywords and poorly chosen keywords. The current decision to reuse 'enum' for manifest constants is yet another example of a designer believing that their intuition is better than their customers', regardless of any evidence to the contrary. Please reconsider that there might be a remote possibility that this decision is actually wrong in this case; 'enum' is not the best choice for developers when it comes to declaring manifest constants. And yes, after using it for awhile we will get used to it, but that is not a reason for having it in the first place. We can get accustomed to the wart on our partners' nose but it will always be a wart. The arguments to date for 'enum' boil down to (1) its easier to implement given the current state of the D compiler, (2) C++ sort of, kind of, uses it sometimes like that, and (3) you think its better than anything else. Could it be that your point of view is not always the same as the developers' trying to use D? -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Dec 29 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Derek Parnell wrote:
 My problems with D2 revolve around the syntax you have chosen for us, and
 the omissions in the 'const' paradigm

I'm not sure what omissions you mean. The const scheme is pretty thorough end-to-end.
 you have decided are acceptable for
 us. Both of those, I foresee, will add to the cost of maintenance.

It's difficult to tell what is right without using it for a while.
 The D programming language already has too many over-used keywords and
 poorly chosen keywords.

Some have also argued that it has too many keywords, period.
 The current decision to reuse 'enum' for manifest constants is yet another
 example of a designer believing that their intuition is better than their
 customers', regardless of any evidence to the contrary. Please reconsider
 that there might be a remote possibility that this decision is actually
 wrong in this case; 'enum' is not the best choice for developers when it
 comes to declaring manifest constants.

There are a number of people who strongly feel it is the correct decision who are not vocal about it.
 And yes, after using it for awhile we will get used to it, but that is not
 a reason for having it in the first place. We can get accustomed to the
 wart on our partners' nose but it will always be a wart.
 
 The arguments to date for 'enum' boil down to (1) its easier to implement
 given the current state of the D compiler,

Actually it's easier to invent another keyword.
 (2) C++ sort of, kind of, uses it sometimes like that, and

I brought up the C++ thing in the context of showing that enum is already routinely used for similar things.
 (3) you think its better than anything else.

That's not really an argument as to why I think it's the best option <g>.
 Could it be that your point of view is not always the same as the
 developers' trying to use D?

All I can say is try using it for a while. Give it a chance, and then see what you think. I initially got criticized a lot for using !( ) for templates rather than < >, but I think that time has shown it was a good decision.
Dec 29 2007
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Sat, 29 Dec 2007 17:40:37 -0800, Walter Bright wrote:

Thank you for responding (N.B. That statement is truthful and not sarcasm)

 Derek Parnell wrote:
 My problems with D2 revolve around the syntax you have chosen for us, and
 the omissions in the 'const' paradigm

I'm not sure what omissions you mean. The const scheme is pretty thorough end-to-end.

Does the scheme allow a mutable pointer to immutable data? ?? (const int)* p Does the scheme allow an immutable pointer to mutable data? ?? (int *) const p Does the scheme allow an immutable pointer to immutable data? ?? (const int)* const p (and for completeness) Does the scheme allow a mutable pointer to mutable data? ?? int *p Can a mutable item become immutable at any time during the run time of an application? Can you take a mutable copy of any immutable item? And is the syntax to do this dependant on the data type of the original? Can you take a mutable copy of any immutable class object, struct or array? And is the syntax to do this dependant on the data type of the original?
 you have decided are acceptable for
 us. Both of those, I foresee, will add to the cost of maintenance.

It's difficult to tell what is right without using it for a while.

That idea does not apply to everything in life. I have not used cigarettes but I know they are not right. Also "goto" can be shown to increase the cost of program maintenance without having to actually use it to demostrate this effect.
 The D programming language already has too many over-used keywords and
 poorly chosen keywords.

Some have also argued that it has too many keywords, period.

I have not heard that comment from anyone.
 The current decision to reuse 'enum' for manifest constants is yet another
 example of a designer believing that their intuition is better than their
 customers', regardless of any evidence to the contrary. Please reconsider
 that there might be a remote possibility that this decision is actually
 wrong in this case; 'enum' is not the best choice for developers when it
 comes to declaring manifest constants.

There are a number of people who strongly feel it is the correct decision who are not vocal about it.

If they are not vocal, how do you know about them? Can you give numbers?
 And yes, after using it for awhile we will get used to it, but that is not
 a reason for having it in the first place. We can get accustomed to the
 wart on our partners' nose but it will always be a wart.
 
 The arguments to date for 'enum' boil down to (1) its easier to implement
 given the current state of the D compiler,

Actually it's easier to invent another keyword.

That is good news then.
 (2) C++ sort of, kind of, uses it sometimes like that, and

I brought up the C++ thing in the context of showing that enum is already routinely used for similar things.

And just like there are many of the bad things in C++ that have made it into D, right? Oh hang on, that's why you started D, to rid us of the misuse and insanity of some C++ idioms.
 (3) you think its better than anything else.

That's not really an argument as to why I think it's the best option <g>.

I know that. But it has been used anyway.
 Could it be that your point of view is not always the same as the
 developers' trying to use D?

All I can say is try using it for a while. Give it a chance, and then see what you think. I initially got criticized a lot for using !( ) for templates rather than < >, but I think that time has shown it was a good decision.

Actually I think that both < > and !() suck big time. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Dec 29 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Derek Parnell wrote:
 Does the scheme allow a mutable pointer to immutable data? 
 
 	?? (const int)* p

Yes: const(int)* p;
 Does the scheme allow an immutable pointer to mutable data? 
 
 	?? (int *) const p

No. If that's the omission you're referring to, I now understand your point.
 Does the scheme allow an immutable pointer to immutable data?
 
 	?? (const int)* const p

Yes: const(int*) p;
 (and for completeness) Does the scheme allow a mutable pointer to mutable
 data?
 
 	?? int *p

Yes: int* p;
 Can a mutable item become immutable at any time during the run time of an
 application?

Yes.
 Can you take a mutable copy of any immutable item?

Yes.
 And is the syntax to do
 this dependant on the data type of the original?

No, but if you want a deep copy, you'll have to implement .dup for your class/struct.
 Can you take a mutable copy of any immutable class object, struct or array?

Yes, but again you have to implement the dup if you want a deep copy.
 And is the syntax to do this dependant on the data type of the original?

No.
 you have decided are acceptable for
 us. Both of those, I foresee, will add to the cost of maintenance.


That idea does not apply to everything in life. I have not used cigarettes but I know they are not right.

I've never smoked because I know I'd like it, and I'd never get that monkey off my back. But there is plenty of experience on smoking - you know exactly what you're in for if you take it up.
 Also "goto" can be shown to increase the cost of program maintenance
 without having to actually use it to demostrate this effect.
 
 The D programming language already has too many over-used keywords and
 poorly chosen keywords.


I have not heard that comment from anyone.

I have.
 The current decision to reuse 'enum' for manifest constants is yet another
 example of a designer believing that their intuition is better than their
 customers', regardless of any evidence to the contrary. Please reconsider
 that there might be a remote possibility that this decision is actually
 wrong in this case; 'enum' is not the best choice for developers when it
 comes to declaring manifest constants.

decision who are not vocal about it.

If they are not vocal, how do you know about them?

They email me. There are many D users who do not participate here, but are still very much involved with D.
 Can you give numbers?

About as many as post here against it. There are also those who believe this is a tempest in a teapot, that we should be arguing about more important things :-)
 And yes, after using it for awhile we will get used to it, but that is not
 a reason for having it in the first place. We can get accustomed to the
 wart on our partners' nose but it will always be a wart.

 The arguments to date for 'enum' boil down to (1) its easier to implement
 given the current state of the D compiler,


That is good news then.
 (2) C++ sort of, kind of, uses it sometimes like that, and

already routinely used for similar things.

And just like there are many of the bad things in C++ that have made it into D, right? Oh hang on, that's why you started D, to rid us of the misuse and insanity of some C++ idioms.

I guess one man's insanity is another man's sanity! Regardless of that, however, I think the C++ usage of it shows that people aren't so terribly confused about it, even if they don't like it.
 (3) you think its better than anything else.


I know that. But it has been used anyway.
 Could it be that your point of view is not always the same as the
 developers' trying to use D?

see what you think. I initially got criticized a lot for using !( ) for templates rather than < >, but I think that time has shown it was a good decision.

Actually I think that both < > and !() suck big time.

What would you have preferred?
Dec 29 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Walter Bright wrote:
 The D programming language already has too many over-used keywords and
 poorly chosen keywords.


I have not heard that comment from anyone.

I have.

I have too, like in comments about D from non-D users on Digg. There seem to be some people who believe that number of keywords is directly related to the complexity of a language. I think the line of reasoning goes: lisp has like 3 keywords; so if you need more than 3 keywords your language must be a crappy rat trap caving in under its own complexity. Some people substitute "C" for "Lisp" or "elegance" for "simplicity". Anyway, keyword count is a very silly way to choose a programming language. I'll give you that lisp is small and elegant. But once you get up to a C-ish number of keywords (~70?) there just ain't a whole lot of difference as long as what you're adding are not commonly used variable names like 'tmp' or 'value'. Maybe someone else has better insight into the minds of these "keyword accountants" but from where I sit it just doesn't make a lot of sense to obsess over +/- a few dozen keywords in a C-like language. --bb
Dec 29 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Maybe someone else has better insight into the minds of these "keyword 
 accountants" but from where I sit it just doesn't make a lot of sense to 
 obsess over +/- a few dozen keywords in a C-like language.

By itself, it is not an issue. But it can be an indicator of sloppy design.
Dec 29 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 Maybe someone else has better insight into the minds of these "keyword 
 accountants" but from where I sit it just doesn't make a lot of sense 
 to obsess over +/- a few dozen keywords in a C-like language.

By itself, it is not an issue. But it can be an indicator of sloppy design.

Agreed. And judging a language merely by keyword count is a certain indicator of sloppy analysis :-) --bb
Dec 29 2007
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Bill Baxter wrote:
 Walter Bright wrote:
 Bill Baxter wrote:
 Maybe someone else has better insight into the minds of these 
 "keyword accountants" but from where I sit it just doesn't make a lot 
 of sense to obsess over +/- a few dozen keywords in a C-like language.

By itself, it is not an issue. But it can be an indicator of sloppy design.

Agreed. And judging a language merely by keyword count is a certain indicator of sloppy analysis :-) --bb

I honestly wonder at what point D is to be considered too wordy? I suppose it's fair to assume that the critical point is determined by the designer(s), but I do wonder how any new syntax is ever to be argued in these forums based on the fact that the designer always brings this argument into play. The general impression is "no new keywords allowed" even when they would seem to be the better option. Even so, I think new keywords will be added... they are bound to be, but only of the designer's choice. Oh well, time for me to let this rather fruitless discussion rest, I suppose. I keep forgetting how the circle goes round and round. :) -JJR
Dec 29 2007
parent bearophile <bearophileHUGS lycos.com> writes:
Too many keywords may give problems, this is a graph related to the Io language:
http://www.iolanguage.com/about/simplicity/

But I think that using the same keyword to express two or more different
meanings may be often worse. You can see a little example here:
http://www.space.unibe.ch/comp_doc/c_manual/C/SYNTAX/static.htm

At end of the page it says, regarding the C language:

For some reason, static has different meanings in in different contexts.

2. When specified with a variable inside a function, it allows the variable to retain its value between calls to the function. See static variables. It seems a little strange that the same keyword has such different meanings...< (Such meanings aren't that different...) So I often don't mind adding some new keywords. Bye, bearophile
Dec 30 2007
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Bill Baxter wrote:
 Walter Bright wrote:
 Bill Baxter wrote:
 Maybe someone else has better insight into the minds of these 
 "keyword accountants" but from where I sit it just doesn't make a lot 
 of sense to obsess over +/- a few dozen keywords in a C-like language.

By itself, it is not an issue. But it can be an indicator of sloppy design.

Agreed. And judging a language merely by keyword count is a certain indicator of sloppy analysis :-) --bb

Well said! -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jan 05 2008
prev sibling next sibling parent Derek Parnell <derek psych.ward> writes:
On Sat, 29 Dec 2007 19:24:05 -0800, Walter Bright wrote:
 All I can say is try using it for a while. Give it a chance, and then 
 see what you think. I initially got criticized a lot for using !( ) for 
 templates rather than < >, but I think that time has shown it was a good 
 decision.

Actually I think that both < > and !() suck big time.

What would you have preferred?

I don't know because I haven't put any real thought to it. It would be pointless to do so now anyway. I wait in great anticipation for the next incarnation of 'const'. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Dec 29 2007
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Walter Bright" wrote
 Derek Parnell wrote:
 Does the scheme allow a mutable pointer to immutable data? ?? (const 
 int)* p

Yes: const(int)* p;

Except in the case of class references, right? I find this to be the most unacceptable ommision. -Steve
Dec 31 2007
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Janice Caron" wrote
 On 12/31/07, Steven Schveighoffer wrote:
 Except in the case of class references, right?  I find this to be the 
 most
 unacceptable ommision.

But when are you /ever/ going to need such a thing in a real-life use case, that you couldn't just code differently?

How about doing an in-place sort of an array of const classes? const(C)[] myarray; ... // swap two items i and j auto tmp = myarray[i]; myarray[i] = myarray[j]; // error myarray[j] = tmp; // error ... Before you answer, building another array isn't acceptable, because that is a waste of resources and adds runtime. Tell me how you do this without having tail-const for class references. I couldn't care less about tail-const for structs, or tail-const for class instances (being defined as a state where the members of the class/struct are mutable, but any objects pointed to by its members are const). This feature of being able to swap two references to const data is a very common algorithmic requirement. -Steve
Dec 31 2007
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 How about doing an in-place sort of an array of const classes?

Good question, and one that I wrestled with a lot. The answer is, just like with strings, build another array.
 const(C)[] myarray;
 
 ...
 // swap two items i and j
 auto tmp = myarray[i];
 myarray[i] = myarray[j]; // error
 myarray[j] = tmp; // error
 ...
 
 Before you answer, building another array isn't acceptable, because that is 
 a waste of resources and adds runtime.

That's what our C intuition tells us, and that's why I resisted immutable strings for so long. But the way caching works on modern processors, our intuition about what is fast and slow about memory operations often is wrong. Furthermore, the bug resistance of immutable strings I believe more than makes up for it.
 Tell me how you do this without having tail-const for class references.  I 
 couldn't care less about tail-const for structs, or tail-const for class 
 instances (being defined as a state where the members of the class/struct 
 are mutable, but any objects pointed to by its members are const).  This 
 feature of being able to swap two references to const data is a very common 
 algorithmic requirement.

You're right, you cannot do it without tail-const for class references. But if you're desperate, you can make it work using casting.
Jan 01 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Walter Bright" wrote
 Steven Schveighoffer wrote:
 How about doing an in-place sort of an array of const classes?

Good question, and one that I wrestled with a lot. The answer is, just like with strings, build another array.
 const(C)[] myarray;

 ...
 // swap two items i and j
 auto tmp = myarray[i];
 myarray[i] = myarray[j]; // error
 myarray[j] = tmp; // error
 ...

 Before you answer, building another array isn't acceptable, because that 
 is a waste of resources and adds runtime.

That's what our C intuition tells us, and that's why I resisted immutable strings for so long. But the way caching works on modern processors, our intuition about what is fast and slow about memory operations often is wrong. Furthermore, the bug resistance of immutable strings I believe more than makes up for it.

I think we are arguing different points here. I am fine with const(T) meaning that T is const whether it be a class reference, or a struct, or primitive type. I absolutely agree with that, and think it is required as you say. My problem is that because classes are inherently references, you have to treat them that way, especially in regards to const. If you can't split out the reference from the const-ness, then code is going to be extra awkward, and require workarounds that will at some point affect the complexity of algorithms. I suppose my example is incorrectly stated, because with the current const system, you cannot state 'an array of mutable references to const classes'. So I agree that with an array of const class references: const(C)[] myarray; you should not be able to swap members. But there should still be a way to specify an array of mutable references to const classes. I don't care how it's done, but it cannot involve convoluted mechanisms to create backing arrays w/ pointers to references. To have to allocate heap space to contain pointers when classes are already pointers seems inherently wasteful, and seems like I am fighting the language instead of having the language allow me to express what I want. This is similar to not having constructors for structs. If I want to create a const struct on the heap so I can store it somewhere outside the stack, instead of having a constructor I have to do: S *s = new S; s.value = 5; const(S)*cs = s; instead of: const(S)*cs = new S(5); Except in this case, the compiler can easily optimize the first to mean the second, and no bloat or runtime waste has occurred, because I'm just re-casting the pointer. However for classes, I need: C c = new C(5); C *cp = new C*; *cp = c; const(C)* ccp = cp; Now, I have an extra heap-allocated pointer for no good reason, and this is not optimized out by the compiler.
 Tell me how you do this without having tail-const for class references. 
 I couldn't care less about tail-const for structs, or tail-const for 
 class instances (being defined as a state where the members of the 
 class/struct are mutable, but any objects pointed to by its members are 
 const).  This feature of being able to swap two references to const data 
 is a very common algorithmic requirement.

You're right, you cannot do it without tail-const for class references. But if you're desperate, you can make it work using casting.

Sure, but the behavior is undefined, right? :P
Jan 02 2008
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Janice Caron wrote:
 It is. I know that's not immediately obvious, but if you follow
 through all the arguments (which I don't want to repeat coz they're
 long and complicated) you eventually have to conclude it can't be
 done.

The best analogy I have come up with is attempting to make a square out of 4 line segments, 1 of which is a different length than the other 3. No matter how you try and fit the segments together, there's a gap somewhere or an angle that isn't 90 degrees. That's what always happened when we tried to make an exception to the const rules. There was always a gap or a bad angle popping up somewhere ugly. C++ made special case exceptions to the way its const worked, ones that seemed to make sense at the time, but the odd problems kept cropping up, and I've been told by metaprogramming experts that the whole system is coming unglued with advanced metaprogramming attempts. That's why the new const regime is 'pure' in that there are no exceptions to the rules. It's end-to-end straightforward.
Jan 01 2008
prev sibling next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 
 It is. I know that's not immediately obvious, but if you follow
 through all the arguments (which I don't want to repeat coz they're
 long and complicated) you eventually have to conclude it can't be
 done.

It would be great if someone who understands it could write down the rationale that lead to the current system. I'm not very convinced by "trust me I thought of everything". Even when it's myself who thinks he thought of everything, I don't really believe it till I write it all down and see that the reasoning still stands up. --bb
Jan 01 2008
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 On 1/1/08, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 Janice Caron wrote:
 It is. I know that's not immediately obvious, but if you follow
 through all the arguments (which I don't want to repeat coz they're
 long and complicated) you eventually have to conclude it can't be
 done.

rationale that lead to the current system. I'm not very convinced by "trust me I thought of everything". Even when it's myself who thinks he thought of everything, I don't really believe it till I write it all down and see that the reasoning still stands up.

Quite right. I absolutely agree completely. No one should ever be convinced by "trust me I thought of everything". The rationale that leads to the current system is in this forum though. It's /a lot/ of reading. It essentially consists of all of the arguments and counterarguments about const that have gone on in the past several months. For this /particular/ piece of the argument, the next stage of reasoning would likely go like this: A: It is an unacceptable omission that there is no way to specify mutable reference to const class data B: Then let us proceed by reductio ad absurdum. Please unambiguously specify exactly what you want, and then I will show that it leads to a contradiction. A is then either unable to unambiguously specify exactly what they want, or the argument proceeds to the next stage. But eventually, it will hit a brick wall.

What was the fundamental problem with creating some syntax that would let you peel the reference part off a class reference? Anyway I like the concept of the new const regime being lean and mean and covering the common cases with no exceptions to the rules. If that works out then great. But even if experience eventually reveals that some exceptions are actually needed, it's much better to be starting from something clean. --bb
Jan 01 2008
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 On 1/1/08, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 What was the fundamental problem with creating some syntax that would
 let you peel the reference part off a class reference?


Thanks for taking the time to write out the explanation below.
 It needs to be defined for all types, not just classes. If C is a
 class, and we define
 
     const(C)&
 
 to mean mutable-reference-to-const-data, then you have only
 /partially/ defined &. You need to define it for all types. You need
 to define what
 
     const(T)&
 
 means, for all possible types T. You need to define it for each of the cases:
 
     T is a primitive type
     T is a pointer to U
     T is an array of U
     T is an associative array of U[V]
     T is a struct
     T is a union
     T is a function
     T is a delegate
     T is a typedef
     T is a named enum
 
 Until it is fully defined, it is not possible to discuss its
 consequences. The fundamental problem is, things start to fall over
 when you start trying to define it for struct and union.

Seems easy enough. Just make it mean no-op for the things where it doesn't make sense, namely things that aren't pointers. struct Struct { int* p; int v; } class Class { int* p; int v; } const(int*)& equiv to const(int)* const(int)& equiv to const(int) const(Struct*)& equiv to const(Struct)* const(Struct)& equiv to const(Struct) const(Class)& equiv to const(Class)& So this doesn't seem to be the point yet where "things start to fall over" that you speak of. --bb
Jan 01 2008
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 What was the fundamental problem with creating some syntax that would 
 let you peel the reference part off a class reference?

const(C)&[] a; is a sortable array of constant C's. But what is: const(int)&[] a; Is it sortable or not? If it is sortable, then & means "tail const". If it is not sortable, then how, in generic code, do we specify a sortable array of type T? const(T)&[] a; // is it sortable or not? Now, if & is to mean "tail const", what do we do with: struct S { int i; int* p; void foo() { *p = 3; } } const(S)& s; Does that mean we can modify the members of S, but not what those members may point to? How do we specify that member function foo is "tail const" ? And what do we do with: struct S { C c; } const(S)&[] a; Here, we've wrapped a class with a struct. Is it possible to make S behave like its underlying C? If not, we don't have general purpose UDTs. We have a heaping pile of special cases.
Jan 01 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Walter Bright" wrote
 Bill Baxter wrote:
 What was the fundamental problem with creating some syntax that would let 
 you peel the reference part off a class reference?

const(C)&[] a; is a sortable array of constant C's. But what is: const(int)&[] a;

A sortable array of int references. If references are to be consistent, the meaning of an int reference is that it acts like an int until you assign to another int reference. If you assign it to another int reference, then type now references the same thing as the new int reference. If you assign it to another int, that is a compiler error (can't assign a non reference value to a reference just like you can't assign a non pointer value to a pointer).
 Is it sortable or not? If it is sortable, then & means "tail const". If it 
 is not sortable, then how, in generic code, do we specify a sortable array 
 of type T?

You are missing the point. & does not mean tail const. const(int)*[] a; This is an array of int pointers that are TAIL CONST. This does not mean * is tail const, does it? & means 'a reference to', just like * means 'a pointer to'. There is no ambiguity, no inconsistency, no violation of const rules.
 const(T)&[] a; // is it sortable or not?

 Now, if & is to mean "tail const", what do we do with:

 struct S
 { int i;
   int* p;
   void foo() { *p = 3; }
 }

 const(S)& s;

 Does that mean we can modify the members of S, but not what those members 
 may point to? How do we specify that member function foo is "tail const" ?

Nope, it means you cannot modify members of S and you cannot call foo because it is not const. const(S)& is a mutable reference to a const S just like const(S)* is a mutable pointer to a const S.
 And what do we do with:

 struct S { C c; }
 const(S)&[] a;

 Here, we've wrapped a class with a struct. Is it possible to make S behave 
 like its underlying C? If not, we don't have general purpose UDTs. We have 
 a heaping pile of special cases.

Why wouldn't you be able to? The only overload that you cannot change is the assignment to another S reference. You can overload assign to a C, because it is not a reference to an S. In this case however, since S is const, you cannot assign to another C, just like you wouldn't be able to assign a C to a const(C). You may look at this whole post and think "ok, & is just like *, why even have &?", well, the point is, for classes, & is a reference to the class data, not a reference to a class reference. So for a class C, C& x is equivalent to C x. The thing & gets us is a way to specify universally 'reference to'. This would actually be very beneficial to generic programming. There is one other possibility that you have not (at least publicly) considered, which I outlined in my post on 12/7 titled "The problem with const (and a solution)": const(*C)*[] array; This would be an array of mutable class references. Having this possibility gives us at least a way to specify tail-const class references. This solution has the benefit of not introducing references to other types (which would be a lot of work for you). My preference is to have the reference operator, & if possible, but the *C solution is at least workable. One further thing. If you could at least pledge to have a way to specify a tail-const class reference before 2.0 is officially released, I would be willing to accept that for now. I understand that adding something like the reference operator would be a lot of extra work besides the const stuff, so I would understand if you did your current const proposal with the intent of doing the reference work later. -Steve
Jan 02 2008
next sibling parent reply "Bruce Adams" <tortoise_74 yeah.who.co.uk> writes:
On Wed, 02 Jan 2008 17:53:28 -0000, Steven Schveighoffer  =

<schveiguy yahoo.com> wrote:

 If you do:

 setValueTo5(T)(T x)
 {
    x.value =3D 5;
 }

 If T is a class, then it affects data outside the function.  If T is a=

 struct, it does not.  We have to know if T is a class or not.

You seem to be talking about purity rather than constness here.
Jan 02 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Bruce Adams" wrote
On Wed, 02 Jan 2008 17:53:28 -0000, Steven Schveighoffer wrote:

 If you do:

 setValueTo5(T)(T x)
 {
    x.value = 5;
 }

 If T is a class, then it affects data outside the function.  If T is a
 struct, it does not.  We have to know if T is a class or not.

You seem to be talking about purity rather than constness here.

This example has nothing to do with const :) What I'm talking about is the argument against my idea. The argument is that it is impossible to implement a tail-const reference to a class because anything you do results in you having to know whether a generic type is a class or not. For example, if const(*C)* is a tail-const reference to a class C, then the generic code: f(T)(const(*T)* x) {....} Will only compile for T's that are reference types (i.e. classes or pointers). The argument is that this is not desired, because no matter what we do, we should be able to substitute any type in there and have it work. My counter-argument is that there are already inconsistencies between classes and structs and primitives, in that classes are references and you have to treat them as such. Since we may already need to check if a type in a template is a reference or non-reference type, the original argument that my const ideas cannot be implemented is contradictory. You can't say the new behavior violates some rule when the current behavior already violates that rule. My point is, the rule is incorrect, not the behavior. -Steve
Jan 02 2008
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Janice Caron wrote:
 But whatever the syntax, I must conclude that it can't be done,
 without violating one or more of the principles of D, and that's what
 Walter (and I) are trying to explain here.

You pick over cases where this is clearly the case; those where it is not clear, you just say this and no more. You could at least provide a link to the relevant discussions in webnews. Otherwise, I have no reason to believe you and every reason to doubt.
 If references are to be consistent, the
 meaning of an int reference is that it acts like an int until you assign to
 another int reference.  If you assign it to another int reference, then type
 now references the same thing as the new int reference.  If you assign it to
 another int, that is a compiler error (can't assign a non reference value to
 a reference just like you can't assign a non pointer value to a pointer).

D doesn't have a reference-to-int type, only reference-to-class-data.

We do, actually: int*.
 This appears to be a new feature request.

Yup. Because it looks kludgy to use const(T)*, and it looks kludgy to use const(T), and so I'm betting const will be used as often in D as in C++.
 One further thing.  If you could at least pledge to have a way to specify a
 tail-const class reference before 2.0 is officially released, I would be
 willing to accept that for now.

Walter cannot do that without sacrificing generic programming.

Well, the thing is, we already have a technique to get tailconst anything, and that's using a pointer. As far as I can tell, people just want a prettier syntax for using mutable pointers to const data, and an equivalent to const(Object)* that involves one pointer dereference instead of two to access the object. Pretty syntax isn't a minor thing, either. Also, there's the problem, with pointers: const(T)*[] array = init_array(); array.sort; // sorts according to pointer values -- eep! This can mess with generic programming, too: struct S { int i; } void reset_first_element(T)(array[] array) { static if (is (T == class)) { array[0] = new T(); } else { array[0] = T.init; } } const(S)*[] array = init_array(); reset_first_element(array); (channeling Gunther Hermann) I wanted *array[0] == S.init. It gave me segmentation fault. Then the 'right' way would be something like: void reset_first_element(T)(array[] array) { static if (is (T == class)) { array[0] = new T(); } else static if (is (T == const(U)*, U)) { static if (is (T == class)) { *array[0] = new U(); } else { *array[0] = U.init; } } else { array[0] = T.init; } } And that doesn't distinguish between situations where I want a reference and I want an actual pointer. Basically, references solve a bunch of problems with const and with generic programming. The previous example becomes: void reset_first_element(T)(array[] array) { static if (is (T == class)) { array[0] = new T(); } else static if (is (T == U&, U)) { array[0] = U.init; } else { array[0] = T.init; } } Or maybe, depending on what T&.init is, you could eliminate the second element. C# did something clever: for any value type T, new T() returns T.init. This makes sense; for value type T, T.init is usually sensible, or at least a lot more useful than null. So you'd get: void reset_first_element(T)(array[] array) { static if (is (T == U&, U)) { array[0] = new U(); } else { array[0] = new T(); } } Or even: void reset_first_element(T)(array[] array) { array[0] = new T(); } Whether it's desirable for D is another matter.
Jan 02 2008
prev sibling next sibling parent Christopher Wright <dhasenan gmail.com> writes:
Janice Caron wrote:
 On 12/31/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 ...and that would work now.

space and extra processing, and creating such an array is too complicated.

Too complicated? const(C)*[] addPointers(const(C)[] a) { const(C)*[] r; foreach(i,e:a) { r ~= a.ptr + i; } return r; } const(C)[] removePointers(const(C)*[] a) { const(C)[] r; foreach(p:a) { r ~= *p; } return r; } It's a few extra lines of code, that's all. I'm not saying this is a generic solution which will solve every problem you can think of, but the point is, there are always workarounds. On the other hand, adding a tailconst function to D would wreck the type system. I wouldn't want a const(int)[] array to be mutable, and likewise I wouldn't want a const(C)[] array to be mutable. Once upon a time I argued for the syntax "const(C)&[]", but Walter patiently explained why that would cause insurmountable problems elsewhere. So it's one of those "lesser of two evils" things. Make the programmer think a bit and do things differently, versus wreck the type system. I think Walter made the right choice.

Insurmountable problems with templates? Not really; you'd just have to make the unary post-& more general, referring to the reference for classes and an automatically dereferenced pointer for value types. Which is a decently large change, but it wouldn't break any existing code. Then you're basically left with your pointer workaround, but you don't have to think about that fact unless you're creating the array. This wouldn't break the type system, as far as I can tell. It's essentially converting reference types to value types when you declare a special kind of pointer to them. Or leaving reference types alone and converting value types to reference types. But it won't be implemented, so there's no point in me discussing it further.
Jan 01 2008
prev sibling next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 1/2/08, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 Seems easy enough.  Just make it mean no-op for the things where it
 doesn't make sense, namely things that aren't pointers.

 struct Struct { int* p; int v; }
 class Class { int* p; int v; }

 const(int*)&     equiv to  const(int)*
 const(int)&      equiv to  const(int)
 const(Struct*)&  equiv to  const(Struct)*
 const(Struct)&   equiv to  const(Struct)
 const(Class)&    equiv to  const(Class)&

OK, at this point, arguments start to happen, because not everyone will agree on those definitions. For example, further down this thread, Stephen Schveighoffer argues that "If references are to be consistent, the meaning of an int reference is that it acts like an int until you assign to another int reference". Instantly, much confusion abounds because now people are arguing about what int& should mean, instead of what actually happens when you nail down a definition. But to avoid confusion here, we'll go with /your/ definition...
 So this doesn't seem to be the point yet where "things start to fall
 over" that you speak of.

Using your definitions, the compiler is unable to tell whether or not the following is OK: void f(T)(const(T)&[] a) { a[0] = a[1]; } This violates the D compiler rule of "context free grammar". Of course you could define & differently, so that that particular problem does not arise - for example by inventing generic C++-like references to all types (which I believe is what Stephen suggests), but you will find then that /different/ problems arise.
Jan 02 2008
prev sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 1/2/08, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 "Walter Bright" wrote
 Bill Baxter wrote:
 What was the fundamental problem with creating some syntax that would let
 you peel the reference part off a class reference?

const(C)&[] a; is a sortable array of constant C's. But what is: const(int)&[] a;

A sortable array of int references.

Now observe. Bill's idea of what & should mean is /different/ from Stephen's idea of what & should mean. Here, Walter responds to Bill's interpretation of what & should mean, and is immediately lambasted by Stephen who interprets it differently. This puts poor Walter in a hopeless position. I really have sympathy for him. I have come to the conclusion that /no/ syntax for references and/or tail constancy is devoid of its own insurmountable problems, but this is just very, very hard to get across because everyone is using different words for the same thing and/or the same word for different things. We could probably have simplified the discussion a bit by saying: assume the syntax for mutable-ref-to-const data is "tailconst(T)", rather than "const(T)&", and then we wouldn't have got sidetracked into what "&" means in isolation. But whatever the syntax, I must conclude that it can't be done, without violating one or more of the principles of D, and that's what Walter (and I) are trying to explain here.
 If references are to be consistent, the
 meaning of an int reference is that it acts like an int until you assign to
 another int reference.  If you assign it to another int reference, then type
 now references the same thing as the new int reference.  If you assign it to
 another int, that is a compiler error (can't assign a non reference value to
 a reference just like you can't assign a non pointer value to a pointer).

D doesn't have a reference-to-int type, only reference-to-class-data. This appears to be a new feature request.
 You may look at this whole post and think "ok, & is just like *, why even
 have &?", well, the point is, for classes, & is a reference to the class
 data, not a reference to a class reference.  So for a class C, C& x is
 equivalent to C x.  The thing & gets us is a way to specify universally
 'reference to'.  This would actually be very beneficial to generic
 programming.

That leads to different problems. I know because that used to be my idea, until I got persuaded I was wrong.
 const(*C)*[] array;

 This would be an array of mutable class references.

It doesn't matter what the syntax is. We can pick amonst syntaxes till the cows come home. But whatever syntax you choose, you're still going to have to answer the question "what happens when C isn't a class?" (and cover all possible other types). And that's when problems start.
 One further thing.  If you could at least pledge to have a way to specify a
 tail-const class reference before 2.0 is officially released, I would be
 willing to accept that for now.

Walter cannot do that without sacrificing generic programming.
Jan 02 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Janice Caron" wrote
 On 1/2/08, Steven Schveighoffer wrote:
 "Walter Bright" wrote
 Bill Baxter wrote:
 What was the fundamental problem with creating some syntax that would 
 let
 you peel the reference part off a class reference?

const(C)&[] a; is a sortable array of constant C's. But what is: const(int)&[] a;

A sortable array of int references.

Now observe. Bill's idea of what & should mean is /different/ from Stephen's idea of what & should mean. Here, Walter responds to Bill's interpretation of what & should mean, and is immediately lambasted by Stephen who interprets it differently.

Bill's idea in this statement above was congruent with my idea. In Bill's statement above, he states that there should be some syntax that allows you to peel the reference part off a class reference, which is encompassed by my idea as well. Bill's response to Walter's statement in a different thread is not in congruence with mine, but as this is a new syntax, we are both allowed to interpret what we think it should be. There is no previous definition here, Bill and I are not on a side together arguing the same thing.
 This puts poor Walter in a hopeless position. I really have sympathy for 
 him.

Walter is a big boy. I'm sure he can figure out how to sort through all the subtle differences in feature requests made on this forum.
 We could probably have simplified the discussion a bit by saying:
 assume the syntax for mutable-ref-to-const data is "tailconst(T)",
 rather than "const(T)&", and then we wouldn't have got sidetracked
 into what "&" means in isolation.

 But whatever the syntax, I must conclude that it can't be done,
 without violating one or more of the principles of D, and that's what
 Walter (and I) are trying to explain here.

I do not wish to have tailconst structures or tailconst builtin types (such as int). What I want are consistent tailconst references. The fact that I can specify a tailconst reference (pointer) to a struct or int, but not a tailconst reference to a class is a big hole in my opinion.
 If references are to be consistent, the
 meaning of an int reference is that it acts like an int until you assign 
 to
 another int reference.  If you assign it to another int reference, then 
 type
 now references the same thing as the new int reference.  If you assign it 
 to
 another int, that is a compiler error (can't assign a non reference value 
 to
 a reference just like you can't assign a non pointer value to a pointer).

D doesn't have a reference-to-int type, only reference-to-class-data. This appears to be a new feature request.

Yes it is. That was not a secret :) Please view my post on 12/7 describing my original idea.
 You may look at this whole post and think "ok, & is just like *, why even
 have &?", well, the point is, for classes, & is a reference to the class
 data, not a reference to a class reference.  So for a class C, C& x is
 equivalent to C x.  The thing & gets us is a way to specify universally
 'reference to'.  This would actually be very beneficial to generic
 programming.

That leads to different problems. I know because that used to be my idea, until I got persuaded I was wrong.

That anyone got persuaded that something is wrong is not proof that it is wrong. "this leads to different problems" is not an explanation.
 const(*C)*[] array;

 This would be an array of mutable class references.

It doesn't matter what the syntax is. We can pick amonst syntaxes till the cows come home. But whatever syntax you choose, you're still going to have to answer the question "what happens when C isn't a class?" (and cover all possible other types). And that's when problems start.

If C isn't a reference type, then it doesn't compile. struct S {}; class C {}; alias S *X; alias int *Y; const(*X)*[] array; // compiles, X is a reference type const(*Y)*[] array; // compiles, Y is a reference type. const(*C)*[] array; // compiles, C is a reference type. const(*S)*[] array; // failure, S is a value type, cannot be dereferenced. const(*int)*[] array; // failure, int is a value type, cannot be dereferenced const(*C)[] array; // failure, cannot declare a value type of *C. Generic programming is already "broken" as you say because you can't treat a class as a value type. There are differences which must be accounted for. For example: class (T) C { T x; this(int m) { // initialize T with m, assuming T is a class x = new T(m); } } What happens if T is a struct or int? There is no generic way to do it.
 One further thing.  If you could at least pledge to have a way to specify 
 a
 tail-const class reference before 2.0 is officially released, I would be
 willing to accept that for now.

Walter cannot do that without sacrificing generic programming.

Allowing *C syntax would not break anything that is not already broken. If you have an example of why it would break generic programming, please share with us. And I invite Walter to still respond to this personally. -Steve
Jan 02 2008
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Janice Caron wrote:
 On 12/31/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 Except in the case of class references, right?  I find this to be the most
 unacceptable ommision.

But when are you /ever/ going to need such a thing in a real-life use case, that you couldn't just code differently?

Going through the thought process, I finally realized that a true reference type (which is what classes are) should look to the user like a value type, i.e. the reference part should not be separable from the value.
 I thought that ommission was bad at first too, until I thought it
 through. But Walter's right - its absence doesn't present any real
 programming problems. There's really nothing you can't just do another
 way. By contrast, its presence would really screw up the type system.
 Weighing up the pros and cons, I'd say its better to live with this
 than have to deal with all the complication that
 mutable-ref-to-const-heap-data would entail.

It's interesting how having fully transitive const seems to affect the way you code and your notions about coding.
Jan 01 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Walter Bright" wrote
 Janice Caron wrote:
 On 12/31/07, Steven Schveighoffer wrote:
 Except in the case of class references, right?  I find this to be the 
 most
 unacceptable ommision.

But when are you /ever/ going to need such a thing in a real-life use case, that you couldn't just code differently?

Going through the thought process, I finally realized that a true reference type (which is what classes are) should look to the user like a value type, i.e. the reference part should not be separable from the value.

I'm not asking to have the value seperable from the reference. I'm asking to have the ability to modify the constness of the value seperately from the constness of the reference.
 I thought that ommission was bad at first too, until I thought it
 through. But Walter's right - its absence doesn't present any real
 programming problems. There's really nothing you can't just do another
 way. By contrast, its presence would really screw up the type system.
 Weighing up the pros and cons, I'd say its better to live with this
 than have to deal with all the complication that
 mutable-ref-to-const-heap-data would entail.

It's interesting how having fully transitive const seems to affect the way you code and your notions about coding.

I have no problem with fully transitive const, and I think it's a much better improvement over C++. I originally thought fully transitive const was an error, because there are rational reasons to want to have 'logical' const. But in reality, logical const is just not const, and should be treated that way. But the difference here is, having to port code due to transitive const does not add code bloat or affect runtime execution. Having to port code due to not having tail-const class references does. -Steve
Jan 02 2008
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 1/1/08, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 What was the fundamental problem with creating some syntax that would
 let you peel the reference part off a class reference?

It needs to be defined for all types, not just classes. If C is a class, and we define const(C)& to mean mutable-reference-to-const-data, then you have only /partially/ defined &. You need to define it for all types. You need to define what const(T)& means, for all possible types T. You need to define it for each of the cases: T is a primitive type T is a pointer to U T is an array of U T is an associative array of U[V] T is a struct T is a union T is a function T is a delegate T is a typedef T is a named enum Until it is fully defined, it is not possible to discuss its consequences. The fundamental problem is, things start to fall over when you start trying to define it for struct and union.
Jan 01 2008
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Derek Parnell wrote:
 
 The current decision to reuse 'enum' for manifest constants is yet 
 another
 example of a designer believing that their intuition is better than their
 customers', regardless of any evidence to the contrary. Please reconsider
 that there might be a remote possibility that this decision is actually
 wrong in this case; 'enum' is not the best choice for developers when it
 comes to declaring manifest constants.

There are a number of people who strongly feel it is the correct decision who are not vocal about it.

I don't suppose the use of 'enum' in this context has had any impact on named enumerations? ie. We still cannot have a named enum which contains strings, correct? Also, are traditional unnamed enums still legal? enum { a, b, c } enum : long { d, e, f } Sean
Jan 01 2008
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Sean Kelly wrote:
 Walter Bright wrote:
 Derek Parnell wrote:

 The current decision to reuse 'enum' for manifest constants is yet 
 another
 example of a designer believing that their intuition is better than 
 their
 customers', regardless of any evidence to the contrary. Please 
 reconsider
 that there might be a remote possibility that this decision is actually
 wrong in this case; 'enum' is not the best choice for developers when it
 comes to declaring manifest constants.

There are a number of people who strongly feel it is the correct decision who are not vocal about it.

I don't suppose the use of 'enum' in this context has had any impact on named enumerations? ie. We still cannot have a named enum which contains strings, correct? Also, are traditional unnamed enums still legal? enum { a, b, c } enum : long { d, e, f }

err... assume there are values assigned to the members above. Sean
Jan 01 2008
parent Sean Kelly <sean f4.ca> writes:
Sean Kelly wrote:
 Sean Kelly wrote:
 Walter Bright wrote:
 Derek Parnell wrote:

 The current decision to reuse 'enum' for manifest constants is yet 
 another
 example of a designer believing that their intuition is better than 
 their
 customers', regardless of any evidence to the contrary. Please 
 reconsider
 that there might be a remote possibility that this decision is actually
 wrong in this case; 'enum' is not the best choice for developers 
 when it
 comes to declaring manifest constants.

There are a number of people who strongly feel it is the correct decision who are not vocal about it.

I don't suppose the use of 'enum' in this context has had any impact on named enumerations? ie. We still cannot have a named enum which contains strings, correct? Also, are traditional unnamed enums still legal? enum { a, b, c } enum : long { d, e, f }

err... assume there are values assigned to the members above.

Seems it does still work that way. It's not a big thing, but is perhaps worth mentioning that the new enum feature does change the behavior of existing code: enum { a = byte.max } void main( char[][] args ) { printf( "%.*s: %d\n", typeid(typeof(a)).toString, a ); } Under D 1.0 this prints: int: 127 And under D 2.0 this prints: byte: 127 I can see this causing occasional rare problems for code transitioning to 2.0, but probably nothing serious. Fortunately, this is disallowed in 1.0: enum { a = long.max } Sean
Jan 01 2008
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Sean Kelly wrote:
 I don't suppose the use of 'enum' in this context has had any impact on 
 named enumerations?  ie. We still cannot have a named enum which 
 contains strings, correct?

You can do named enums with strings now.
 Also, are traditional unnamed enums still 
 legal?

Yes.
 enum
 {
     a, b, c
 }
 
 enum : long
 {
     d, e, f
 }

Jan 01 2008
parent Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Sean Kelly wrote:
 I don't suppose the use of 'enum' in this context has had any impact 
 on named enumerations?  ie. We still cannot have a named enum which 
 contains strings, correct?

You can do named enums with strings now.

Really? Well that eliminates a lot of my issues with consistency. Sean
Jan 03 2008
prev sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Walter Bright wrote:
 
 The current decision to reuse 'enum' for manifest constants is yet
 another example of a designer believing that their intuition is better
 than their customers', regardless of any evidence to the contrary. Please
 reconsider that there might be a remote possibility that this decision is
 actually wrong in this case; 'enum' is not the best choice for developers
 when it comes to declaring manifest constants.

There are a number of people who strongly feel it is the correct decision who are not vocal about it.

It is hard to try to be involved (in any capacity) with D language evolution when there are silent (or rather non-public) opinions that weighs more than this newsgroup, and I think as people on the newsgroup figures this out, it will be a loss for D. In earlier situations that are similar to this one, it has always looked like the unvocal persons are C++-users, thus we end up in a very C++ inspired language when that often is definately not what we want. If one were to have a "panel" of experienced users, one should strive to have one with equally much experience in the various big languages (too bad that it is hard finding anyone with 10+ years in Java and 5+ in C#). As it is now, the overweight of C++ seems to be too big (from the outside), which sounds doubly bad considering D is touted as a language fixing C++ mistakes. Most C++-users I know refuse to even acknowledge that C++ is bad.
 (2) C++ sort of, kind of, uses it sometimes like that, and

I brought up the C++ thing in the context of showing that enum is already routinely used for similar things.

The problem with this argument is that it appears that this is a typical "feature" of C++ that D should claim to fix. Instead it is copied, bringing a seemingly bad convention into D. There is plenty of opportunity to fix this upfront, and it is not taken.
 Could it be that your point of view is not always the same as the
 developers' trying to use D?

All I can say is try using it for a while. Give it a chance, and then see what you think. I initially got criticized a lot for using !( ) for templates rather than < >, but I think that time has shown it was a good decision.

It is hard to know, but I believe that by gouging the opinions in the newsgroup and in the IRC channels, you'll get a rather representative set, and if that is the case, the majority does not want enum, but rather manifest (or pure as Don suggested some time ago). -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 01 2008
next sibling parent reply Michiel Helvensteijn <nomail please.com> writes:
Lars Ivar Igesund wrote:

 If one were to have a "panel" of experienced users, one should strive to
 have one with equally much experience in the various big languages (too
 bad that it is hard finding anyone with 10+ years in Java and 5+ in C#).
 As it is now, the overweight of C++ seems to be too big (from the
 outside), which sounds doubly bad considering D is touted as a language
 fixing C++ mistakes. Most C++-users I know refuse to even acknowledge that
 C++ is bad.

C++ user here. C++ and Java are both just hopelessly outdated. However, when C++ was new it was the best language of its type around. And after many years of use it has become extremely stable and reliable. Because it is so popular, it is also impossible to change the meaning of anything as often used as enum. I will agree that C++ is not perfect. But it is not bad. If you claim it is, I'd like to hear some arguments. At first I really liked the D specs. The explicit contracts / invariants / unittests, the useful template possibilities, the variadic functions, to name a few. But right now D seems far too unstable and convoluted for me. It's already past version 1, well into 2 and already planning for 3. Not so much fixing and stabilizing (or, you know, standardizing) the existing language as adding more and more features. I'm glad I have something as reliable as C++ to work with. Now I will admit that I haven't used D for some time and am mostly going by what I read in this newsgroup. And I'll be happy to hear counter-arguments. -- Michiel
Jan 01 2008
next sibling parent John Reimer <terminal.node gmail.com> writes:
Michiel Helvensteijn wrote:
 Lars Ivar Igesund wrote:
 
 If one were to have a "panel" of experienced users, one should strive to
 have one with equally much experience in the various big languages (too
 bad that it is hard finding anyone with 10+ years in Java and 5+ in C#).
 As it is now, the overweight of C++ seems to be too big (from the
 outside), which sounds doubly bad considering D is touted as a language
 fixing C++ mistakes. Most C++-users I know refuse to even acknowledge that
 C++ is bad.

C++ user here. C++ and Java are both just hopelessly outdated. However, when C++ was new it was the best language of its type around. And after many years of use it has become extremely stable and reliable. Because it is so popular, it is also impossible to change the meaning of anything as often used as enum. I will agree that C++ is not perfect. But it is not bad. If you claim it is, I'd like to hear some arguments. At first I really liked the D specs. The explicit contracts / invariants / unittests, the useful template possibilities, the variadic functions, to name a few. But right now D seems far too unstable and convoluted for me. It's already past version 1, well into 2 and already planning for 3. Not so much fixing and stabilizing (or, you know, standardizing) the existing language as adding more and more features. I'm glad I have something as reliable as C++ to work with. Now I will admit that I haven't used D for some time and am mostly going by what I read in this newsgroup. And I'll be happy to hear counter-arguments.

There is a bit of confusion around D versions, and it seems to be a result of the versioning system in use. * D 1.x represents the stable version of D; bugs continue to be fixed; no new features are added (nor are features usually removed). * D 2.x is really just the experimental/developmental version of D (think 1.9999); it's not intended to be stable or even used for general development; new features are added, changed, and removed with almost every release. I think it was somewhat of a mistake calling it D 2.0 because it confuses people into thinking it's a final release. -JJR
Jan 01 2008
prev sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Michiel Helvensteijn wrote:

 Lars Ivar Igesund wrote:
 
 If one were to have a "panel" of experienced users, one should strive to
 have one with equally much experience in the various big languages (too
 bad that it is hard finding anyone with 10+ years in Java and 5+ in C#).
 As it is now, the overweight of C++ seems to be too big (from the
 outside), which sounds doubly bad considering D is touted as a language
 fixing C++ mistakes. Most C++-users I know refuse to even acknowledge
 that C++ is bad.

C++ user here.

Previous user here (may still return for the right contract, but it is unlikely).
 
 C++ and Java are both just hopelessly outdated. However, when C++ was new
 it was the best language of its type around. And after many years of use
 it has become extremely stable and reliable. 

This weren't the truth only a few years ago, when any cross platform use made exceptions and anything but trivial templates banned from the projects I worked on. If the specification is too difficult to implement in homogenous way, then I won't call it reliable (although the spec itself is stable).
 Because it is so popular, it 
 is also impossible to change the meaning of anything as often used as
 enum.

Sure. I accept that there won't be more changes to D 1.0
 
 I will agree that C++ is not perfect. But it is not bad. If you claim it
 is, I'd like to hear some arguments.

And sure C++ is not the worst thing ever. Overall, I consider it bad. I'm bad at good argumentation over this, but after I've been using D and Java (and a very short bout of C#) for some years after I did any serious C++, I am convinced, deep into my heart, that most details (often just syntactical stuff! The features are mostly good, and it certainly creates fast executables) can be improved upon, and often in a major way. D shows this. C++ is a very big language, bigger yet than D (at least as far as the spec goes) and almost everything is possible through some (probably) non-intential way that has become convention and rooted into specification and/or use-base libraries. The thing here is that those conventions tend to crop up in the D discussions as good reasons to do those things the same way in D, and _that_ is what frustrates me. I do _not_ think overloading a keyword with a new meaning in anyway reduce language bloat (the feature is still there, even if it don't have a keyword of its own).
 
 At first I really liked the D specs. The explicit contracts / invariants /
 unittests, the useful template possibilities, the variadic functions, to
 name a few. But right now D seems far too unstable and convoluted for me.
 It's already past version 1, well into 2 and already planning for 3. Not
 so much fixing and stabilizing (or, you know, standardizing) the existing
 language as adding more and more features. I'm glad I have something as
 reliable as C++ to work with.

As has been pointed out, the versioning of D is a bigger problem than stability itself as it is confusing. 1.0xx is stable, 2.0xx is not (and I have no idea how the version is meant to look when it becomes stable). -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 01 2008
parent reply Michiel Helvensteijn <nomail please.com> writes:
Lars Ivar Igesund wrote:

 C++ is a very big language, bigger yet than D (at least as far as
 the spec goes) and almost everything is possible through some (probably)
 non-intential way that has become convention and rooted into specification
 and/or use-base libraries. The thing here is that those conventions tend
 to crop up in the D discussions as good reasons to do those things the
 same way in D, and _that_ is what frustrates me. I do _not_ think
 overloading a keyword with a new meaning in anyway reduce language bloat
 (the feature is still there, even if it don't have a keyword of its own).

I agree. Overloading an existing keyword is not the answer. It can only cause confusion. Even though it does have the merit of not breaking existing code. No, C++ convention is not a reason to do the same in a new language. And I even think D is still too much like C++. To name a trivial example, the assignment operator should not be =. It should be non-symmetrical, like <- or :=. You know, some people might say that it should even be ->. As in, expression left, variable right. But this convention is so rooted into every programmers mind, even I wouldn't change it anymore.
 At first I really liked the D specs. The explicit contracts / invariants
 / unittests, the useful template possibilities, the variadic functions,
 to name a few. But right now D seems far too unstable and convoluted for
 me. It's already past version 1, well into 2 and already planning for 3.
 Not so much fixing and stabilizing (or, you know, standardizing) the
 existing language as adding more and more features. I'm glad I have
 something as reliable as C++ to work with.

As has been pointed out, the versioning of D is a bigger problem than stability itself as it is confusing. 1.0xx is stable, 2.0xx is not (and I have no idea how the version is meant to look when it becomes stable).

Hm.. Yes. I might have a look at 1.0xx again. However, what's the point if I have to switch to 2.0xx (or whatever the stable equivalent is) in a year and have to rewrite all my 1.0xx code? The good thing about the development of C++ is that: 1. It is standardized. 2. For every new version, changes are painstakingly examined to make sure they break as little existing code as possible. -- Michiel
Jan 01 2008
parent Lars Ivar Igesund <larsivar igesund.net> writes:
Michiel Helvensteijn wrote:

 At first I really liked the D specs. The explicit contracts / invariants
 / unittests, the useful template possibilities, the variadic functions,
 to name a few. But right now D seems far too unstable and convoluted for
 me. It's already past version 1, well into 2 and already planning for 3.
 Not so much fixing and stabilizing (or, you know, standardizing) the
 existing language as adding more and more features. I'm glad I have
 something as reliable as C++ to work with.

As has been pointed out, the versioning of D is a bigger problem than stability itself as it is confusing. 1.0xx is stable, 2.0xx is not (and I have no idea how the version is meant to look when it becomes stable).

Hm.. Yes. I might have a look at 1.0xx again. However, what's the point if I have to switch to 2.0xx (or whatever the stable equivalent is) in a year and have to rewrite all my 1.0xx code? The good thing about the development of C++ is that: 1. It is standardized. 2. For every new version, changes are painstakingly examined to make sure they break as little existing code as possible.

That is good for broad acceptance, but it is also among the reasons for why C++ has gotten a bad reputation in many places. It just picks up more cruft :) As for D, the D 1.0 marker was very artificial, and so it is far from perfect, but still very good (and after being around D for a while, very relaxing to not have to change on every compiler release). That 2.0 may be marked as stable within a year may become a problem though, since it will have improved immensely upon 1.0 and for many projects an upgrade will be hard to avoid (I know we in Tango land have some expectations). -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 01 2008
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Lars Ivar Igesund wrote:
 It is hard to try to be involved (in any capacity) with D language evolution
 when there are silent (or rather non-public) opinions that weighs more than
 this newsgroup, and I think as people on the newsgroup figures this out, it
 will be a loss for D.

It is not that various opinions weigh more. It is more trying to pick the best possible course of action. Note that I do my best to argue the cases based on their merits, not based on votes. Consider that after the feedback in this group, the first two const regimes were scrapped. You guys made a convincing argument that it was confusing, overly complex, and basically sucked.
 In earlier situations that are similar to this one, it has always looked
 like the unvocal persons are C++-users, thus we end up in a very C++
 inspired language when that often is definately not what we want.

const in D is very unlike const in C++.
 Most C++-users I know refuse to even acknowledge that C++ is bad.

Interestingly, many C++ users I know will not publicly acknowledge the flaws in C++. Off the record, though, they say very different things. People do not want to damage their careers built up around C++. There are some pretty high level C++ experts who have been privately very helpful to me in explaining how to do things right.
Jan 01 2008
next sibling parent James Dennett <jdennett acm.org> writes:
Walter Bright wrote:
 Most C++-users I know refuse to even acknowledge that C++ is bad.

Interestingly, many C++ users I know will not publicly acknowledge the flaws in C++. Off the record, though, they say very different things. People do not want to damage their careers built up around C++. There are some pretty high level C++ experts who have been privately very helpful to me in explaining how to do things right.

That is interesting. One of the things I've found almost unique about C++, of widespread programming languages, is that its experts are absolutely willing to discuss weaknesses of the language, and not to pretend that it's perfect, or to spend excessive time denigrating other languages (which also have their strengths and weaknesses). C++ is a very open language, though unfortunately it's too big and complex for anyone to master all of it, and its big and complex enough that many mistakenly think they understand it. However: saying "C++ is bad" is too simplistic to be useful. C++ is not beautiful; however, it's immensely useful and powerful. The same could be said for Perl (which takes it to a whole new level). C++ is flawed; so are all other programming languages. There's no point wasting time debating whether (any) language is "good" or "bad" -- it's necessary to speak in terms of specific pros and cons, in specific contexts. -- James
Jan 02 2008
prev sibling next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Walter Bright wrote:

 Lars Ivar Igesund wrote:
 It is hard to try to be involved (in any capacity) with D language
 evolution when there are silent (or rather non-public) opinions that
 weighs more than this newsgroup, and I think as people on the newsgroup
 figures this out, it will be a loss for D.

It is not that various opinions weigh more. It is more trying to pick the best possible course of action. Note that I do my best to argue the cases based on their merits, not based on votes. Consider that after the feedback in this group, the first two const regimes were scrapped. You guys made a convincing argument that it was confusing, overly complex, and basically sucked.
 In earlier situations that are similar to this one, it has always looked
 like the unvocal persons are C++-users, thus we end up in a very C++
 inspired language when that often is definately not what we want.

const in D is very unlike const in C++.
 Most C++-users I know refuse to even acknowledge that C++ is bad.

Interestingly, many C++ users I know will not publicly acknowledge the flaws in C++. Off the record, though, they say very different things. People do not want to damage their careers built up around C++. There are some pretty high level C++ experts who have been privately very helpful to me in explaining how to do things right.

I am not really attacking your integrity here, although I guess it sounds like it most of the time. My point is more to the fact that the argumentation that in the end leads to how something is implemented, often is kept (intentionally or not) from the public, leading to the impression that you from time to time make arbitrary decisions. This wouldn't necessarily be that big a problem if you could convey the actual argumentation to the newsgroup in a convincing manner. For the enum/manifest constant case I dare to say that you have failed to do that as I have yet to see a reply to your argumentation going like this "Ah, you're right!". There's been a few of "Hmm, I guess I'll accept it ...", but no turnarounds. Again, in this case it is not about functionality, as all seems to agree we want manifest constants (I certainly do), just about looks and whether the scheme will be confusing or not. In the discussion of C++, it is my opinion that although D is improving upon C++, the masses that it would be nice to pull in come from the VM (Java, C#) world and they won't have any understanding for design decisions based on conventions in C++. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 02 2008
prev sibling parent Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Lars Ivar Igesund wrote:
 
 Most C++-users I know refuse to even acknowledge that C++ is bad.

Interestingly, many C++ users I know will not publicly acknowledge the flaws in C++. Off the record, though, they say very different things. People do not want to damage their careers built up around C++. There are some pretty high level C++ experts who have been privately very helpful to me in explaining how to do things right.

I've noticed this as well, though I can't say I understand it. It's certainly possible to have issues with something and still consider it the best around. In fact, having (sufficiently informed) issues with something is a mark of experience in my opinion. I'd much rather hire someone who knows a tool well enough to understand its limitations than who has never said anything negative about it. I'd wonder if they were trying to sell me snake oil. Sean
Jan 03 2008
prev sibling next sibling parent Mike <vertex gmx.at> writes:
On Sat, 29 Dec 2007 06:35:41 +0100, Jarrett Billingsley  
<kb3ctd2 yahoo.com> wrote:

 Congratulations, you've completed the circle.  See my thread on this  
 group
 from 6/4/2007.

Thanks :)
 Const isn't going to go away for the simple fact that there will always  
 be
 people who were raised on C++ who think that you *need* const to do
 *anything* and *anything else* is heresy.

 Sorry.  We lose.

That's interesting. My only exposure to const was in my last job (about 10 years ago), where there was one const advocate. He also introduced hungarian notation (the Microsoft one), and I needed some years to get that one out of my head again. I'm still prefixing member variables with "m", but that's a huge improvement from "m_psz". It's interesting to see that this was the same person, and I kind of see a pattern: probably there was a book where some things were written and they were very convincing. In the last weeks, reading the posts about this topic the question "why would I need this?" came up more and more. And this outrage about enum just did it for me: there must be something wrong if it only produces so much controversy and lots of arguments, again and again. I didn't really have an opinion until now, but I'm starting to oppose it. -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Dec 29 2007
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/31/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 Except in the case of class references, right?  I find this to be the most
 unacceptable ommision.

But when are you /ever/ going to need such a thing in a real-life use case, that you couldn't just code differently? I thought that ommission was bad at first too, until I thought it through. But Walter's right - its absence doesn't present any real programming problems. There's really nothing you can't just do another way. By contrast, its presence would really screw up the type system. Weighing up the pros and cons, I'd say its better to live with this than have to deal with all the complication that mutable-ref-to-const-heap-data would entail.
Dec 31 2007
prev sibling next sibling parent reply 0ffh <frank youknow.what.todo.interNETz> writes:
Mike wrote:
 Seems like we're running in circles again.
 [...]

Well, I decided some time ago that I *so don't care* about const. =) regards, frank
Dec 29 2007
parent Mike <vertex gmx.at> writes:
On Sat, 29 Dec 2007 09:16:32 +0100, 0ffh  =

<frank youknow.what.todo.interNETz> wrote:

 Mike wrote:
 Seems like we're running in circles again.

Well, I decided some time ago that I *so don't care* about const. =3D)=

 regards, frank

I didn't with C++, I was initially happy to see it in D and thought: nea= t, = another C++ thing that will now be understandable. In my career I = introduced only one subtle bug that constness would have caught, and tha= t = was because I freed a char** in a plugin which I shouldn't have done. Bu= t = I'm not sure if const would have caught that anyway. So usually I don't = = care about const too. I care more about the fact that Walter's brain nee= ds = to be free to give us more of those nice unique things like scope guards= = and the arrays which make D so great :) -- = Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Dec 29 2007
prev sibling next sibling parent "Bruce Adams" <tortoise_74 yeah.who.co.uk> writes:
On Sat, 29 Dec 2007 03:46:19 -0000, Mike <vertex gmx.at> wrote:

 Seems like we're running in circles again.

 So I simply have to ask this:

 Wouldn't it be better to ditch the _whole concept_ of constness and co=

 up with some thing else that actually solves problems instead of being=

 an endless stream of new problems, arguments and confusion? After all =

 this time it seems quite obvious that the problem here is constness  =

 itself, not the implementation. Didn't C++ fail to get it right? So  =

 maybe that's proof that the whole concept is flawed and that D won't g=

 it right either.

 What problem does constness solve anyway? Manifest const, read-only  =

 access, const values/references ... aren't this unrelated concepts tha=

 are shoehorned into one single syntax that doesn't fit?

 Maybe it's time for some other approach - borrow C#'s property syntax,=

 let properties stand free and make them "private scope". Borrow Pascal=

 ":=3D" operator - this will mean "I define a manifest constant". Ok,  =

 please don't take that too seriously, but the more discussion about  =

 const we have the less faith I have that const will work in D.

 -Mike

Manifest constants has little to do with constness in the C++ sense. It just so happens that in C++ const means both "declare a constant" and= "this is a ready only view of an object". The issue with manifest constants is that they should not use any storag= e space if they are not used. Although this sounds like just an optimisati= on, the huge numbers of constants defined in the Windows headers significant= ly bloat executables. The only time C++ style constness comes back into the manifest constant = = debate is when we start talking about the type of a manifest constant. Bizzarel= y some claim we need manifest constants to declare mutable types though th= e = constant values cannot themselves be mutable by definition. Personally I think th= is = is silly.
Dec 29 2007
prev sibling next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 12/31/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 How about doing an in-place sort of an array of const classes?

 const(C)[] myarray;

How would you even /create/ such a thing in the first place? How could you populate it? In any case, the obvious solution is to just do things a different way. There are plenty of alternative strategies. The most obvious one which springs to my mind is just to use pointers: const(C)*[] myarray;
 // swap two items i and j
 auto tmp = myarray[i];
 myarray[i] = myarray[j]; // error
 myarray[j] = tmp; // error

...and that would work now.
 This
 feature of being able to swap two references to const data is a very common
 algorithmic requirement.

Neither C nor C++ lets you do this. C doesn't even /have/ references. C++ has references, but they are always const. For both of these languages, you have to use pointers if you want to do this sort of thing. It's not a big deal. We can live without it.
Dec 31 2007
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Janice Caron" wrote
 On 12/31/07, Steven Schveighoffer wrote:
 How about doing an in-place sort of an array of const classes?

 const(C)[] myarray;

How would you even /create/ such a thing in the first place? How could you populate it?

Obviously if it's so difficult to imagine such a concept, then something is broken. I recall from Walter's original post that if you want an array of const class references, you build it by appending them. I think that strategy sucks.
 In any case, the obvious solution is to just do things a different
 way. There are plenty of alternative strategies. The most obvious one
 which springs to my mind is just to use pointers:

    const(C)*[] myarray;

Remember that a const(C)* is a pointer to a reference, so now you need something to hold the memory that is the reference itself. You can't just do myarray[x] = new C. So you have to do 2 allocations, one to allocate the const class, and one to allocate the const reference to the class, which means your heap is holding an extra pointer when there is no need, just so the language spec can be 'simpler'. I think to fill this array, it's going to be just as hard as filling the const(C)[] array.
 // swap two items i and j
 auto tmp = myarray[i];
 myarray[i] = myarray[j]; // error
 myarray[j] = tmp; // error

...and that would work now.

Fair enough, but the solution still fails because I have to use double the space and extra processing, and creating such an array is too complicated.
 This
 feature of being able to swap two references to const data is a very 
 common
 algorithmic requirement.

Neither C nor C++ lets you do this. C doesn't even /have/ references. C++ has references, but they are always const. For both of these languages, you have to use pointers if you want to do this sort of thing. It's not a big deal. We can live without it.

D references ARE pointers. The problem is that with classes, I can't change the constness of the class without changing the constness of the pointer (reference). With C++ I can. With D structs I can. Tell me, why is it acceptable to have tail const for struct references, but not for class references? There is no technical reason this can't exist. It's not required for Walter's const dream to have class references always have the same constness as the referenced class itself. It's not required to have tail-const for structs (not struct references) if you have tail-const for class references. My belief is that he just can't find the right way to express this idea, and so instead of trying to work through it, he's given up. I think he inexplicably can't unlink tail const for structs from tail-const for references (pointers). In his mind, it's both or none, which both suck. The right answer is: tail-const for references and pointers, no tail-const for structs. And no, *we* can't live without it. Maybe you can, but I can't. I'm done arguing this point. If you can't see the value in having tail-const for class references after all this, and the lack of a good reason for not having it, then there is no reason to keep trying to convince you. I believe that in the end, when Walter starts trying out this new const, he'll find it very unwieldly and have to change it again. I'm just trying to help him see that ahead of time. -Steve
Dec 31 2007
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 And no, *we* can't live without it.  Maybe you can, but I can't.

That's why using const isn't required. You don't need to use const in your programs at all. My opinions on things (like the validity of gc) sometimes took years to change. That doesn't mean you're necessarily wrong, just that I wouldn't expect any experienced programmer to change their opinion overnight. All I ask is that you try it out here and there, and see how it works for you.
Jan 01 2008
next sibling parent Dan <murpsoft hotmail.com> writes:
Walter Bright Wrote:

 Steven Schveighoffer wrote:
 And no, *we* can't live without it.  Maybe you can, but I can't.

That's why using const isn't required. You don't need to use const in your programs at all. My opinions on things (like the validity of gc) sometimes took years to change. That doesn't mean you're necessarily wrong, just that I wouldn't expect any experienced programmer to change their opinion overnight. All I ask is that you try it out here and there, and see how it works for you.

I respect that. In fact, I'll agree with the common argument that it's why you're doing so well by D. I also find myself in a similar boat to Steve though. 2.000 breaks my program in over 300 different places simply because of char literals needing a cast to not be const. I spent 3 hours working on converting it to use const in the right places like the idea suggests - to 2.000 from 1.020 before finally giving up and reverting (for now). It's not readily optional unless I'm missing something obvious. Regards, Dan
Jan 01 2008
prev sibling parent Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Steven Schveighoffer wrote:
 And no, *we* can't live without it.  Maybe you can, but I can't.

That's why using const isn't required. You don't need to use const in your programs at all.

To be fair, we need to use it a bit because it is not possible to pass string literals to non-const function parameters. But otherwise I agree. Sean
Jan 01 2008
prev sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 1/2/08, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 That anyone got persuaded that something is wrong is not proof that it is
 wrong.

For clarification, what persuaded me was /logic/, not the force of Walter's personality! :-) Unless I have misunderstood some step of the reasoning, every scheme to allow mutable-reference-to-const-class-data which has so far been proposed has been proven unworkable. The same logic should lead you, or anyone else, to the same conclusion. Of course, this is not a proof that there is /no/ solution, only that the suggestions made up to this point all have fatal flaws.
 "this leads to different problems" is not an explanation.

Of course not. I'm hardly going to condense six months' worth of patient reasoning into a single sentence. You're proposing something which has already been proposed before (by me, as it happens), and has been shown not to work.
 If C isn't a reference type, then it doesn't compile.

That was my suggestion too. In the thread "const again", I said "I had in mind that that would be a syntax error", to which Walter replied "A special syntax for class types means that one has to know that type T is a class." And this is the flaw here: It must compile without knowing what T is.
Jan 02 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Janice Caron" wrote
 On 1/2/08, Steven Schveighoffer wrote:
 That anyone got persuaded that something is wrong is not proof that it is
 wrong.

Unless I have misunderstood some step of the reasoning, every scheme to allow mutable-reference-to-const-class-data which has so far been proposed has been proven unworkable. The same logic should lead you, or anyone else, to the same conclusion. Of course, this is not a proof that there is /no/ solution, only that the suggestions made up to this point all have fatal flaws.

I highly contest this statement. I have never seen any statements that my proposal (dated 12/7) proved unworkable. In fact, Walter completely ignored it. The assumption you are making here is that because Walter didn't consider a possibility proves it's unworkable.
 "this leads to different problems" is not an explanation.

Of course not. I'm hardly going to condense six months' worth of patient reasoning into a single sentence. You're proposing something which has already been proposed before (by me, as it happens), and has been shown not to work.

I've been through that also :) I read through all the 'const sucks' and 'const again' and all those proposals. I have not yet seen proof that all solutions are unworkable. It seems like (seems like, not is) Walter has put considerable thought and effort into trying to get tail const for class references to work, and could not form a solution that was reasonable. Therefore, he concluded it was not possible, and for some reason, will not even consider new ideas.
 If C isn't a reference type, then it doesn't compile.

That was my suggestion too. In the thread "const again", I said "I had in mind that that would be a syntax error", to which Walter replied "A special syntax for class types means that one has to know that type T is a class." And this is the flaw here: It must compile without knowing what T is.

Again, this inconsistency already exists today! The inconsistency stems from the fact that classes ARE reference types. There is no way around having to know that. If you do: setValueTo5(T)(T x) { x.value = 5; } If T is a class, then it affects data outside the function. If T is a struct, it does not. We have to know if T is a class or not. My counter-argument is "yes, it's inconsistent, but not any different than what we have today, how is this any worse?" In fact, I believe the only way to make it consistent would be to make classes value types (which I believe is a bad idea). -Steve
Jan 02 2008
prev sibling next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/31/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 ...and that would work now.

Fair enough, but the solution still fails because I have to use double the space and extra processing, and creating such an array is too complicated.

Too complicated? const(C)*[] addPointers(const(C)[] a) { const(C)*[] r; foreach(i,e:a) { r ~= a.ptr + i; } return r; } const(C)[] removePointers(const(C)*[] a) { const(C)[] r; foreach(p:a) { r ~= *p; } return r; } It's a few extra lines of code, that's all. I'm not saying this is a generic solution which will solve every problem you can think of, but the point is, there are always workarounds. On the other hand, adding a tailconst function to D would wreck the type system. I wouldn't want a const(int)[] array to be mutable, and likewise I wouldn't want a const(C)[] array to be mutable. Once upon a time I argued for the syntax "const(C)&[]", but Walter patiently explained why that would cause insurmountable problems elsewhere. So it's one of those "lesser of two evils" things. Make the programmer think a bit and do things differently, versus wreck the type system. I think Walter made the right choice.
 D references ARE pointers.

So are C++ references.
 The problem is that with classes, I can't change
 the constness of the class without changing the constness of the pointer
 (reference).  With C++ I can.

No you can't. In C++, the equivalent declaration would be either of const C & * myarray; C const & * myarray; That's a pointer to (=array of) reference to class C. Again, I'm not even sure how you would initialise such a beast, but I'm certain you wouldn't be able to change the target of a reference. What /you/ want to do is (in C++) either of: const C * myarray; C const * myarray; Well, if you remove the ampersand, then what you've done is you've removed the reference semantics. In D terms, you've made C a struct, not a class. The D equivalent then becomes const(C)*[] myarray; (where C is a struct, not a class).
 It's not
 required for Walter's const dream to have class references always have the
 same constness as the referenced class itself.

It is. I know that's not immediately obvious, but if you follow through all the arguments (which I don't want to repeat coz they're long and complicated) you eventually have to conclude it can't be done.
 The right answer is: tail-const for references and pointers, no
 tail-const for structs. <snip> I'm done arguing this point.

That's not logical. You can't say "The right answer is" and then declare it end of subject. The logical thing to do is to work through all the consequences until you reach a conclusion, /or/ to say "I don't know what the right answer is and I'm done arguing the point". Only Douglas Adams gets to say what the right answer is (42) without having to explain it.
 If you can't see the value in having tail-const for class references
 after all this, and the lack of a good reason for not having it, then
 there is no reason to keep trying to convince you.

Not too long ago I was arguing exactly as you argue now. I didn't need "convincing" because I already fully supported the idea, and argued vociferously for it. However, because I remained open minded, I engaged in argument, and Walter was able to persuade me I was wrong. I have to go where the evidence leads. I can indeed "see the value" in having tail-const for class references. But now, I can also see the cost, and the cost outweighs the value.
Jan 01 2008
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 1/1/08, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 Janice Caron wrote:
 It is. I know that's not immediately obvious, but if you follow
 through all the arguments (which I don't want to repeat coz they're
 long and complicated) you eventually have to conclude it can't be
 done.

It would be great if someone who understands it could write down the rationale that lead to the current system. I'm not very convinced by "trust me I thought of everything". Even when it's myself who thinks he thought of everything, I don't really believe it till I write it all down and see that the reasoning still stands up.

Quite right. I absolutely agree completely. No one should ever be convinced by "trust me I thought of everything". The rationale that leads to the current system is in this forum though. It's /a lot/ of reading. It essentially consists of all of the arguments and counterarguments about const that have gone on in the past several months. For this /particular/ piece of the argument, the next stage of reasoning would likely go like this: A: It is an unacceptable omission that there is no way to specify mutable reference to const class data B: Then let us proceed by reductio ad absurdum. Please unambiguously specify exactly what you want, and then I will show that it leads to a contradiction. A is then either unable to unambiguously specify exactly what they want, or the argument proceeds to the next stage. But eventually, it will hit a brick wall.
Jan 01 2008