www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - so what exactly is const supposed to mean?

reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Ok, I know that the const issue has apparently been beaten to death on 
the digitalmars.D NG, but ....

Can someone please explain to me what does const mean? and doesn't D 
already have a const keyword?
I think it's something from C++, no? what is it? what does it do? and 
why do people think it's useful?

(hmm, I have a feeling that I've asked this before, but can't really 
remember)

While you're at it, would you mind explaining the implications of 
implemeting the proposed "const by default" feature?
Jul 02 2006
next sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Hasan Aljudy wrote:
 Ok, I know that the const issue has apparently been beaten to death on 
 the digitalmars.D NG, but ....
 
 Can someone please explain to me what does const mean? and doesn't D 
 already have a const keyword?
 I think it's something from C++, no? what is it? what does it do? and 
 why do people think it's useful?
 
 (hmm, I have a feeling that I've asked this before, but can't really 
 remember)
 
 While you're at it, would you mind explaining the implications of 
 implemeting the proposed "const by default" feature?

The meaning of const depends on the language it is in. Are you asking about D's const or C++'s const (or other even)? -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 02 2006
parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
Bruno Medeiros wrote:
 Hasan Aljudy wrote:
 
 Ok, I know that the const issue has apparently been beaten to death on 
 the digitalmars.D NG, but ....

 Can someone please explain to me what does const mean? and doesn't D 
 already have a const keyword?
 I think it's something from C++, no? what is it? what does it do? and 
 why do people think it's useful?

 (hmm, I have a feeling that I've asked this before, but can't really 
 remember)

 While you're at it, would you mind explaining the implications of 
 implemeting the proposed "const by default" feature?

The meaning of const depends on the language it is in. Are you asking about D's const or C++'s const (or other even)?

hehe .. well, if I knew I wouldn't ask '^_^ Just the const thing that everyone is talking about.
Jul 03 2006
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Hasan Aljudy wrote:
 Ok, I know that the const issue has apparently been beaten to death on 
 the digitalmars.D NG, but ....
 
 Can someone please explain to me what does const mean?

That depends. Typically it means that a reference won't be used to mutate referenced data, but that leaves a lot of room for interpretation. C++, for example, uses "logical const" for classes and 'mutable' qualified members can actually be altered by const member functions. The mutable qualifier is useful in instances where a class has members that are more of an implementation detail (a mutex or DB connection handle, for example) that may need to be mutated in the course of processing const-qualified methods.
 and doesn't D already have a const keyword?

D has const as a storage attribute, which is a bit different from the above. D's const may only apply to concrete data types, and implies that the data will never be modified for the duration of the program. This allows the compiler to place such data in ROM and to perform some optimizations that would otherwise not be possible. But this is quite limited in that it may only be applied to data that can be evaluated at compile-time.
 I think it's something from C++, no? what is it? what does it do? and 
 why do people think it's useful?

Logical const (as in C++) provides a contract ensuring that the user of const-qualified data will not modify it in observable ways. This serves to catch accidental errors and to make programmers feel better about passing references into unknown code.
 While you're at it, would you mind explaining the implications of 
 implemeting the proposed "const by default" feature?

Again, this depends a lot on how Walter decides to do things, but as he's interested in guarantees a compiler can exploit, any form of const behavior in D would likely be far stronger than the logical const used by C++. It would likely say more that "this reference will not be used to modify its underlying data in any way," similar to how the const storage attribute operates. "const by default" stems from the observation that, in terms of set relations, the set of mutable data is actually a subset of the set of const data. ie. of all the data in the world, only some of it will ever be altered. Thus, a typical application would likely have far more 'const' qualifiers in it to describe programmer intent than it would have 'mutable' qualifiers. Also, it seems far more meaningful to state that a particular function *will* alter a particular piece of data than that it will not alter the data. The implication is that references through which mutating operations will occur would likely have to be qualified as 'mutable' or 'inout' or some such, and that mutating member functions of classes and structs would probably have to be labeled as 'mutable' as well. But I don't want to speculate beyond that as I haven't given the issue nearly as much thought as Walter has. Sean
Jul 02 2006
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Sean Kelly wrote:
 Hasan Aljudy wrote:
 
 Ok, I know that the const issue has apparently been beaten to death on 
 the digitalmars.D NG, but ....

 Can someone please explain to me what does const mean?

That depends. Typically it means that a reference won't be used to mutate referenced data, but that leaves a lot of room for interpretation. C++, for example, uses "logical const" for classes and 'mutable' qualified members can actually be altered by const member functions. The mutable qualifier is useful in instances where a class has members that are more of an implementation detail (a mutex or DB connection handle, for example) that may need to be mutated in the course of processing const-qualified methods.

hm, so basically making an object immutable? Sorry, I didn't get the second part about C++. What do you mean by "logical const"?
 I think it's something from C++, no? what is it? what does it do? and 
 why do people think it's useful?

Logical const (as in C++) provides a contract ensuring that the user of const-qualified data will not modify it in observable ways. This serves to catch accidental errors and to make programmers feel better about passing references into unknown code.

Is there anything preventing anyone from creating immutable classes?
 
 While you're at it, would you mind explaining the implications of 
 implemeting the proposed "const by default" feature?

The implication is that references through which mutating operations will occur would likely have to be qualified as 'mutable' or 'inout' or some such, and that mutating member functions of classes and structs would probably have to be labeled as 'mutable' as well. But I don't want to speculate beyond that as I haven't given the issue nearly as much thought as Walter has.

damn, this doesn't sound too good. I for one don't give a damn about const, so why should I be bothered to think about the constness of my code/classes and add "mutable" qualifiers all over the place?
Jul 03 2006
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Hasan Aljudy wrote:
 
 damn, this doesn't sound too good.
 I for one don't give a damn about const, so why should I be bothered to
 think about the constness of my code/classes and add "mutable"
 qualifiers all over the place?

Hmm, this sounds bad, for you ... you are aware that immutable objects are your guarantee in multithreaded system to have safe sharing of data? Have you looked at any well designed library in languages like C++, Java or C#? Try to count the immutable classes present, I think you'll find quite a few. -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Jul 03 2006
parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Lars Ivar Igesund wrote:
 Hasan Aljudy wrote:
 
damn, this doesn't sound too good.
I for one don't give a damn about const, so why should I be bothered to
think about the constness of my code/classes and add "mutable"
qualifiers all over the place?

Hmm, this sounds bad, for you ... you are aware that immutable objects are your guarantee in multithreaded system to have safe sharing of data? Have you looked at any well designed library in languages like C++, Java or C#? Try to count the immutable classes present, I think you'll find quite a few.

Let me repeat: Is there anything preventing anyone from creating immutable classes?
Jul 03 2006
next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Hasan Aljudy wrote:

 Lars Ivar Igesund wrote:
 Hasan Aljudy wrote:
 
damn, this doesn't sound too good.
I for one don't give a damn about const, so why should I be bothered to
think about the constness of my code/classes and add "mutable"
qualifiers all over the place?

Hmm, this sounds bad, for you ... you are aware that immutable objects are your guarantee in multithreaded system to have safe sharing of data? Have you looked at any well designed library in languages like C++, Java or C#? Try to count the immutable classes present, I think you'll find quite a few.

Let me repeat: Is there anything preventing anyone from creating immutable classes?

Do you see that question at all in your quote above? As it is, it is rather difficult making immutable classes in D, much because the OOP rules in D has deteriorated lately, and the spec has as well. In addition there really is no construct making any useful guarantees about constness, neither for classes nor for code not using classes (which I'm well aware that you abhor). -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Jul 03 2006
prev sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Hasan Aljudy wrote:
 Lars Ivar Igesund wrote:
 
 Hasan Aljudy wrote:

 damn, this doesn't sound too good.
 I for one don't give a damn about const, so why should I be bothered to
 think about the constness of my code/classes and add "mutable"
 qualifiers all over the place?

Hmm, this sounds bad, for you ... you are aware that immutable objects are your guarantee in multithreaded system to have safe sharing of data? Have you looked at any well designed library in languages like C++, Java or C#? Try to count the immutable classes present, I think you'll find quite a few.

Let me repeat: Is there anything preventing anyone from creating immutable classes?

Technically no. Although at present, there are precisely two possible methods, and both require wrapping every single field up with a D-style property. (True properties could actually have the potential to make this simpler... but we don't have those either.) Method #1 - Write the class as innately immutable, then write a mutable subclass. This is the methodology at work in Mango, for example, where the module mango.io.FilePath actually defines two classes, FilePath:Object and MutableFilePath:FilePath. Method #2 - Same as above, but with one class that has a pair of methods (mutable() and immutable() for example) that activate/deactivate mutability, usually locking on something such as instance of another class (the identity of which doesn't particularly matter). For (quick'n'dirty) example: # class Foo { # private Object mlock ; # # public void mutable (Object o) { # if (mlock is o) # mlock = null; # } # # public void immutable (Object o) { # if (mlock is null) # mlock = o; # } # # private void checkLock () { # if (mlock !is null) # throw new Exception("immutable object"); # } # # /* ... everything else ... */ # } Now then, if in class Foo we want to define some property bar as an int, we now have no choice but to do something like this: # private int p_bar ; # # public int bar () { return p_bar; } # # public int bar (int x) { # checkLock; # return p_bar = x; # } Imagine if class Foo has twenty different fields/properties, most of which surely don't require any special processing -- meaning that the property wraps are pointless like the example above, although canonical. Also imagine you have classes you wish to use as immutable, which you have no control over the design of: then you have to write an entire wrapper class, fully re-implementing the original class's readable interface. Ew. -- Chris Nicholson-Sauls
Jul 03 2006
parent reply kris <foo bar.com> writes:
Chris Nicholson-Sauls wrote:
 Technically no.  Although at present, there are precisely two possible 
 methods, and both require wrapping every single field up with a D-style 
 property.  (True properties could actually have the potential to make 
 this simpler... but we don't have those either.)
 
 Method #1 - Write the class as innately immutable, then write a mutable 
 subclass.  This is the methodology at work in Mango, for example, where 
 the module mango.io.FilePath actually defines two classes, 
 FilePath:Object and MutableFilePath:FilePath.
 
 Method #2 - Same as above, but with one class that has a pair of methods 
 (mutable() and immutable() for example) that activate/deactivate 
 mutability, usually locking on something such as instance of another 
 class (the identity of which doesn't particularly matter). For 
 (quick'n'dirty) example:

Method #3 - each mutator function/method actually creates a clone of the original, mutates it, and returns that instead. Method #1 & #2 are typically the most efficient, but can expose an achilles heel. For instance, suppose you had an immutable String class? At some point, it will need to expose the content therein -- perhaps via a toString() method, or perhaps something more subtle? At that point, the class either returns a .dup of the internal content, or it exposes the internal content directly by returning it (as an array). Neither of these options are entirely attractive, and it's the reason why fully immutable classes/structs are not entirely practical in D at this time. This "return value" concern is also the reason why I believe that a "minimalist" support for "read-only" would be to protect just the return values. With the latter, one could happily return internal aggregate content (as arrays) and be safe in the knowledge that the compiler will catch pedestrian errors. However, I'd much rather see const-by-default instead -- that's a more practical solution, and should offer notable opportunities for optimization. One should note that the goal of such mechanisms is to tighten up the "contract" between caller and callee. This becomes increasingly important within multithreaded designs, to the point of becoming a fundamental requirement in some ways (in terms of robustness, simplicitly, efficiency, deterministic behaviour, etc). CoW is another mechansism intended to achieve similar results, but the key distinction is the lack of an enforceable contract. With mutable/immutable decls, the compiler has the necessary information to catch cases where the contract is being broken. With CoW, the compiler does not have that meta information available (whether the design says it's OK to alias or not). Of course, this won't stop some determined fool from bypassing the contract altogether: even with immutable-by-default, one could presumably cast() lvalues in some manner to subvert the contract. But that's not the point -- the compiler would be looking to catch honest mistakes, and not trying to cure stupidity :p Hope this helps.
Jul 03 2006
parent reply David Medlock <noone nowhere.com> writes:
kris wrote:
 Chris Nicholson-Sauls wrote:
 
 Technically no.  Although at present, there are precisely two possible 
 methods, and both require wrapping every single field up with a 
 D-style property.  (True properties could actually have the potential 
 to make this simpler... but we don't have those either.)

 Method #1 - Write the class as innately immutable, then write a 
 mutable subclass.  This is the methodology at work in Mango, for 
 example, where the module mango.io.FilePath actually defines two 
 classes, FilePath:Object and MutableFilePath:FilePath.

 Method #2 - Same as above, but with one class that has a pair of 
 methods (mutable() and immutable() for example) that 
 activate/deactivate mutability, usually locking on something such as 
 instance of another class (the identity of which doesn't particularly 
 matter). For (quick'n'dirty) example:

Method #3 - each mutator function/method actually creates a clone of the original, mutates it, and returns that instead. Method #1 & #2 are typically the most efficient, but can expose an achilles heel. For instance, suppose you had an immutable String class? At some point, it will need to expose the content therein -- perhaps via a toString() method, or perhaps something more subtle? At that point, the class either returns a .dup of the internal content, or it exposes the internal content directly by returning it (as an array). Neither of these options are entirely attractive, and it's the reason why fully immutable classes/structs are not entirely practical in D at this time. This "return value" concern is also the reason why I believe that a "minimalist" support for "read-only" would be to protect just the return values. With the latter, one could happily return internal aggregate content (as arrays) and be safe in the knowledge that the compiler will catch pedestrian errors. However, I'd much rather see const-by-default instead -- that's a more practical solution, and should offer notable opportunities for optimization. One should note that the goal of such mechanisms is to tighten up the "contract" between caller and callee. This becomes increasingly important within multithreaded designs, to the point of becoming a fundamental requirement in some ways (in terms of robustness, simplicitly, efficiency, deterministic behaviour, etc). CoW is another mechansism intended to achieve similar results, but the key distinction is the lack of an enforceable contract. With mutable/immutable decls, the compiler has the necessary information to catch cases where the contract is being broken. With CoW, the compiler does not have that meta information available (whether the design says it's OK to alias or not). Of course, this won't stop some determined fool from bypassing the contract altogether: even with immutable-by-default, one could presumably cast() lvalues in some manner to subvert the contract. But that's not the point -- the compiler would be looking to catch honest mistakes, and not trying to cure stupidity :p Hope this helps.

Not intending to start a long drawn out 'const' discussion again but... Multithreading appears to be the hardest of hardware parallelism to implement. Race conditions will not magically disapear with const-correctness (Delegates alone negate that). I really believe that true hardware parallelism will come from data parallelism: Data[1000] mydata; foo( mydata ); processor 1 operates on mydata[0-499] processor 2 operates on mydata[500-999] Data parallelism is (in the general sense) inherently faster,doesn't require locking, and is not prone to things like task-switching, locks, race conditions, etc Apparently NVidia has figured this out already. Of course this requires a more relational/vector view of the data than is currently mainstream. Here is a relevant presentation: http://www.cs.princeton.edu/~dpw/popl/06/Tim-POPL.ppt (PDF here:http://www.st.cs.uni-sb.de/edu/seminare/2005/advanced-fp/docs/sweeny.pdf ). Const has some nice properties, but I rate it about a 5 on a scale of 10 for dire features. Yes, I know libraries benefit from it. I would counter that library authors have serious design issues to consider even with const, and that COW is not a bad tradeoff in the meantime. -DavidM
Jul 03 2006
next sibling parent reply kris <foo bar.com> writes:
David Medlock wrote:
[snip]
 Not intending to start a long drawn out 'const' discussion again but...

nor I :D
 Multithreading appears to be the hardest of hardware parallelism to 
 implement.  Race conditions will not magically disapear with 
 const-correctness (Delegates alone negate that).

Not all of them, no. But a surprising number of instances do; almost as if by magic. I'm just speaking from experience only. Nothing theoretical or empirically measured. BTW: I'm one of those who feel the multithreading model is just too hard for 95%+ of programmers to get right. I'm among that 95%, although I've written OS schedulers and so on. It's just too easy to make a subtle mistake, and not being able to mechanically 'prove' the correctness of a typical/traditional multithreaded design illustrates just how bad the situation really is. But that does not hinder the value of immutability ~ it's very useful for single-thread designs also.
 I really believe that true hardware parallelism will come from data 
 parallelism:
 
 Data[1000]    mydata;
 foo( mydata );
 
 processor 1 operates on mydata[0-499]
 processor 2 operates on mydata[500-999]
 
 Data parallelism is (in the general sense) inherently faster,doesn't 
 require locking, and is not prone to things like task-switching, locks, 
 race conditions, etc

No question about that, but you still need rendezvous points or some other form of synchronization, unless there's no (fan-in) response involved? The thing is that immutable, as part of a contract, makes the conversation between callers and callees that much more deterministic. This is a useful artifact regardless of how many threads or how much hardware duplication there is - even single threaded. After all, don't we want the compiler to tell us when we're doing something contrary to someone else's design? It may even be beneficial somewhere in the above example. But yeah ... no long, drawn-out discussion needed :)
 Apparently NVidia has figured this out already.
 Of course this requires a more relational/vector view of the data than 
 is currently mainstream.
 
 Here is a relevant presentation:
 http://www.cs.princeton.edu/~dpw/popl/06/Tim-POPL.ppt
 
 (PDF 
 here:http://www.st.cs.uni-sb.de/edu/seminare/2005/advanced-fp/docs/sweeny.pdf 
 ).

Thanks; they look interesting. There are a number of excellent alternatives to multithreading ~ you might be interested in perusing for occam/tputer/csp/jcsp etc
 
 Const has some nice properties, but I rate it about a 5 on a scale of 10 
 for dire features.  Yes, I know libraries benefit from it.

Yes; like everything else, the priority is often dependent upon what you doing.
 I would counter that library authors have serious design issues to 
 consider even with const, 

That can be true. But as those are resolved, the need for const becomes more pronounced :D
 and that COW is not a bad tradeoff in the
 meantime.

Sure; as a stopgap measure it is ok. It's the lack of 'enforcability' that makes it less than suitable for a long-term solution ~ IMO ----- But it's not at all clear what your messsage is, David. Are you speculating that D is currently too immature for immutability to be useful? Or, that the multithreading model should be re-evaluated? Asking only because I'm not sure what you're getting at overall?
Jul 03 2006
parent reply David Medlock <noone nowhere.com> writes:
kris wrote:

 David Medlock wrote:
 [snip]
 
 But it's not at all clear what your messsage is, David. Are you 
 speculating that D is currently too immature for immutability to be 
 useful? Or, that the multithreading model should be re-evaluated? Asking 
 only because I'm not sure what you're getting at overall?
 
 

Basically that multithreaded as a 'hold the computers hand' is a semantic dead end street. Sure it works in small cases, but for programming in the large you hit Ahmdal's Law, among other issues. No question some programmers can do it, but there are better methods imo. Code-level multithreading won't have much(any?) effect on processors such as the Cell from what I have read so far. Look at that presentation: 500 Gigaflops of computing power on consumer hardware. It just requires you to follow its vectorized paradigm. By comparison the first Cray had like 2 MegaFlops of crunching power. Looking at the Wiki entry for Seymour Cray, he notes that keeping the computer 'fed' I/O data was the trick. Sounds awfully familliar. -Just my opinion, of course. DavidM
Jul 03 2006
next sibling parent David Medlock <noone nowhere.com> writes:
David Medlock wrote:

 kris wrote:
 
 David Medlock wrote:
 [snip]

 But it's not at all clear what your messsage is, David. Are you 
 speculating that D is currently too immature for immutability to be 
 useful? Or, that the multithreading model should be re-evaluated? 
 Asking only because I'm not sure what you're getting at overall?

Basically that multithreaded as a 'hold the computers hand' is a semantic dead end street. Sure it works in small cases, but for programming in the large you hit Ahmdal's Law, among other issues. No question some programmers can do it, but there are better methods imo. Code-level multithreading won't have much(any?) effect on processors such as the Cell from what I have read so far. Look at that presentation: 500 Gigaflops of computing power on consumer hardware. It just requires you to follow its vectorized paradigm. By comparison the first Cray had like 2 MegaFlops of crunching power. Looking at the Wiki entry for Seymour Cray, he notes that keeping the computer 'fed' I/O data was the trick. Sounds awfully familliar. -Just my opinion, of course. DavidM

PS. D has vector capabilities so I wouldn't rule it out at all. (Though I don't know what Walter's long term strategy is here...)
Jul 03 2006
prev sibling parent reply kris <foo bar.com> writes:
David Medlock wrote:
 kris wrote:
 
 David Medlock wrote:
 [snip]

 But it's not at all clear what your messsage is, David. Are you 
 speculating that D is currently too immature for immutability to be 
 useful? Or, that the multithreading model should be re-evaluated? 
 Asking only because I'm not sure what you're getting at overall?

Basically that multithreaded as a 'hold the computers hand' is a semantic dead end street. Sure it works in small cases, but for programming in the large you hit Ahmdal's Law, among other issues. No question some programmers can do it, but there are better methods imo. Code-level multithreading won't have much(any?) effect on processors such as the Cell from what I have read so far. Look at that presentation: 500 Gigaflops of computing power on consumer hardware. It just requires you to follow its vectorized paradigm. By comparison the first Cray had like 2 MegaFlops of crunching power. Looking at the Wiki entry for Seymour Cray, he notes that keeping the computer 'fed' I/O data was the trick. Sounds awfully familliar. -Just my opinion, of course. DavidM

Yes, it does sounds very familiar -- to take full advantage of specific hardware you may need to step away from the 'norm'. Whatever that 'norm' may be. No surprise then, that it pays to keep an open mind? You won't hear any argument from me regarding the typical multithreading "paradigm" ... and there are most certainly more effective methods in one manner or another ... there have been for 30 years ... *shrug* If you intend to go on a crusade, to change the face of multithreading as we currently know and "love" it, I'll sign right up :D But, again, the state of immutability is *not* married to multithreading -- it just happens to be particularly useful there too :p
Jul 03 2006
parent reply David Medlock <ashleymedlock no.spam.yahoo.com> writes:
kris wrote:
 
 Yes, it does sounds very familiar -- to take full advantage of specific 
 hardware you may need to step away from the 'norm'. Whatever that 'norm' 
 may be. No surprise then, that it pays to keep an open mind?
 
 You won't hear any argument from me regarding the typical multithreading 
 "paradigm" ... and there are most certainly more effective methods in 
 one manner or another ... there have been for 30 years ... *shrug*
 
 If you intend to go on a crusade, to change the face of multithreading 
 as we currently know and "love" it, I'll sign right up :D
 
 But, again, the state of immutability is *not* married to multithreading 
 -- it just happens to be particularly useful there too :p
 
 
 

I can barely work on my own projects with my daughters(1 and 3 yrs). My point was simply that const isn't the 'pot of gold' its made out to be(at least in the form espoused thus far). 1. Tiny multithreaded advantages. 2. Limited optimization benefits. 3. Some memory optimizations for structs(call by reference). Changing the whole language for the above just does seem like good investment vs return. Cheers -David
Jul 04 2006
next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
David Medlock wrote:

 kris wrote:
 
 Yes, it does sounds very familiar -- to take full advantage of specific
 hardware you may need to step away from the 'norm'. Whatever that 'norm'
 may be. No surprise then, that it pays to keep an open mind?
 
 You won't hear any argument from me regarding the typical multithreading
 "paradigm" ... and there are most certainly more effective methods in
 one manner or another ... there have been for 30 years ... *shrug*
 
 If you intend to go on a crusade, to change the face of multithreading
 as we currently know and "love" it, I'll sign right up :D
 
 But, again, the state of immutability is *not* married to multithreading
 -- it just happens to be particularly useful there too :p
 
 
 

I can barely work on my own projects with my daughters(1 and 3 yrs).

What you mean? They can't code yet? ;)
 
 My point was simply that const isn't the 'pot of gold' its made out to
 be(at least in the form espoused thus far).
 
 1. Tiny multithreaded advantages.
 2. Limited optimization benefits.
 3. Some memory optimizations for structs(call by reference).
 
 Changing the whole language for the above just does seem like good
 investment vs return.
 
 Cheers
 -David

I believe you downplay those points too much, particularly the multithreaded advantages. You did also forget the most important point, IMO: If you as a library writer or application writer care about the integrity of your data (very often you have to, as this might be necessary to guarantee correct operation), then you need to make sure that users of the library, or other threads don't modify the data in ways that breaks this integrity. Since D actually aims to make it easier to create safer software, strong immutability enforcement, however it is implemented (the logical const from C++ do seem like a somewhat dead end), is a must. -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Jul 04 2006
prev sibling parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
David Medlock wrote:
 kris wrote:
 Yes, it does sounds very familiar -- to take full advantage of 
 specific hardware you may need to step away from the 'norm'. Whatever 
 that 'norm' may be. No surprise then, that it pays to keep an open mind?

 You won't hear any argument from me regarding the typical 
 multithreading "paradigm" ... and there are most certainly more 
 effective methods in one manner or another ... there have been for 30 
 years ... *shrug*

 If you intend to go on a crusade, to change the face of multithreading 
 as we currently know and "love" it, I'll sign right up :D

 But, again, the state of immutability is *not* married to 
 multithreading -- it just happens to be particularly useful there too :p

I can barely work on my own projects with my daughters(1 and 3 yrs). My point was simply that const isn't the 'pot of gold' its made out to be(at least in the form espoused thus far). 1. Tiny multithreaded advantages. 2. Limited optimization benefits. 3. Some memory optimizations for structs(call by reference). Changing the whole language for the above just does seem like good investment vs return. Cheers -David

I'm assuming you meant "just doesn't seem like" up there. The form exposed so far isn't all, const isn't just for multithreading apps: An immutability mechanism is great for ownership management, better than CoW because, like Kris said, the program becomes more expressive and there is more that the compiler can check and enforce (and it prevents redundant duping/cloning). -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 04 2006
prev sibling parent John Reimer <terminal.node gmail.com> writes:
David Medlock wrote:
e this helps.
 
 Not intending to start a long drawn out 'const' discussion again but...
 
 Multithreading appears to be the hardest of hardware parallelism to 
 implement.  Race conditions will not magically disapear with 
 const-correctness (Delegates alone negate that).
 
 I really believe that true hardware parallelism will come from data 
 parallelism:
 
 Data[1000]    mydata;
 foo( mydata );
 
 processor 1 operates on mydata[0-499]
 processor 2 operates on mydata[500-999]
 
 Data parallelism is (in the general sense) inherently faster,doesn't 
 require locking, and is not prone to things like task-switching, locks, 
 race conditions, etc
 
 Apparently NVidia has figured this out already.
 Of course this requires a more relational/vector view of the data than 
 is currently mainstream.
 
 Here is a relevant presentation:
 http://www.cs.princeton.edu/~dpw/popl/06/Tim-POPL.ppt
 
 (PDF 
 here:http://www.st.cs.uni-sb.de/edu/seminare/2005/advanced-fp/docs/sweeny.pdf 
 ).
 
 Const has some nice properties, but I rate it about a 5 on a scale of 10 
 for dire features.  Yes, I know libraries benefit from it.
 I would counter that library authors have serious design issues to 
 consider even with const, and that COW is not a bad tradeoff in the 
 meantime.
 
 -DavidM
 
 
 

I can see why Nvidia would want to look at concurrency from a data parallelism perspective. That's what graphics is all about... processing and moving masses of data. Since the data weighs so heavily in graphics world, is much like a large array and easily partitioned into "work" loads, it seems obvious for graphics hardware manufacturers to look at parallelism from that perspective. This is a specific case, though, and may not work at all the same way in networks and other generic systems. Adopting such a perspective for all other possibilities may be just as dangerous for general-purpose langauges as it is beneficial for Nvidia's specific field of operation. Nonetheless, I'm sure it's good to be aware of such methodologies. Looking at things from a different angle is always a good idea. But certain process algebras like CSP have done a very good job of describing concurrency in a clear and provable fashion. Feature additons, like immutability, would seem to be highly useful low level features to help strengthen the possible concurrency implementations. -JJR
Jul 03 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Sean Kelly wrote:
 
  > and doesn't D already have a const keyword?
 
 D has const as a storage attribute, which is a bit different from the 
 above.  D's const may only apply to concrete data types, and implies 
 that the data will never be modified for the duration of the program. 
 This allows the compiler to place such data in ROM and to perform some 
 optimizations that would otherwise not be possible.  But this is quite 
 limited in that it may only be applied to data that can be evaluated at 
 compile-time.
 

There is a slight difference from D's const and a const that places the data in ROM as you cannot get the address of a D const var (it's not an lvalue). Resummarizing: D's const has two meanings. The usual meaning is from the form: const int var = <some constant initializer>; and it means that the variable is a compile-time constant and no storage is allocated for it, instead the value is substituted whenever the var is used (like #define, but safer). The second meaning is from the form: const int var; // no initializer and means that the var must be initialized once in a constructor, and then it becomes non-recursively immutable (meaning you can't change the value of the var, but you can change referenced values). The var has storage and as such is an lvalue. This is basically the same as final in other languages (Java, C#), and I wonder why it isn't in D as well(?). Walter said he didn't want a const keyword overloaded with many different meanings. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 03 2006
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Bruno Medeiros wrote:
 Sean Kelly wrote:
  > and doesn't D already have a const keyword?

 D has const as a storage attribute, which is a bit different from the 
 above.  D's const may only apply to concrete data types, and implies 
 that the data will never be modified for the duration of the program. 
 This allows the compiler to place such data in ROM and to perform some 
 optimizations that would otherwise not be possible.  But this is quite 
 limited in that it may only be applied to data that can be evaluated 
 at compile-time.

There is a slight difference from D's const and a const that places the data in ROM as you cannot get the address of a D const var (it's not an lvalue).

Ever tried taking the address of a const string? That you can't take the address of other const types is simply a result of optimization.
 Resummarizing:
 
 D's const has two meanings. The usual meaning is from the form:
   const int var = <some constant initializer>;
 and it means that the variable is a compile-time constant and no storage 
 is allocated for it, instead the value is substituted whenever the var 
 is used (like #define, but safer).
 
 The second meaning is from the form:
   const int var; // no initializer
 and means that the var must be initialized once in a constructor, and 
 then it becomes non-recursively immutable (meaning you can't change the 
 value of the var, but you can change referenced values). The var has 
 storage and as such is an lvalue.

Yup. Sean
Jul 03 2006
parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Sean Kelly wrote:
 Bruno Medeiros wrote:
 Sean Kelly wrote:
  > and doesn't D already have a const keyword?

 D has const as a storage attribute, which is a bit different from the 
 above.  D's const may only apply to concrete data types, and implies 
 that the data will never be modified for the duration of the program. 
 This allows the compiler to place such data in ROM and to perform 
 some optimizations that would otherwise not be possible.  But this is 
 quite limited in that it may only be applied to data that can be 
 evaluated at compile-time.

There is a slight difference from D's const and a const that places the data in ROM as you cannot get the address of a D const var (it's not an lvalue).

Ever tried taking the address of a const string? That you can't take the address of other const types is simply a result of optimization.

I tried it now, and the const string also can't be taken an address from: const char[] str = "ABC"; void func() { *(&str) = "123"; // : "ABC" is not an lvalue } -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 04 2006
parent reply Sean Kelly <sean f4.ca> writes:
Bruno Medeiros wrote:
 Sean Kelly wrote:
 Bruno Medeiros wrote:
 There is a slight difference from D's const and a const that places 
 the data in ROM as you cannot get the address of a D const var (it's 
 not an lvalue).

Ever tried taking the address of a const string? That you can't take the address of other const types is simply a result of optimization.

I tried it now, and the const string also can't be taken an address from: const char[] str = "ABC"; void func() { *(&str) = "123"; // : "ABC" is not an lvalue }

That's interesting. I would have expected all strings to live in a static data segment. And in fact they seem to, though initialization seems to happen in a slightly weird manner: const char[] str = "ABC"; void main() { printf( "%.*s\n", str ); } generates: _DATA segment db 041h,042h,043h,000h,000h,000h,000h,000h _D4test3strAa: db 003h,000h,000h,000h dd offset FLAT:_DATA db 041h,042h,043h,000h,000h,000h,000h,000h db 003h,000h,000h,000h dd offset FLAT:_D4test3strAa[8] db 025h,02eh,02ah,073h,00ah,000h _DATA ends CONST segment CONST ends _BSS segment _BSS ends __Dmain comdat assume CS:__Dmain L0: push dword ptr _D4test3strAa[014h] push dword ptr _D4test3strAa[010h] push offset FLAT:_D4test3strAa[018h] call near ptr _printf xor EAX,EAX add ESP,0Ch ret __Dmain ends Notice that "041h,042h,043h" exists both by itself as a literal and within the static initializer for 'str'. Notice also that 'str' does indeed live within a static data segment. I'm not entirely certain why the literal isn't optimized away, however, as it's only ever used for initializing 'str'. Sean
Jul 04 2006
parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Sean Kelly wrote:
 Bruno Medeiros wrote:
 Sean Kelly wrote:
 Bruno Medeiros wrote:
 There is a slight difference from D's const and a const that places 
 the data in ROM as you cannot get the address of a D const var (it's 
 not an lvalue).

Ever tried taking the address of a const string? That you can't take the address of other const types is simply a result of optimization.

I tried it now, and the const string also can't be taken an address from: const char[] str = "ABC"; void func() { *(&str) = "123"; // : "ABC" is not an lvalue }

That's interesting. I would have expected all strings to live in a static data segment. And in fact they seem to, though initialization seems to happen in a slightly weird manner:

Yes, they have to live in a static data segment. But does that change anything? The value of "ABC" is already the address of the string, thus &"ABC" is not valid. (akin to &(&somevar) ) -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 05 2006
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Bruno Medeiros wrote:
 D's const has two meanings. The usual meaning is from the form:
   const int var = <some constant initializer>;
 and it means that the variable is a compile-time constant and no storage 
 is allocated for it, instead the value is substituted whenever the var 
 is used (like #define, but safer).
 
 The second meaning is from the form:
   const int var; // no initializer
 and means that the var must be initialized once in a constructor, and 
 then it becomes non-recursively immutable (meaning you can't change the 
 value of the var, but you can change referenced values). The var has 
 storage and as such is an lvalue.
 This is basically the same as final in other languages (Java, C#), and I 
 wonder why it isn't in D as well(?). Walter said he didn't want a const 
 keyword overloaded with many different meanings.

I agree. I think it's a mistake to have a 'const' that isn't actually const! 'final' seems far more appropriate.
Jul 04 2006
parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Don Clugston wrote:
 Bruno Medeiros wrote:
 
 D's const has two meanings. The usual meaning is from the form:
   const int var = <some constant initializer>;
 and it means that the variable is a compile-time constant and no 
 storage is allocated for it, instead the value is substituted whenever 
 the var is used (like #define, but safer).

 The second meaning is from the form:
   const int var; // no initializer
 and means that the var must be initialized once in a constructor, and 
 then it becomes non-recursively immutable (meaning you can't change 
 the value of the var, but you can change referenced values). The var 
 has storage and as such is an lvalue.
 This is basically the same as final in other languages (Java, C#), and 
 I wonder why it isn't in D as well(?). Walter said he didn't want a 
 const keyword overloaded with many different meanings.

I agree. I think it's a mistake to have a 'const' that isn't actually const! 'final' seems far more appropriate.

We do have a 'final' keyword in D already. Applied to a class decleration it describes a class which may not be inherited from. Applied to class member function (method) declerations, it means a member which may not be overriden. So far as I am aware, it is meaningless anywhere else. Since 'final' in D currently means, in over-generalized terms, "this cannot be replaced," I don't think it would be much of a stretch to use 'final' to mean what 'const' currently does. -- Chris Nicholson-Sauls
Jul 04 2006