On Tue, Feb 02, 2016 at 09:35:13PM +0000, IceCreamEater via Digitalmars-d wrote: > On Tuesday, 2 February 2016 at 20:17:20 UTC, H. S. Teoh wrote: > >On Tue, Feb 02, 2016 at 09:13:41PM +0100, anonymous via Digitalmars-d > >wrote: [...] > >>The other signature is no different. Two occurrences of "immutable", > >>applying to two different things. > >> > >>I agree that it can be unclear to newbies what exactly is immutable > >>when a method is marked immutable, but the meaning of the keyword is > >>the same as elsewhere. Using another word there would be more > >>confusing. > > > >Another way to think about it, is that the "immutable" on the > >function means that the implicit `this` reference to the object is > >immutable. > > > > > >T > > I thought immutable was added to the language as a better guarantee to > 'const'. Which really tells me const wasn't cutting it and wasn't a > proper guarantee.
You're misunderstanding D's type system. Immutable is not a "better const", as though const is somehow defective. Perhaps the following diagram may help to clear things up: const / \ (mutable) immutable What this means is that both mutable and immutable are implicitly convertible to const. Or, to put it another way, const is a kind of "wildcard" that can point to underlying data that's either mutable or immutable. Mutable data is, well, mutable -- anybody who can get to it, can modify it. Immutable means *nobody* can modify it once it's initialized. Why const, then? Const is useful for when a function doesn't care whether the underlying data is mutable or not, because it doesn't need to change the data. Const provides guarantees to the caller that the function won't touch the data -- even if the data is actually mutable in the caller's context. It's a "no-mutation view" on data that's possibly mutable by a third party. Furthermore, since const provides actual guarantees that the called function isn't going to touch the data, this opens up optimization opportunities for the compiler. E.g., it can assume that any part(s) of the data that are held in registers will remain valid after the function call (provided said registers aren't touched by the function), so it doesn't need to issue another load after the function returns. As a contrived example, say you have code like this: struct Data { int x; } int func1(Data* d) { ... } int func2(const(Data)* d) { ... } ... void main() { Data d; int value1 = d.x*func1(&d) + d.x; int value2 = d.x*func2(&d) + d.x; d.x++; } When evaluating value1, the compiler may have issued a load for the first occurrence of d.x, then it calls func1. But since func1 may modify d.x, the second d.x needs another load in order to ensure the correct value is used. When evaluating value2, however, since func2 takes a const pointer to the Data, the compiler knows the value of d.x cannot possibly change across that function call, so it can safely reuse the value of d.x that was previously loaded. It may also go further and refactor the expression as d.x*(func2(&d) + 1), because the const guarantees that func2 can't mutate d.x behind our backs and invalidate the result. Such a refactoring is invalid with func1, because there is no guarantee that d.x will have the same value after func1 returns. Now, the same argument applies if immutable was used in place of const. However, the last line in main() illustrates why we need const rather than immutable in this case: we actually *want* to modify d.x in main(). We just don't want func2 to touch anything. So we can't use immutable -- since immutable means *nobody* can touch the data. So, const provides both the guarantee that func2 won't touch the data, thus allowing the aforementioned optimization, and also continues to let main() mutate the data at its leisure. As an added benefit, you can also call func2 with immutable Data: you know it's safe, because even though func2 doesn't require immutability, it also guarantees that it won't touch the data. So you don't need to write two copies of func2, one to work with mutable data and one to work with immutable data. This is why both mutable and immutable can implicitly cast to const. T -- He who does not appreciate the beauty of language is not worthy to bemoan its flaws.