www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How does "immutable" work.

reply "egslava" <egslava gmail.com> writes:
Hello! Sorry for my English.

I read manual about "immutable" and "const" keyword:
http://dlang.org/const3.html

And tried to build my program:
http://dpaste.dzfl.pl/f803ae94

If I will change "immutable" to "const" output will not changed.
But why? Why output is look like this?

I would understand the output like this:
10
10
7FFF7E68AEB0
7FFF7E68AEB0

In this case, I would think - we just ignoring all assign 
operators.

I would understand the output like this:
10
20
7FFF7E68AEB0
FFFFFFFFFFFFF

In this case, I would think - we just one more time located 
memory and copied value of variable.

But why the output does look like this? How does this 
construction work? Why memory addresses are same, assign is 
working, but value of immutable variable doesn't change?

I would even think, that in compile-time compiler changes
writeln(x) to writeln(10), but why we can dereference "x"?
Aug 09 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/09/2012 10:25 AM, egslava wrote:
 Hello! Sorry for my English.
Thank you for using English.
 I read manual about "immutable" and "const" keyword:
 http://dlang.org/const3.html

 And tried to build my program:
 http://dpaste.dzfl.pl/f803ae94
Here it is: import std.stdio; void main(string[] args) { immutable int x = 10; int *y = cast(int*) &x; *y += 10; writeln(x); writeln(*y); writeln(&x); writeln(y); } You are subverting the type system by treating an immutable variable as mutable.
 If I will change "immutable" to "const" output will not changed.
immutable and const are the same thing on a variable. I have written my understanding about this topic here: http://ddili.org/ders/d.en/const_and_immutable.html I have unpublished amendments to that page. I am going to add this section: ================= Should a parameter be const or immutable? The two sections above may give the impression that const should be preferred over immutable because it is more flexible. This is not always true because const erases the information about whether the original variable is mutable or immutable. This information is hidden even from the compiler. A consequence of this fact is that const parameters cannot be passed as arguments to functions that take immutable parameters. The following code produces a compilation error related to this fact: void main() { /* The original variable is immutable */ immutable int[] slice = [ 10, 20, 30, 40 ]; foo(slice); } /* A function that takes its parameter as const, in order to * be more useful. */ void foo(const int[] slice) { bar(slice); // ← compilation ERROR } /* A function that takes its parameter as immutable for a * plausible reason. */ void bar(immutable int[] slice) { /* ... */ } The code cannot be compiled as it is not known whether the original variable that foo()'s const parameter references is immutable or not. Note: It is clear in the code above that the original variable in main() is immutable. However, the compiler compiles functions individually without regard to all of the places that function is called from. According to the compiler, the slice parameter of foo() may refer to a mutable variable, as well as an immutable one. A solution would be to call bar() with an immutable copy of the parameter: void foo(const int[] slice) { bar(slice.idup); } Although that is a sensible solution, it does have the cost of copying, which would be wasteful in the case where the original variable has been immutable to begin with. After this analysis, it should be clear that taking parameters always as const does not seem to be the best approach in every situation. After all, if foo()'s parameter has been defined as immutable, there would not be any need to copy it before calling bar(): void foo(immutable int[] slice) // This time immutable { bar(slice); // Copying is not needed anymore } The consequence of that choice is having to make an immutable copy of the original variable when calling foo(), if that variable were not immutable to begin with: foo(mutableSlice.idup); The decision of whether a parameter should be marked as const or immutable is not always easy. Templates can provide some help with this decision. (We will see templates in later chapters.) Although I don't expect you to fully understand the following function at this point in the book, I will show it as a solution to this very problem. The following function template foo() can be called both by mutable variables and by immutable variables. The parameter would be copied only if the original variable has been mutable; no copying would take place if it has been immutable: import std.conv; // ... /* Because it is a template, foo() can be called by mutable * and immutable variables. */ void foo(T)(T[] slice) { /* 'to()' does not make a copy if the original variable is * already immutable. */ bar(to!(immutable T[])(slice)); } =================
 But why? Why output is look like this?
Here is the output: 10 20 7FFF62F454F0 7FFF62F454F0
 I would understand the output like this:
 10
 10
 7FFF7E68AEB0
 7FFF7E68AEB0
For that to make sense, the assignment through y should have been ignored. Would that make sense? What should the compiler favor?
 In this case, I would think - we just ignoring all assign operators.
I don't think the assignments are being ignored. Since you told the compiler that x is immutable, it can use its value instead of reading from memory every time. Reading from the memory would be unnecessary, right? It is immutable after all.
 I would understand the output like this:
 10
 20
 7FFF7E68AEB0
 FFFFFFFFFFFFF
That would not make sense. That doesn't look like a valid address to me.
 In this case, I would think - we just one more time located memory and
 copied value of variable.

 But why the output does look like this? How does this construction work?
 Why memory addresses are same, assign is working, but value of immutable
 variable doesn't change?
The compiler uses the value of x instead of reading it from the memory.
 I would even think, that in compile-time compiler changes
 writeln(x) to writeln(10), but why we can dereference "x"?
Yes, that's the case. Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
Aug 09 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 09 Aug 2012 19:25:47 +0200, egslava <egslava gmail.com> wrote:

 Hello! Sorry for my English.

 I read manual about "immutable" and "const" keyword:
 http://dlang.org/const3.html

 And tried to build my program:
 http://dpaste.dzfl.pl/f803ae94

 If I will change "immutable" to "const" output will not changed.
 But why? Why output is look like this?

 I would understand the output like this:
 10
 10
 7FFF7E68AEB0
 7FFF7E68AEB0

 In this case, I would think - we just ignoring all assign operators.

 I would understand the output like this:
 10
 20
 7FFF7E68AEB0
 FFFFFFFFFFFFF

 In this case, I would think - we just one more time located memory and  
 copied value of variable.

 But why the output does look like this? How does this construction work?  
 Why memory addresses are same, assign is working, but value of immutable  
 variable doesn't change?

 I would even think, that in compile-time compiler changes
 writeln(x) to writeln(10), but why we can dereference "x"?
The compiler has optimized the call to writeln(x), by assuming x will never change (which is reasonable). Now, since x is a variable, not a manifest constant (which you would get by writing enum x = 10;, for instance), it has a memory location, so you can ask for its address. The reason you get the same value for both y and &x, is that they point to the same location, and the first writeln call simply ignores the value stored there. Finally, the reason this does not behave like you'd expect is because casts are a deliberate hole in the type system, and casting away immutability leads to undefined behavior (in this case, changing the value of the immutable variable does not change the value where that variable is used). -- Simen
Aug 09 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Thursday, 9 August 2012 at 17:25:48 UTC, egslava wrote:
 If I will change "immutable" to "const" output will not changed.
 But why? Why output is look like this?
Just to repeat the gist of it: immutable is a guarantee that the value stored in the variable will never change, and the compiler is free to assume that when optimizing code. By using a cast and then writing to the location, you have subverted the type system, so all bets are off – in fact, your program is experiencing undefined behavior. David
Aug 09 2012
prev sibling parent "Chris Cain" <clcain uncg.edu> writes:
In addition to what everyone else said, I think it's important to 
also say that, in general, you should _not_ cast away immutable 
or const like you did. As far as I'm concerned, it's a 
programming error. It's possible that future compilers might  
have immutable data stored in Read-Only Memory and forcing a 
change like this could potentially crash your program.
Aug 09 2012